如果你想成爲一名逆向分析或惡意代碼檢測工程師,或者對系統安全非常感興趣,就必須要認真分析一些惡意樣本。熊貓燒香病毒就是一款非常具有代表性的病毒,當年造成了非常大的影響,並且也有一定技術手段。本文將詳細講解熊貓燒香的行爲機理,並通過軟件對其功能行爲進行分析,這將有助於我們學習逆向分析和反病毒工作。後續作者還將對其進行逆向調試,以及WannaCry勒索蠕蟲、各種惡意樣本及木馬的分析。基礎性文章,希望您喜歡!
IDA和OD作爲逆向分析的“倚天劍和“屠龍刀”,學好它們的基本用法至關重要。本文重點分析熊貓燒香病毒的功能函數,大家掌握這些技巧後才能更好地分析更多的代碼。同時,本文部分實驗參考姜曄老師的視頻分析,真的非常佩服和值得去學習的一位老師。技術路上哪有享樂,爲了提升安全能力,別抱怨,幹就對了~
從2019年7月開始,我來到了一個陌生的專業——網絡空間安全。初入安全領域,是非常痛苦和難受的,要學的東西太多、涉及面太廣,但好在自己通過分享100篇“網絡安全自學”系列文章,艱難前行着。感恩這一年相識、相知、相趣的安全大佬和朋友們,如果寫得不好或不足之處,還請大家海涵!
接下來我將開啓新的安全系列,叫“安全攻防進階篇”,也是免費的100篇文章,作者將更加深入的去研究惡意樣本分析、逆向分析、內網滲透、網絡攻防實戰等,也將通過在線筆記和實踐操作的形式分享與博友們學習,希望能與您一起進步,加油~
- 推薦前文:網絡安全自學篇系列-100篇
話不多說,讓我們開始新的征程吧!您的點贊、評論、收藏將是對我最大的支持,感恩安全路上一路前行,如果有寫得不好或侵權的地方,可以聯繫我刪除。基礎性文章,希望對您有所幫助,作者目的是與安全人共同進步,加油~
文章目錄
一.實驗背景
對病毒進行逆向分析,可以徹底弄清楚病毒的行爲,從而採取更有效的針對手段。爲了節省篇幅,在這裏我不打算將“熊貓燒香”進行徹底的分析,只會講解一些比較重要的部分,大家只要掌握了這些思想,那麼就可以處理很多的惡意程序了。
這裏主要使用的工具包括:
- PEiD:病毒加殼、脫殼基礎性分析
- IDA Pro:靜態分析
- OllyDbg:動態分析
實驗文件:
- setup.exe:熊貓燒香病毒
基本流程:
- 利用查殼工具檢查病毒是否帶殼
- 利用OD動態分析病毒
- 利用IDA靜態分析病毒
注意:由於OD工具會將程序運行起來,所以我們在進行惡意代碼分析時儘量在搭建好的虛擬機中操作。如果病毒傳播性較強如WannaCry,建議斷開網絡和斷開共享分析。
二.PEiD加殼檢查
我們在分析病毒之前,首先需要調用工具檢查是否帶殼,如果病毒還需要先進行脫殼操作。這次研究的“熊貓燒香”程序並沒有加殼,但後續的文章我會詳細分享加殼與脫殼的內容,更好地幫助大家理解病毒分析及保護措施。
首先打開PEiD工具人,然後將熊貓燒香病毒拖進去,會發現病毒的基本信息。
分析信息如下:
- 該程序並沒有加殼,採用Delphi Borland Delphi 6.0-7.0編寫
注意,這裏補充姜老師對Delphi編寫代碼和VC++編寫代碼的理解。
- 區別:Delphi在函數調用時參數的傳遞不完全用棧,主要用寄存器。而C++程序函數調用前會使用push語句將參數入棧,然後再進行call。Delphi一般將第一個參數放入eax寄存器,第二個參數放入edx,第三個參數放入ecx寄存器,其餘參數按照與VC程序類似的方式壓棧。總之,Delphi編譯器默認以register方式傳遞函數參數。這一點與VC編譯的程序完全不同。
- 提示:棧上給局部變量分配空間的時候,棧是向下增長的,而棧上的數組、字符串、結構體等卻是向上增長的。理解這一點可以幫助識別棧上的變量。
三.IDA靜態分析和OD動態分析
當我們完成病毒樣本的檢測後,接下來就需要使用反彙編工具進行分析了。
1.基本載入
第一步,使用IDA Pro載入病毒樣本。
下圖爲Delphi自己生產的內容,並不是我們關心的重點。我們更關心病毒程度的功能代碼,本文主要講解病毒的關鍵函數。
第二步,定位到0x0040CB7E位置,發現這兩個call是調用了同一個函數sub_403C98。
- 0x0040CB7E
- sub_403C98
注意:某些病毒在IDA中會自動分析出字符串“感謝艾瑪…”,並且是在調用sub_403C98函數之前,我們可以推測上面那個函數也傳遞了一個字符串。接着可以通過OD動態調試獲取字符串對應的值。
但是,我目前的IDA並沒有自動解析出字符串的值,只能通過經驗進行分析或OD動態調試。我們發現EBP是堆棧基址,接近着兩次調用sub_403C98函數,前面的mov賦值經過是參數傳遞的工作,從而猜測出它的功能是:參數傳遞給函數調用。
2.sub_403C98函數分析
第三步,調用OD進行動態分析,查看sub_403C98函數調用前傳遞的參數。
- 0x0040CB79
- sub_403C98
打開OD如上圖所示,我們需要定位到0x0040CB79位置。直接按F8執行代碼(單步步過),當執行到0x0040CB79位置可以看到對應的值爲“武漢男生感染下載者”。
當然某些OD不會顯示該值,只會顯示“0040CC40=setup.0040CC40”,此時需要我們進一步在數據窗口跟隨。
- 數據窗口右鍵->轉到->表達式
接着輸入“40CC40”,查找傳遞參數對應的值。
顯示結果如下圖所示,可以看到“武漢男生感染下載者”,包括“艾瑪…”,這就是病毒作者的信息。早些年病毒作者處於炫耀目的,都會加入一些自己的特徵。同樣,現在APT攻擊溯源也會通過文件路徑等獲取病毒作者的信息。
- 0x0040CC40
第四步,分析病毒程序利用00403C98函數做了什麼。
- call 00403C98
接着再這個位置(0x0040CB7E)按下F2增加斷點,然後按F9執行過來,按下F7進入call函數,進入的函數如下圖所示。
接着按F7執行,遇到call 00403D08繼續按下F7進入,再進入call 00402520,繼續進入。
- call 00403D08
- call 00402520
- call dword ptr ds:[0x40D030]
- call 00401860
當進入call 00401860函數後,我們分析這裏的兩個API函數,它是對互斥空間進行初始化。
- 00401876 . E8 39F9FFFF call 004011B4 ;InitializeCriticalSection
- 00401889 . E8 2EF9FFFF call 004011BC ;EnterCriticalSection
我們繼續按下F8單步步過執行往下分析,發現在0x004018B3位置調用LocalAlloc函數,該函數用於內存分配。它會分配大小爲FF8的空間,Flags爲LMEM_FIXED表示分配一個固定的內存。該函數執行結果會返回一個指向新分配的內存對象的句柄。
- LocalAlloc
寫到這裏,基本就確定了這個call 00403D08的功能,即分配一定大小的內存空間。我們已經進入了好幾層Call,那怎麼返回的呢?接下來我們再回到IDA進行分析。
第五步,打開IDA進入sub_403C98函數。
- 0x0040CB7E call sub_403C98
整個sub_403C98函數由兩個函數組成,剛纔我們所進入的是第一個call sub_403D08的位置,並且分析了其功能是分配一定大小的空間。接着我們嘗試分析下一個函數sub_402650。
- 0x00403CB3 call sub_402650
接着記住這個地址“403CB3”,我們回到OD進行動態調試分析其功能。
- 轉到->表達式->輸入403CB3
顯示結果如下圖所示,然後我們按下F2增加斷點,再按F9執行程序至此處,繼續按下F7單步進入該函數。
第六步,分析sub_402650函數的功能。
上一步最終顯示結果如下圖所示,需要注意的是REP位置。
按下F8單步步過執行至0x0040267D位置。
- 0x0040267D rep movs dword ptr es:[edi],dword ptr ds:[esi]
注意,該REP是將ESI指向地址的值以4字節方式拷貝到EDI指向的地址中。下圖展示了ESI和EDI,重執行ECX次,每次執行後ESI+4、EDI+4、ECX-1,OD中在這段代碼中下斷後按F7單步步入就可以觀察到這3個寄存器的變化。
- ecx=00000008 (十進制 8.)
- ds:[esi]=[0040CC5C]=2A2A2ADF
- es:[edi]=[021C0028]=00000000
我們先看看它複製的內容是什麼,選擇ESI右鍵“數據窗口鐘跟隨地址”。
ESI顯示“武漢男生”信息,所要複製的空間是EDI爲空白空間。
按下F8運行後發現該空間被賦值“武漢男生”。寫到這裏,基本確定了sub_402650函數功能就是字符串的複製。
總結,Sub_403C98主要包括兩個函數,其對應功能如下:
- sub_403D08:分配內存空間
- sub_402650:字符串拷貝功能
同時,我們可以在IDA中對sub_403C98進行重命名操作,命名爲“AllocStackAndCopyString”。重命名能將整個程序中該函數進行修改,便於我們理解及分析整個病毒。
sub_403C98函數有兩個參數,由於採用的是Delphi編譯器,因此在反彙編中,第一個參數保存在eax中,第二個參數保存在edx中。這個函數首先完成堆空間的申請,然後將edx中保存的字符串複製到新申請的空間中。這個函數在最初賦值的時候,eax的值均爲0,而在執行後,eax中保存的就是新申請的堆空間中,所複製的字符串的首地址。爲了易於觀察,我把IDA Pro中的sub_403C98重命名爲AllocStackAndCopyString。
下面補充一段姜老師的註釋,對大家逆向分析和彙編理解很有幫助。
CODE:00403C98 sub_403C98 proc near ; CODE XREF: sub_403ED4+8j
CODE:00403C98 ; sub_403F18+6j ...
CODE:00403C98 test edx, edx
; 對edx進行驗證,這裏的test相當於and,不同的是test只進行比較,而不會將結果保存
; 在edx中。由於edx保存的是病毒作者所編寫的一段字符串,因此這裏的結果一定是非0的。
CODE:00403C9A jz short loc_403CC0
; 由於上一條語句的結果是非0的,因此這條跳轉語句並不會被執行到。
CODE:00403C9C mov ecx, [edx-8]
; 利用OD進行動態分析可知,[edx-8]是將edx-8這個地址中的值取出來,賦給ecx,那麼賦值
; 完以後,ecx的值爲0x0FFFFFFFF。
CODE:00403C9F inc ecx
; ecx自增1,那麼ecx的值就變爲了0x0,注意這個自增的運算會使得ZF的值變爲1。
CODE:00403CA0 jg short loc_403CBC
; 這裏的jg表明不大於則跳轉。或者更準確地說,其跳轉條件是SF=OF且ZF=0。由於經過上一步
; 的運算,ZF=1,因此本跳轉不成立。
CODE:00403CA2 push eax
CODE:00403CA3 push edx
CODE:00403CA4 mov eax, [edx-4]
; 經過賦值後,eax中保存的值爲0x20。
CODE:00403CA7 call sub_403D08
; 結合OD在虛擬機中進行動態分析,進入一層又一層的調用可以得知,這個CALL主要是調用了
; LocalAlloc函數,它從堆中分配大小爲0xFF8的空間,函數參數uFlags=0,即
; LMEM_FIXED,意思是分配固定內存,返回值是指向一個內存對象的指針。LocalAlloc函數
; 如果執行成功則返回一個指向新分配的內存對象的句柄。
CODE:00403CAC mov edx, eax
CODE:00403CAE pop eax
CODE:00403CAF push edx
CODE:00403CB0 mov ecx, [eax-4]
CODE:00403CB3 call sub_402650
; 結合OD在虛擬機中進行動態分析,這個CALL的主要功能是將之前保存在edx中的字符串(病
; 毒信息與作者感言)拷貝到上面所分分配的堆空間中。如圖5所示。
CODE:00403CB8 pop edx
CODE:00403CB9 pop eax
CODE:00403CBA jmp short loc_403CC0
3.sub_405360函數分析
第七步,繼續從0x0040CB92位置往下分析,將該地址複製到OD中動態調試。
操作如下:
- 轉到->表達式->輸入“40CB92”
- 按下F2增加斷點
- 按下F9執行,將代碼調試到該位置
然後按F8單步執行,可以看到0x0040CB9A存儲的值,某些情況還需要去數據窗口跟隨。
- 數據窗口右鍵->轉到->表達式->輸入40CCA4
可以發現在“40CCA4”位置保存了一段字符串,它可能是一段亂碼,目前無法分析它的含義。
繼續按下F8執行到0x0040CB9F,按下F7進入函數。
- 0x0040CB9F call 00405360
進入後先簡單瀏覽下這個函數,發現後續有一個粗線循環,我們在0x004053CC下個斷點跳轉到這個循環處,並進入循環。
- F2按下在0x004053CC處增加斷點
- F9執行到循環處
- F8進入循環
按下F8單步執行代碼,此時發現字符串“xboy”,我們暫時不知道它是做什麼的。
接着繼續按下F8調試,發現它將字母“b”賦值給了EAX,我們懷疑它跟“xboy”有關。
接下來的代碼分析如下:
- MOV ECX, 0xA
將常量“A”賦值給ECX。通常存在兩種可能性,一種可能是ECX作爲循環的此時,即可能循環A次;另一種可能是EXC作爲一個運算的除數。 - XOR EDX, EDX
異或操作將自身清空。 - DIV ECX
可以發現它是一個除法操作,除數即爲ECX。結果顯示如下圖所示,除法的商EAX爲9,餘數EDX爲8。
通常除法有兩種可能,要麼獲取EAX的商值,要麼獲取餘數EDX的內容。那麼這個程序究竟需要哪一個值呢?
- MOVX eax, byte ptr ds:[eax+ebx-0x1]
該語句將值賦給EAX,所以上述程序做除法的目的是獲取EDX這個值。
接着在數據窗口中跟隨地址,查看這個值保存的是什麼內容。
輸出結果如下圖所示,它是剛纔我們發現的亂碼,暫時還不知道它的具體作用。繼續按下F8執行程序。
- XOR EDX, EAX
EDX和EAX異或操作,其值保存在EDX中,即除法的餘數EDX和亂碼EAX進行異或操作。
繼續按下F8單步走,在0x00405408處出現了個地址,我們在數據窗口中跟隨數值。
發現這個結果是“2A”,該值正式剛纔異或出來的EDX結果。
接着我們嘗試在下列兩個位置增加斷點。
- 0x004053E8
- 0x00405408
接着按下F9運行,查看輸出的結果,分析如下:
- 將“xboy”的第三個字母“o”取出解密
- 數據窗口新增很多內容,完成字符串拷貝
反覆繼續按F9調試,發現它依次獲取“xboy”中的值,再進行異或操作。
小結:最終解密的值如下圖所示,“武漢男生感染下載者”逐漸出現。sub_405360函數我們在IDA中重命名爲“DecodeString”,即解密字符串。
補充彙編代碼:
CODE:004053D1 loc_4053D1: ; CODE XREF: sub_405360+B5 j
CODE:004053D1 mov eax, [ebp+var_14]
CODE:004053D4 call sub_403ECC
CODE:004053D9 push eax
CODE:004053DA mov eax, ebx
CODE:004053DC pop edx
CODE:004053DD mov ecx, edx
CODE:004053DF cdq
CODE:004053E0 idiv ecx
CODE:004053E2 mov edi, edx
CODE:004053E4 inc edi
CODE:004053E5 mov eax, [ebp+var_14]
CODE:004053E8 movzx eax, byte ptr [eax+edi-1]
; 每次循環逐字節取出“xboy”中的字符進行運算,注意這裏首先取出的是“b”。
CODE:004053ED mov ecx, 0Ah
; 將ecx賦值爲0x0A,作爲接下來除法運算的除數。
CODE:004053F2 xor edx, edx
; 清空edx。
CODE:004053F4 div ecx
; 做除法運算,商保存在eax中,餘數保存在edx中。
CODE:004053F6 mov eax, [ebp+var_4]
; 這裏由於給eax重新賦值,說明程序實際想使用的是edx中的餘數。
CODE:004053F9 movzx eax, byte ptr [eax+ebx-1]
; 每次循環逐字節取出亂碼中的字符,賦值給eax進行接下來的運算。
CODE:004053FE xor edx, eax
; 異或運算,結果保存在edx中,也就是通過運算最終得出的字符。
CODE:00405400 lea eax, [ebp+var_18]
CODE:00405403 call sub_403E2C
CODE:00405408 mov edx, [ebp+var_18]
CODE:0040540B lea eax, [ebp+var_10]
CODE:0040540E call sub_403ED4
CODE:00405413 inc ebx
CODE:00405414 dec esi
CODE:00405415 jnz short loc_4053D1
4.sub_404018函數分析
第八步,繼續分析sub_404018函數的功能。
記住地址0x0040CBA4,複製到OD中進行調試。
首先取消剛纔解密的兩個斷點,然後跟隨表達式“40CBA4”,在該位置按下F2增加斷點,然後F9執行過來。
首先看到兩條賦值語句,將值賦給EDX和EAX中,由於這個程序是使用Delphi編寫,所以在call之前會將參數放到寄存器中,我們首先看看EDX中的內容。
在數據窗口中跟隨數值,發現它們都是“武漢男生感染下載者”。注意第一個是我們剛纔解密出來的內容。
- 0040CBA4 . 8B55 EC mov edx,dword ptr ss:[ebp-0x14]
- 0040CBA7 . A1 D4E74000 mov eax,dword ptr ds:[0x40E7D4]
接着按下F8執行,再按F7進入Call 0040018函數。大致瀏覽該函數後,發現又存在一個循環,我們的重點就是分析該循環,按下F2增加斷點,再按F9執行過來。
- 0x00404041
在數據窗口中跟隨,發現ECX和EBX就是剛纔所說的兩個參數,一個是原始的“武漢男生感染下載者”,另外一個是解密之後的“武漢男生感染下載者”。再按F8發現這個函數比較兩個字符串是否相同的操作。
- CMP ECX, EBX
總結:回到IDA,我們將函數sub_404018重命名爲字符串比較函數“CMPString”。
5.loc_40CBBC功能分析
第九步,分析loc_40CBBC功能。
繼續往下看,發現只要CMPString兩個字符串相同,就會跳轉到loc_40CBBC的位置。
繼續分析發現這裏同樣存在字符串解密和字符串比較的操作,並且解密字符編程了武漢男孩(whboy),這裏不再進行解讀。
解密比較成功之後,繼續跳轉到loc_40CBE6的位置。這裏看到了三個call函數,它們又是什麼功能呢?這三個call是熊貓燒香病毒最重要的功能,我們下一篇論文繼續分析。
四.總結
寫到這裏,熊貓燒香病毒起始階段的逆向分析就介紹完畢,簡單總結如下:
- 0x0040CB7E call sub_403C98
– 重命名爲:AllocStackAndCopyString
– sub_403D08:分配內存空間
– sub_402650:字符串拷貝功能 - 0x0040CB9F call sub_00405360
– 重命名爲:DecodeString
– 0x004053CC:循環入口點
– 0x004053E8:獲取“xboy”解密字符
– 0x00405408:完成異或解密操作 - 0x0040CBAC call sub_404018
– 重命名爲:CMPString
– 0x00404041:循環入口點
– 功能:字符串比較“武漢男生感染下載者” - 0x0040CBCC loc_40CBBC
– 功能:字符串解密和比較操作,解密字符“whboy”
– DecodeString
– CMPString
後續會繼續分析熊貓燒香病毒的核心功能三個函數,正如姜老師所說“由於反彙編代碼總會出現各種調用與跳轉,所以分析時會顯得很是凌亂,可能會打消大家的積極性。但也可以看見逆向分析工作需要各位讀者的耐心與細緻,需要大家沉得住氣,不斷跟蹤每一個可疑的CALL;需要大家時刻留意寄存器中的內容,才能夠找到我們需要的信息。當然經驗也是非常重要的。” 再次感謝姜老師的分享,真的受益匪淺,也希望自己不斷深入,真正能在逆向分析和惡意代碼中學到東西,加油!
學安全一年,認識了很多安全大佬和朋友,希望大家一起進步。這篇文章中如果存在一些不足,還請海涵。作者作爲網絡安全和系統安全初學者的慢慢成長路吧!希望未來能更透徹撰寫相關文章。同時非常感謝參考文獻中的安全大佬們的文章分享,深知自己很菜,得努力前行。編程沒有捷徑,逆向也沒有捷徑,它們都是搬磚活,少琢磨技巧,幹就對了。什麼時候你把攻擊對手按在地上摩擦,你就贏了,也會慢慢形成了自己的安全經驗和技巧。加油吧,少年希望這個路線對你有所幫助,共勉。
2020年8月18新開的“娜璋AI安全之家”,主要圍繞Python大數據分析、網絡空間安全、人工智能、Web滲透及攻防技術進行講解,同時分享CCF、SCI、南核北核論文的算法實現。娜璋之家會更加系統,並重構作者的所有文章,從零講解Python和安全,寫了近十年文章,真心想把自己所學所感所做分享出來,還請各位多多指教,真誠邀請您的關注!謝謝。
(By:Eastmount 2020-12-08 星期二 晚上9點寫於武漢 http://blog.csdn.net/eastmount/ )
參考文獻:
姜曄老師真的非常佩服和值得去學習,希望自己和大家的技術能不斷提升,加油!
[1] [網絡安全自學篇] 木馬原理詳解、遠程服務器IPC $漏洞及木馬植入實驗
[2] 姜曄老師的技術空間目錄 - CSDN
[3] 騰訊安全聯合實驗室 - 知乎文章
[4] [網絡安全自學篇] 七十九.Windows PE病毒原理、分類及感染方式詳解
[5] 姜曄老師技術分享 - B站
[6] [網絡安全自學篇] 四十九.Procmon軟件基本用法及文件進程、註冊表查看
[7] [安全攻防進階篇] 八.那些年的熊貓燒香及PE病毒行爲機理分析
[8] [網絡安全自學篇] 七十三.WannaCry勒索病毒復現及分析(四)蠕蟲傳播機制源碼詳解
[9] https://blog.csdn.net/ioio_jy/article/details/41207265