IDF實驗室-簡單的ELF逆向 writeup


題目:http://ctf.idf.cn/index.php?g=game&m=article&a=index&id=39

下載得到ElfCrackMe1文件,直接用IDA打開。

最早想到的是 function一路F5下去。可以看到關鍵的main函數

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // ebx@6
  const char **v4; // rdx@22
  __int64 v6; // [sp+0h] [bp-C0h]@1
  __int64 v7; // [sp+8h] [bp-B8h]@1
  __int64 v8; // [sp+10h] [bp-B0h]@1
  __int64 v9; // [sp+18h] [bp-A8h]@1
  __int64 v10; // [sp+20h] [bp-A0h]@1
  __int64 v11; // [sp+28h] [bp-98h]@1
  __int64 v12; // [sp+30h] [bp-90h]@1
  __int64 v13; // [sp+38h] [bp-88h]@1
  int v14; // [sp+40h] [bp-80h]@1
  char v15[17]; // [sp+80h] [bp-40h]@2
  char v16; // [sp+91h] [bp-2Fh]@14
  char v17; // [sp+92h] [bp-2Eh]@15
  char v18; // [sp+93h] [bp-2Dh]@16
  char v19; // [sp+94h] [bp-2Ch]@17
  char v20; // [sp+95h] [bp-2Bh]@18
  int v21; // [sp+A4h] [bp-1Ch]@1
  int v22; // [sp+A8h] [bp-18h]@7
  int i; // [sp+ACh] [bp-14h]@9

  v21 = 0;
  memset(&v6, 0, 0x58uLL);
  v6 = 854698492143LL;
  v7 = 880468295913LL;
  v8 = 597000454391LL;
  v9 = 605590388953LL;
  v10 = 932007903423LL;
  v11 = 760209211613LL;
  v12 = 579820585151LL;
  v13 = 940597838039LL;
  v14 = 191;
  printf(
    "plz enter the flag:",
    argv,
    11LL,
    854698492143LL,
    880468295913LL,
    597000454391LL,
    605590388953LL,
    932007903423LL,
    760209211613LL,
    579820585151LL,
    940597838039LL,
    *(_QWORD *)&v14);
  while ( 1 )
  {
    v3 = v21;
    v15[v3] = getch();
    if ( !v15[v3] || v15[v21] == 10 )
      break;
    if ( v15[v21] == 8 )
    {
      printf("\b\b", v6, v7, v8, v9, v10, v11, v12, v13, *(_QWORD *)&v14);
      --v21;
    }
    else
    {
      putchar(v15[v21++]);
    }
  }
  v22 = 0;
  if ( v21 != 22 )
    v22 = 1;
  for ( i = 0; i <= 16; ++i )
  {
    if ( v15[i] != (*((_DWORD *)&v6 + i) - 1) / 2 )
    {
      v22 = 1;
      argv = (const char **)((*((_DWORD *)&v6 + i) - 1) / 2);
      printf("%d", argv, v6, v7, v8, v9, v10, v11, v12, v13, *(_QWORD *)&v14);
    }
  }
  if ( v16 != 48 || v17 != 56 || v18 != 50 || v19 != 51 || v20 != 125 )
    v22 = 1;
  v15[v21] = 0;
  puts("\r");
  if ( v22 )
  {
    puts("u r wrong\r\n\r");
    main((unsigned __int64)"u r wrong\r\n\r", argv, v4);
  }
  else
  {
    puts("u r right!\r");
  }
  return 0;
}

 

看到最下面代碼

  

當v22=1時 輸出 u r wrong 

所以就正確就得使v22為0 

我們往上看

當v16 != 48 || v17 != 56 || v18 != 50 || v19 != 51 || v20 != 125時

V22=1 

所以就是v16=48 v17=56 v18 = 50 v19=51 v20= 125  

V22=0

用python的chr()轉化下得到 0 8 2 3 }

可以猜測這個是flag的后半部分

繼續往上看發現一串while代碼,讀起來很吃力。。。所以果斷選擇放棄,直接去看看匯編代碼

觀察視圖 找到while循環的那一部分

shr指令與sar指令,查了下是邏輯右移和算術右移,在編程里都是<< 

但選擇用什么是編譯器決定的……
所以編程時,最好只對unsigned類型做這種操作……

起初lea=eax,[rcx+rax]這指令沒看懂,只知道eax=rcx+rax 。就不知道什么意思,

后來查閱質料才知道因為是64位,所以寄存器變化了

64位寄存器的變化
eax,ebx,ecx,edx,esi,edi,ebp,esp等變為
rax,rbx,rcx,rdx,rsi,rdi,rbp,rsp

所以得出 a[i]=((a2[i]-1)+((a2[i])-1)>>1Fh))>>1 

要注意運算優先級,直接要括號就行了。

所以我們要找a2[i]的值,

跳轉到a2[i]的定義,看到:

在回代碼,往上看到:

所以知道,a2[i]的值是[0x0EF, 0x0C7, 0x0E9, 0x0CD, 0x0F7, 0x8B, 0x0D9,0x8D, 0x0BF, 0x0D9, 0x0DD, 0x0B1, 0x0BF, 0x87,0x0D7, 0x0DB, 0x0BF]

這樣就可以直接寫python腳本

#!usr/bin/env python
#!coding=utf-8

__author__ = 'zhengjim'


a2=[0x0EF, 0x0C7, 0x0E9, 0x0CD, 0x0F7, 0x8B, 0x0D9,
    0x8D, 0x0BF, 0x0D9, 0x0DD, 0x0B1, 0x0BF, 0x87,
    0x0D7, 0x0DB, 0x0BF]
L=[]
for i in range(17):
    flag =((a2[i] - 1) + ((a2[i] - 1) >> 0x1f))>>1
    aa = chr(flag)
    L.append(aa)
flag1 = ''.join(L)
print flag1

 

  得到

在與前面的0 8 2 3 }連接 得到:

wctf{ElF_lnX_Ckm_0823}

 


免責聲明!

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



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