標籤:windows驅動開發 windows核心 windows核心api 進程遍曆 系統模組遍曆
windows核心api就是ntoskrnl.exe匯出的函數。我們可以跟調用應用程式層的api一樣,調用核心api。不過核心api需要注意的是,如果函數匯出了,並且函數文檔化(也就是可以直接在msdn上搜尋到)。ExFreePool函數匯出,並且文檔化,那麼我們可以直接調用。匯出了未文檔化,那麼我們就要聲明。什麼叫文檔化和未文檔化呢?大家來看一個函數:
UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process);
文檔化:就是假設函數匯出了,並且在msdn上可以搜尋到。就是文檔化我們調用文檔化的函數就是直接調用。
未文檔化:就是假設函數已經匯出了,但是在msdn上沒有搜到,就是未文檔化函數我們要調用它,就得自己手動聲明。
核心編程就跟應用程式層一樣,都是api的調用,都是Hook,都是反Hook,一樣的編程思維。它們本質的區別只是在於一個先後順序,比如看圖-什麼叫本質的區別:順序掉
從ring3到SSDT層主體實現函數的調用順序:
OpenProcesss-->ntdll!ZwOpenProcess-->ntos!ZwOpenProcess-->ntos!NtOpenProcess-->後面。如果你以核心層和應用的角度去理解,那麼就是openprocess一直調用到NtOpenProcess還有後面。
範例程式碼:
KernelApiCode.c
#include <ntifs.h>#include <ntimage.h>//調用功能號#define SystemModuleInformation 11#define SystemProcessesAndThreadsInformation 5// 系統進程資訊結構體typedef struct _SYSTEM_PROCESSES{ULONG NextEntryDelta;ULONG ThreadCount;ULONG Reserved[6];LARGE_INTEGER CreateTime;LARGE_INTEGER UserTime;LARGE_INTEGER KernelTime;UNICODE_STRING ProcessName; //進程的名稱KPRIORITY BasePriority; ULONG ProcessId; //進程的PIDULONG InheritedFromProcessId;ULONG HandleCount;ULONG Reserved2[2];VM_COUNTERS VmCounters;IO_COUNTERS IoCounters;} _SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;// 系統模組資訊結構體節點typedef struct _SYSTEM_MODULE_INFORMATION {ULONG Reserved[2]; ULONG Base; //模組的基址ULONG Size; //模組的大小 ULONG Flags; USHORT Index; USHORT Unknown; USHORT LoadCount; USHORT ModuleNameOffset;CHAR ImageName[256]; //模組的名稱} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;//模組鏈結構typedef struct _tagSysModuleList{ULONG ulCount;SYSTEM_MODULE_INFORMATION smi[1];} MODULES, *PMODULES;//ZwQuerySystemInformation函數匯出了,但是未文檔化,所以要手動聲明NTSTATUS __stdcall ZwQuerySystemInformation(ULONG_PTR SystemInformationClass, //調用功能號PVOID SystemInformation, //資訊結構體ULONG SystemInformationLength, //資訊結構體的位元組長度PULONG ReturnLength //返回的實際長度);//在驅動層遍曆進程VOID EnumProcessList(){//聲明變數NTSTATUS status;ULONG NeededSize,i;PVOID pBuffer = NULL; //用來指向緩衝區PSYSTEM_PROCESSES pInfo = NULL; //指向SYSTEM_PROCESSES的指標__try{//擷取存放系統的進程和線程資訊的實際位元組長度status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation,NULL,0,&NeededSize);if (status != STATUS_INFO_LENGTH_MISMATCH){//長度不匹配 DbgPrint("!= STATUS_INFO_LENGTH_MISMATCH");return;}//根據擷取的NeededSize申請非分頁式記憶體pBuffer = ExAllocatePool(NonPagedPool, NeededSize);if (pBuffer != NULL){DbgPrint("NeededSize:%d\r\n", NeededSize);//使用5號功能來擷取系統的進程和線程的資訊status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, //SystemProcessesAndThreadsInformation = 5 pBuffer,NeededSize, NULL);//如果調用成功if (NT_SUCCESS(status)) {DbgPrint("ZwQuerySystemInformation() success\r\n");//指標類型轉換pInfo = (PSYSTEM_PROCESSES)pBuffer;while (TRUE){//PID=0,系統的if (pInfo->ProcessId == 0){DbgPrint("PID %5d System Idle Process\r\n", pInfo->ProcessId);}else{//列印進程的PID和進程的名稱DbgPrint("PID %5d %ws\r\n", pInfo->ProcessId, pInfo->ProcessName.Buffer);//這裡是unicode}//如果沒有下一個就結束if (pInfo->NextEntryDelta == 0){break;}//遍曆下一個pInfo = (PSYSTEM_PROCESSES)(((PUCHAR)pInfo) + pInfo->NextEntryDelta);}}}}//異常的處理 __except(EXCEPTION_EXECUTE_HANDLER){//輸出異常資訊codeDbgPrint("%08x\r\n", GetExceptionCode());}//釋放申請的非分頁式記憶體資源if (pBuffer != NULL){ExFreePool(pBuffer);pBuffer = NULL;}}//驅動層遍曆系統模組VOID GetKernelModuleInfo(){//變數的聲明NTSTATUS status;ULONG NeededSize, i;PVOID pBuffer = NULL; //用來指向緩衝區PMODULES pModuleList = NULL; //指向MODULES指標__try{//擷取存放系統模組資訊結構體的緩衝區的大小status = ZwQuerySystemInformation(SystemModuleInformation, NULL,0,&NeededSize);if (status != STATUS_INFO_LENGTH_MISMATCH){DbgPrint("!= STATUS_INFO_LENGTH_MISMATCH");return;}//根據NeededSize的大小,申請非分頁式記憶體的大小pBuffer = ExAllocatePool(NonPagedPool, NeededSize);if (pBuffer){//調用功能號11來擷取系統的模組的資訊status=ZwQuerySystemInformation(SystemModuleInformation, //SystemModuleInformation = 11pBuffer,NeededSize,NULL);if (NT_SUCCESS(status)){//指標類型轉換pModuleList = (PMODULES)pBuffer;//遍曆系統的模組的資訊for (i = 0; i< pModuleList->ulCount; i++){//列印系統模組的基址、模組的大小、模組的名稱DbgPrint("0x%08X:%d:%s\r\n", pModuleList->smi[i].Base, pModuleList->smi[i].Size, pModuleList->smi[i].ImageName);}}}}__except(EXCEPTION_EXECUTE_HANDLER){//列印異常的代碼DbgPrint("%08x\r\n", GetExceptionCode());}//釋放申請的非分頁式記憶體資源if (pBuffer){ExFreePool(pBuffer);pBuffer = NULL;}}/**建立註冊表*SafeKey註冊表的路徑*Reg_Type註冊表的索引值類型*ValueName註冊表的索引值的名稱*Value註冊表的索引值的值*/BOOLEAN Safe_CreateValueKey(PWCHAR SafeKey, ULONG_PTR Reg_Type, PWCHAR ValueName, PWCHAR Value){//聲明變數OBJECT_ATTRIBUTES objectAttributes;UNICODE_STRING RegUnicodeString, Unicode_ValueName;NTSTATUS ntStatus;HANDLE hRegister;ULONG_PTR ulValue_DWORD;ULONG_PTR ulResult = 0;BOOLEAN bRetOK = FALSE;//WCHAR字串轉UNICODE_STRING字串RtlInitUnicodeString(&Unicode_ValueName, ValueName); //索引值的名稱RtlInitUnicodeString(&RegUnicodeString, SafeKey); //註冊表的路徑//初始化objectAttributesInitializeObjectAttributes(&objectAttributes,&RegUnicodeString, //註冊表的路徑OBJ_CASE_INSENSITIVE, //對大小寫敏感 NULL, NULL );//開啟註冊表ntStatus = ZwCreateKey(&hRegister, //返回註冊表的控制代碼KEY_ALL_ACCESS, //註冊表的許可權&objectAttributes,0,NULL,REG_OPTION_NON_VOLATILE,&ulResult);if (NT_SUCCESS(ntStatus)){bRetOK = TRUE;//根據傳入參數Reg_Type來實現各種功能//調用ZwSetValueKey函數來設定註冊表的switch (Reg_Type){case REG_SZ:{ZwSetValueKey(hRegister,&Unicode_ValueName, //索引值的名稱0,Reg_Type, //索引值的類型Value, //索引值的值wcslen(Value)*2);DbgPrint("REG_SZ--註冊表建立成功!\n");break;}case REG_EXPAND_SZ:{ZwSetValueKey(hRegister,&Unicode_ValueName, //索引值的名稱0,Reg_Type, //索引值的類型Value, //索引值的值wcslen(Value)*2);DbgPrint("REG_EXPAND_SZ--註冊表建立成功!\n");break;}case REG_DWORD:{ulValue_DWORD = sizeof(REG_DWORD);ZwSetValueKey(hRegister,&Unicode_ValueName, //索引值的名稱0,Reg_Type, //索引值的類型&Value,sizeof(ulValue_DWORD) //索引值的值);DbgPrint("REG_DWORD--註冊表建立成功!\n");break;}}//關閉控制代碼ZwClose(hRegister);}return bRetOK;}//******************************************************************************************************************************//驅動卸載常式函數VOID DriverUnload(IN PDRIVER_OBJECT DriverObject){DbgPrint("卸載完成!\n");}//驅動入口函數DriverEntryNTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath){//設定驅動的卸載常式函數DriverObject->DriverUnload = DriverUnload;//遍曆系統的進程EnumProcessList();//遍曆系統的驅動模組GetKernelModuleInfo();//建立註冊表Safe_CreateValueKey(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\", REG_DWORD, L"Start", (PWCHAR)0x3);Safe_CreateValueKey(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\", REG_SZ, L"Start_String", L"Hi~ i am agp");return STATUS_SUCCESS;}
makefile檔案:
## DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source# file to this component. This file merely indirects to the real make file# that is shared by all the driver components of the Windows NT DDK#!INCLUDE $(NTMAKEENV)\makefile.def
sources檔案
TARGETNAME=KernelApiCodeTARGETPATH=objTARGETTYPE=DRIVER# Additional defines for the C/C++ preprocessorC_DEFINES=$(C_DEFINES)SOURCES=KernelApiCode.c drvversion.rc
參考資料:
AGP講課資料整理和學習
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
windows核心Api的學習