Reversing
revmem
strace
strace is a diagnostic, debugging and instructional userspace utility for Linux. It is used to monitor and tamper with interactions between processes and the Linux kernel, which include system calls, signal deliveries, and changes of process state.
ltrace
ltrace is a library call tracer and it is primarily used to trace calls made by programs to library functions. It can also trace system calls and signals, like strace.
A first approach
Reversing challenge, meaning that we have just the binary and no remote connection needed. We just need to find the correct output that will make our binary print the flag. In this case we can start launching the binary with some random input to check its behaviour:
Ok, now lets strace
it:
Not useful at all.
Actually is way easier than it looks like
Now lets try ltrace
on it:
Well...
This is happening because of this line of code:
From which we can see that the program is taking the flag which is hardcoded in memory.
From this snippet of code we can see that the flag is put in memory by a malloc
after being obtained by XORing the encoded version of the flag. Because of the strcmp
with the flag in memory and our input we can see the flag in clear with ltrace
.
revmemp
Very similar to revmem. Both strace
and ltrace
outputs are not very useful in this case. We can try to debug the application when the strcmp
between the user input and the flag gets executed. From the disassembler:
Which corresponds to:
If we try to put a breakpoint there and to debug it:
Turns out we can't debug it with gdb:
Rip. This is a special function called INIT
function, which is called before the begin of the main, which means that they are kind of hidden. Good way to find them: looking at which text output they prints, and search for it into Ghidra, or run strings on the binary
Can we stop the binary from escaping that check? Yes, we just need to patch the binary: we could, for example, replace the exit(-1)
with tops to avoid this check altogether.
Still, we have another problem. The following function gets called multiple time during execution:
It basicaly checks if the first and second symbols of entry are breakpoints (0xcc
). It basically avoids the user from using them.
How to patch the binary (xxd
, the hard way)
xxd
, the hard way)We'll be using vim. First of all open the binary: vim ./revmemnp
. then input the following:
this gives us hex dump of the binary. Then we need to search for the byte codes of the instruction we want to replace. To search in vim we use the forward slash command. So, we want to replace the exit in the debugger avoider function to be a bunch of nop. So we'll first search for its first opcode:
Then press enter, and keep pressing n until we find our function:
Then we can use I to enter intert mode, overwrite it with pops (note that it is made up of 5 opcodes, which means we need 5 nops), and pass :%!xdd -r
and :wq
to save and exit. Or you could just use a gui hex editor, it works either way.
The exploit
Basically we just need to overwrite both checks, the one which prevents us from setting a breakpoint, and the one that checks if we have gdb attached. Once the binary has been patched to remove the exit, we just start the binary with gdb
, set a breakpoint in the strcmp
, and then we can just see the flag in clear as argument of the strcmp
:
keycheck_baby
In this challenge we have to reverse engineer a key encryption algorithm divided in two steps. We have the key which is split in two and encrypted differently using two loops.
Pt.1
This first loop XORs the key with characters from the string babuzz
% 6 (modulo), which is the length of the string itself. Easy reverse, since we have the result of the XOR, which is the magic0
variable and we can just XOR the two to get past it (since the XOR is an invertible function):
Pt.2
As for the second one:
We have a CBC encryption algorithm:
Implemented as such:
Note: in both loops the label LAB_00101487
take the instruction pointer to the end of the main, making the program exit. To reverse this we need an equation system as such:
Where $IV$ is the initialization vector. This can be implemented in python as follows:
In the code above $p_{i}$ are characters of the flag, while $c_{i}$ are characters of magic1
.
crackme
Another easy reversing challenge, in this case we have a XOR cypher:
Solution:
Last updated