内核对象和句柄
內核對象的數據結構只能由操作系統的內核訪問,所以應用程序不能再內存中定位這些數據結構并直接修改其內容。
可以利用windows的api函數進行操作。當調用一個會創建內核對象的函數后,會返回一個句柄,它標識了所創建的對象。
這些句柄值是與進程相關的,如果傳遞給其他進程,可能會失敗,因為每個進程會有一個句柄表,所以使用的時候可能是完全不用的內核對象。
內核對象的所有者是操作系統,當進程創建一個內核對象,然后進程終止,則內核對象并不一定銷毀。
大多數情況下,這內核對象是會銷毀的,但是假如另外一個進程也在使用我們進程創建的內核對象,那么在其他進程使用完他之前,他是不會銷毀的。
操作系統內核知道有多少進程正在使用一個特定的內核對象,因為每個對象都包含了一個使用計數!,只有當使用計數為0,操作系統才會銷毀這內核對象。
用于插件內核對象的所有函數基本都有一個指向SECURITY_ATTRIBUTES結構的指針作為參數,一般都是傳入NULL,這樣創建的內核對象具有默認的安全性,要取決于當前進程的安全令牌。
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength; / /結構體的大小,可用SIZEOF取得
LPVOID lpSecurityDescriptor; / /安全描述符
BOOL bInheritHandle ;/ /安全描述的對象能否被新創建的進程繼承
} SECURITY_ATTRIBUTES,* PSECURITY_ATTRIBUTES; 一個進程在初始化時,系統將會為他分配一個句柄表,這句柄表供內核對象使用,不適用于用戶對象和GDI對象。 用于插件內核對象的函數都會返回一個與進程相關的句柄,系統用所以來表示內核對象的信息保存在進程句柄表中的具體位置。 無論以什么方式創建內核對象,我們都需要調用closehandle來關閉內核對象。這時候會通過句柄值找到內核對象的數據結構的地址,減少結構中的使用計數,如果使用計數為0,則銷毀內核對象。 跨進程邊界共享內核對象 三種方法 使用對象句柄繼承:只有在一個父子關系的時候才可以使用,當父進程創建一個內核對象,父進程必須向系統指出它希望這對象的句柄是可以繼承的。 為了插件一個可繼承的句柄,父進程必須分配并初始化一個SECURITY_ATTRIBUTES,將bInheritHandle設置為true,這時候創建出來的對象在句柄表中的標志就是可繼承的。 下一步是父進程生成子進程, BOOL CreateProcess
(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATIONlpProcessInformation
); 其中的bInheritHandles設置為true,這樣子進程就會繼承父進程的可繼承的句柄的值。系統會遍歷父進程的句柄表,對他的每個記錄項進行檢查,凡是包含一個有效的可繼承的標識,,都會被完整的復制到子進程的句柄表。除了復制句柄表的記錄項,系統還會遞增內核對象的使用計數。對于32bit系統,內核地址在0x80000000到0xffffffff,對于64bit的系統則是0x000004000 00000000 到0xffffffff ffffffff。 改變句柄的標志 BOOL WINAPI SetHandleInformation(
_In_ HANDLE hObject,
_In_ DWORD dwMask,
_In_ DWORD dwFlags
); 第一個參數hObject標識了一個有效句柄。 第二個參數dwMask告訴函數我們想更改哪個或者哪些標志: 1\ HANDLE_FLAG_INHERIT 用CreateProcess(bInheritHandle設為TRUE)創建出來的子進程可以繼承對象句柄 2\HANDLE_FLAG_PROTECT_FROM_CLOSE 無法調用CloseHandle關閉對象句柄 第三個參數dwFlags指出希望把標志設為什么。 跨進程共享內核對象的第二個方法就是為對象命名,不過不怎么推介。 第三種就是復制對象句柄,這應該是比較常見的。 BOOL WINAPI DuplicateHandle(
__in HANDLE hSourceProcessHandle,
__in HANDLE hSourceHandle,
__in HANDLE hTargetProcessHandle,
__out LPHANDLE lpTargetHandle,
__in DWORD dwDesiredAccess,
__in BOOL bInheritHandle,
__in DWORD dwOptions
); hSourceProcessHandle:源進程內核句柄(即負責傳遞內核對象句柄的進程句柄) hSourceHandle:要傳遞的內核對象句柄
hTargetProcessHandle:目標進程內核句柄 lpTargetHandle:接收內核對象句柄的地址 dwDesiredAccess:TargetHandle句柄使用何種訪問掩碼(這個掩碼是在句柄表中的一項) bInheritHandle:是否擁有繼承 dwOptions:當設DUPLICATE_SAME_ACCESS時,表示目標句柄擁有和源進程的句柄一樣的訪問掩碼,如果設置次參數,會忽略dwDesiredAccess。 當設DUPLICATE_CLOSE_SOURCE時,傳輸完后,關閉源中的內核對象句柄。 //ALL of the following code is executed by Process S. //Createamutex object accessible by Process S. HANDLE hObjProcessS = CreateMutex(NULL, FALSE, NULL);//Open ahandle to Process T's kernel object. HANDLE hProcessT = OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessIdT);//Anuninitilized handle relative to Process T. HANDLE hObjProcessT;//GiveProcess T accesss to our mutex object DuplicateHandle(GetCurrentProcess(),hObjProcessS,hProcessT,&hObjProcessT, 0, FALSE,DUPLICATE_SAME_ACCESS);//Usesome IPC mechanism to get the handle //valuein hOnjProcess S into Process T //We nolonger need to communicate with Process T. CloseHandle(hProcessT);//WhenProcess S no longer needs to Use the mutex, //itshould close it. CloseHandle(hObjProcessS);
hTargetProcessHandle:目標進程內核句柄 lpTargetHandle:接收內核對象句柄的地址 dwDesiredAccess:TargetHandle句柄使用何種訪問掩碼(這個掩碼是在句柄表中的一項) bInheritHandle:是否擁有繼承 dwOptions:當設DUPLICATE_SAME_ACCESS時,表示目標句柄擁有和源進程的句柄一樣的訪問掩碼,如果設置次參數,會忽略dwDesiredAccess。 當設DUPLICATE_CLOSE_SOURCE時,傳輸完后,關閉源中的內核對象句柄。 //ALL of the following code is executed by Process S. //Createamutex object accessible by Process S. HANDLE hObjProcessS = CreateMutex(NULL, FALSE, NULL);//Open ahandle to Process T's kernel object. HANDLE hProcessT = OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessIdT);//Anuninitilized handle relative to Process T. HANDLE hObjProcessT;//GiveProcess T accesss to our mutex object DuplicateHandle(GetCurrentProcess(),hObjProcessS,hProcessT,&hObjProcessT, 0, FALSE,DUPLICATE_SAME_ACCESS);//Usesome IPC mechanism to get the handle //valuein hOnjProcess S into Process T //We nolonger need to communicate with Process T. CloseHandle(hProcessT);//WhenProcess S no longer needs to Use the mutex, //itshould close it. CloseHandle(hObjProcessS);
總結
- 上一篇: cmd mysql uroot p不是内
- 下一篇: 深入浅出 kvm qemu libvir