IDF-CTF-簡單的Elf逆向Writeup


ElfCrackMe1

簡單的Elf逆向Writeup

題目來源:IDF實驗室 CTF訓練營;題目鏈接http://ctf.idf.cn/index.php?g=game&m=article&a=index&id=39
題目下載:http://pan.baidu.com/s/1kTl5wxD

解法1:

IDA查看偽代碼法:

  1. 下載文件,現在Linux環境下運行,可以看到關鍵字符串u r wrongplz enter the flag:
  2. 把文件拖到IDA中,shift+F12查找字符串,雙擊u r right跳轉到相應位置
  3. 如下圖,雙擊調用關鍵字符串u r right的函數,
    跳轉后F5查看偽代碼如下
     1 int __cdecl main(int argc, const char **argv, const char **envp)
     2 {
     3   int v3; // ebx@6
     4   const char **v4; // rdx@22
     5   __int64 v6; // [sp+0h] [bp-C0h]@1
     6   __int64 v7; // [sp+8h] [bp-B8h]@1
     7   __int64 v8; // [sp+10h] [bp-B0h]@1
     8   __int64 v9; // [sp+18h] [bp-A8h]@1
     9   __int64 v10; // [sp+20h] [bp-A0h]@1
    10   __int64 v11; // [sp+28h] [bp-98h]@1
    11   __int64 v12; // [sp+30h] [bp-90h]@1
    12   __int64 v13; // [sp+38h] [bp-88h]@1
    13   int v14; // [sp+40h] [bp-80h]@1
    14   char v15[17]; // [sp+80h] [bp-40h]@2
    15   char v16; // [sp+91h] [bp-2Fh]@14
    16   char v17; // [sp+92h] [bp-2Eh]@15
    17   char v18; // [sp+93h] [bp-2Dh]@16
    18   char v19; // [sp+94h] [bp-2Ch]@17
    19   char v20; // [sp+95h] [bp-2Bh]@18
    20   int v21; // [sp+A4h] [bp-1Ch]@1
    21   int v22; // [sp+A8h] [bp-18h]@7
    22   int i; // [sp+ACh] [bp-14h]@9
    23 
    24   v21 = 0;
    25   memset(&v6, 0, 0x58uLL);
    26   v6 = 854698492143LL;
    27   v7 = 880468295913LL;
    28   v8 = 597000454391LL;
    29   v9 = 605590388953LL;
    30   v10 = 932007903423LL;
    31   v11 = 760209211613LL;
    32   v12 = 579820585151LL;
    33   v13 = 940597838039LL;
    34   v14 = 191;
    35   printf(
    36     "plz enter the flag:",
    37     argv,
    38     11LL,
    39     854698492143LL,
    40     880468295913LL,
    41     597000454391LL,
    42     605590388953LL,
    43     932007903423LL,
    44     760209211613LL,
    45     579820585151LL,
    46     940597838039LL,
    47     *(_QWORD *)&v14);
    48   while ( 1 )
    49   {
    50     v3 = v21;
    51     v15[v3] = getch();
    52     if ( !v15[v3] || v15[v21] == 10 )
    53       break;
    54     if ( v15[v21] == 8 )
    55     {
    56       printf("\b\b", v6, v7, v8, v9, v10, v11, v12, v13, *(_QWORD *)&v14);
    57       --v21;
    58     }
    59     else
    60     {
    61       putchar(v15[v21++]);
    62     }
    63   }
    64   v22 = 0;
    65   if ( v21 != 22 )
    66     v22 = 1;
    67   for ( i = 0; i <= 16; ++i )
    68   {
    69     if ( v15[i] != (*((_DWORD *)&v6 + i) - 1) / 2 )
    70     {
    71       v22 = 1;
    72       argv = (const char **)((*((_DWORD *)&v6 + i) - 1) / 2);
    73       printf("%d", argv, v6, v7, v8, v9, v10, v11, v12, v13, *(_QWORD *)&v14);
    74     }
    75   }
    76   if ( v16 != 48 || v17 != 56 || v18 != 50 || v19 != 51 || v20 != 125 )
    77     v22 = 1;
    78   v15[v21] = 0;
    79   puts("\r");
    80   if ( v22 )
    81   {
    82     puts("u r wrong\r\n\r");
    83     main((unsigned __int64)"u r wrong\r\n\r", argv, v4);
    84   }
    85   else
    86   {
    87     puts("u r right!\r");
    88   }
    89   return 0;
    90 }
    View Code

     

分析這段偽代碼,可以得到關鍵部分如下:

  • v22需為0,按'/'隨手注釋
  • 如上圖中所示,要使v22==0,所有v22=1的語句均不能運行,則需要:v21==22,69行判斷均不進入,既要 v15[i] != (*((_DWORD *)&v6 + i) - 1) / 2,同時,v16~v20依次等於48,56,50,51,125,即字符0823}(在相應數字上按r鍵把相應的ASCII碼轉換為字符)
    同樣按'/'鍵隨手注釋
  • 找到定義v15的代碼處,則根據上述的關鍵條件,初步猜測需要輸入22位字符,其中前17位存入字符串v15中,后5位覆蓋v16~v20的取值,使v16~v20分別等於0823}
  • 繼續向下分析,找到輸入的代碼塊,經過分析可得到關鍵信息如上圖,其中v21即為輸入的長度,通過關鍵條件v21==22驗證了猜測輸入字符串長度為22,同時需要保證輸入的后五位為0823}
  • 向下分析v15需要滿足的條件,着重分析v15[i] != (*((_DWORD *)&v6 + i) - 1) / 2

    &v6為取v6的地址;(_DWORD *)&v6強制轉化為_DWORD型指針,即兩個字節;((_DWORD *)&v6 + i)為從&v6向后取sizeof(_DWORD)*i個字節;*((_DWORD *)&v6 + i) - 1)為取從&v6向后取4i個字節的值
    關於地址與指針加減問題http://www.cnblogs.com/WangAoBo/p/6365114.html

  • 如上,分析v6的賦值段代碼,v6~v13為_int64型,占8個字節,int型為4個字節,化為16進制如上圖
  • v6~v14通過小端存儲方式在內存中的存儲情況如上

則可寫出python腳本解得flag: wctf{ElF_lnX_Ckm_0823}


python腳本如下:

 1 v6=[0x0EF, 0x0C7, 0x0E9, 0x0CD, 0x0F7, 0x8B, 0x0D9,
 2     0x8D, 0x0BF, 0x0D9, 0x0DD, 0x0B1, 0x0BF, 0x87,
 3     0x0D7, 0x0DB, 0x0BF]
 4 
 5 L=[]
 6 for i in range(17):
 7     num = (v6[i] - 1)/2
 8     ans = chr(int(num))
 9     L.append(ans)
10 
11 
12 flag = ''.join(L)
13 flag+='0823}'
14 
15 print(flag)

  

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM