惡意代碼 實驗三1,3 PE文件病毒感染與恢復


1.分析感染后的可執行程序

(1)確定感染后程序包含哪幾個節,每個節的訪問屬性如何;

訪問屬性參考文檔

來源於PE Explorer的幫助文檔

The last member of a section header is the 32 bits 'Characteristics', which is a bunch of flags describing how the section's memory should be treated:

If bit 5 (IMAGE_SCN_CNT_CODE) is set, the section contains executable code.

If bit 6 (IMAGE_SCN_CNT_INITIALIZED_DATA) is set, the section contains data that gets a defined value before execution starts. In other words: the section's data in the file is meaningful.

If bit 7 (IMAGE_SCN_CNT_UNINITIALIZED_DATA) is set, this section's data is uninitialized data and will be initialized to all-0-bytes before execution starts. This is normally the BSS.

If bit 9 (IMAGE_SCN_LNK_INFO) is set, the section doesn't contain image data but comments, description or other documentation.

If bit 11 (IMAGE_SCN_LNK_REMOVE) is set, the data is part of an object file's section that is supposed to be left out when the executable file is linked.

If bit 12 (IMAGE_SCN_LNK_COMDAT) is set, the section contains "common block data", which are packaged functions of some sort.

Bit 15 (IMAGE_SCN_MEM_FARDATA) is reserved for future use.

Bit 17 (IMAGE_SCN_MEM_PURGEABLE) is reserved for future use.

The same is IMAGE_SCN_MEM_16BIT.

Bit 18 (IMAGE_SCN_MEM_LOCKED) is reserved for future use.

Bit 19 (IMAGE_SCN_MEM_PRELOAD) is reserved for future use.

Bits 20 to 23 specify an alignment of data on a 1/8192-byte boundary. This is valid for object files only.

Bit 24 (IMAGE_SCN_LNK_NRELOC_OVFL) indicates that the count of relocations for the section exceeds the 16 bits reserved for it in section header. If the bit is set and the NumberOfRelocations field in the section header is 0xffff, the actual relocation count is stored in the 32-bit VirtualAddress field of the first relocation.

If bit 25 (IMAGE_SCN_MEM_DISCARDABLE) is set, the section's data is not needed after the process has started. This is the case, for example, with the relocation information. I've seen it also for startup routines of drivers and services that are only executed once.

If bit 26 (IMAGE_SCN_MEM_NOT_CACHED) is set, the section's data should not be cached. Don't ask my why not. Does this mean to switch off the 2nd-level-cache?

If bit 27 (IMAGE_SCN_MEM_NOT_PAGED) is set, the section's data should not be paged out. This may be interesting for drivers.

If bit 28 (IMAGE_SCN_MEM_SHARED) is set, the section's data is shared among all running instances of the image. If it is e.g. the initialized data of a DLL, all running instances of the DLL will at any time have the same variable contents.
Note that only the first instance's section is initialized. Sections containing code are always shared.

If bit 29 (IMAGE_SCN_MEM_EXECUTE) is set, the process gets 'execute'-access to the section's memory.

If bit 30 (IMAGE_SCN_MEM_READ) is set, the process gets 'read'-access to the section's memory.

If bit 31 (IMAGE_SCN_MEM_WRITE) is set, the process gets 'write'-access to the section's memory.

--------------

After the section headers we find the sections themselves. They are, in the file, aligned to 'FileAlignment' bytes (that is, after the optional header and after each section's data there will be padding bytes). When loaded (in RAM), the sections are aligned to 'SectionAlignment' bytes.

As an example, if the optional header ends at file offset 981 and 'FileAlignment' is 512, the first section will start at byte 1024. Note that you can find the sections via the 'PointerToRawData' or the 'VirtualAddress', so there is hardly any need to actually fuss around with the alignments.

The remainder of an image file contains blocks of data that are not necessarily at any specific file offset. Instead the locations are defined by pointers in the Optional Header or a section header. An exception is for images with a Section Alignment value (see the Optional Header description) of less than the page size of the architecture (4K for Intel x86 and for MIPS; 8K for Alpha). In this case there are constraints on the file offset of the section data. Another exception is that attribute certificate and debug information must be placed at the very end of an image file (with the attribute certificate table immediately preceding the debug section), because the loader does not map these into memory. The rule on attribute certificate and debug information does not apply to object files, however.

原本的彈窗程序test.exe被感染后

image-20210508111631026

image-20210508111701730

image-20210508111755707

image-20210508111822974

原本的記事本程序重命名為test.exe並被感染后

image-20210508112035356

image-20210508112100097

image-20210508112131942

image-20210508112207455

原本的計算器程序重命名為test.exe並被感染后

image-20210508112336663

image-20210508112354218

image-20210508112419215

image-20210508112450994

(2)這兩方面與感染前程序相比,有什么變化

原本的彈窗程序test.exe被感染前

image-20210508112819613

image-20210508112842043

image-20210508112913453

原本的記事本程序notepad.exe被感染前

image-20210508113034143

image-20210508113051129

image-20210508113115072

原本的計算器程序calc.exe被感染前

image-20210511220704458

image-20210511220739565

image-20210511220906182

分析發現,不管是哪個文件,文件被感染后比被感染前多出了一個.hum節,其訪問屬性是IMAGE_SCN_CNT_CODE(節中包含可執行的代碼)、IMAGE_SCN_MEM_EXECUTE(進程對節的內存有執行權限)、IMAGE_SCN_MEM_READ(進程對節的內存有讀權限)、IMAGE_SCN_MEM_WRITE(進程對節的內存有寫內存)。而感染前本來就有的節沒有發生變化。

(3)判斷“病毒”程序是否會反復感染同一文件;如果可以,多次感染和一次感染的不同點是什么;如果不可以,那么“病毒” 程序如何做到不重復感染

“病毒”程序不可以反復感染同一文件。

test.exe已經被感染后嘗試再次運行病毒程序,提示沒有再次感染。

image-20210512065747901

GetApiA部分代碼的調試

用ollydbg調試,F7單步執行,步入GetApiA

image-20210512005951647

GetApiA中調用另外一個過程

image-20210512010159449

發現程序死循環在這個過程里面

image-20210511225910756

查資料后發現這並不是死循環,而是當每次循環使計數器減一,當計數器值為0時跳出循環。此處loop使用的計數器是寄存器ECX,而通過寄存器EAX查找目標函數,根據堆棧和ESI,猜測要尋找的是GetModuleHandleA函數。根據cmp bl,byte ptr ds:[edx+eax] je short 感染程序.00401016完成判斷跳出循環。

image-20210511231435410

用depends打開一個exe,查看user32.dll中的函數,發現GetModuleHandleA的編號是177。

image-20210511233801668

此時找到GetModuleHandleA

image-20210511233329683

一個字符一個字符地進行比較,把相同的位數存到EDX中

image-20210511233529904

發現之后又使用這個循環去尋找其他函數,那么直接用F8跳過找函數的call 40100A這部分代碼即可。注意到其在查找GetModuleHandleA之后又尋找了GetProcAddressLoadLibraryACreateFileACreatingFileMappingAMapViewOfFileUnmapViewOfFileCloseHandleGetFileSizeSetFilePointerSetEndOfFileExitProcess這些函數。

image-20210511234352987

my_infect部分代碼的調試

跳轉到40144D處,F2下斷點,F9運行至斷點處,步入my_infect部分的代碼

image-20210512000900556

經過call [ebp+aCreateFile]inc eax后,EAX的值不為0,ZF值為0,所以je _Err不會進行跳轉,說明打開目標文件test.exe成功。

image-20210512002042687

同理,后面的得到文件大小、關閉文件、創建文件映射、映射文件也都成功,my_include部分代碼順利執行完畢。

modipe.asm部分代碼的調試

my_include部分執行結束后,緊接着的是modipe.asm

image-20210512003241690

image-20210512003152740

執行cmp word ptr [esi],'ZM'后,ZF為1,所以jne CouldNotInfect不跳轉。

image-20210512003950663

執行cmp word ptr [esi],'EP'后,ZF為1,所以jne CouldNotInfect不跳轉

image-20210512003455143

執行cmp dword ptr [esi+8],'dark'后,ZF為1,所以je CouldNotInfect跳轉。也就是說,因為文件中已經存在了dark這個感染標記,所以不再次感染此文件。

image-20210512004047972

CouldNotInfect部分代碼的調試

image-20210512004323196

執行test eax,eax后,ZF為0,所以jnz @g12不跳轉

image-20210512004411222

然后會依次call No captioncall _tips

_tips部分代碼的調試

image-20210512004840570

這里調用MessageBoxA函數,彈出彈窗“本程序僅感染本目錄下未被感染過的test.exe程序。”

image-20210512004948783

_where部分代碼的調試

image-20210512005115201

執行cmp dword ptr [esi+8],'dark'后,ZF為0,判斷出是啟動程序而不是HOST程序,所以je jmp_oep不跳轉

image-20210512005319476

然后jmp _xit跳轉到_xit

_xit部分的代碼調試

image-20210512005538186

退出啟動程序。

2.分析源程序main.asm

(1)定位並分析其中重定位相關的代碼,說明存儲相應偏差位移量的寄存器是哪個;

(2)定位並分析其中獲取kernel32.dll在內存中裝載位置的代碼,說明記錄裝載位置的存儲單元(包含寄存器和變量)

3.手工清除被感染程序中的“病毒”部分,將感染程序盡可能還原為原正常的程序,同時達到免疫效果

用winhex和PEview恢復文件並實現免疫

用winhex打開一個被感染后和一個被感染前的test.exe,進行對比,同時借助PEview理解PE文件格式。

image-20210512060422197

B6處的節數修改為原來的3

image-20210512061757231

image-20210512061830066

B8處的感染標記"dark"不要刪除,這是使test.exe免疫此實驗中的病毒所要利用的。

image-20210512061026678

D8處的入口點地址需要修改為原來的1000

image-20210512060959836

image-20210512061253054

100處的Image大小修改為原來的4000

image-20210512061451036

image-20210512061545509

220248的.hum的IMAGE_SECTION_HEADER清0

image-20210512062231813

image-20210512062403136

A00到最后的.hum節清零

image-20210512062531281

image-20210512062846777

A00到最后的.hum節刪掉,把文件恢復至原來大小

使用winhex的選塊選擇這部分

image-20210512063228021

鼠標右鍵→編輯→移除

image-20210512063330226

發現剩下了近一行,繼續移除

image-20210512063434128

至此文件恢復完畢

image-20210512063451477

保存恢復后的文件為test_Rev.exe,發現其大小已經變為被感染前的2560字節,而不再是被感染后的6656字節。

image-20210512063724479

比較恢復后和被感染前的文件

在linux中使用xxd指令將二進制文件轉為16進制文本文件

xxd test_Rev.exe > test_Rev.txt

xxd test.exe > test.txt

然后用vscode比較兩個文本文件的不同

image-20210512065102517

image-20210512065124380

比較發現,兩個文件唯一不同的地方就在於test_Rev.exe具有"dark"這個感染標記,則確定已經盡可能將文件恢復為感染前的樣子

image-20210512065222461

運行測試結果

運行test_Rev.exe,可以實現與被感染前的test.exe一樣的效果

image-20210512065409833

image-20210512065422068

test_Rev.exe重命名為test.exe,放到與病毒文件同一個文件夾中,嘗試用病毒文件感染它

image-20210512065546078

提示無法感染

再次運行test.exe,發現確實沒有被感染

image-20210512065619113

image-20210512065631552


免責聲明!

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



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