Hi Pwntools, Goodbye Shell Scripts
Intro
Tl;dr: use pwntools. Interact with the process using pwntools and use rabin2 -z to get the strings from the file. Profit.
In this challenge we have an unknown file ‘intro’ which would give us a hint to the flag. Time to get into it.
Run the file command to find out what files I’m dealing with (prettified)
1
2
3
4
5intro: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV),
dynamically linked,
interpreter /lib/ld-linux.so.2,
for GNU/Linux 3.2.0, BuildID[sha1]=177bf7376a9ca94f15c6557a9301244afc7c00f4,
with debug_info, not strippedSo its an Elf binary => An executable program (assuming C)
Since it is executable, and because I expect it to be safe enough, I run it.
1
2
3
4Yay you connected!
If you connected WITHOUT using pwntools, please exit and do that first!
Lets see if you can strip out this address: {0x1337}
Now send it back to me in decimal form!Ah, interacting with another process.
I remember when I would write programs for the same and it would never work, resorting to shell loops was also hopeless.
Well pwntools is here to solve all problems.I used (pwnlib.tubes.process)[https://docs.pwntools.com/en/stable/tubes/processes.html] to run and interact with the process. Spawn a new process using the
process
function, then using thereaduntil(<str>)
function you can very literally read until the passed string is found in the input. Then usesendline(<str>)
to write data back to the process.process()
has a flag:shell
which would interpret the argument as a shell command instead of a file to runreaduntil()
has a flag:drop
which would drop the delimiter you passed insendline(<str>)
function will write a newline after the string is printed
The binary throws a couple of challenges my way: converting hex to decimal, basic maath operations, reading and writing bytes etc. Here are the list of functions (from pwntools) I used to solve them:
- (p32)[https://docs.pwntools.com/en/stable/util/packing.html#pwnlib.util.packing.p32]: convert (pack) integer into raw byte form
- (u32)[https://docs.pwntools.com/en/stable/util/packing.html#pwnlib.util.packing.u32]: Unpack raw bytes into integer form
Finally, the binary asks for a secret hidden in the file. Easily found by running
strings
on the file. But if you ever downloaded radare2, I recommend using1
rabin2 -z intro
to get the strings. The command gets only the strings in the data section of memory so you don’t have to peer through the long list.
The string password which was not seen used before, so assuming that that was the one, you test it, and it works.
The final step is to use the
interactive()
function frompwnlib.tubes
to interact with the shell that the process spawns on finishing all the challenges. Runcat flag
to get the flag in the directory.
This makes the final script to run the following.
1 | from pwn import * |
Tip
- One thing that helped me in my endeavors is the
DEBUG
flag. On running the script with the flag, it prints all debug output like what data was received from the spawned process, which is amazing for debugging.
Too-Slow
Tl;dr: Pwntools is pretty cool. You can pass multiple delimiters to readuntil()
!
We come across a strange file named ‘too-slow’. Time to analyze it.
Similar to the previous one, start by running the file command.
1
2
3
4
5
6
7
8too-slow: ELF 32-bit LSB shared object,
Intel 80386,
version 1 (SYSV),
dynamically linked,
interpreter /lib/ld-linux.so.2,
for GNU/Linux 3.2.0,
BuildID[sha1]=fc21f7e613d118404b5c0e038868a6e938b8766e,
with debug_info, not strippedELF-binary. Yay
Running it, we see it wants you to solve math problems. Fast. Now, unless you’re a human calculator with godlike typing speeds, it’s best to leave this one to pwntools. Same as the last one, use pwntools to read and write to the process. Now, you would realize that you have to do this in a loop to solve all the problems.
When you do that however, the program gets stuck after a while. Using the DEBUG flag, we see that we have solved all the math problems and the program has opened up a shell. Pwntools is trying to read from the process, but no data is sent across. So it’s not interactive, and you cannot talk to the shell it just spawned.
Now, you have two ways to fix this. Either brute force it, finding the number of problems the program asks you to solve or use the
readuntil()
function better. Using the DEBUG flag to understand the format of the inut, you see that there are essentially 3 types of lines. Correct Answer\n, number + number =, Well done\n. On looking at the pwntools documentation, you see thatreaduntil()
accepts a list of delimiters. Using this information you can parse the input better to solve the problem.Lastly, you need the
interactive
method again to talk to the shell that was spawned.
So the final script was
1 | from pwn import * |
Conclusion
Pwntools truly is amazing. I look forward to using the other features too.