• 【pwnable.kr】 codemap


    pwnable新的一题。

    download: http://pwnable.kr/bin/codemap.exe

    ssh codemap@pwnable.kr -p2222 (pw:guest)

    这道题虽然是在pwnable下,但是是一道逆向题。。。 //前web狗膜一发二进制大佬

    根据提示,需要查看 0x403E65 运行时,寄存器 EAX,EBX 的内容。

    先不考虑运行的内容,先看程序。首先这个程序没有加壳,直接可以用ida查看内容.

    然后可以看到程序的框架,在main函数中,默默按下F5...

    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      int seed; // esi@3
      int (***v4)(void); // eax@3
      int (***v5)(void); // edi@3
      int v6; // esi@4
      int (**v7)(void); // eax@4
      int (***random_funtion)(void); // ecx@5
      unsigned int v9; // eax@8
      unsigned int v10; // esi@8
      char *eax_now_str; // ebx@8
      unsigned int i; // esi@9
      char *max_eax_str; // [sp+10h] [bp-60h]@0
      unsigned int eax_now; // [sp+14h] [bp-5Ch]@8
      unsigned int count; // [sp+18h] [bp-58h]@1
      unsigned int max_eax; // [sp+1Ch] [bp-54h]@1
      char word_str; // [sp+20h] [bp-50h]@9
      int v19; // [sp+6Ch] [bp-4h]@3
    
      printf("I will make 1000 heap chunks with random size
    ");
      printf("each heap chunk has a random string
    ");
      printf("press enter to start the memory allocation
    ");
      sub_3440B1();
      max_eax = 0;
      count = 0;
      srand(0);
      while ( 1 )
      {
        seed = 10000 * rand() % 1337;
        v4 = (int (***)(void))operator new(8u);
        v5 = v4;
        v19 = 0;
        if ( v4 )
        {
          *v4 = (int (**)(void))&off_34F2EC;
          v6 = (10000 * seed >> 1) + 123;
          v7 = (int (**)(void))operator new(8u);
          if ( v7 )
          {
            v7[1] = (int (*)(void))v6;
            v5[1] = v7;
            random_funtion = v5;
          }
          else
          {
            v5[1] = 0;
            random_funtion = v5;
          }
        }
        else
        {
          random_funtion = 0;
        }
        v19 = -1;
        v9 = (**random_funtion)();
        v10 = v9 % 0x186A0;
        eax_now = v9 % 0x186A0;
        eax_now_str = (char *)malloc(v9 % 0x186A0);
        if ( v10 >= 0x10 )
        {
          qmemcpy(&word_str, "abcdefghijklmnopqrstubwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 0x3Fu);
          i = 0;
          do
            eax_now_str[++i - 1] = *(&word_str + rand() % 62);
          while ( i < 0xF );
          eax_now_str[15] = 0;
          if ( eax_now > max_eax )
          {
            max_eax = eax_now;
            max_eax_str = eax_now_str;
          }
        }
        if ( ++count >= 0x3E8 )                     // 0x3e8 = 1000
          break;
        srand(count);
      }
      printf("the allcated memory size of biggest chunk is %d byte
    ", max_eax);
      printf("the string inside that chunk is %s
    ", max_eax_str);
      printf("log in to pwnable.kr and anwer some question to get flag.
    ");
      sub_3440B1();
      return 0;
    }

    这是把F5以后的反编译程序,加上自己的理解改成了这个样子。

    这个是一个循环申请内存空间,并随机填充16个a~Z0~9字符的程序,循环次数为1000次。

    每次循环后,找到申请空间最大的那次,并打印出来。

    上面最重要的是random_function变量,它的结果是下图这些sub_*的函数,内容就是根据现在的执行上下文生成一个随机数。

    由于上面代码中用的随机函数都是伪随机,或者种子固定,因此,每次运行该程序,申请的大小、字符串的添加都是一样的。

    而题目中给的提示,EAX、EBX是执行的结果,其中EAX存储的是申请内存的大小、EBX存储一个char指针,指向填充的字符串。

    做了以上分析之后,可以想出解决思路,每次在该位置下断点,获取EAX、EBX的内容,最后做删选即可。

    而通过服务器上所给的提示,随后需要提交第二、第三大分配内存块所填充的字符串内容。

    由于做了1000次循环,因此人工寻找几乎不可能。

    还好ida工具有ida 脚本这样一种工具,可以动态获取指定内容。

    可以编写ida脚本来完成查找。我使用了IDA Python这一工具。其实和idc基本相同。

    思路就是下断点——获取EAXEBX的值,最终进行比较,由于没想到好的排序算法,就直接采用最简单粗暴的方法

    脚本如下,另外每次程序加载到内存中的位置不同,使用时应修改添加断点的内存地址。

    from idaapi import *  
    from idc import *  
    import os
    
    count = 0
    eax_list = list()
    ebx_list = list()
    
      
    try:
        if debugger:
            print("Removing previous hook ...")
            debugger.unhook()
    except:
        pass
    AddBpt (0x403e65)
    print "[*] set hook OK...
    "
    StartDebugger("","","")  
    for i in range(0,999):
        GetDebuggerEvent(WFNE_SUSP|WFNE_CONT, -1)
        print "[+]",i
        eax = GetRegValue("EAX")
        eax_list.append(eax)
        ebx = GetRegValue("EBX")
        ebx_list.append(ebx)
        if i == 998:
            print '[+] eax max : ',max(eax_list)
            index = eax_list.index(max(eax_list))
            a = ebx_list[index]
            #message( "[+] ebx max : %x",%(ebx_list[eax_list.index(max(eax_list))]))
            Message("%x"%a)
            print "max",GetString(a)
            del(eax_list[index])
            del(ebx_list[index])
    #        
            print '[+] eax second : ',max(eax_list)
            index = eax_list.index(max(eax_list))
            a = ebx_list[index]
            #message( "[+] ebx max : %x",%(ebx_list[eax_list.index(max(eax_list))]))
            Message("%x"%a)
            print "second",GetString(a)
            del(eax_list[index])
            del(ebx_list[index])        
    #        
            print '[+] eax third : ',max(eax_list)
            index = eax_list.index(max(eax_list))
            a = ebx_list[index]
            #message( "[+] ebx max : %x",%(ebx_list[eax_list.index(max(eax_list))]))
            Message("%x"%a)
            print "third",GetString(a)
            del(eax_list[index])
            del(ebx_list[index])

    最终,运行的结果如下: 

     nc 0 9021输入字符串之后可以获得该题的flag:

  • 相关阅读:
    [转]lftp的致命错误:证书验证:不信任
    github每次push都需要密码以及用户名的解决办法
    Fedora最小化安装后没有ifconfig命令
    [转载]MySql常用命令总结
    chrome浏览器强制采用https加密链接
    红帽系列linux自行配置本地yum源
    linux 下dd命令直接清除分区表(不用再fdisk一个一个的删除啦)
    linux分区工具fdisk的使用
    Java多线程实现......(1,继承Thread类)
    第一篇文章--我为什么要写博客?
  • 原文地址:https://www.cnblogs.com/p4nda/p/7159730.html
Copyright © 2020-2023  润新知