LOADING

加载过慢请开启缓存 浏览器默认开启

ret2dlresolve 学习笔记(施工中)

2025/7/2 pwn rop

直接上题:

好大的栈溢出……

还有 backdoor。

先溢出到 backdoor 观察一下先。

payload = b'a'*0x68 + p64(backdoor)
p.send(payload)

注意是 si 单步进入。

可以看见跳转到了 0x7df595569d30。

x/40i:

vmmap 查看,鉴定为来自 ld,gdb 暂时无法解析。查看 0x401000:

注意到它们 jmp 的相同,但 push 的不同;所有的函数最后都 push [rip + 0x2302],然后 jmp [rip + 0x2303] <0x7df595569d30>;

在经过这个神必函数后,@got.plt被填上相应libc的地址,下次调用直接跳转:

所以可以得知,我们的 payload 在 padding 后面加上 p64(0x401020) + p64(0x2),就会执行 exit。

试试:

payload = b'a'*0x68 + p64(wtf) + p64(0x2)
p.send(payload)

确实如此:

试试把 0x2 换成 0x3:

程序崩了:

查询资料可知,之前的神必函数叫做 _dl_runtime_resolve,然后这个报错是因为
_dl_runtime_resolve 调用了 _dl_fixup,里面有一句:

_dl_fixup(struct link_map *l,ElfW(Word) reloc_arg)
/*......*/
assert(ELF(R_TYPE)(reloc->info) == ELF_MACHINE_JMP_SLOT);
//就是这句话导致了报错。

Elf64_Word 就是整数,就是我们传入的 0x3。

那么前面的 struct link_map 就很有意思了,这就是需要我们构造的贵物,查看资料得知在调用 dl_runtime_resolve 前就已经传入。

众所周知第一个参数在 rdi 上,我们跟进神必函数。

从 rbx 的偏移中读取数值,其中就有我们传入的 0x2。

这也意味着有个关键的东西 (struct link_map) 也被 push 了进去,重开再观察一次。

[rip + 0x2302] 就是我们要找的 link_map;

dl_runtime_resolve 的反汇编中,rsp 传给了 rbx:

因此,我们的 payload 可以变为:

fake_link_map_addr = 0x0 # 因为不知道在 stack 上怎么伪造,所以需要 stack pivot 把输入搞到地址确定的 .bss 上.
enter = 0x401026
payload = b'a'*0x68 + p64(enter) + p64(fake_link_map_addr) + p64(0x2) # 0x2 的“意思”就是 exit,当然要是真伪造成功,肯定就不是 exit 而是 system 了。
p.send(payload)

先学习栈迁移吧。