一個PE文件的逆向分析

一個PE文件的逆向分析

idf-ctf上有個題,是PE文件的逆向,反正對我來講作出來就是有意思的題,作不出來就沒勁。言歸正傳,下面看一下吧數組

你們想玩能夠去這個地方去拿題http://pan.baidu.com/s/1dDzUL0X函數

而後,上次說到了IDA的F5插件,是的,很牛。以前不用是由於太菜,不會。。。。。。而後此次用了下,果真神器,因此最近也頗有必要學一學IDA的東西,推薦你們看《IDA Pro權威指南》。插件

好的吧,先把文件拖peid,沒殼。而後拖OD,搗啊搗,腦殼大,下斷點啊啥的,反正就是弄的很煩,就換IDA了,不過OD查了下字符串,仍是獲得了一些信息的3d

拉到IDA先看看吧,指針

有點暈,看看代碼吧code

.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

很好,看到了熟悉的字符串往下拉就是對和錯的字符串。orm

push    offset asc_415764 ; "\r\n"
.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!\r\n"      
                               //正確嘍
.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\r\n\r\n"
                               //錯誤啊
.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就出現瞭如下狀況。blog

c語言啊。。。。隨後看了下這F5插件的相關資料,原來須要在對應函數區域才管用,因此這就是爲啥上次我按死了也沒用的緣由。v8

不對,剛剛又出了個問題,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("\b\b");
      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("\r\n");
  sub_411136();
  if ( v3 )                      //這邊輸出判斷是以v3爲標誌的
  {
    printf("u r wrong\r\n\r\n");
    sub_411136();
    sub_41113B();
  }
  else
  {
    printf("u r right!\r\n");
    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的一些基本功不牢,求指正啊?

相關文章
相關標籤/搜索