[문제]
[풀이]
보호기법 분석
- 32bits 바이너리
- 카나리 존재 → bof 불가
- NX bits 존재
- PIE 없음
소스코드 분석 - passcode.c
#include <stdio.h>
#include <stdlib.h>
void login(){
int passcode1;
int passcode2;
printf("enter passcode1 : ");
scanf("%d", passcode1);
fflush(stdin); //buffer를 지워줌
// 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;
}
- main 함수에서는 단순히 welcome 함수와 login 함수를 호출함
- welcome 함수
- name에 대한 정보를 입력 받는데, 100byte 만큼 입력할 수 있음
- login 함수
- passcode1, passcode2를 입력 받아 각각 338150, 13371337이면 flag를 출력함
- 그러나 passcode1, passcode2는 초기화되지 않아 에러가 발생함 → 쓰레기 값을 주소로 가리키기 때문Segmentation fault (core dumped) in c - pointers and memory management
- scanf 함수
- 그런데 해당 값을 입력하면 Segmentation Fault가 발생함
gdb 분석 - 함수 주소
gdb-peda$ info func
All defined functions:
Non-debugging symbols:
0x080483e0 _init
0x08048420 printf@plt
0x08048430 fflush@plt
0x08048440 __stack_chk_fail@plt
0x08048450 puts@plt
0x08048460 system@plt
0x08048470 __gmon_start__@plt
0x08048480 exit@plt
0x08048490 __libc_start_main@plt
0x080484a0 __isoc99_scanf@plt
0x080484b0 _start
0x080484e0 __do_global_dtors_aux
0x08048540 frame_dummy
0x08048564 login
0x08048609 welcome
0x08048665 main
0x080486a0 __libc_csu_init
0x08048710 __libc_csu_fini
0x08048712 __i686.get_pc_thunk.bx
0x08048720 __do_global_ctors_aux
0x0804874c _fini
gdb 분석 - welcome
gdb-peda$ disass 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] #user name 저장 위치
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.
- 사용자의 입력 값은 ebp-0x70에 저장됨
- 임의의 입력값(다수의 a)를 넣었을 때 ebp-0x70에 잘 저장됨을 알 수 있음
gdb 분석 - login
gdb-peda$ disass 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] #passcode1
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] #passcode2
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.
- passcode1, passcode2로 입력한 값은 각각 ebp-0x10, ebp-0xc에 저장됨
- 그러나 해당 위치에 값이 저장되지 않음
- 임의의 값(다수의 1)을 입력하면 0xffd624c0에 저장됨
- passcode1에 임의의 값(다수의 1)을 입력하면 Segmemtation Fault가 발생함
- scanf가 내부적으로 호출하는 _IO_vfscanf 함수에서 에러 발생
- 그런데 welcome과 login 함수의 ebp 값이 동일함
→ 같은 스택에 데이터를 저장한다!
→ name은 ebp-0x70, passcode1은 ebp-0x10, passcode2는 ebp-0xc에 각각 저장되는 것
- 전체적인 스택 구조를 그려보면 passcode1이 name에 중첩되어 있음
문제 해결
💡 login함수를 살펴보면 passcode1의 입력 값을 받은 후, fflush 함수를 호출하고 있는데 여기서 got주소를 이용할 수 있음. fflush함수를 호출하게 되면 plt 주소에서 got주소를 참조하여 찾아가게 되는데, 이 got 주소를 login+127의 주소로 변경해주면 조건문의 조건을 충족하지 않아도 flag 획득 가능
name에서 96byte만큼의 dummy를 채운 다음 4byte를 fflush함수의 GOT주소를 넣어주고 system 함수의 주소를 넣어주면 system 함수를 실행할 수 있음
즉, [dummy(96)] + [GOT Address(4)] + [system(4)]
- 정리해보자면, name 100byte 중 passcode1 부분을 name 입력 받을 때 fflush@got으로 변경(scanf("%d", fflush@got)의 형태가 됨)→ 실제 passcode1을 scanf로 받는 부분에서 system 함수 호출 부분을 10 진수 형태로 입력(got 주소가 변경되었기 때문에 fflush 대신 system(”/bin/cat flag”)를 호출함)
- scanf(”%d”, passcode1)로 받기 때문에 int type으로 입력해줘야 함
- fflush함수는 리눅스에서는 제 기능을 하지 못함!
+이전에 적었던 풀이 → fflush이외에도 다른 함수로 exploit 하는 방법
- GOT 주소들은 readelf 명령을 통해 확인해볼 수 있고, printf, fflush, exit 모두 무관하게 이용 가능함
flag
🍒 Sorry mom.. I got confused about scanf usage :(
'Wargame > Pwnable.kr' 카테고리의 다른 글
[Pwnable.kr] input (2) | 2022.10.15 |
---|---|
[Pwnable.kr] random (0) | 2022.10.14 |
[Pwnable.kr] flag (0) | 2022.10.14 |
[Pwnable.kr] bof (0) | 2022.10.14 |
[Pwnable.kr] collision (0) | 2022.10.14 |