http://hi.baidu.com/_achillis/item/8b33ead8ccac28ea3cc2cb17
簡單說,即調用第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++;
}
}
該功能是通過遍歷PsLoadedModuleList實現的,所以要隱藏的話,最簡單的方法還是斷鏈~~
更高級的方法比如抹DriveObject,抹PE信息等等,以后再玩~