Patching binaries with pwntools
Last updated
Was this helpful?
Last updated
Was this helpful?
So... what actually is patching binaries?
Patching binaries is quite as it seems by the name. It is basically changing some binary in order to make it work in a better way or simply to bypass some protection directly from assembly level.
In order to have a better understanding of it, we will be using the "be quick or be dead" picoCTF challenges.
If you download the be-quick-or-be-dead-1
binary at the folder at this repo, you can check it out yourself.
A good idea is, before anything, to check all the symbols at the programs
This way, you can load the binary as an ELF
file and iterate through the items at the symbols table, that can be obtained with pwntools elf.symbols.iteritems
.
In order to exploit the binary, first we need to understand what it is doing. That can be discovered for example using a disassembler, like IDA, radare2 or hopper.
The pseudo-code of the main is as the following:
So we see that there is a function header, that prints the header of the challenge.
Then, it calls the function set_timer()
that is the following:
First there is an error checking, just to see if the alarm signal will work properly. Then it sets up a 1 second alarm, that will be toggled when the time ends.
After this function, it will continue normally with the get_key()
function, that calls calculate_key()
, that works as the following:
As you can see, it simply gets v1 and sums until v1 is -538274182
, what will happen quite after the overflow. After that, it will return 3756693114LL
.
There are basically two ways of solving this challenge.
The easier one in my opinion is to simply "jump" the timer function, this way after the computation finishes the flag will be printed.
In order to do it with pwntools, we do as the following:
As before, we load the binary as ELF.
Then, we overwrite the assembly instruction that is at the beginning of the alarm
function with a ret
, this way as soon as the program enters at this function, it will return, not setting the timer.
In the end, a new patched binary is generated. In order to solve the challenge is enough to execute it.
As we could see from the analysis, the calculate_key
function did a lot of unnecessary computation, just to return 3756693114
.
So we modify that one just to mov
that value to eax, that is the convention of the return values of functions, and than returns. The following C represent the new calculate_key function.
Therefore, generating the patched binary and executing it, we successfully obtain the flag.