zoukankan      html  css  js  c++  java
  • 【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:

  • 相关阅读:
    【数据结构】线性表&&顺序表详解和代码实例
    【智能算法】超详细的遗传算法(Genetic Algorithm)解析和TSP求解代码详解
    【智能算法】用模拟退火(SA, Simulated Annealing)算法解决旅行商问题 (TSP, Traveling Salesman Problem)
    【智能算法】迭代局部搜索(Iterated Local Search, ILS)详解
    10. js时间格式转换
    2. 解决svn working copy locked问题
    1. easyui tree 初始化的两种方式
    10. js截取最后一个斜杠后面的字符串
    2. apache整合tomcat部署集群
    1. apache如何启动
  • 原文地址:https://www.cnblogs.com/p4nda/p/7159730.html
Copyright © 2011-2022 走看看