—BlindROP 盲打例题
参考资料:https://www.cnblogs.com/HX-Note/p/17291361.html
axb_2019_brop64
首先连接一下远程环境,看一看程序会发送出来什么信息,我们又需要输入什么,先了解程序的基本运行流程:
寻找程序的偏移量:
这里我们可以看到,在 Please tell me: 后用户可以进行字符串的输入,之后会返回 Repeater 和 GoodBye。我们从偏移为 1 开始暴力枚举,当程序崩溃的时候代表缓冲区已经填充满,-1 即为最大填充长度,也就是偏移:
1 | from pwn import * |
寻找 stop gadgets:
stop gadgets 一般指的是这样一段代码:当程序的执行这段代码时,程序会进入无限循环,这样使得攻击者能够一直保持连接状态。 如果该地址是非法地址,那么程序就会crash。这样的话,在攻击者看来程序只是单纯的crash了。因此,攻击者就会认为在这个过程中并没有执行到任何的useful gadget,从而放弃它。
寻找 main 函数地址
我们想要寻找 main_addr 作为本题的 stop gadgets,从而可以无限次返回本题的 main 函数进行攻击:
我们首先需要知道栈上的分布:
AAAA…(216 个 A) + \x70\x08\x40\x00\x00\x00\x00\x00(返回地址-假设的)+ Goodbye!
根据栈的分布,我们可以截取出返回地址的值,它要跳回代码原.text 段,也就是我们想要的 main 地址。
1 | from pwn import * |
寻找 stop_gadgets:
0x400834-216=0x40075C
1 | from pwn import * |
存疑 stop_addr = 0x4007d6
寻找 brop_gadgets
寻找BROP gadgets,这段gadget也就是libc_csu_init中的这段gadget。 我们需要用到这一段的内容:
1 |
|
由于我们后面的目标是运用 puts@plt 表,所以我们当前要做的是寻找 pop rdi;ret
典型的 BROP gadget 是 pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret(6 个 pop + 1 个 ret)—— 执行时会从栈上弹出 6 个值(对应 p64(0)*6),然后 ret 跳转到 stop_addr;如果 addr 不是 BROP gadget(比如指令无效)程序会崩溃;如果是有效 gadget,程序会正常执行到 stop_addr。
1 | +---------------------------+ |
1 | from pwn import * |
至此我们得到 pop rdi;ret 地址为 0x40059a + 0x9
寻找 puts.plt:
为了让程序有健壮性,在软件构建的时候,采用了动态链接。也就是,需要才去找他这个函数存在于哪里,利用plt和got表配合使用,从而实现这个功能。而 puts-plt有跳转执行函数的功能,找到puts-plt就能执行puts函数。
对于寻找的思路,我们依旧是暴力枚举,(爆破范围是0x0000~0xFFFF),基址为0x400000
1 | +---------------------------+ |
1 | from pwn import * |
得到 puts.plt = 0x400635
获取 puts.got 表地址
我们知道,plt表里,存着got地址,如果我们把plt表dump出来,那么我们就知道got的地址,知道got的地址,我们就能泄露真实的函数地址 :


更新: 2026-03-05 19:33:14
原文: https://www.yuque.com/idcm/wnemg9/zvyb0o9g494ivfo8