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:

  • 相关阅读:
    ASP.NET2.0中将文件上传到数据库
    C#中数据类型转换
    数据绑定以及Container.DataItem的具体分析
    CodeSmith开发系列资料总结
    Jquery信息专题收集
    microsoft .net framework专题汇总
    ASP.NET中插入FLASH代码
    javascript专题汇总
    经典SQL行列转换
    前台js调用后台c#方法
  • 原文地址:https://www.cnblogs.com/p4nda/p/7159730.html
Copyright © 2011-2022 走看看