ZwQuerySystemInformation枚舉內核模塊及簡單應用

 

簡單說,即調用第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信息等等,以後再玩~

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

1.接口說明

NTKERNELAPI NTSTATUS ZwQuerySystemInformation(
  IN ULONG SystemInformationClass,
  IN OUT PVOID SystemInformation,
  IN ULONG SystemInformationLength,
  IN PULONG ReturnLength OPTIONAL );
第一個參數是一個枚舉類型,傳入的是你需要查詢的信息的類型以下是這個enmu類型的定義。
typedef enum _SYSTEM_INFORMATION_CLASS {
 SystemBasicInformation, // 0 Y N
 SystemProcessorInformation, // 1 Y N
 SystemPerformanceInformation, // 2 Y N
 SystemTimeOfDayInformation, // 3 Y N
 SystemNotImplemented1, // 4 Y N
 SystemProcessesAndThreadsInformation, // 5 Y N
 SystemCallCounts, // 6 Y N
 SystemConfigurationInformation, // 7 Y N
 SystemProcessorTimes, // 8 Y N
 SystemGlobalFlag, // 9 Y Y
 SystemNotImplemented2, // 10 Y N
 SystemModuleInformation, // 11 Y N    枚舉內核模塊時用
 SystemLockInformation, // 12 Y N
 SystemNotImplemented3, // 13 Y N
 SystemNotImplemented4, // 14 Y N
 SystemNotImplemented5, // 15 Y N
 SystemHandleInformation, // 16 Y N
 SystemObjectInformation, // 17 Y N
 SystemPagefileInformation, // 18 Y N
 SystemInstructionEmulationCounts, // 19 Y N
 SystemInvalidInfoClass1, // 20
 SystemCacheInformation, // 21 Y Y
 SystemPoolTagInformation, // 22 Y N
 SystemProcessorStatistics, // 23 Y N
 SystemDpcInformation, // 24 Y Y
 SystemNotImplemented6, // 25 Y N
 SystemLoadImage, // 26 N Y
 SystemUnloadImage, // 27 N Y
 SystemTimeAdjustment, // 28 Y Y
 SystemNotImplemented7, // 29 Y N
 SystemNotImplemented8, // 30 Y N
 SystemNotImplemented9, // 31 Y N
 SystemCrashDumpInformation, // 32 Y N
 SystemExceptionInformation, // 33 Y N
 SystemCrashDumpStateInformation, // 34 Y Y/N
 SystemKernelDebuggerInformation, // 35 Y N
 SystemContextSwitchInformation, // 36 Y N
 SystemRegistryQuotaInformation, // 37 Y Y
 SystemLoadAndCallImage, // 38 N Y
 SystemPrioritySeparation, // 39 N Y
 SystemNotImplemented10, // 40 Y N
 SystemNotImplemented11, // 41 Y N
 SystemInvalidInfoClass2, // 42
 SystemInvalidInfoClass3, // 43
 SystemTimeZoneInformation, // 44 Y N
 SystemLookasideInformation, // 45 Y N
 SystemSetTimeSlipEvent, // 46 N Y
 SystemCreateSession, // 47 N Y
 SystemDeleteSession, // 48 N Y
 SystemInvalidInfoClass4, // 49
 SystemRangeStartInformation, // 50 Y N
 SystemVerifierInformation, // 51 Y Y
 SystemAddVerifier, // 52 N Y
 SystemSessionProcessesInformation // 53 Y N
}SYSTEM_INFORMATION_CLASS;

2.調用方式:
(1).功能號爲11,先獲取所需的緩衝區大小

(1).功能號爲11,先獲取所需的緩衝區大小
ZwQuerySystemInformation(SystemModuleInformation,NULL,0,&needlen);
(2).申請內存
Ring3層 ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,0,&needlen,MEM_COMMIT,PAGE_READWRITE);
Ring0層 ExAllocatePool( NonPagedPool, NeedSize );
(3).再次調用
ZwQuerySystemInformation(SystemModuleInformation,(PVOID)pBuf,truelen,&needlen);
......
(4).最後,釋放內存
Ring3層 ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,&needlen,MEM_RELEASE);
Ring0層 ExFreePool(pBuffer);
3.返回數據:
緩衝區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;

4.基於pBuf的幾個函數封裝:
//函數功能:輸出所有模塊信息
//參數pBuf:ZwQuerySystemInformation返回的緩衝區首址
void ShowAllModules(char *pBuf)
{
 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++)
 {
    DbgPrint("%d/t0x%08X 0x%08X %s/n",pSysModuleInfo->LoadOrderIndex,pSysModuleInfo->Base,pSysModuleInfo->Size,pSysModuleInfo->ImageName);
    pSysModuleInfo++;
 }
}

//函數功能:返回系統內核(ntoskrnl.exe或ntkrnlpa.exe)的基址和路徑
//參數pBuf:ZwQuerySystemInformation返回的緩衝區首址
//參數KernelBase:接收返回的系統內核的基址
//參數szKrnlPath:接收返回的內核文件的路徑
void GetOSKrnlInfo(char *pBuf,DWORD *KernelBase,char *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,'//'));
 }
}

//函數功能:找出給定地址所在的模塊
//參數pBuf:緩衝區地址,同上
//參數dwAddress:要查詢的內核地址
//參數ModulePath:接收返回的模塊路徑
void DetectModule(char *pBuf,DWORD dwAddress,char *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++;
 }
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章