This page looks best with JavaScript enabled

Pwnable: Passcode

 ·  ☕ 3 min read

Introduction

We are given the following code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#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;
}

Let’s see what flags it is compiled with:

Security flags

So far we can’t execute shellcode on the stack. However it doesn’t have ASLR enabled so we can reference segments of code without leaking addresses.

Solution

The challenge description mentions some warnings compiling the code, let’s compile it:

Compilation warnings

Basically it’s pointing that scanf uses both passcode1 and passcode2 uninitialized, so it uses the “garbage” available in the stack when executing it.

Let’s see where in the stack is located:

Login disassembly

Here is the stack frame for the login function, luckily enough passcode1 (0xebp-0x10) is a valid pointer. However pastcode2(0xebp-0xc) is an invalid memory address so scanf causes segmentation fault when attempting to write in that address.

Stack view

If we now enter all 100 characters on welcome we corrupt the login stack frame just until passcode1(included):

Stack view smashed

At this point we can overwrite the address where scanf writes, that means that we can write an int (the same as 4 bytes) in an arbitrary address.

Our goal now is to modify an address so that we can return to system("/bin/cat flag"). Firstly thought to bruteforce modifying the first but then realized that scanf adds a terminating null byte (\0).
The only option left is to overwrite the got address. There are the following functions available before the code exits:

  • fflush
  • printf
  • puts
  • exit

Here is the GOT addresses using gdb gef:

GOT addresses

After some debugging realized that x00 and x0c are bad chars for scanf (using %s formatter), therefore we can’t override printf or puts.

To generate the payload we can use python:

python2 -c 'print("A"*96+"<GOT_DIR>"+"<RET_DIR>")' > fflush

Don’t forget to jump to the previous direction of system call, otherwise the argument wouldn’t be passed, also the address has to be sent in decimal form due to %d formatter.

Here is the result with the different functions:

Solution

Mentions

Share on

ITasahobby
WRITTEN BY
ITasahobby
InTernet lover