初學者的靜態分析挑戰writeup4

題目來源至 https://www.malwaretech.com/beginner-malware-reversing-challenges

所有挑戰都是在不使用調試器的情況下完成的,你的目標應該是能夠在不運行exe的情況下完成每個挑戰。

這些挑戰利用與位置無關的代碼來解密flag,弄清楚shellcode的作用並自己解密。

shellcode1.exe

包含存儲在可執行文件中的flag。運行時,程序將輸出flag的MD5哈希值,但不輸出原始值,難度等級1星。

本地解壓後:
在這裏插入圖片描述
IDA打開,如下:
在這裏插入圖片描述
還是先找一下生成hash的方法,可以確定 call ?digestString@MD5@@QAEPADPAD@Z ; MD5::digestString(char *) 爲生成hash的方法。

找這個函數的參數,發現前面存在一個push操作,爲 push offset Str ; “2b\n:蹥B*bb”

發現Str爲一個字符串的地址,
在這裏插入圖片描述
在這裏插入圖片描述
可以先將字符串當做flag輸入進行檢測,經過實踐後,發現這裏的字符串並不是真正的flag。

說明這個地址保存的字符串在前面的流程中進行了改寫,我們繼續往上查看彙編代碼。

call [ebp+Dst]

直接調用了一個地址,首先這個地址應該是一個函數的開始地址。那麼如何得到這個地址的?

繼續往上看

push    10h
push    0
call    ds:GetProcessHeap
push    eax
call    ds:HeapAlloc
mov     [ebp+var_4], eax
mov     eax, [ebp+var_4]
mov     dword ptr [eax], offset Str ; "2b\n:蹥B*bb"
push    offset Str      ; "2b\n:蹥B*bb"
call    strlen
add     esp, 4
mov     ecx, [ebp+var_4]
mov     [ecx+4], eax
push    40h
push    1000h
push    0Dh
push    0
call    ds:VirtualAlloc
mov     [ebp+Dst], eax
push    0Dh             ; MaxCount
push    offset unk_404068 ; Src
mov     edx, [ebp+Dst]
push    edx             ; Dst
call    memcpy
add     esp, 0Ch
mov     esi, [ebp+var_4]
call    [ebp+Dst]

首先往上發現了memcpy方法,屬於C庫函數。

void *memcpy(void *str1, const void *str2, size_t n) 從存儲區 str2 複製 n 個字符到存儲區 str1。

edx爲str1,unk_404068爲str2,0Dh爲n

這裏發現將unk_404068的內容複製到了Dst地址處,恰巧Dst爲下面call調用的地址。

push    40h
push    1000h
push    0Dh
push    0
call    ds:VirtualAlloc
mov     [ebp+Dst], eax

這裏使用VirtualAlloc生成了一塊虛擬內存,並且設置爲可執行,說明[ebp+Dst]處的地址是可執行的,具體可以參考MSDN此函數的用法。

我們跟進unk_404068看看,雙擊unk_404068進入如下:

在這裏插入圖片描述
目前是以數據顯示,猜測這裏應該是代碼(不然call調用了無法執行)。所以選中unk_404068,Edit 選中Code,生成代碼。
在這裏插入圖片描述
在這裏插入圖片描述
可以發現,IDA分析後確實生成了代碼。
在這裏插入圖片描述
call [ebp+Dst] 這裏已經解決了,接着查找這個函數的輸入參數。

往上發現了mov esi, [ebp+var_4],而函數內部也對這個esi寄存器進行了操作,判斷這裏是寄存器傳遞參數。

現在的問題變成了(ebp+var_4)地址處的值是什麼?

push    10h
push    0
call    ds:GetProcessHeap
push    eax
call    ds:HeapAlloc
mov     [ebp+var_4], eax

首先來到第一次對[ebp+var_4]進行操作的地方,這段彙編的意思是調用HeapAlloc生成了一段堆空間,並將起始地址賦值給了
[ebp+var_4]

mov     eax, [ebp+var_4]
mov     dword ptr [eax], offset Str ; "2b\n:蹥B*bb"
push    offset Str      ; "2b\n:蹥B*bb"
call    strlen
add     esp, 4
mov     ecx, [ebp+var_4]
mov     [ecx+4], eax

接着[ebp+var_4]賦值給了eax,而eax地址處的存儲值變成了Str字符串的起始地址。

Str字符串地址入棧,調用了strlen C庫函數。將字符串長度eax賦值給了[ecx+4]。

[ecx+4]爲[ebp+var_4][1]

現在我們發現

[ebp+var_4][0]=Str[0]
[ebp+var_4][1]=eax=strlen(Str)

進一步,[ebp+var_4]目前的值爲Str存儲的字符串的地址。

而上面我們發現,esi的值爲[ebp+var_4]的值。

所以現在進入 call [ebp+Dst] 函數裏進行分析

               sub_404068      proc near               ; DATA XREF: start+5E↑o
.data:00404068                 mov     edi, [esi]
.data:0040406A                 mov     ecx, [esi+4]
.data:0040406D
.data:0040406D loc_40406D:                             ; CODE XREF: sub_404068+A↓j
.data:0040406D                 rol     byte ptr [edi+ecx-1], 5
.data:00404072                 loop    loc_40406D
.data:00404074                 retn
.data:00404074 sub_404068      endp

mov esi, [ebp+var_4]
call [ebp+Dst]

call strlen
add esp, 4
mov ecx, [ebp+var_4]
mov [ecx+4], eax

esi爲Str字符串的起始地址,[esi+4]爲eax的值,eax的值是strlen的結果,所以是字符串的長度。

rol byte ptr [edi+ecx-1], 5

這句彙編的含義是將Str的每個字符串循環左移5位之後再放回原位,所以最後的值是Str字符串。

之後可計算出flag

FLAG{SHELLCODE-ISNT-JUST-FOR-EXPLOITS}

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