• 一个PE文件的逆向分析


    一个PE文件的逆向分析

    idf-ctf上有个题,是PE文件的逆向,反正对我来说做出来就是有意思的题,做不出来就没劲。言归正传,下面看一下吧

    大家想玩可以去这个地方去拿题http://pan.baidu.com/s/1dDzUL0X

    然后,上次说到了IDA的F5插件,是的,很牛。之前不用是因为太菜,不会。。。。。。然后这次用了下,果然神器,所以最近也很有必要学一学IDA的东西,推荐大家看《IDA Pro权威指南》。

    好的吧,先把文件拖peid,没壳。然后拖OD,捣啊捣,脑袋大,下断点啊啥的,反正就是弄的很烦,就换IDA了,不过OD查了下字符串,还是得到了一些信息的

    拉到IDA先看看吧,

    有点晕,看看代码吧

    .text:0041148B                 mov     esi, esp
    .text:0041148D                 push    offset Format   ; "plz enter the flag:"
    .text:00411492                 call    ds:printf
    .text:00411498                 add     esp, 4
    .text:0041149B                 cmp     esi, esp
    .text:0041149D                 call    sub_411136
    

    很好,看到了熟悉的字符串往下拉就是对和错的字符串。

    push    offset asc_415764 ; "
    "
    .text:004115E1                 call    ds:printf
    .text:004115E7                 add     esp, 4
    .text:004115EA                 cmp     esi, esp
    .text:004115EC                 call    sub_411136
    .text:004115F1                 cmp     [ebp+var_C0], 0
    .text:004115F8                 jnz     short loc_411613
    .text:004115FA                 mov     esi, esp
    .text:004115FC                 push    offset aURRight ; "u r right!
    "      
                                   //正确喽
    .text:00411601                 call    ds:printf
    .text:00411607                 add     esp, 4
    .text:0041160A                 cmp     esi, esp
    .text:0041160C                 call    sub_411136
    .text:00411611                 jmp     short loc_41162F
    .text:00411613 ; ---------------------------------------------------------------------------
    .text:00411613
    .text:00411613 loc_411613:                             ;    CODE XREF: sub_4113A0+258j
    .text:00411613                 mov     esi, esp
    .text:00411615                 push    offset aURWrong ; "u r wrong
    
    "
                                   //错误啊
    .text:0041161A                 call    ds:printf
    .text:00411620                 add     esp, 4
    .text:00411623                 cmp     esi, esp
    .text:00411625                 call    sub_411136
    .text:0041162A                 call    sub_41113B
    

    但是吧,这个有点看着头疼,于是想到了之前说过的F5大法,按了一下F5就出现了以下情况。

    c语言啊。。。。随后看了下这F5插件的相关资料,原来需要在对应函数区域才管用,所以这就是为啥上次我按死了也没用的原因。

    不对,刚刚又出了个问题,X86版本的才能对该程序F5,我刚打开的是X64,所以这个也得注意。

    int sub_4113A0()
    {
      int v1; // [sp+Ch] [bp-194h]@1
      int i; // [sp+D4h] [bp-CCh]@8
      int v3; // [sp+E0h] [bp-C0h]@8
      int v4; // [sp+ECh] [bp-B4h]@1
      int v5; // [sp+F0h] [bp-B0h]@1
      int v6; // [sp+F4h] [bp-ACh]@1
      int v7; // [sp+F8h] [bp-A8h]@1
      int v8; // [sp+FCh] [bp-A4h]@1
      int v9; // [sp+100h] [bp-A0h]@1
      int v10; // [sp+104h] [bp-9Ch]@1
      int v11; // [sp+108h] [bp-98h]@1
      int v12; // [sp+10Ch] [bp-94h]@1
      int v13; // [sp+110h] [bp-90h]@1
      int v14; // [sp+114h] [bp-8Ch]@1
      int v15; // [sp+118h] [bp-88h]@1
      int v16; // [sp+11Ch] [bp-84h]@1
      int v17; // [sp+120h] [bp-80h]@1
      int v18; // [sp+124h] [bp-7Ch]@1
      int v19; // [sp+128h] [bp-78h]@1
      int v20; // [sp+12Ch] [bp-74h]@1
      int v21; // [sp+130h] [bp-70h]@1
      int v22; // [sp+134h] [bp-6Ch]@1
      int v23; // [sp+138h] [bp-68h]@1
      int v24; // [sp+13Ch] [bp-64h]@1
      int v25; // [sp+140h] [bp-60h]@1
      char v26; // [sp+14Fh] [bp-51h]@1
      char v27[17]; // [sp+178h] [bp-28h]@2   //一个数组啊
      char v28; // [sp+189h] [bp-17h]@13
      char v29; // [sp+18Ah] [bp-16h]@14
      char v30; // [sp+18Bh] [bp-15h]@15
      char v31; // [sp+18Ch] [bp-14h]@16
      char v32; // [sp+18Dh] [bp-13h]@17
      unsigned int v33; // [sp+19Ch] [bp-4h]@1
      int savedregs; // [sp+1A0h] [bp+0h]@1
    
      memset(&v1, 0xCCu, 0x194u);
      v33 = (unsigned int)&savedregs ^ dword_417000;
      v26 = 0;
      v4 = 1;
      v5 = 4;
      v6 = 14;
      v7 = 10;
      v8 = 5;
      v9 = 36;
      v10 = 23;
      v11 = 42;
      v12 = 13;
      v13 = 19;
      v14 = 28;
      v15 = 13;
      v16 = 27;
      v17 = 39;
      v18 = 48;
      v19 = 41;
      v20 = 42;
      v21 = 26;
      v22 = 20;
      v23 = 59;
      v24 = 4;
      v25 = 0;                         //为啥定义那么多?
      printf("plz enter the flag:");
      sub_411136();
      while ( 1 )
      {
        getch();                       //这应该是获取输入的
        v1 = sub_411136();
        v27[v26] = v1;
        if ( !(_BYTE)v1 || v27[v26] == 13 )
          break;
        if ( v27[v26] == 8 )
        {
          printf("");
          sub_411136();
          --v26;
        }
        else
        {
          printf("%c", v27[v26]);
          sub_411136();
          ++v26;
        }
      }
      v3 = 0;
      for ( i = 0; i < 17; ++i )
      {
        if ( v27[i] != byte_415768[*(&v4 + i)] )
          v3 = 1;
      }
      if ( v28 != 49 || v29 != 48 || v30 != 50 || v31 != 52 || v32 != 125 )
        v3 = 1;
      v27[v26] = 0;
      printf("
    ");
      sub_411136();
      if ( v3 )                      //这边输出判断是以v3为标志的
      {
        printf("u r wrong
    
    ");
        sub_411136();
        sub_41113B();
      }
      else
      {
        printf("u r right!
    ");
        sub_411136();
      }
      system("pause");
      sub_411136();
      sub_411082(&savedregs, &dword_411678);
      sub_411014(v1);
      return sub_411136();
    }
    

    首先,我们看到咱们的输出是以v3为标志的,所以需要看下v3的值是如何变化的。

    以上有两个地方对v3进行了修改,要想得到right,必须是的v3为0。因此上面讲v3改成1的操作都应该避开,来看一下紧挨着的上面的语句。

    这是一个if的判断语句,是v28是否为49/48/50/52/125,如果不是则v3置1,查找ascll码表,我们可以看到,对应的是“1024}”这几个字符,和预想的一样,因为这个题是ctf题,而出题方给的答题要求是wctf{}格式,因此这应该就是结尾。

    再继续往上看,for循环一共17轮,核心语句是v27[i] != byte_415768[*(&v4 + i)],其中v27是一个数组,备注写了。byte_415768[]应该也是个数组,我们跟到定义位置看一下。

     byte_415768     db 73h                  ; DATA XREF: sub_4113A0+1E3r
     aWfxcGdvFwfctsl db 'wfxc{gdv}fwfctslydRddoepsckaNDMSRITPNsmr1_=2cdsef66246087138',0
    

    一长条的字符串,先不管它,看[]里面的,这是个指针,取v4地址后加i后为一个地址然后取该地址的内容作为数组的标号。

    再查看上面的定义

      v4 = 1;    //w
      v5 = 4;    //c
      v6 = 14;   //t
      v7 = 10;   //f
      v8 = 5;    //{
      v9 = 36;   //P
      v10 = 23;  //e
      v11 = 42;  //_
      v12 = 13;  //c
      v13 = 19;  //R
      v14 = 28;  //a
      v15 = 13;  //c
      v16 = 27;  //k
      v17 = 39;  //m
      v18 = 48;  //e
      v19 = 41;  //1
      v20 = 42;  //_
      v21 = 26;
      v22 = 20;
      v23 = 59;
      v24 = 4;
      v25 = 0;
    

    对照该表依次查找,所查找的内容是之前那个字符串的内容,对应找到后内容请看上面的备注,我们只需关注前17个,因为只循环了17轮。

    结合上面,我们初步得出结果wctf{Pe_cRackme1_1024},验证了一下,没有问题。

    总觉得有一点点小问题,没有想明白,可能脑子短路了吧,问题就是,这个字符数组[]中是1的情况下应该取得是字符数组中第二个字符,也就是答案是以c为开头,后面每个字符都后挪以为。但是根据出题人意思,开头肯定是wctf形式,不是很明白,也可能我C的一些基本功不牢,求指正啊?

  • 相关阅读:
    thinkphp 前后端分离
    git常用命令总结
    DIV常用属性大全
    shell编程学习之使用jq对json数据进行提取
    shell编程之if语句
    shell编程之变量赋值
    【总结】sqli-labs Less(1-35) 小结
    【总结】sqlmap常用命令
    【总结】kali(amd64)中安装nessus
    【总结】ettercap工具之DNS劫持
  • 原文地址:https://www.cnblogs.com/miaohj/p/6138363.html
Copyright © 2020-2023  润新知