• <big id="vhnbr"></big>

      muling1m

      所有資源可以在官網下載

      代碼逆向工程

      逆向分析法

      靜態分析

      不執行代碼,觀察外部特征,獲取其文件類型、大小、PE頭、Import/Export API、字符串、是否運行時解壓縮、注冊信息、調試信息、數字證書、反匯編代碼等

      動態分析

      在程序文件執行的過程中對代碼進行分析。

      一般首先靜態分析,再進行動態分析。

      逆向Hello World

      代碼如下:

      #include<windows.h>
      #include<tchar.h>
      int _tmain(int argc,TCHAR *argv[])
      {
      	MessageBox(NULL, L"Hello World!", L"Muling", MB_OK);
      	return 0;
      }
      

      調試器與匯編

      分析二進制文件時,需要使用調試器(Debugger)的反匯編模塊,將二進制代碼轉換為匯編代碼。

      調試HelloWorld.exe

      目標

      目標:調試HelloWorld.exe可執行文件,在匯編代碼中找到main函數中的MessageBox函數的調用。

      打開文件

      Ollydbg打開,窗口如下:

      image-20230308160553332image-20230308160657713

      調試器停下的位置為程序的入口地址。

      image-20230308160849646

      在入口點調用了0040270c函數,并跳轉到了0040104f。

      跟蹤0040270c

      F7(步進)進入0040270c

      image-20230308161432584

      右側區域有Od提供的注釋,紅色是調用的API函數名稱,這里看到的是VS自動添加的一些啟動函數調用,F8步過即可。

      直到RETN返回仍然沒有看到main和MessageBox

      跟蹤0040104f

      F7步入,如下:

      image-20230308162040903

      這個部分為VS啟動函數部分,跟蹤它們可以找到main的位置。

      相同IDE生成的啟動函數都大致相同,在熟悉后可以比較快速地找到啟動函數并定位代碼

      不斷跟蹤,F7進入后Ctrl+F9退出嘗試,找到調用了MessageBox的Main函數位置

      image-20230309153140803

      設置camp

      • 使用Goto(Ctrl+G)跳轉指針到40104f,再使用F4運行到指標位置

      • F2設置BP,打開Alt+B可以看到BP列表,雙擊一個BP即可跳轉到任一個斷點(只是高亮位置移到該點),也可直接調試,會自動停止在斷點處。

      • 使用‘;’可以進行注釋,右鍵->查找->注釋可以查到注釋的位置。

        image-20230309154144225image-20230309154120667
      • 使用‘:’可以添加標簽,

        如下為在40104f處添加標簽

        image-20230309154607833image-20230309154641666

        右鍵->查找->所有用戶定義的標簽可以查看標簽

      查找指定的代碼

      一般來說main函數不會出現在EP位置上,EP上一般是開發工具添加的一些啟動函數。

      代碼執行法

      在程序功能明確、代碼量不大的情況下可以使用,逐條執行指令來找到需要查找的指令位置。

      比如調用MessageBox的代碼,一直按F8步過,一定會有一個指令執行后出現消息框。彈出消息對話框的函數為main函數。

      字符串檢索

      右鍵->查找->所有被引用的字符串可以查看所有程序引用的字符串。

      image-20230309161414518

      雙擊”Hello World!”可以定位到MessageBox函數。

      在內存Dump窗口使用Ctrl+G可以進一步查看004092A0處。

      API檢索法(1):調用代碼中設置斷點

      右鍵->查找->所有模塊間調用

      程序輸出時,需要調用Win32 API,觀察一個程序后,就可以大致了解其調用的APi函數有哪些。

      比如程序跳出消息框,可以斷定調用了MessageBox API。

      這個方法可以找到程序調用的所有API列表。

      image-20230309162338165

      API檢索法(2):API代碼中設置斷點

      右鍵->查找->所有

      對于壓縮器/保護器,列出API調用列表比較麻煩

      image-20230309171606232

      在這種情況下,可以在DLL代碼庫加載到進程內存后直接向DLL代碼庫添加斷點。

      API是操作系統提供的一系列函數,存放在C:\Windows\systems32文件夾內

      所以程序執行操作時需要向OS提出請求使用API,然后API對應的DLL文件才會被加載進來。

      (Alt+M)打開內存映射菜單,可以看到user32庫被加載到了內存。

      image-20230309172206119

      使用查找所有模塊中的名稱可以列出被加載的DLL中的所有API,單擊按名稱排序,再鍵盤輸入MessageBoxW可以找到MessageBox

      image-20230309173105641

      雙擊即可定位到其代碼部分。

      image-20230309173237760

      在函數起始位置使用F2設置斷點,然后繼續執行,會自動停在這一行。

      image-20230309173508549

      此時,ESP=0019FF70,此值指向堆棧位置中存放返回地址值為00401014,也即調用此函數后的下一句。

      image-20230309173800936

      打補丁修改程序字符串

      打補丁常常用于修復程序中的BUG/添加新功能,打補丁的對象可以是文件、內存、程序的代碼、數據等

      Ctrl+F2重新調試,F9執行到main函數位置。

      直接修改字符串緩沖區

      該方法操作簡單,但對新內容的長度有限制

      “Hello World!”保存在4092A0處,只要修改這段即可。

      跳轉后Ctrl+E打開編輯窗口,修改字符串即可。

      image-20230310100825151

      在Dump窗口,右鍵->復制到可執行文件即可將修改保存到exe文件中,在彈出的hex窗口中右鍵保存文件。

      其他區域添加新字符串并傳給消息函數

      再次運行到main函數處。

      在401007處有一條Push命令,將字符串傳給消息函數。

      再次找到HelloWorld處4092A0,往后一直拖,會看到一個未填充區域。

      選擇合適的位置如409F50處寫入新字符串。

      再轉到代碼401007處,空格打開匯編窗口,輸入PUSH 409F50

      image-20230310103428825image-20230310103631084

      小端序標記法

      image-20230310104521988

      IA-32寄存器

      IA-32支持以下寄存器

      通用寄存器



      ESP指示棧頂位置,EBP指示棧的及地址,函數調用時用于保存ESP的值,返回時再還給ESP。ESI和EDI主要用于內存復制。

      段寄存器

      狀態/控制寄存器

      EFLAGS 標志寄存器
      image-20230310112826490
      image-20230310112845836

      指令指針寄存器 EIP


      作用

      • 局部變量存儲

      • 傳參

      • 保存返回地址

      特征

      棧結構如下:

      image-20230310132241127

      ESP為棧頂指針,初始在棧底(高地址),PUSH使ESP自減移到棧頂方向。

      參數入棧

      傳參時,參數逆序入棧(相對C語言),即從右向左

      操作示例

      • OD打開stack.exe。初始時棧頂位置在0019FF74處
      image-20230310215122098
      • 執行push 0x100,ESP=ESP-4,

        image-20230310215247583

      棧幀

      介紹

      利用EBP訪問棧內的局部變量、參數、函數返回地址等內容。

      調用函數時,先將棧頂指針ESP賦給EBP,無論ESP如何變化,EBP不變,能方便訪問到局部變量、參數、返回地址等值。

      image-20230311231218136

      調試stackframe.exe

      //StackFrame.exe
      #include<stdio.h>
      long add(long a,long b)
      {
          long x = a, y = b;
          return x + y;
      }
      
      int main(int argc,char* argv[])
      {
          long a = 1, b = 2;
          printf("%d\n",add(a,b));
          return 0;
      }
      
      • Ctrl+G到401000
        image-20230311233245555

      • 執行mov ebp,esp后,??臻g大致如下

      image-20230311235135674
      • 可以右鍵->地址->相對于EBP,方便觀察
        image-20230311235356400

      • call 時自動push返回地址并跳轉,call后自動pop地址并跳轉

      abex crackme#2-VB文件

      運行

      image-20230312165952839

      這個程序要求找出程序的序列號,輸入Name和Serial,按Check,如下:

      image-20230312170116323

      VB文件

      這個程序由VB編寫而成,調試前需要先學習相關特征。

      VB專用引擎

      使用VB專用引擎MSVBVM60.dll。

      比如VB代碼中調用MsgBox()實現消息框,其真正調用的是MSVBVM60.dll中的rtcMsgBox(),該函數再調用user32.dll中的MessageBoxW()。

      本地代碼和偽代碼

      根據編譯選項,VB文件可以編譯為本地代碼(N code)與偽代碼(P code),本地代碼使用易于調試的IA-32指令,而偽代碼是解釋性語言,使用VB引擎實現虛擬機并自解析指令。

      要想準確解析VB偽代碼,需要分析VB引擎并實現模擬器。

      image-20230312170709633

      事件處理程序

      VB主要用于編寫GUI程序,采用Windows的事件驅動方式工作,在main和WinMain中不存在用戶代碼,用戶代碼在各個事件處理程序中。

      本程序的用于代碼就在Check代碼觸發的事件處理程序內。

      未文檔化的結構體

      VB中各種信息以結構體形式存在文件內部,這些結構體并沒有被微軟公開。

      調試

      image-20230312195534006

      先push一個RT_MainStruct結構體的地址,然后call 調用401232處的JMP,跳轉到VB引擎的主函數ThunRTMain(),push的值作為其參數。

      間接調用

      40123D處Call 401232調用ThunRTMain()函數,使用了間接調用,通過401232處的JMO跳轉,而不是直接call MSVBVM60.dll中的ThunRTMain()函數。

      401232處的JMP如下:

      4010A0為IAT(導入地址表)區域,包含MSVBVM60.ThunRTMain()函數的實際地址。

      RT_MainStruct

      該結構體在401E14處。

      image-20230312200307086

      雖然微軟沒有公布,但在國外有逆向高手完成了對其的分析。

      該結構體用于獲取程序運行需要的所有信息。

      ThunRTMain

      進入主函數,如下:

      image-20230312200455692

      內存地址完全不同,因為這里是MSVBVM60.dll的地址區域。

      分析crackme

      • 檢索字符串
        image-20230312200849332

      • 雙擊 wrong serial可以轉到代碼,這種代碼一般分為兩個部分,即序列號正確和錯誤兩種,判斷后通過跳轉輸出正確/錯誤的消息框。

      image-20230312200927413
      • 向上拖動代碼,可以找到條件轉移代碼
      image-20230313125030999
      • 此處調用了__vbaVarTstEq()函數,比較(TEST)返回值AX后,如果AX為0,則跳轉到輸出正確消息,否則不跳轉輸出錯誤消息。
      image-20230312201257150
      • 該函數為字符串比較函數,前面兩個push語句應當是傳參,即被比較的字符串。

      • F4運行到403329處,輸入字符串,點擊check。edx=0019F1AC,eax=0019F1BC

        image-20230312201516074

      • dump區轉到19f1AC。類似于C++中的stringg類型,VB中的字符串使用可變長度的字符串類型。(字符串對象)
      image-20230312202532432
      • 兩串內容只有中間4個字節不同,推斷這串是地址。使用右鍵->長型->ASCII數據地址,可以對地址對應的字符串進行顯示。

      可以看出EDX(EBP-0x44)為正確serial值,而EAX(EBP-0x34)為用戶輸入serial值。

      • 如下,輸入serial即可

        image-20230312204626709

      Serial生成算法

      預測代碼

      如果win32 API程序,應當有如下步驟:

      • 讀取Name字符串(GetWindowText、GetDlgItemText 等API)

      • 啟動循環,對字符運算

      VB代碼也應當是類似的原理。所以可以從代碼開始處(指check回調函數的開始)調試,找到讀取name字符串的部分,緊接著就會出現加密循環。

      找到name讀取代碼

      由于需要調用API函數,所以可以以call指令為主要注意對象??梢宰⒁獾饺缦耤all語句。

      image-20230312225356326

      先將ebp-0x88的位置賦給edx,然后將此地址作為參數傳入,調試跳過該call后會發現ebp-0x88位置出現name,判斷此call為name讀取函數。

      找到加密循環

      書上并沒有詳細說明加密循環的部分是如何找出來的,所以對于書上的這部分,我并沒有太理解,以下是自己的分析過程。

      既然是循環,肯定會有一個向上的jmp過程,主要找到符合這種特征的指令即可。翻找jmp指令,可以看到4032A0處有一個jmp向上跳轉。

      image-20230315124526833

      看看跳轉到的部分,可以看到jmp到的位置為test 接jmp,這段主要判斷eax是否為0,如果為0就跳到前面那個jmp的后一條指令,這樣的指令完美符合循環的特征??梢耘袛?032A0為循環末尾,403197為循環判斷部分。

      image-20230315124632639

      后面不會啦~

      函數調用約定

      主要函數調用約定如下:

      • cdecl
      • stdcall
      • fastcall
      • this
      • naked

      cdecl

      C語言中常用的調用方式,調用者處理棧。使用push從右至左傳參。

      cdecl方式好處在于可以傳遞長度可變的參數(如printf)。

      stdcall

      常用于win32 API,被調用者處理棧。參數傳遞方式相同。在C語言中需要在函數前添加“_stdcall”關鍵字以使用stdcall方式編譯。

      image-20230315105742309

      RETN 8表示返回后pop8個字節,將ESP增加到合適的大小。

      fastcall

      被調用者平衡棧。ECX、EDX傳遞第1、2個參數,其他參數與stdcall相同。常用于內核程序,這種調用方式比較快。

      this

      被調用者平衡棧。ECX傳遞this,其余參數相同。C++成員函數常用。

      naked

      被調用者平衡棧。傳參方式相同。使用此調用方式,編譯器自動為函數生成如下的進入和退出代碼。

      PUSH EBP
      MOV EBP,ESP
      ......
      POP EBP
      RET 8
      

      CRACKME

      程序分析

      • 打開exe,彈出消息框

        image-20230315133331048

      要求去除所有的nag(大概就是消息框吧)并取得注冊碼。

      • 點擊確定,界面如下:

        image-20230315133419767
      • 隨意輸入,如下

        image-20230315133504477

      去除消息框

      觀察

      • 先嘗試去除消息框,查找所有的代碼間調用。這個一般調用rtcMsgBox(從外面的dll文件再到熟悉的啟動函數可以判斷是vb程序),可以找到三個調用。右鍵選擇在每個rtcMsgBox上設置斷點,直接F9運行,調試器自動停止,這個點(402CFE)就是msgbox的位置。需要注意窗口主界面有一個“Nag?”按鈕,可以嘗試再次F9運行,發現它執行跳轉到402CFE,所以只需要對一個進行修改。
      image-20230315135320442

      方法一

      • 可以運行msgbox函數試試,觀察寄存器:

      這樣可以知道msgbox傳入了0x14字節的參數。

      • 空格修改匯編,如下。nop是為了填補空缺,因為原來的call占用5字節,而add指令占用3字節,為了不影響后面的指令,必須填補這兩字節的空缺。

      • 這樣修改后,msgbox會被越過,且棧會平衡,但仍然有一個問題,就是返回值并沒有處理。msgbox會使用eax返回1,表示用戶按下確定,這里并沒有處理eax,導致返回值為0,所以程序會在運行時認為按下了否,程序自動退出。

        大家可能會想到這樣的代碼:

        add esp,0x14
        mov eax,1
        

        這個代碼是可行的,但是由于代碼長度只有5,所以添加一個mov指令會超出這個限制,導致后面的代碼被侵占。

      方法二

      • 直接向上翻找到函數入口,修改push ebp

        image-20230315143002263
      • 這個0x4可以由兩個地方確定,一個是函數末尾使用了retn 0x4,一個是返回地址處的call前后esp變化了0x4。

      • 這樣修改后直接跳過該函數的執行過程,消息框自然就被去除了。

      找到注冊碼

      • 查找所有引用字符串,可以找到“Yep”
        image-20230315152830773

      這個應當是注冊碼輸入正確時執行的指令。

      • 向前找到je

        image-20230315152933346

      這個jmp指令應當為對注冊碼正確與否的判斷。

      這里要求di!=si,可以向上繼續尋找,

      • 在前面有個strcmp函數,其push 的兩個參數分別為“I'mlena151”和用戶輸入的注冊碼(ebp-0x58)?;究梢圆聹y注冊碼即為“I'mlena151”。

      相關文章:

      国产免费三A级精品大片|久久久久久女乱国产|操逼无码播放六区|黄色毛片在线观看视频

    1. <big id="vhnbr"></big>