?? 手工(代碼)分析硬盤(pán)分區(qū)表 .txt
字號(hào):
手工(代碼)分析硬盤(pán)分區(qū)表
作者:wp231957 于2007-11-16上傳
--------------------------------------------------------------------------------
By wp231957
一、WINHEX軟件
如果你對(duì)硬盤(pán)分區(qū)表不熟悉,建議你下載一個(gè)WINHEX的軟件,利用它來(lái)輔助理解本文(本人實(shí)際上就是這么做的,一邊看書(shū),一邊打開(kāi)WINHEX,一邊調(diào)試程序)。在使用WINHEX時(shí),有一點(diǎn)需要注意一下,我們看到的最小單元就是一個(gè)BYTE,連續(xù)4個(gè)單元就是1個(gè)DWORD,不過(guò)它是倒著顯示的,也就是說(shuō)我們看到的A1B2C3D4這是一個(gè)DWORD數(shù)據(jù),那么它實(shí)際上等于D4C3B2A1H。(參考1)
二、硬盤(pán)數(shù)據(jù)存儲(chǔ)區(qū)域
對(duì)于FAT文件系統(tǒng)(NTFS及其他文件系統(tǒng)不在本文討論的范圍內(nèi))硬盤(pán)上數(shù)據(jù)大致可以分為MBR DBR FAT DIR DATA五個(gè)區(qū)域,本文只討論MBR區(qū)。MBR區(qū)又稱(chēng)為主引導(dǎo)記錄區(qū),位于整個(gè)硬盤(pán)的0磁道 0柱面 1扇區(qū),一共512個(gè)字節(jié),其實(shí)MBR一共占用63個(gè)扇區(qū),不過(guò)通常只使用第一個(gè)扇區(qū)而已。其中,前446個(gè)字節(jié)為引導(dǎo)程序,隨后的64個(gè)字節(jié)為硬盤(pán)分區(qū)表,每個(gè)分區(qū)表描述信息占位16個(gè)字節(jié),一共可以描述4個(gè)分區(qū),最后2個(gè)字節(jié)為55H AAH 是分區(qū)有效結(jié)束標(biāo)志。關(guān)于引導(dǎo)程序我們PASS略過(guò),主要介紹隨后的分區(qū)表信息,它們每16個(gè)字節(jié)的各個(gè)字節(jié)表述含義都是一樣的。
三、關(guān)于分區(qū)數(shù)大于4
很多情況下,我們的分區(qū)數(shù)目不止于四個(gè),但MBR中最多只能容納四個(gè),為此MS引入了虛擬MBR的概念,所謂虛擬MBR就是在硬盤(pán)分區(qū)表的后面還有很多和主引導(dǎo)扇區(qū)一樣的扇區(qū)(具體個(gè)數(shù)取決于你硬盤(pán)分區(qū)的數(shù)量),此虛擬MBR占位512個(gè)字節(jié),只不過(guò)它的引導(dǎo)程序沒(méi)有任何意義,一般為全0填充,它的分區(qū)表信息也只有2項(xiàng)(各個(gè)字節(jié)含義同主引導(dǎo)扇區(qū)),第一個(gè)部分描述本分區(qū)信息,第二個(gè)部分描述的是下一個(gè)分區(qū)的信息。如果下一個(gè)分區(qū)的信息為全0 則表示分區(qū)結(jié)束。通常情況下,主引導(dǎo)扇區(qū)的4個(gè)分區(qū)也不是全都使用的,第一個(gè)為引導(dǎo)區(qū)(通常的C盤(pán)),第2個(gè)為擴(kuò)展分區(qū),順著這個(gè)鏈就可以一直找出所有的分區(qū)。
四、關(guān)于硬盤(pán)邏輯鎖
由于系統(tǒng)啟動(dòng)時(shí),是需要掃描這個(gè)分區(qū)鏈的,正常這個(gè)分區(qū)鏈?zhǔn)情_(kāi)鏈,也就是有開(kāi)始有結(jié)束(全0結(jié)束)。但是如果認(rèn)為的將這個(gè)分區(qū)鏈變成一個(gè)閉合的鏈,那勢(shì)必將引導(dǎo)程序陷入一個(gè)死循環(huán),引導(dǎo)程序如果不能找到全0的分區(qū)結(jié)束標(biāo)志,那么它就會(huì)一直再這個(gè)鏈上跑,并不會(huì)啟動(dòng)系統(tǒng),這就是所謂的硬盤(pán)邏輯鎖的產(chǎn)生原因。(需要注意的是,這個(gè)動(dòng)作和操作系統(tǒng)有關(guān)系。比如老的DOS系統(tǒng)中有這個(gè)掃描動(dòng)作,因此可以根據(jù)這個(gè)原理制作“硬盤(pán)鎖”。)
好了,講到這里,我們借助于WINHEX,隨便打開(kāi)一個(gè)物理硬盤(pán)(參考2),我們順著這個(gè)分區(qū)鏈就可以找出全部的分區(qū)了,并能了解該分區(qū)的一些基本信息,比如起始扇區(qū),分區(qū)類(lèi)型,分區(qū)大小等等,下面我們使用ASM代碼來(lái)描述一下如何掃描這個(gè)鏈表。為了保持程序的完整性和可讀性,不再有講解性內(nèi)容,而是以注釋的形式進(jìn)行講解。
;#Mode=CON
.586
.Model Flat, StdCall
Option Casemap :None
Include windows.inc
Include user32.inc
Include kernel32.inc
include fpu.inc
include gdi32.inc
include masm32.inc
includelib masm32.lib
includelib gdi32.lib
IncludeLib user32.lib
IncludeLib kernel32.lib
includelib fpu.lib
include macro.asm
.data
diskname db '\\.\PHYSICALDRIVE0',0
ctitle db '分區(qū)號(hào) 分區(qū)首地址(扇區(qū)) 分區(qū)容量(MB)',0
cline db '=======================================',0
cspace db ' ',0
_13 db 13,0
_10 db 10,0
.data?
iobuffer db 512 dup(?)
strbuffer db 512 dup(?)
fqhbuf db 128 dup (?)
fqaddr db 128 dup (?)
vmbrbuf db 128 dup (?)
hdisk dd ?
dwbytesread dd ?
nextp dd ?
vmbrsec dd ?
vmbr dq ?
vmbr2 dq ?
fqh dd ?
.const
_2048 dd 2048
.CODE
START:
mov fqh,1
invoke StdOut,offset ctitle
invoke StdOut,offset _13
invoke StdOut,offset _10
invoke StdOut,offset cline
invoke StdOut,offset _13
invoke StdOut,offset _10
invoke CreateFile,addr diskname,GENERIC_READ or GENERIC_WRITE ,\
FILE_SHARE_READ or FILE_SHARE_WRITE ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
mov hdisk,eax
invoke SetFilePointer,hdisk,0,NULL,FILE_BEGIN
invoke ReadFile,hdisk,addr iobuffer,512,addr dwbytesread,0
;讀取MBR區(qū)(0扇區(qū))
mov esi,offset iobuffer
;0扇區(qū)所有的數(shù)據(jù)都在iobuffer里,我們主要操作緩沖區(qū)
xor ebx,ebx
.while ebx<4
;MBR區(qū)只能有4個(gè)主引導(dǎo)區(qū),所以我們循環(huán)4次就可以了
.if ebx>0
add esi,16 ;每個(gè)主分區(qū)信息占16個(gè)字節(jié),這里對(duì)下面—>
.endif ;|——————————————————>
mov eax,[esi+450] ;—>[ESI+450]能否正確尋址,至關(guān)重要
.if al==11 || al==12 || al==07 ;11也就是0BH ,0cH表示FAT32 07表示NTFS分區(qū)
finit
fild DWORD ptr[esi+458]
fild _2048
fdiv ;除以2048后,轉(zhuǎn)換為MB單位
invoke FpuFLtoA,0,2,addr strbuffer,SRC1_FPU OR SRC2_DIMM OR STR_REG ;調(diào)用浮點(diǎn)函數(shù)庫(kù)轉(zhuǎn)換浮點(diǎn)到字符
;需要引用庫(kù)includelib fpu.lib include fpu.inc
invoke wsprintf,addr fqaddr,CTEXT('%8X'),DWORD PTR [ESI+454]
invoke wsprintf,addr fqhbuf,CTEXT('%4d'),fqh
invoke StdOut,offset fqhbuf
invoke StdOut,offset fqaddr
invoke StdOut,offset cspace
invoke StdOut,offset strbuffer
invoke StdOut,offset _13
invoke StdOut,offset _10
inc fqh
.endif
.if al==15 || al==05 ;15 or 05也就是0FH(05H) 表示擴(kuò)展分區(qū)
mov eax,[esi+454]
;這里取VMBR地址鏈的首地址(虛擬MBR的基地址,這2種叫法都是我自己叫的
;別人不知道正是的中文翻譯是什么)
mov vmbrsec,eax ;保存VMBR首地址,因?yàn)橄旅嬉?jì)算和輸出這個(gè)地址
xor edx,edx
shld edx,eax,9
shl eax,9
;對(duì)VMBR地址進(jìn)行*512的計(jì)算,因?yàn)榻Y(jié)果大于32位,
;所以以下代碼段引進(jìn)了64位的計(jì)算
mov DWORD ptr vmbr,eax
mov DWORD ptr vmbr+4,edx
invoke SetFilePointer,hdisk,DWORD ptr vmbr,addr DWORD ptr vmbr+4,FILE_BEGIN ;設(shè)置文件指針,因?yàn)樯婕暗?4位,請(qǐng)注意
;該函數(shù)的第3個(gè)參數(shù),一定是64位中高32位
;的值的指針
invoke ReadFile,hdisk,addr iobuffer,512,addr dwbytesread,0
jmp localsector ;轉(zhuǎn)到掃描擴(kuò)展分區(qū)鏈的處理程序段
.endif
inc ebx
.endw
localsector: ;擴(kuò)展分區(qū)鏈處理
.repeat
mov esi,offset iobuffer
finit
fild DWORD ptr[esi+458] ;取分區(qū)容量,單位扇區(qū)
fild _2048
fdiv
invoke FpuFLtoA,0,2,addr strbuffer,SRC1_FPU OR SRC2_DIMM OR STR_REG
mov eax,DWORD ptr [esi+470] ;
add eax,63 ;
add eax,vmbrsec ;VMBR表首地址+63后是分區(qū)的首地址
invoke wsprintf,addr fqaddr,CTEXT('%8X'),eax
invoke wsprintf,addr fqhbuf,CTEXT('%4d'),fqh
invoke StdOut,offset fqhbuf
invoke StdOut,offset fqaddr
invoke StdOut,offset cspace
invoke StdOut,offset strbuffer
invoke StdOut,offset _13
invoke StdOut,offset _10
mov eax,DWORD ptr [esi+470];取下一個(gè)分區(qū)的VMBR的指針
mov nextp,eax
;保存,以備循環(huán)終止條件使用,這個(gè)指針為0時(shí),則擴(kuò)展分區(qū)掃描結(jié)束
push eax
pop eax
xor edx,edx
shld edx,eax,9
shl eax,9 ;EAX*512 乘積放在EDX:EAX中
add eax,DWORD ptr vmbr
adc edx,DWORD ptr vmbr+4
;2個(gè)DQ型數(shù)據(jù)相加,表示下一個(gè)分區(qū)的指針(NEXTP*512+VMBR)
mov DWORD ptr vmbr2,eax
mov DWORD ptr vmbr2+4,edx ;新指針保存另一個(gè)變量中,以備下面調(diào)用
;這里絕對(duì)不能更改VMBR的值
.break .if nextp == 0
invoke SetFilePointer,hdisk,DWORD ptr vmbr2,addr DWORD ptr vmbr2+4,FILE_BEGIN ;注意這里指針是VMBR2了
invoke ReadFile,hdisk,addr iobuffer,512,addr dwbytesread,0
inc fqh ;分區(qū)號(hào)自增1
.until nextp==0;如果NEXTP=0 表示分區(qū)結(jié)束,就是再也沒(méi)有分區(qū)了,程序結(jié)束
ret
end START
運(yùn)行結(jié)果:
參考:
1.“big endian和little endian是CPU處理多字節(jié)數(shù)的不同方式。例如“漢”字的Unicode編碼是6C49。那么寫(xiě)到文件里時(shí),究竟是將6C寫(xiě)在前面,還是將49寫(xiě)在前面?如果將6C寫(xiě)在前面,就是big endian。還是將49寫(xiě)在前面,就是little endian。“endian”這個(gè)詞出自《格列佛游記》。小人國(guó)的內(nèi)戰(zhàn)就源于吃雞蛋時(shí)是究竟從大頭(Big-Endian)敲開(kāi)還是從小頭(Little-Endian)敲開(kāi),由此曾發(fā)生過(guò)六次叛亂,其中一個(gè)皇帝送了命,另一個(gè)丟了王位。
我們一般將endian翻譯成“字節(jié)序”,將big endian和little endian稱(chēng)作“大尾”和“小尾”。
Intel處理器采用的是“小尾”方式。http://blog.tianya.cn/blogger/post_show.asp?BlogID=182860&PostID=2114034
2:WinHex默認(rèn)啟動(dòng)時(shí)彈出打開(kāi)向?qū)В绻麤](méi)有的話,可以從 tools 菜單中打開(kāi)。
--------------------------------------------------------------------------------
<<<上一篇 歡迎訪問(wèn)AoGo匯編小站:http://www.aogosoft.com 下一篇>>>
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -