passcode
{"author": ["ret2basic"]}
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 [email protected] -p2222 (pw:guest)
#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;
}
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:
welcome()

login()
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:

fflush()
This
fflush()
is [email protected]
, and the first jmp
instruction jumps to [email protected]
. The idea is:- 1.Send 96 bytes of junk data to fill the buffer.
- 2.Overwrite
password1
with0x804a004
, then thescanf()
statement becomesscanf("%100s", 0x804a004)
. This would allow us to input arbitrary data to the memory location0x804a004
, which is[email protected]
. - 3.Once the
scanf()
function is called, send the integer representation (because of"%100s"
) ofsystem("/bin/cat")
. Once[email protected]
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()
:
login()
Here
0x80485d7
is the address of system("/bin/cat")
. To get its integer representation, use str(0x80485d7)
in Python.
Get flag
Last modified 11mo ago