电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

《Undocumented Windows 2000 Secrets》翻譯 --- 第四章(5)

瀏覽:95日期:2023-08-25 16:01:28

第四章 探索 Windows 2000 的內(nèi)存管理機(jī)制

翻譯: Kendiv( fcczj@263.net )

更新: Sunday, February 17, 2005

聲明:轉(zhuǎn)載請注明出處,并保證文章的完整性,本人保留譯文的所有權(quán)利。

IOCTL 函數(shù) SPY_IO_INTERRUPT

SPY_IO_INTERRUP 類似于 SPY_IO_SEGEMT ,不過該函數(shù)僅影響存儲在系統(tǒng)中斷描述符表( IDT )的中斷描述符,不會涉及 LDT 或 GDT 描述符。 IDT 最多可容納 256 個描述符,這些描述符可用來描述任務(wù)門、中斷門或陷阱門(參見 Intel 1999c, pp. 5-11ff )。順便說一下,中斷和陷阱在本質(zhì)上十分相似,二者只存在微小的差異:在進(jìn)入一個中斷處理例程后,總是會屏蔽其他中斷;而進(jìn)入陷阱處理例程卻不會修改中斷標(biāo)志。 SPY_IO_INTERRUPT 的調(diào)用者提供一個 0 到 255 之間的中斷號,該中斷號將位于輸入緩沖區(qū)中,而一個 SPY_INTERRUPT 結(jié)構(gòu)將作為輸出數(shù)據(jù)被存放到輸出緩沖區(qū)中,如果成功返回,該結(jié)構(gòu)中將包含對應(yīng)的中斷處理例程的屬性。由 Dispatcher 調(diào)用的幫助函數(shù) SpyOutputInterrupt() 只是一個簡單的外包函數(shù),它實際上調(diào)用 SpyInterrupt() 函數(shù)并且將需要返回的數(shù)據(jù)復(fù)制到輸出緩沖區(qū)中。 列表 4-18 給出了這兩個函數(shù),以及它們操作的 SPY_INTERRUPT 結(jié)構(gòu)。稍后一些, SpyInterrupt() 函數(shù)將填充如下項目:

l Selector 用來指定一個任務(wù)狀態(tài)段( Task-State Segment, TSS )或代碼段( Code Segment )的選擇器。代碼段選擇器用來確定中斷或陷阱處理例程所在的段。

l Gate 用來表示一個 64 位的任務(wù)門、中斷門或陷阱門描述符,由 Selector 確定其地址。

l Segment 包含段的屬性,該段的地址由前面的 Gate 給出。

l pOffset 指定中斷或陷阱處理例程的入口地址相對基地址的偏移量。這里的基地址是指中斷或陷阱處理例程所在代碼段的起始地址。因為任務(wù)門不包含偏移量,所以,如果輸入的選擇器指向一個 TSS ,則忽略該成員。

l fOk 一個標(biāo)志變量,用來指示 SPY_INTERRUPT 結(jié)構(gòu)中的數(shù)據(jù)是否有效。

通常情況下, TSS 被用來保證一個錯誤情況可以被一個有效的任務(wù)處理。這是一個特殊的系統(tǒng)段類型( system segment type ),它可以保存 104 個字節(jié)的進(jìn)程狀態(tài)信息,該信息在任務(wù)切換時,用來進(jìn)行任務(wù)的恢復(fù),如 4-3 所示。當(dāng)與任務(wù)相關(guān)的中斷發(fā)生時, CPU 總是強制切換該任務(wù),并將所有的 CPU 寄存器保存到 TSS 中。 Windows 2000 在中斷位置 0x02 (非屏蔽中斷 [NMI] , 0x08[Double Fault] 和 0x12[ 堆棧段故障 ] )處保存任務(wù)門。剩余的位置指向中斷處理例程。不使用的中斷由一個啞元例程 ---KiUnexpectedInterruptNNN() 處理,這里的 NNN 為一個十進(jìn)制數(shù)。這些啞元例程最后都匯集到內(nèi)部函數(shù) KIEndUnexpectedRange() ,在這里,這些例程將依次進(jìn)入 KiUnexpectedInterruptTail() 。

typedef struct _SPY_INTERRUPT

{

X86_SELECTOR Selector;

X86_GATE Gate;

SPY_SEGMENT Segment;

PVOID pOffset;

BOOL fOk;

}

SPY_INTERRUPT, *PSPY_INTERRUPT, **PPSPY_INTERRUPT;

#define SPY_INTERRUPT_ sizeof (SPY_INTERRUPT)

// -----------------------------------------------------------------

NTSTATUS SpyOutputInterrupt (DWord dInterrupt,

PVOID pOutput,

DWORD dOutput,

PDWORD pdInfo)

{

SPY_INTERRUPT si;

SpyInterrupt (dInterrupt, &si);

return SpyOutputBinary (&si, SPY_INTERRUPT_,

pOutput, dOutput, pdInfo);

}

// -----------------------------------------------------------------

BOOL SpyInterrupt (DWORD dInterrupt,

PSPY_INTERRUPT pInterrupt)

{

BOOL fOk = FALSE;

if (pInterrupt != NULL)

{

if (dInterrupt <= X86_SELECTOR_LIMIT)

{

fOk = TRUE;

if (!SpySelector (X86_SEGMENT_OTHER,

dInterrupt << X86_SELECTOR_SHIFT,

&pInterrupt->Selector))

{

fOk = FALSE;

}

if (!SpyIdtGate (&pInterrupt->Selector,

&pInterrupt->Gate))

{

fOk = FALSE;

}

if (!SpySegment (X86_SEGMENT_OTHER,

pInterrupt->Gate.Selector,

&pInterrupt->Segment))

{

fOk = FALSE;

}

pInterrupt->pOffset = SpyGateOffset (&pInterrupt->Gate);

}

else

{

RtlZeroMemory (pInterrupt, SPY_INTERRUPT_);

}

pInterrupt->fOk = fOk;

}

return fOk;

}

// -----------------------------------------------------------------

PVOID SpyGateOffset (PX86_GATE pGate)

{

return (PVOID) (pGate->Offset1 | (pGate->Offset2 << 16));

}

列表 4-18. 查詢中斷屬性

表 4-3. 任務(wù)狀態(tài)段( TSS )中的 CPU 狀態(tài)域

偏移量

位數(shù)

ID

0x00

16

前一個任務(wù)的鏈接

0x04

32

ESP0

Ring0 級的堆棧指針寄存器

0x08

16

SS0

Ring0 級的堆棧段寄存器

0x0C

32

ESP1

Ring1 級的堆棧指針寄存器

0x10

16

SS1

Ring1 級的堆棧段寄存器

0x14

32

ESP2

Ring2 級的堆棧指針寄存器

0x18

16

SS2

Ring2 級的堆棧段寄存器

0x1C

32

CR3

頁目錄基址寄存器( PDBR )

0x20

32

EIP

指令指針寄存器

0x24

32

EFLAGS

處理器標(biāo)志寄存器

0x28

32

EAX

通用寄存器

0x2C

32

ECX

通用寄存器

0x30

32

EDX

通用寄存器

0x34

32

EBX

通用寄存器

0x38

32

ESP

堆棧指針寄存器

0x3C

32

EBP

基地址指針寄存器

0x40

32

ESI

源索引寄存器

0x44

32

EDI

目標(biāo)索引寄存器

0x48

16

ES

擴(kuò)展段寄存器

0x4C

16

CS

代碼段寄存器

0x50

16

SS

堆棧段寄存器

0x54

16

DS

數(shù)據(jù)段寄存器

0x58

16

FS

附加的數(shù)據(jù)段寄存器 #1

0x5C

16

GS

附加的數(shù)據(jù)段寄存器 #2

0x60

16

LDT

本地描述符標(biāo)的段選擇器

0x64

1

1

調(diào)試陷阱標(biāo)志

0x66

16

I/O Map 的基地址

0x68

-

CPU 狀態(tài)信息結(jié)束

SpyInterrupt() 調(diào)用的 SpySegment() 、 SpySelector() 函數(shù)已經(jīng)在 列表 4-5 列表 4-16 中給出。 SpyGateOffset() 位于 列表 4-18 的末尾,它的工作和 SpyDescriptorBase() 、 SpyDescriptorLimit() 類似,從 X86_GATE 結(jié)構(gòu)中取出 Offset1 和 Offset2 位域,并適當(dāng)?shù)慕M織它們以構(gòu)成一個 32 位地址。 SpyIdtGaet() 定義于 列表 4-19 。它與 SpyDescriptor() 十分類似。匯編指令 SIDT 存儲一個 48 位的值,該值就是 CPU 的 IDT 寄存器的內(nèi)容,它由一個 16 位的表大小限制值和 IDT 的 32 位線性基地址構(gòu)成。 列表 4-19 中的剩余代碼將選擇器的描述符索引和 IDT 的大小限制值進(jìn)行比較,如果 OK ,則對應(yīng)的中斷描述符將被復(fù)制到調(diào)用者提供的 X86_GATE 結(jié)構(gòu)中。否則,門結(jié)構(gòu)的所有成員都將被設(shè)置為 0 。

BOOL SpyIdtGate (PX86_SELECTOR pSelector,

PX86_GATE pGate)

{

X86_TABLE idt;

PX86_GATE pGates = NULL;

BOOL fOk = FALSE;

if (pGate != NULL)

{

if (pSelector != NULL)

{

__asm

{

sidt idt.wLimit

}

if ((pSelector->wValue & X86_SELECTOR_INDEX)

<= idt.wLimit)

{

pGates = idt.pGates;

}

}

if (pGates != NULL)

{

RtlCopyMemory (pGate,

pGates + pSelector->Index,

X86_GATE_);

fOk = TRUE;

}

else

{

RtlZeroMemory (pGate, X86_GATE_);

}

}

return fOk;

}

列表 4-19. 獲取 IDT 門的值

IOCTL 函數(shù) SPY_IO_PHYSICAL

SPY_IO_PHYSICAL 函數(shù)很簡單,它完全依賴于 ntoskrnl.exe 導(dǎo)出的 MmGetPhysicalAddress() 函數(shù)。該 IOCTL 函數(shù)通過簡單的調(diào)用 SpyInputPointer() (參見 列表 4-10 )來獲取需要轉(zhuǎn)換的線性地址,然后讓 MmGetPhysicalAddress() 查找對應(yīng)的物理地址,最后將結(jié)果作為 PHYSICAL_ADDRESS 結(jié)構(gòu)返回給調(diào)用者。注意, PHYSICAL_ADDRESS 是一個 64 位的 LARGE_INTEGER 。在大多數(shù) i386 系統(tǒng)上,其高 32 位總是為 0 。不過,若系統(tǒng)啟用了物理地址擴(kuò)展( Physical Address Extension, PAE ),并且安裝的內(nèi)存大于 4GB ,這些位可能就是非 0 值了。

MmGetPhysicalAddress() 使用起始于線性地址 0xC0000000 的 PTE 數(shù)組,來進(jìn)行物理地址的查找。其基本的工作機(jī)制如下:

l 如果線性地址位于: 0x80000000----0x9FFFFFFF ,則其高 3 位將被設(shè)為零,最后產(chǎn)生的物理地址位于: 0x00000000-----0x1FFFFFFF 。

l 否則,線性地址的高 20 位將作為 PTE 數(shù)組(起始于 0xC0000000 )的索引。

l 如果目標(biāo) PTE 的 P 位已被設(shè)置,這表示其對應(yīng)得數(shù)據(jù)頁存在于物理內(nèi)存中。除了 20 位的 PFN 外,所有的 PTE 位都可以被剝離出來,線性地址最低的 12 位將作為在數(shù)據(jù)頁中的偏移量被加到最后的 32 位物理地址上去。

l 如果數(shù)據(jù)頁沒有存在于物理內(nèi)存中, MmGetPhysicalAddress() 返回 0 。

MmGetPhysicalAddress() 假設(shè)內(nèi)核內(nèi)存范圍: 0x80000000----0x9FFFFFF 之外的所有線性地址都使用 4KB 的頁。而其他函數(shù),如 MmIsAddressValid() ,會首先加載線性地址的 PDE ,并且檢查該 PDE 的 PS 位,以檢查頁大小是 4KB 還是 4MB 。這是一個非常通用的方法,可以處理任意的內(nèi)存配置。不過上述兩個函數(shù)都會返回正確的結(jié)果,這是因為 Windows 2000 僅針對內(nèi)存范圍: 0x80000000-----0x9FFFFFFF ,使用 4MB 頁。不過某些內(nèi)核 API 函數(shù),顯然設(shè)計的比其它的靈活許多。

IOCTL 函數(shù) SPY_IO_CPU_INFO

個別的 CPU 指令僅對運行于 Ring 0 級的代碼有效, Ring 0 是五個特權(quán)級( Intel 系列的 CPU 只支持兩個特權(quán)級: Ring0 和 Ring3 )中級別最高的一個。用 Windows 術(shù)語來說, Ring 0 意味著內(nèi)核模式( Kernel-mode )。這些被禁止的指令有:讀取控制寄存器 CR0 、 CR2 和 CR3 的內(nèi)容。因為這些寄存器中保存著非常有趣的信息,應(yīng)用程序可能想要找到一個辦法來訪問它們,解決方案就是 SPY_IO_CPU_INFO 函數(shù)。如 列表 4-20 所示, IOCTL 處理例程調(diào)用的 SpyOutputCpuInfo() 函數(shù)使用了一些嵌入式匯編來讀取控制寄存器,以及其他一些有價值的信息,比如 IDT 的內(nèi)容, GDT 和 LDT 寄存器以及存儲在寄存器 CS 、 DS 、 ES 、 FS 、 GS 、 SS 和 TR 中的段選擇器。任務(wù)寄存器( Task Register, TR )還包含一個涉及當(dāng)前任務(wù)的 TSS 的選擇器。

typedef struct _SPY_CPU_INFO

{

X86_REGISTER cr0;

X86_REGISTER cr2;

X86_REGISTER cr3;

SPY_SEGMENT cs;

SPY_SEGMENT ds;

SPY_SEGMENT es;

SPY_SEGMENT fs;

SPY_SEGMENT gs;

SPY_SEGMENT ss;

SPY_SEGMENT tss;

X86_TABLE idt;

X86_TABLE gdt;

X86_SELECTOR ldt;

}

SPY_CPU_INFO, *PSPY_CPU_INFO, **PPSPY_CPU_INFO;

#define SPY_CPU_INFO_ sizeof (SPY_CPU_INFO)

// -----------------------------------------------------------------

NTSTATUS SpyOutputCpuInfo (PVOID pOutput,

DWORD dOutput,

PDWORD pdInfo)

{

SPY_CPU_INFO sci;

PSPY_CPU_INFO psci = &sci;

__asm

{

push eax

push ebx

mov ebx, psci

mov eax, cr0

mov [ebx.cr0], eax

mov eax, cr2

mov [ebx.cr2], eax

mov eax, cr3

mov [ebx.cr3], eax

sidt [ebx.idt.wLimit]

mov [ebx.idt.wReserved], 0

sgdt [ebx.gdt.wLimit]

mov [ebx.gdt.wReserved], 0

sldt [ebx.ldt.wValue]

mov [ebx.ldt.wReserved], 0

pop ebx

pop eax

}

SpySegment (X86_SEGMENT_CS, 0, &sci.cs);

SpySegment (X86_SEGMENT_DS, 0, &sci.ds);

SpySegment (X86_SEGMENT_ES, 0, &sci.es);

SpySegment (X86_SEGMENT_FS, 0, &sci.fs);

SpySegment (X86_SEGMENT_GS, 0, &sci.gs);

SpySegment (X86_SEGMENT_SS, 0, &sci.ss);

SpySegment (X86_SEGMENT_TSS, 0, &sci.tss);

return SpyOutputBinary (&sci, SPY_CPU_INFO_,

pOutput, dOutput, pdInfo);

}

列表 4-20. 查詢 CPU 狀態(tài)信息

可使用幫助函數(shù) SpySegement() 獲取段選擇器,在前面,我們已討論過該函數(shù)。參見 列表 4-15

標(biāo)簽: Windows系統(tǒng)
主站蜘蛛池模板: 道达尔润滑油-食品级润滑油-道达尔导热油-合成导热油,深圳道达尔代理商合-深圳浩方正大官网 | 船老大板材_浙江船老大全屋定制_船老大官网 | 集装箱展厅-住人集装箱住宿|建筑|房屋|集装箱售楼处-山东锐嘉科技工程有限公司 | 成都热收缩包装机_袖口式膜包机_高速塑封机价格_全自动封切机器_大型套膜机厂家 | 新中天检测有限公司青岛分公司-山东|菏泽|济南|潍坊|泰安防雷检测验收 | 大鼠骨髓内皮祖细胞-小鼠神经元-无锡欣润生物科技有限公司 | 企业彩铃制作_移动、联通、电信集团彩铃上传开通_彩铃定制_商务彩铃管理平台-集团彩铃网 | 碳纤维复合材料制品生产定制工厂订制厂家-凯夫拉凯芙拉碳纤维手机壳套-碳纤维雪茄盒外壳套-深圳市润大世纪新材料科技有限公司 | 电缆故障测试仪_电缆故障定位仪_探测仪_检测仪器_陕西意联电气厂家 | 食品无尘净化车间,食品罐装净化车间,净化车间配套风淋室-青岛旭恒洁净技术有限公司 | 冷油器-冷油器换管改造-连云港灵动列管式冷油器生产厂家 | 电动高尔夫球车|电动观光车|电动巡逻车|电动越野车厂家-绿友机械集团股份有限公司 | 气胀轴|气涨轴|安全夹头|安全卡盘|伺服纠偏系统厂家-天机传动 | 右手官网|右手工业设计|外观设计公司|工业设计公司|产品创新设计|医疗产品结构设计|EMC产品结构设计 | 深圳快餐店设计-餐饮设计公司-餐饮空间品牌全案设计-深圳市勤蜂装饰工程 | 老城街小面官网_正宗重庆小面加盟技术培训_特色面馆加盟|牛肉拉面|招商加盟代理费用多少钱 | 气密性检测仪_气密性检测设备_防水测试仪_密封测试仪-岳信仪器 | Akribis直线电机_直线模组_力矩电机_直线电机平台|雅科贝思Akribis-杭州摩森机电科技有限公司 | 精密模具制造,注塑加工,吹塑和吹瓶加工,EPS泡沫包装生产 - 济南兴田塑胶有限公司 | 全钢实验台,实验室工作台厂家-无锡市辰之航装饰材料有限公司 | 压力喷雾干燥机,喷雾干燥设备,柱塞隔膜泵-无锡市闻华干燥设备有限公司 | 定制/定做冲锋衣厂家/公司-订做/订制冲锋衣价格/费用-北京圣达信 | 冰晶石|碱性嫩黄闪蒸干燥机-有机垃圾烘干设备-草酸钙盘式干燥机-常州市宝康干燥 | 天然气分析仪-液化气二甲醚分析仪|传昊仪器 | 无缝钢管-聊城无缝钢管-小口径无缝钢管-大口径无缝钢管 - 聊城宽达钢管有限公司 | 等离子表面处理机-等离子表面活化机-真空等离子清洗机-深圳市东信高科自动化设备有限公司 | 洛阳永磁工业大吊扇研发生产-工厂通风降温解决方案提供商-中实洛阳环境科技有限公司 | 木材烘干机,木炭烘干机,纸管/佛香烘干设备-河南蓝天机械制造有限公司 | 冷库安装厂家_杭州冷库_保鲜库建设-浙江克冷制冷设备有限公司 | 盘装氧量分析仪-防爆壁挂氧化锆分析仪-安徽吉帆仪表有限公司 | PCB厂|线路板厂|深圳线路板厂|软硬结合板厂|电路板生产厂家|线路板|深圳电路板厂家|铝基板厂家|深联电路-专业生产PCB研发制造 | 帽子厂家_帽子工厂_帽子定做_义乌帽厂_帽厂_制帽厂_帽子厂_浙江高普制帽厂 | 高压微雾加湿器_工业加湿器_温室喷雾-昌润空气净化设备 | 光照全温振荡器(智能型)-恒隆仪器 | 上海噪音治理公司-专业隔音降噪公司-中广通环保 | 切铝机-数控切割机-型材切割机-铝型材切割机-【昆山邓氏精密机械有限公司】 | 骁龙云呼电销防封号系统-axb电销平台-外呼稳定『免费试用』 | 环境模拟实验室_液体-气体控温机_气体控温箱_无锡双润冷却科技有限公司 | 浇钢砖,流钢砖_厂家价低-淄博恒森耐火材料有限公司 | 网架支座@球铰支座@钢结构支座@成品支座厂家@万向滑动支座_桥兴工程橡胶有限公司 | 灰板纸、灰底白、硬纸板等纸品生产商-金泊纸业 |