0

So I am currently doing a beginner CTF challengeon pwnable.tw, the "start" challenge specifically. After reversing the challenge binary I found out there was a buffer overflow exploit, and one thing I would have to do to get an ideal starting point would be to leak the stack address by pointing it back to a specific address (0x08048087), so i crafted a payload, that would then overwrite the return address with the address I was aiming for. However, I'm having trouble converting the byte data into a string format to be fed to the vulnerable program.

Below is my python code:

from pwn import *
shellcode = b'A' * 20
shellcode += pack(0x08048087, 32)
print(shellcode)

I use the pwn library to simplify packing the address, and then I print it and then pipe it into the vulnerable binary as stdin. However, what will happen when I print this, is that rather than printing the string equivalent of the associated hex values of that address, it will instead print this:

b'AAAAAAAAAAAAAAAAAAAA\x87\x80\x04\x08'

Just a string literal version of the hex values themselves. However, this will of course not be interpreted by the program in the way i intend it to be. So I try to decode it into utf-8 or an ASCII string, or even use str to convert it no matter which way I choose I get the following error:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x87 in position 20: invalid start byte

It would seem it can't decode the 0x87, which makes sense, in this case there does not seem to be an equivalent for it to decode to. But then my question becomes how can I deliver my shell code, specifically the hexadecimal address part, to the program in a way that the program will interpret that portion of the overflowed buffer as the address that i intend it to, rather than it being incorrectly mapped since my script gave me a stringified version of the hex values themselves?

7
  • print requires a string. Import sys and use sys.stdout.write. Commented Nov 24, 2022 at 7:59
  • pwntools lets you interact with running programs. Use process (ELF running on your PC) or remote (remote connection) to connect to the process, then you can use the functions send and recv (and derivatives) Commented Nov 24, 2022 at 23:37
  • @MargaretBloom so I did what you said and replaced it with sys.stdout.write and if i run it regularly it will print out: AAAAAAAAAAAAAAAAAAAA\x87\x80\x04% Which is the output, but still seems to be displayed in string format? Also when I try to use output pipe to direct it into a test.txt file with python3 shell.py >> test.txt I simply get: TypeError: write() argument must be str, not bytes Which is......strange, I don't see how adding an output redirect to the terminal command itself could do that, especially given it's creating a file rather than using a pre-existing one. Commented Nov 25, 2022 at 2:16
  • 1
    @MargaretBloom My understanding is mostly solid, I've been using it professionally for two years now. It's just in most general software use cases in Python you don't usually think about having to force output of invalid bytes as stdout to a terminal. But I was able to figure it out, it turns out using sys.stdout.buffer.write was the answer, which gives me the forced terminal output I need. As for the prior issue, again output redirect happens at the shell level after the data has been written to stdout, no idea why python has an issue with it, so that eludes me still. Thanks for the help! Commented Nov 25, 2022 at 18:04
  • 1
    @leatherprofitable You are right! Sorry! I should be the one brushing up on Python! sys.stdout is a TextIOWrapper that accepts strings. The underlying binary (buffered) stream is in its buffer property, so its sys.stdout.buffer.write to write bytes. But escapes on bytes objects should work regardless of how they are used. But consider using the process class of pwntools, it s simpler. Commented Nov 25, 2022 at 18:24

1 Answer 1

0

So I ended up finding the answer, it was to use sys.stdout.buffer.write(), rather than print or sys.stdout.write() since sys.stdout.buffer.write() uses a BufferedWriter which simply operates on raw bytes rather than the other two which operate on text/strings. Thank you to everyone in the comments who helped me!

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

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.