一個入門級CTF的Reverse


這道題是XCTF攻防世界上的一道新手入門題目!

年前剛接觸逆向時IDA,OD了這些工具都不會用(負基礎),當時做這些題的時候覺得挺難(主要是缺少練習,沒思路無從下手)。現在回頭再來看這些題目感覺確實是入門級的題目,所以逆向是門藝術更是門技術,需要多練習熟悉工具和掌握一些技巧,下面就來分析一下這道題目。

題目給了一個附件是一個exe的可執行文件,那好我們先來執行一下他好了!
在這里插入圖片描述結果出來一大堆英文,奈何本人英文真的很菜,高考40分:),渾身發憷,不怕手機自帶拍照翻譯,雖然翻譯的水平很一般但是磕磕絆絆的還是能明白他什么意思:
這是個游戲(游戲規則:把那幾個圖形都看成燈,當其都亮時,也就是圖形變成實心的游戲勝利),你必須把這個游戲過了之后才會得到我們想要的flag。 我們是要通過工具來獲得這個flag,當然如果你玩游戲很nb的話你也可以通關他獲得flag。
好廢話不多說我們現在就來尋找flag!
1. 我們先用PEID分析一下程序的基本信息
在這里插入圖片描述在這里插入圖片描述可以看到檢測到其未壓縮,說明此程序無殼。下面我們可以選擇用靜態分析工具IDA來分析程序,也可以選用動態調試工具Ollydbg。
我們先用IDA來分析吧,因為此程序為32位的所以我們用32位的IDA打開程序。

  1. 我們按Ctrl + E彈出入口函數的信息,點擊確定進入入口函數。因為此程序是一個控制台程序,所以我們需要找到main函數(處理邏輯在main函數里)。

在這里插入圖片描述進入start函數后我們就可以利用IDA一個強大插件的功能:把反匯編指令轉化為C語言式的偽代碼,這樣我們方便尋找main函數。在這里插入圖片描述一般經過IDA的處理后都會顯示出main函數的函數名,這種情況我們就可以直接通過尋找main函數名來尋找main函數。
但是有的程序在編譯時,進行一些設置后IDA無法顯示出main函數的函數名,這時我們就不能直接通過查找main函數名來尋找main函數,我們需要通過代碼特征進行定位main函數,因為main()結束后會調用exit()函數來退出進程,所以我們只要找到exit函數,那么在其上方的函數就是main函數(也有可能是在這個上方函數的函數才是main函數)。

在這里插入圖片描述這個程序我們找到了exit函數,其上方有個invoke_main()函數,那么此函數應該為main函數(或者main函數在其內部),雙擊此函數進入函數內部。在這里插入圖片描述果然main函數在此函數內部,我們在雙擊進入main函數最里層,查看main函數的邏輯代碼。在這里插入圖片描述我們對main函數中的邏輯代碼進行分析看flag是怎么產生的。往下查看代碼發現一處判斷,正好像是判斷那幾盞燈是否都亮的邏輯,當這幾盞燈都亮(也就是其值都為1)時,調用Sub_457Ab4( )函數,此函數應該就是flag產生的代碼。
在這里插入圖片描述我們雙擊進入sub_457AB4()其處理代碼為:

int sub_45E940()
{
  signed int i; // [esp+D0h] [ebp-94h]
  char v2; // [esp+DCh] [ebp-88h]
  char v3; // [esp+DDh] [ebp-87h]
  char v4; // [esp+DEh] [ebp-86h]
  char v5; // [esp+DFh] [ebp-85h]
  char v6; // [esp+E0h] [ebp-84h]
  char v7; // [esp+E1h] [ebp-83h]
  char v8; // [esp+E2h] [ebp-82h]
  char v9; // [esp+E3h] [ebp-81h]
  char v10; // [esp+E4h] [ebp-80h]
  char v11; // [esp+E5h] [ebp-7Fh]
  char v12; // [esp+E6h] [ebp-7Eh]
  char v13; // [esp+E7h] [ebp-7Dh]
  char v14; // [esp+E8h] [ebp-7Ch]
  char v15; // [esp+E9h] [ebp-7Bh]
  char v16; // [esp+EAh] [ebp-7Ah]
  char v17; // [esp+EBh] [ebp-79h]
  char v18; // [esp+ECh] [ebp-78h]
  char v19; // [esp+EDh] [ebp-77h]
  char v20; // [esp+EEh] [ebp-76h]
  char v21; // [esp+EFh] [ebp-75h]
  char v22; // [esp+F0h] [ebp-74h]
  char v23; // [esp+F1h] [ebp-73h]
  char v24; // [esp+F2h] [ebp-72h]
  char v25; // [esp+F3h] [ebp-71h]
  char v26; // [esp+F4h] [ebp-70h]
  char v27; // [esp+F5h] [ebp-6Fh]
  char v28; // [esp+F6h] [ebp-6Eh]
  char v29; // [esp+F7h] [ebp-6Dh]
  char v30; // [esp+F8h] [ebp-6Ch]
  char v31; // [esp+F9h] [ebp-6Bh]
  char v32; // [esp+FAh] [ebp-6Ah]
  char v33; // [esp+FBh] [ebp-69h]
  char v34; // [esp+FCh] [ebp-68h]
  char v35; // [esp+FDh] [ebp-67h]
  char v36; // [esp+FEh] [ebp-66h]
  char v37; // [esp+FFh] [ebp-65h]
  char v38; // [esp+100h] [ebp-64h]
  char v39; // [esp+101h] [ebp-63h]
  char v40; // [esp+102h] [ebp-62h]
  char v41; // [esp+103h] [ebp-61h]
  char v42; // [esp+104h] [ebp-60h]
  char v43; // [esp+105h] [ebp-5Fh]
  char v44; // [esp+106h] [ebp-5Eh]
  char v45; // [esp+107h] [ebp-5Dh]
  char v46; // [esp+108h] [ebp-5Ch]
  char v47; // [esp+109h] [ebp-5Bh]
  char v48; // [esp+10Ah] [ebp-5Ah]
  char v49; // [esp+10Bh] [ebp-59h]
  char v50; // [esp+10Ch] [ebp-58h]
  char v51; // [esp+10Dh] [ebp-57h]
  char v52; // [esp+10Eh] [ebp-56h]
  char v53; // [esp+10Fh] [ebp-55h]
  char v54; // [esp+110h] [ebp-54h]
  char v55; // [esp+111h] [ebp-53h]
  char v56; // [esp+112h] [ebp-52h]
  char v57; // [esp+113h] [ebp-51h]
  char v58; // [esp+114h] [ebp-50h]
  char v59; // [esp+120h] [ebp-44h]
  char v60; // [esp+121h] [ebp-43h]
  char v61; // [esp+122h] [ebp-42h]
  char v62; // [esp+123h] [ebp-41h]
  char v63; // [esp+124h] [ebp-40h]
  char v64; // [esp+125h] [ebp-3Fh]
  char v65; // [esp+126h] [ebp-3Eh]
  char v66; // [esp+127h] [ebp-3Dh]
  char v67; // [esp+128h] [ebp-3Ch]
  char v68; // [esp+129h] [ebp-3Bh]
  char v69; // [esp+12Ah] [ebp-3Ah]
  char v70; // [esp+12Bh] [ebp-39h]
  char v71; // [esp+12Ch] [ebp-38h]
  char v72; // [esp+12Dh] [ebp-37h]
  char v73; // [esp+12Eh] [ebp-36h]
  char v74; // [esp+12Fh] [ebp-35h]
  char v75; // [esp+130h] [ebp-34h]
  char v76; // [esp+131h] [ebp-33h]
  char v77; // [esp+132h] [ebp-32h]
  char v78; // [esp+133h] [ebp-31h]
  char v79; // [esp+134h] [ebp-30h]
  char v80; // [esp+135h] [ebp-2Fh]
  char v81; // [esp+136h] [ebp-2Eh]
  char v82; // [esp+137h] [ebp-2Dh]
  char v83; // [esp+138h] [ebp-2Ch]
  char v84; // [esp+139h] [ebp-2Bh]
  char v85; // [esp+13Ah] [ebp-2Ah]
  char v86; // [esp+13Bh] [ebp-29h]
  char v87; // [esp+13Ch] [ebp-28h]
  char v88; // [esp+13Dh] [ebp-27h]
  char v89; // [esp+13Eh] [ebp-26h]
  char v90; // [esp+13Fh] [ebp-25h]
  char v91; // [esp+140h] [ebp-24h]
  char v92; // [esp+141h] [ebp-23h]
  char v93; // [esp+142h] [ebp-22h]
  char v94; // [esp+143h] [ebp-21h]
  char v95; // [esp+144h] [ebp-20h]
  char v96; // [esp+145h] [ebp-1Fh]
  char v97; // [esp+146h] [ebp-1Eh]
  char v98; // [esp+147h] [ebp-1Dh]
  char v99; // [esp+148h] [ebp-1Ch]
  char v100; // [esp+149h] [ebp-1Bh]
  char v101; // [esp+14Ah] [ebp-1Ah]
  char v102; // [esp+14Bh] [ebp-19h]
  char v103; // [esp+14Ch] [ebp-18h]
  char v104; // [esp+14Dh] [ebp-17h]
  char v105; // [esp+14Eh] [ebp-16h]
  char v106; // [esp+14Fh] [ebp-15h]
  char v107; // [esp+150h] [ebp-14h]
  char v108; // [esp+151h] [ebp-13h]
  char v109; // [esp+152h] [ebp-12h]
  char v110; // [esp+153h] [ebp-11h]
  char v111; // [esp+154h] [ebp-10h]
  char v112; // [esp+155h] [ebp-Fh]
  char v113; // [esp+156h] [ebp-Eh]
  char v114; // [esp+157h] [ebp-Dh]
  char v115; // [esp+158h] [ebp-Ch]

  sub_45A7BE("done!!! the flag is ");
  v59 = 18;
  v60 = 64;
  v61 = 98;
  v62 = 5;
  v63 = 2;
  v64 = 4;
  v65 = 6;
  v66 = 3;
  v67 = 6;
  v68 = 48;
  v69 = 49;
  v70 = 65;
  v71 = 32;
  v72 = 12;
  v73 = 48;
  v74 = 65;
  v75 = 31;
  v76 = 78;
  v77 = 62;
  v78 = 32;
  v79 = 49;
  v80 = 32;
  v81 = 1;
  v82 = 57;
  v83 = 96;
  v84 = 3;
  v85 = 21;
  v86 = 9;
  v87 = 4;
  v88 = 62;
  v89 = 3;
  v90 = 5;
  v91 = 4;
  v92 = 1;
  v93 = 2;
  v94 = 3;
  v95 = 44;
  v96 = 65;
  v97 = 78;
  v98 = 32;
  v99 = 16;
  v100 = 97;
  v101 = 54;
  v102 = 16;
  v103 = 44;
  v104 = 52;
  v105 = 32;
  v106 = 64;
  v107 = 89;
  v108 = 45;
  v109 = 32;
  v110 = 65;
  v111 = 15;
  v112 = 34;
  v113 = 18;
  v114 = 16;
  v115 = 0;
  v2 = 123;
  v3 = 32;
  v4 = 18;
  v5 = 98;
  v6 = 119;
  v7 = 108;
  v8 = 65;
  v9 = 41;
  v10 = 124;
  v11 = 80;
  v12 = 125;
  v13 = 38;
  v14 = 124;
  v15 = 111;
  v16 = 74;
  v17 = 49;
  v18 = 83;
  v19 = 108;
  v20 = 94;
  v21 = 108;
  v22 = 84;
  v23 = 6;
  v24 = 96;
  v25 = 83;
  v26 = 44;
  v27 = 121;
  v28 = 104;
  v29 = 110;
  v30 = 32;
  v31 = 95;
  v32 = 117;
  v33 = 101;
  v34 = 99;
  v35 = 123;
  v36 = 127;
  v37 = 119;
  v38 = 96;
  v39 = 48;
  v40 = 107;
  v41 = 71;
  v42 = 92;
  v43 = 29;
  v44 = 81;
  v45 = 107;
  v46 = 90;
  v47 = 85;
  v48 = 64;
  v49 = 12;
  v50 = 43;
  v51 = 76;
  v52 = 86;
  v53 = 13;
  v54 = 114;
  v55 = 1;
  v56 = 117;
  v57 = 126;
  v58 = 0;
  for ( i = 0; i < 56; ++i )						
  {
    *(&v2 + i) ^= *(&v59 + i);
    *(&v2 + i) ^= 0x13u;
  }
  return sub_45A7BE("%s\n");
}

其是將V2 - V57與 V59 - V114的字符分別異或之后再與0x13u異或后,得到的字符串就為flag
注意此代碼不能直接復制粘貼到進行使用,因為其默認V2 - V115的變量是連續存儲的(即地址是連續的),而實際其會因為字節對齊而不連續存儲,所以要自己寫代碼的到flag。
下面是我用c++寫的代碼(python語法都忘光了!)。

#include <iostream>
using namespace std;
int main()
{
char a[] = {123, 32, 18, 98, 119, 108, 65, 41, 124,80,125,38, 124,111,74, 49, 83, 108,94,
			108, 84, 6,  96, 83,  44,  121,104,110,32,95, 117,101, 99,123,127,119,96, 48,
			107, 71, 92, 29, 81,  107, 90, 85, 64, 12,43, 76, 86, 13, 114,1,  117,126,0,
			18,	 64, 98, 5,  2,   4,   6,  3,  6,  48,49, 65, 32, 12, 48, 65, 31, 78, 62,
			32,  49, 32, 1,  57,  96,  3,  21, 9,  4, 62, 3,  5,  4,  1,  2,  3,  44, 65,
			78,  32, 16, 97, 54,  16,  44, 52, 32, 64,89, 45, 32, 65, 15, 34, 18, 16, 0 };

  cout<<"done!!! the flag is: ";
  for (int i = 0; i < 56; ++i )
  {
	  a[i] = a[i] ^ a[i+57];
	  a[i] = a[i] ^ 0x13u;	
	  cout<<a[i];
  }
  return 0;
}

flag為zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}
下面我們用Ollydbg來分析這道題:
打開OD運行這個程序,其會停在入口處,然后我們點擊鼠標右鍵-》中文搜索引擎-》智能搜索。會彈出所有字符串的信息!在這里插入圖片描述我們會發現this is a flag:字符串(說明字符串是在此處產生的),我們雙擊此字符串進入此代碼塊。
在這里插入圖片描述進入代碼塊后我們往下查看代碼,在這里插入圖片描述我們發現%s/n字符串作為參數傳給一個函數,所以此函數應該為printf函數,eax為顯示字符串的指針。(此字符串就是flag)
上方代碼應為flag的處理代碼。
我們要獲得flag就必須執行這塊代碼,所以我們在其flag的處理代碼塊的第一條指令處右擊鼠標-》點擊設置為新eip,在printf函數的入口參數處下斷點,然后運行程序。
在這里插入圖片描述在這里插入圖片描述當程序到達斷點處是會停止運行,因為斷點處為printf函數處,而eax為所顯示flag字符串的指針所以我們在OD右上角的寄存器窗口中可以看到flag。
在這里插入圖片描述


免責聲明!

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



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