passcode
{"author": ["ret2basic"]}

Source Code

1
#include <stdio.h>
2
#include <stdlib.h>
3
4
void login(){
5
int passcode1;
6
int passcode2;
7
8
printf("enter passcode1 : ");
9
scanf("%d", passcode1);
10
fflush(stdin);
11
12
// ha! mommy told me that 32bit is vulnerable to bruteforcing :)
13
printf("enter passcode2 : ");
14
scanf("%d", passcode2);
15
16
printf("checking...\n");
17
if(passcode1==338150 && passcode2==13371337){
18
printf("Login OK!\n");
19
system("/bin/cat flag");
20
}
21
else{
22
printf("Login Failed!\n");
23
exit(0);
24
}
25
}
26
27
void welcome(){
28
char name[100];
29
printf("enter you name : ");
30
scanf("%100s", name);
31
printf("Welcome %s!\n", name);
32
}
33
34
int main(){
35
printf("Toddler's Secure Login System 1.0 beta.\n");
36
37
welcome();
38
login();
39
40
// something after login...
41
printf("Now I can safely trust you that you have credential :)\n");
42
return 0;
43
}
Copied!

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:
1
scanf("%100s", name);
2
...
3
scanf("%d", passcode1);
4
...
5
scanf("%d", passcode2);
Copied!
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:
1
name => ebp-0x70
2
passcode1 => ebp-0x10
3
passcode2 => ebp-0xc
Copied!
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):
1
void login(){
2
...
3
printf("enter passcode1 : ");
4
scanf("%d", passcode1);
5
fflush(stdin);
6
...
7
}
Copied!
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 with 0x804a004, then the scanf() statement becomes scanf("%100s", 0x804a004). This would allow us to input arbitrary data to the memory location 0x804a004, which is [email protected].
    3.
    Once the scanf() function is called, send the integer representation (because of "%100s") of system("/bin/cat"). Once [email protected] is called, the jmp instruction will jump to system("/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

Get flag
Last modified 5mo ago
Copy link