簡單說,即呼叫第11號功能,列舉一下核心中已載入的模組。
部分程式碼如下:
//功能號為11,先獲取所需的緩衝區大小
ZwQuerySystemInformation(SystemModuleInformation,NULL,0,&needlen);
//申請記憶體
ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,0,&needlen,MEM_COMMIT,PAGE_READWRITE);
//再次呼叫
ZwQuerySystemInformation(SystemModuleInformation,(PVOID)pBuf,truelen,&needlen);
......
//最後,釋放記憶體
ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,&needlen,MEM_RELEASE);
突出過程,省略了錯誤判斷,和呼叫其它的功能時操作並沒有什麼區別。
關鍵在返回的內容中,緩衝區pBuf的前四個位元組是已載入的模組總數,記為ModuleCnt,接下來就是共有ModuleCnt個元素的模組資訊陣列了。
該結構如下:
typedef struct _SYSTEM_MODULE_INFORMATION { ULONG Count; SYSTEM_MODULE_INFORMATION_ENTRY Module[1]; } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
模組詳細資訊結構如下:
typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY { HANDLE Section; PVOID MappedBase; PVOID Base; ULONG Size; ULONG Flags; USHORT LoadOrderIndex; USHORT InitOrderIndex; USHORT LoadCount; USHORT PathLength; CHAR ImageName[256]; } SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;
一個for迴圈,迴圈ModuleCnt次就OK了。
基於此,寫了三個簡單的函式。
void ShowAllModules(char *pBuf) { //函式功能:輸出所有模組資訊 //引數pBuf:ZwQuerySystemInformation返回的緩衝區首址 PSYSTEM_MODULE_INFORMATION_ENTRY pSysModuleInfo; DWORD Modcnt=0; Modcnt=*(DWORD*)pBuf; pSysModuleInfo=(PSYSTEM_MODULE_INFORMATION_ENTRY)(pBuf+sizeof(DWORD)); for (DWORD i=0;i<Modcnt;i++) { printf("%d\t0x%08X 0x%08X %s\n",pSysModuleInfo->LoadOrderIndex,pSysModuleInfo->Base,pSysModuleInfo->Size,pSysModuleInfo->ImageName); pSysModuleInfo++; } } void GetOSKrnlInfo(char *pBuf,DWORD *KernelBase,char *szKrnlPath) { //函式功能:返回系統核心(ntoskrnl.exe或ntkrnlpa.exe)的基址和路徑 //引數pBuf:ZwQuerySystemInformation返回的緩衝區首址 //引數KernelBase:接收返回的系統核心的基址 //引數szKrnlPath:接收返回的核心檔案的路徑 PSYSTEM_MODULE_INFORMATION_ENTRY pSysModuleInfo; DWORD Modcnt=0; *KernelBase=0; Modcnt=*(DWORD*)pBuf; pSysModuleInfo=(PSYSTEM_MODULE_INFORMATION_ENTRY)(pBuf+sizeof(DWORD)); //其實第一個模組就是了,還是驗證一下吧 if (strstr((strlwr(pSysModuleInfo->ImageName),pSysModuleInfo->ImageName),"nt")) { *KernelBase=(DWORD)pSysModuleInfo->Base; GetSystemDirectory(szKrnlPath,MAX_PATH); lstrcat(szKrnlPath,strrchr(pSysModuleInfo->ImageName,'\\')); } } void DetectModule(char *pBuf,DWORD dwAddress,char *ModulePath) { //函式功能:找出給定地址所在的模組 //引數pBuf:緩衝區地址,同上 //引數dwAddress:要查詢的核心地址 //引數ModulePath:接收返回的模組路徑 PSYSTEM_MODULE_INFORMATION_ENTRY pSysModuleInfo; DWORD Modcnt=0; Modcnt=*(DWORD*)pBuf; pSysModuleInfo=(PSYSTEM_MODULE_INFORMATION_ENTRY)(pBuf+sizeof(DWORD)); for (DWORD i=0;i<Modcnt;i++) { if ((dwAddress>=(DWORD)pSysModuleInfo->Base)&&(dwAddress<(DWORD)pSysModuleInfo->Base+pSysModuleInfo->Size)) { lstrcpy(ModulePath,pSysModuleInfo->ImageName); } pSysModuleInfo++; }