Another way to mess with functions in GDB is to change register values to bypass conditionals. Inspiration from this came from a HackTheBox challenge made by w3th4nds. You can find it here
The Code
We have a short program where the argument for the i_am_locked
function is used as a conditional. We are not in control of what goes into the function call in main
but we have a debugger!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
void i_am_locked(long lock) {
if (lock == 0x6d617465) {
printf("\n\nUnlocked!\n");
return;
}
printf("Normal return.\n");
}
int main() {
printf("Speak \"friend\" and enter:\n");
i_am_locked(424242);
return 0;
}
Running it
Let’s compile and run it:
gcc locked.c -o locked
We get the following output, but no “Unlocked!”.
GDB
So let’s open the GDB and see what we can do. We already know which functions are in the ELF but let’s repeat to practice:
We see the i_am_locked
. Let’s set a break point there to dig deeper.
b i_am_locked
We have paused just inside the i_am_locked
function and the next few instructions are interesting. The current instruction is related to moving the stack pointer to make room for the new function. The next one however is where the fun starts. It moves the contents of register rdi
to rbp
with an offset (0x8). Then it uses whatever is stored on the -0x8(%rbp)
to compare to the desired value (0x6d617465). Let’s change move to the next instruction and alter the rdi
value.
By looking at the registers we can tell that rdi
currently holds the decimal value of 424242 which we also saw in the code at the function call to i_am_locked
. We can change the value in this register with
set $rdi = 0x6d617465
With the register changed the program will now continue with the conditional which should now evaluate to true. Let’s see!
There we go!