2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

淺析本機(jī)API

 一葉扁舟 2006-12-23
此文只能說(shuō)是一篇筆記,是關(guān)于本機(jī)API的.本機(jī)API是除了Win32 API,NT平臺(tái)開(kāi)放了另一個(gè)基本接口。本

機(jī)API也被很多人所熟悉,因?yàn)閮?nèi)核模式模塊位于更低的系統(tǒng)級(jí)別,在那個(gè)級(jí)別上環(huán)境子系統(tǒng)是不可見(jiàn)的

。盡管如此,并不需要驅(qū)動(dòng)級(jí)別去訪問(wèn)這個(gè)接口,普通的Win32程序可以在任何時(shí)候向下調(diào)用本機(jī)API。并

沒(méi)有任何技術(shù)上的限制,只不過(guò)微軟不支持這種應(yīng)用開(kāi)發(fā)方法。
  

User32.dll,kernel32.dll,shell32.dll,gdi32.dll,rpcrt4.dll,comctl32.dll,advapi32.dll,version.d

ll等dll代表了Win32 API的基本提供者。Win32 API中的所有調(diào)用最終都轉(zhuǎn)向了ntdll.dll,再由它轉(zhuǎn)發(fā)至

ntoskrnl.exe。ntdll.dll是本機(jī) API用戶模式的終端。真正的接口在ntoskrnl.exe里完成。事實(shí)上,內(nèi)

核模式的驅(qū)動(dòng)大部分時(shí)間調(diào)用這個(gè)模塊,如果它們請(qǐng)求系統(tǒng)服務(wù)。Ntdll.dll的主要作用就是讓內(nèi)核函數(shù)

的特定子集可以被用戶模式下運(yùn)行的程序調(diào)用。Ntdll.dll通過(guò)軟件中斷int 2Eh進(jìn)入ntoskrnl.exe,就是

通過(guò)中斷門切換CPU特權(quán)級(jí)。比如kernel32.dll導(dǎo)出的函數(shù)DeviceIoControl()實(shí)際上調(diào)用ntdll.dll中導(dǎo)

出的NtDeviceIoControlFile(),反匯編一下這個(gè)函數(shù)可以看到,EAX載入magic數(shù)0x38,實(shí)際上是系統(tǒng)調(diào)

用號(hào),然后EDX指向堆棧。目標(biāo)地址是當(dāng)前堆棧指針ESP+4,所以EDX指向返回地址后面一個(gè),也就是指向

在進(jìn)入NtDeviceIoControlFile()之前存入堆棧的東西。事實(shí)上就是函數(shù)的參數(shù)。下一個(gè)指令是int 2Eh,

轉(zhuǎn)到中斷描述符表IDT位置0x2E處的中斷處理程序。

反編匯這個(gè)函數(shù)得到:

mov eax, 38h

lea edx, [esp+4]

int 2Eh

ret 28h

當(dāng)然int 2E接口不僅僅是簡(jiǎn)單的API調(diào)用調(diào)度員,他是從用戶模式進(jìn)入內(nèi)核模式的main gate。

W2k Native API由248個(gè)這么處理的函數(shù)組成,比NT 4.0多了37個(gè)??梢詮膎tdll.dll的導(dǎo)出列表中很容易

認(rèn)出來(lái):前綴Nt。Ntdll.dll中導(dǎo)出了249個(gè),原因在于NtCurrentTeb()為一個(gè)純用戶模式函數(shù),所以不需

要傳給內(nèi)核。令人驚奇的是,僅僅Native API的一個(gè)子集能夠從內(nèi)核模式調(diào)用。而另一方面,

ntoskrnl.exe導(dǎo)出了兩個(gè)Nt*符號(hào),它們不存在于ntdll.dll中: NtBuildNumber, NtGlobalFlag。它們不

指向函數(shù),事實(shí)上,是指向ntoskrnl.exe的變量,可以被使用C編譯器extern關(guān)鍵字的驅(qū)動(dòng)模塊導(dǎo)入。

Ntdll.dll和ntoskrnl.exe中都有兩種前綴Nt*,Zw*。事實(shí)上ntdll.dll中反匯編結(jié)果兩者是一樣的。而在

ntoskrnl.exe中,nt前綴指向真正的代碼,而zw還是一個(gè)int 2Eh的stub。也就是說(shuō)zw*函數(shù)集通過(guò)用戶模

式到內(nèi)核模式門傳遞的,而Nt*符號(hào)直接指向模式切換以后的代碼。Ntdll.dll中的NtCurrentTeb()沒(méi)有相

對(duì)應(yīng)的zw函數(shù)。Ntoskrnl并不導(dǎo)出配對(duì)的Nt/zw函數(shù)。有些函數(shù)只以一種方式出現(xiàn)。

2Eh中斷處理程序把EAX里的值作為查找表中的索引,去找到最終的目標(biāo)函數(shù)。這個(gè)表就是系統(tǒng)服務(wù)表SST

,C的結(jié)構(gòu)SYSTEM_SERVICE_TABLE的定義如下:清單也包含了結(jié)構(gòu)SERVICE_DESCRIPTOR_TABLE中的定義,為

SST數(shù)組第四個(gè)成員,前兩個(gè)有著特別的用途。

typedef NTSTATUS (NTAPI *NTPROC) ( ) ;

typedef NTPROC *PNTPROC;

#define NTPROC_ sizeof (NTPROC)

typedef struct _SYSTEM_SERVICE_TABLE

{ PNTPROC ServiceTable; // 這里是入口指針數(shù)組

PDWORD CounterTable; // 此處是調(diào)用次數(shù)計(jì)數(shù)數(shù)組

DWORD ServiceLimit ; // 服務(wù)入口的個(gè)數(shù)

PBYTE ArgumentTable; // 服務(wù)參數(shù)字節(jié)數(shù)的數(shù)組

) SYSTEM_SERVICE_TABLE ,

* PSYSTEM_SERVICE_TABLE ,

* * PPSYSTEM_SERVICE_TABLE ;

/ / _ _ _ _ _ _ _ _ _ _ _ _

typedef struct _SERVICE_DESCRIPTOR_TABLE

{ SYSTEM_SERVICE_TABLE ntoskrnl ; // ntoskrnl所實(shí)現(xiàn)的系統(tǒng)服務(wù),本機(jī)的API}

SYSTEM_SERVICE_TABLE win32k; // win32k所實(shí)現(xiàn)的系統(tǒng)服務(wù)

SYSTEM_SERVICE_TABLE Table3; // 未使用

SYSTEM_SERVICE_TABLE Table4; // 未使用

} SERVICE_DESCRIPTOR_TABLE ,

* PSERVICE_DESCRIPTOR_TABLE,

* PPSERVICE_DESCRIPTOR_TABLE ;

ntoskrnl通過(guò)KeServiceDescriptorTable符號(hào),導(dǎo)出了主要SDT的一個(gè)指針。內(nèi)核維護(hù)另外的一個(gè)SDT,就

是KeServiceDescriptorTableShadow。但這個(gè)符號(hào)沒(méi)有導(dǎo)出。要想在內(nèi)核模式組件中存取主要SDT很簡(jiǎn)單

,只需兩行C語(yǔ)言的代碼:

extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;

PSERVICE_DESCRIPTOR_TABLE psdt= KeServiceDescriptorTable;

NTPROC為本機(jī) API的方便的占位符,他類似于Win32編程中的PROC。Native API正常的返回應(yīng)該是一個(gè)

NTSTATUS代碼,他使用NTAPI調(diào)用約定,它和_stdcall一樣。ServiceLimit成員有在ServiceTable數(shù)組里

找到的入口數(shù)目。在2000下,默認(rèn)值是248。ArgumentTable為BYTEs的數(shù)組,每一個(gè)對(duì)應(yīng)于ServiceTable

的位置并顯示了在調(diào)用者堆棧里的參數(shù)比特?cái)?shù)。這個(gè)信息與EDX結(jié)合,這是內(nèi)核從調(diào)用者堆棧copy參數(shù)到

自己的堆棧所需的。CounterTable成員在free buid的2000中并沒(méi)有使用到,在debug build中,這個(gè)成員

指向代表所有函數(shù)使用計(jì)數(shù)的DWORDS數(shù)組,這個(gè)信息能用于性能分析。
  可以使用這個(gè)命令來(lái)顯示:dd KeServiceDescriptorTable,調(diào)試器把此符號(hào)解析為0x8046e0c0。只有

前四行是最重要的,對(duì)應(yīng)那四個(gè)SDT成員。
  運(yùn)行這個(gè)命令:ln 8046e100,顯示符號(hào)是KeServiceDescriptorTableShadow,說(shuō)明第五個(gè)開(kāi)始確實(shí)為

內(nèi)核維護(hù)的第二個(gè)SDT。主要的區(qū)別在于后一個(gè)包含了win32k.sys的入口,前一個(gè)卻沒(méi)有。在這兩個(gè)表中

,Table3與Table4都是空的。Ntoskrnl.exe提供了一個(gè)方便的API函數(shù)。這個(gè)函數(shù)的名字為:

  KeAddSystemServiceTable
此函數(shù)去填充這些位置。

2Eh的中斷處理標(biāo)記是KisystemService()。這也是ntoskrnl.exe沒(méi)有導(dǎo)出的內(nèi)部的符號(hào),但包含在2k符號(hào)

文件中。關(guān)于KisystemService的操作如下:

1 從當(dāng)前的線程控制塊檢索SDT指針

2 決定使用SDT中4個(gè)SST的其中一個(gè)。通過(guò)測(cè)試EAX中遞送ID的第12和13位來(lái)決定。ID在0x0000-0x0fff的

映射至ntoskrnl表格,ID在

0x1000與0x1ffff的分配給win32k表格。剩下的0x2000-0x2ffff與

0x3000-0x3ffff則是Table3和Table4保留。

3 通過(guò)選定SST中的ServiceLimit成員檢查EAX的0-11位。如果ID超過(guò)了范圍,返回錯(cuò)誤代碼為

STATUS_INVALID_SYSTEM_SERVICE。

4 檢查EAX中的參數(shù)堆棧指針與MmUserProbeAddress。這是一個(gè)ntoskrnl導(dǎo)出的全局變量。通常等于

0x7FFF0000,如果參數(shù)指針不在這個(gè)地址之下,返回STATUS_ACCESS_VIOLATION。

5 查找ArgumentTable中的參數(shù)堆棧的字節(jié)數(shù),從調(diào)用者的堆棧copy所有的參數(shù)至當(dāng)前內(nèi)核模式堆棧。

6 搜索serviceTable中的服務(wù)函數(shù)指針,并調(diào)用這個(gè)函數(shù)。

7 控制轉(zhuǎn)到內(nèi)部的函數(shù)KiserviceExit,在此次服務(wù)調(diào)用返回之后。

從對(duì)SDT的討論可以看到與本機(jī)API一起還有第二個(gè)內(nèi)核模式接口。這個(gè)接口把Win32子系統(tǒng)的圖形設(shè)備接

口和窗口管理器和內(nèi)核模式組件Win32k連接起來(lái)。Win32k接口一樣是基于int 2eh。本機(jī)API的服務(wù)號(hào)是從

0x0000到0x0fff,win32k的服務(wù)號(hào)是從0x1000到0x1fff。(ddW32pServiceTable認(rèn)定win32k.sys的符號(hào)可

用。)win32k總共包含639個(gè)系統(tǒng)服務(wù)。


2Eh的處理過(guò)程沒(méi)有使用全局SDT KeServiceDescriptorTable。

而是一個(gè)與線程相關(guān)的指針。顯然,線程可以有不同得SDT相關(guān)到自身。線程初試化的時(shí)

候,KeInitializeThread()把KeServiceDescriptorTable寫到線程的控制塊。盡管這樣,這個(gè)默認(rèn)設(shè)置之

后可能被改變?yōu)槠渌担鏚eServiceDescriptorTableShadow。


Windows 2000運(yùn)行時(shí)庫(kù)

Ntdll.dll至少導(dǎo)出了不少于1179個(gè)符號(hào)。其中的249/248是屬于Nt*/zw*集合。所以還有682個(gè)函數(shù)不是通

過(guò)int 2eh門中轉(zhuǎn)。很顯然,這么多的函數(shù)不依靠2k的內(nèi)核。

其中一些是和c運(yùn)行時(shí)庫(kù)幾乎一樣的函數(shù)。其實(shí)ntoskrnl也實(shí)現(xiàn)了一些類似C運(yùn)行時(shí)庫(kù)的一些函數(shù)??梢?br>
通過(guò)ddk里的ntdll.lib來(lái)鏈接和使用這些函數(shù)。反匯編ntdll.dll與ntoskrnl.exe的C運(yùn)行時(shí)函數(shù)能發(fā)現(xiàn)

,ntdll.dll并不是依賴ntoskrnl.exe。這兩個(gè)模塊各自實(shí)現(xiàn)了這些函數(shù)。

除了C運(yùn)行時(shí)庫(kù)外,2000還提供了一個(gè)擴(kuò)展的運(yùn)行時(shí)函數(shù)集合。再一次,ntdll.dll與ntoskrnl.exe各自

實(shí)現(xiàn)了它們。同樣,實(shí)現(xiàn)集合有重復(fù),但是并不完全匹配。這個(gè)集合的函數(shù)都是以Rtl開(kāi)頭的。2000運(yùn)行

時(shí)庫(kù)包括一些輔助函數(shù)用于C運(yùn)行時(shí)候無(wú)法完成的任務(wù)。例如有些處理安全事務(wù),另外的操縱2000專用的

數(shù)據(jù)結(jié)構(gòu),還有些支持內(nèi)存管理。微軟僅僅在DDK中記錄了很有用的406個(gè)函數(shù)中的115個(gè)函數(shù)。

Ntdll.dll還提供了另外一個(gè)函數(shù)集合,以__e前綴開(kāi)頭。實(shí)際上它們用于浮點(diǎn)數(shù)模擬器。

還有很多的函數(shù)集合,所有這些函數(shù)的前綴如下:

__e(浮點(diǎn)模擬),Cc(Cache管理),Csr(c/s運(yùn)行時(shí)庫(kù)),Dbg(調(diào)試支持),Ex(執(zhí)行支持),FsRtl(文件系統(tǒng)運(yùn)行

時(shí)),Hal(硬件抽象層),Inbv(系統(tǒng)初試化/vga啟動(dòng)驅(qū)動(dòng)程序bootvid.dll),Init(系統(tǒng)初試



化),Interlocked(線程安全變量操作),Io(IO管理器),Kd(內(nèi)核調(diào)試器支持),Ke(內(nèi)核例程),Ki(內(nèi)核中斷處

理),Ldr(映象裝載器),Lpc(本地過(guò)程調(diào)用),Lsa(本地安全授權(quán)),Mm(內(nèi)存管理),Nls(國(guó)際化語(yǔ)言支持),Nt

(NT本機(jī)API),Ob(對(duì)象管理器),Pfx(前綴處理),Po(電源管理),Ps(進(jìn)程支持),READ_REGISTER_(從寄存器

地址讀),Rtl(2k運(yùn)行時(shí)庫(kù)),Se(安全處理),WRITE_REGISTER_(寫寄存器地址),Zw(本機(jī)API的替換叫法)

,<其它>(輔助函數(shù)和C運(yùn)行時(shí)庫(kù))。

當(dāng)編寫從用戶模式通過(guò)ntdll.dll或內(nèi)核模式通過(guò)ntoskrnl.exe和2000內(nèi)核交互的軟件的時(shí)候,需要處理

很多基本的數(shù)據(jù)結(jié)構(gòu),這些結(jié)構(gòu)在Win32世界中很少見(jiàn)到。

常用數(shù)據(jù)結(jié)構(gòu)

l   整數(shù)

ANSI字符是有符號(hào)的,而Unicode WCHAR是無(wú)符號(hào)的

MASM的TBYTE是80位的浮點(diǎn)數(shù),用于高精度浮點(diǎn)運(yùn)算單元操作,注意它與Win32的TBYTE(text byte)完全

不同。

TABLE 2-3. Equivalent Integral Data Types

BITS   MASM   FUNDAMENTAL   ALIAS #1   ALIAS #2 SIGNED

8     BYTE   unsigned char UCHAR           CHAR
16     WORD   unsigned short USHORT   WCHAR     SHORT

32     DWORD   unsigned long ULONG           LONG

32     DWORD   unsigned int   UINT           INT

64     QWORD   unsigned _int64 ULONGLONG DWORDLONG LONGLONG

80     TBYTE   N/A

typedef union _LARGE_INTEGER

{ struct{

ULONG LowPart;

LONG HighPart;};

LONGLONG QuadPart;

}

LARGE_INTEGER , * PULARGE_INTEGER ;

typedef union _ULARGE_INTEGER{

struct{

ULONG LowPart;

ULONG HighPart;}

ULONGLONG QuadPart;

}ULARGE_INTEGER, *PULARGE_INTEGER;

l   字符

  Win32編程中PSTR用戶CHAR*,PWSTR用于WCHAR*。取決于是否定義了UNICODE,PTSTR解釋為PSTR或者

PWSTR。在2k內(nèi)核模式下,常用的數(shù)據(jù)類型是UNICODE_STRING,而STRING用來(lái)表示ANSI字符串:

typedef struct _UNICODE_STRING{

USHORT Length; //當(dāng)前字節(jié)長(zhǎng)度,不是字符?。?!

USHORT MaximumLength; //Buffer的最大字節(jié)長(zhǎng)度

PWSTR Buffer;}UNICODE_STRING , * PUNICODE_STRING ;

typedef struct _STRING{

USHORT Length;

USHORT MaximumLength;

PCHAR Buffer;}STRING, *PSTRING;

typedef STRING ANSI_STRING, *PANSI_STRING;

typedef STRING OEM_STRING, *POEM_STRING;

操縱函數(shù):RtlCreatUnicodeString(),RtlInitUnicodeString(),

RtlCopyUnicodeString()等等

l   結(jié)構(gòu)

許多內(nèi)核API函數(shù)需要一個(gè)固定大小的OBJECT_ATTRIBUTES結(jié)構(gòu),比如NtOpenFile()。對(duì)象的屬性是OBJ_*

值的組合,可以從ntdef.h中查到。

IO_STATUS_BLOCK結(jié)構(gòu)提供了所請(qǐng)求操作結(jié)果的信息,很簡(jiǎn)單,status成員包含一個(gè)NTSTATUS代碼, 如果

操作成功 information成員提供特定請(qǐng)求的信息。

還有一個(gè)結(jié)構(gòu)是LIST_ENTRY,這是一個(gè)雙向環(huán)鏈表。

typedef struct _OBJECT_ATTRIBUTES

{

ULONG Length;

HANDLE RootDirectory;

PUNICODE_STRING ObjectName;

ULONG Attributes;

PVOID SecurityDescriptor;

PVOID SecurityQualityOfService;

} OBJECT_ATTRIBDTES, *POBJECT_ ATTRIBUTES;

typedef struct _IO_STATUS_BLOCK

{

NTSTATDS Status;

ULONG Information;

}IO_STATUS_BLOCK , * PIO_STATUS_BLOCK ;

typedef struct _LIST_ENTRY

{

Struct _LIST_ENTRY *Flink;

Struct _LIST_ENTRY *Blink;

}LIST_ENTRY, *PLIST_ENTRY;

雙向鏈表的典型例子就是進(jìn)程和線程鏈。內(nèi)部變量PsActiveProcessHead是一個(gè)LIST_ENTRY結(jié)構(gòu),在

ntoskrnl.exe的數(shù)據(jù)段中,指定了系統(tǒng)進(jìn)程列表的第一個(gè)成員。

CLIENT_ID結(jié)構(gòu)由進(jìn)程和線程ID組成。

typedef struct _CLIENT_ID

{ HANDLE UniqueProcess;

HANDLE UniqueThread;

)CLIENT_ID, *PCLIENT_ID;

想要從用戶模式調(diào)用ntdll.dll中的API函數(shù),必須考慮到以下四點(diǎn):

1 SDK頭文件沒(méi)有包括這些函數(shù)的原型

2 這些函數(shù)使用的若干基本數(shù)據(jù)類型沒(méi)有包括在SDK文件中

3 SDK和DDK頭文件不兼容,不能在win32的c源文件包含ntddk.h中

4 ntdll.lib沒(méi)有包括在VC的默認(rèn)導(dǎo)入庫(kù)列表中。

第4個(gè)很容易解決:#progma comment(linker,“/defaultlib:ntdll.lib”)

缺失的定義比較難解決,最簡(jiǎn)單的方法是寫一個(gè)自定義的頭文件,剛剛包含需要調(diào)用ntdll.dll中函數(shù)的

定義。幸運(yùn)的是,已經(jīng)在光盤的w2k_def.h文件中做了這個(gè)工作。因?yàn)檫@個(gè)頭文件將用于用戶模式和內(nèi)核

模式程序,所以必須在用戶模式代碼中,#include<w2k_def.h>之前#define _USER_MODE_,使得DDK中出

現(xiàn)而SDK中沒(méi)有的定義可用。


本文部分翻譯于一篇電子書<win api about>.也感謝朋友GameHunter這位英語(yǔ)極好的朋友幫忙.與Free的指導(dǎo)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多