passcode
{"author": ["ret2basic"]}
Challenge
Mommy told me to make a passcode based login system. My initial C code was compiled without any error! Well, there was some compiler warning, but who cares about that?
ssh passcode@pwnable.kr -p2222 (pw:guest)
Code Review
#include <stdio.h>
#include <stdlib.h>
void login(){
int passcode1;
int passcode2;
printf("enter passcode1 : ");
scanf("%d", passcode1);
fflush(stdin);
// ha! mommy told me that 32bit is vulnerable to bruteforcing :)
printf("enter passcode2 : ");
scanf("%d", passcode2);
printf("checking...\n");
if(passcode1==338150 && passcode2==13371337){
printf("Login OK!\n");
system("/bin/cat flag");
}
else{
printf("Login Failed!\n");
exit(0);
}
}
void welcome(){
char name[100];
printf("enter you name : ");
scanf("%100s", name);
printf("Welcome %s!\n", name);
}
int main(){
printf("Toddler's Secure Login System 1.0 beta.\n");
welcome();
login();
// something after login...
printf("Now I can safely trust you that you have credential :)\n");
return 0;
}
Solution
There is an error in the code: instead of scanf("%d", passcode1)
, it should be scanf("%d", *passcode1)
. Because of this error, passcode1
and passcode2
are considered addresses instead of values. In fact, there are three erros in the code:
scanf("%100s", name);
...
scanf("%d", passcode1);
...
scanf("%d", passcode2);
For each scanf()
, we are able to write some data directly to the address of the variables name
, passcode1
, and passcode2
. Let's read through the assembly to figure out the exact location of each variable:


The location for each variable:
name => ebp-0x70
passcode1 => ebp-0x10
passcode2 => ebp-0xc
The distance between name
and passcode1
is 0x60
, which is 96 in decimal. We are able to input at most 100 bytes for name
, so it is possible to overwrite passcode1
.
Note that the function fflush()
is called right after scanf("%d", passcode1)
:
void login(){
...
printf("enter passcode1 : ");
scanf("%d", passcode1);
fflush(stdin);
...
}
Let's see its disassembly:

This fflush()
is fflush@PLT
, and the first jmp
instruction jumps to fflush@GOT
. The idea is:
Send 96 bytes of junk data to fill the buffer.
Overwrite
password1
with0x804a004
, then thescanf()
statement becomesscanf("%100s", 0x804a004)
. This would allow us to input arbitrary data to the memory location0x804a004
, which isfflush@GOT
.Once the
scanf()
function is called, send the integer representation (because of"%100s"
) ofsystem("/bin/cat")
. Oncefflush@PLT
is called, thejmp
instruction will jump tosystem("/bin/cat")
and execute it.
Essentially, this is a GOT overwrite attack. The last task is finding the address of system("/bin/cat")
. Take another look at the disassembly of login()
:

Here 0x80485d7
is the address of system("/bin/cat")
. To get its integer representation, use str(0x80485d7)
in Python.
Get Flag

Exploit
Last updated