【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:

原文地址:https://www.cnblogs.com/p4nda/p/7159730.html