CTF 【每日一題20160626】簡單的PE文件逆向

簡單的PE文件逆向
來源:http://ctf.idf.cn/index.php?g=game&m=article&a=index&id=38
題目:就在這裏,很簡單的~雖然我不會。。= =! http://pan.baidu.com/s/1dDzUL0X
下載後,有一個PEcrackme1.exe文件。


剛接觸,不明白PE爲何物或逆向分析不甚明瞭的同學,請參考下列文章:

本題解析:

1.言歸正傳,我下載的pecrackme1.exe,在windows xp下運行沒有結果,所以無法像文章:http://blog.csdn.net/calmegm/article/details/49009867 中通過現象有一個初步判斷;但通常,對於一般exe文件的逆向分析都是用IDA pro打開,本題也不例外,打開看看。然後按F5調用C語言轉換插件(將彙編程序轉換爲僞C語言)。

這裏寫圖片描述

2.通過依次點擊左側function 那麼列中的sub_**, 觀察左側僞C編碼,可以發現一個function name爲sub_4113A0函數,裏面內容豐富,前面是一堆變量定義(可先忽略),後面有判斷邏輯(這是重點)。

##Pseudocode-A視圖模式下
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 )
  {
    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();
}

3.可以發現下面語句,應該是要求輸入密鑰字符,然後匹配判斷。其中關鍵是if(v3)。v3==1時,就會報錯。那麼v3什麼時候等於1?看之前v3的賦值部分。
4.v3賦值有兩部分,第一部分是:

for ( i = 0; i < 17; ++i )
  {
    if ( v27[i] != byte_415768[*(&v4 + i)] )
      v3 = 1;
  }

這個循環判斷了長度爲17的數組v27中的每個字符是否與數組byte_415768[]中的對應字符是否相等。在IDA PRO中雙擊byte_415768[],會跳到其定義處,看到如下彙編語句:

##IDA VIEW-A (彙編語言)視圖模式下
......
.rdata:00415768 ; char byte_415768[]
.rdata:00415768 byte_415768     db 73h  ; DATA XREF: sub_4113A0+1E3r
.rdata:00415769 aWfxcGdvFwfctsl db 'wfxc{gdv}fwfctslydRddoepsckaNDMSRITPNsmr1_=2cdsef66246087138',0
.rdata:004157A6                 db    0
.rdata:004157A7                 db    0
.rdata:004157A8                 db    0
.rdata:004157A9                 db    0
.rdata:004157AA                 db    0
.rdata:004157AB                 db    0
.rdata:004157AC                 db    0
.rdata:004157AD                 db    0
.rdata:004157AE                 db    0
.rdata:004157AF                 db    0
.rdata:004157B0                 db    0
.rdata:004157B1                 db    0
.rdata:004157B2                 db    0
.rdata:004157B3                 db    0
......

這不是純彙編語言,IDApro還是做了轉換的,我們看到char byte_415768[]定義了字符數組,並byte_415768第一個字節即byte_415768[0] = 0x73h(十進制數115)。分號後的註釋DATA XREF: sub_4113A0+1E3r,表示外部代碼sub_4113A0中地址偏移爲1E3r的地方引用了該變量。地址爲00415769的彙編語句 aWfxcGdvFwfctsl db wfxc{gdv}fwfctslydRddoepsckaNDMSRITPNsmr1_=2cdsef66246087138’,0定義了一個變量名爲aWfxcGdvFwfctsl 的數組,內容爲:
‘wfxc{gdv}fwfctslydRddoepsckaNDMSRITPNsmr1_=2cdsef66246087138’,0,最後跟的是個0,一般用於表示字符串結束(與c代碼中一致)。
語句byte_415768[(&v4 + i)]中&v4表示取變量v4的地址,然後假設遊標量i,再用運算符找對應地址的值,i從0變到17,那麼byte_41576[]中的序號依次爲v4,v5,v6,….v21,共計17個變量的值,即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。
而byte_415768[1]=’w’,byte_415768[4]=’c’,byte_415768[14]=’t’,byte_415768[10]=’f’,byte_415768[5]=’{‘,…….
最終可以得到’wctf{Pe_cRackme1_’共17個字符。這就是答案的上半部分。

5.下半部分由v3的第二部分賦值代碼來獲得(如下所示)。這裏面有多個變量的或非判斷,即v28,v29,v30,v31,v32不等於49,48,50,52,125時,v3就爲1。從終端錄入的一般是用ascii碼存放,所以查49,48,50,52,125對應的ASCII碼爲’1’,’0’,’2’,’4’,’}’,顯然是字符串“1024}”,聯想這套題的答案都是‘wctf{*}’,所以我們應該是拿到了後半段。

if ( v28 != 49 || v29 != 48 || v30 != 50 || v31 != 52 || v32 != 125 )
    v3 = 1;
......
  if ( v3 )
  {
    printf("u r wrong\r\n\r\n");
    sub_411136();
    sub_41113B();
  }
 ......

6.綜合兩部分,本題答案爲“wctf{Pe_cRackme1_1024}”。題目不難,但對於初學者還是考驗耐心的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章