ZwQuerySystemInformation枚举内核模块及简单应用

来源:互联网 发布:java web面试题目 编辑:程序博客网 时间:2024/06/03 20:53
 

简单说,即调用第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++;
 }
}


 

原创粉丝点击