0x01 前言

  同学问过我进程体中EPROCESS的三条链断了怎么枚举模块,这也是也腾讯面试题。我当时听到也是懵逼的。

  后来在网上看到了一些内存暴力枚举的方法ZwQueryVirtualMemory。

0x02 使用ZwQueryVirtualMemory暴力枚举模块

 NTSTATUS
NtQueryVirtualMemory(HANDLE ProcessHandle, //目标进程句柄
   PVOID BaseAddress, //查询的基址
MEMORY_INFORMATION_CLASS MemoryInformationClass, //枚举宏
PVOID MemoryInformation, //接收信息的结构体
SIZE_T MemoryInformationLength, //缓冲区大小
PSIZE_T ReturnLength); //返回实际长度 //枚举宏
typedef enum _MEMORY_INFORMATION_CLASS {
MemoryBasicInformation,
MemoryWorkingSetList,
MemorySectionName,
MemoryBasicVlmInformation
} MEMORY_INFORMATION_CLASS;

  R0通过遍历SSDT获得函数地址。

  我们要枚举进程模块信息, 需要用到两类内存信息MemoryBasicInformation和MemorySectionName,

  MemoryBasicInformation的缓冲结构体

typedef struct _MEMORY_BASIC_INFORMATION {
PVOID BaseAddress; //查询内存块所占的第一个页面基地址
PVOID AllocationBase; //内存块所占的第一块区域基地址,小于等于BaseAddress,
DWORD AllocationProtect; //区域被初次保留时赋予的保护属性
SIZE_T RegionSize; //从BaseAddress开始,具有相同属性的页面的大小,
DWORD State; //页面的状态,有三种可能值MEM_COMMIT、MEM_FREE和MEM_RESERVE
DWORD Protect; //页面的属性,其可能的取值与AllocationProtect相同
DWORD Type; //该内存块的类型,有三种可能值:MEM_IMAGE、MEM_MAPPED和MEM_PRIVATE
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

  MemorySectionName的缓冲结构体为

//MemorySectionName
typedef struct _MEMORY_SECTION_NAME {
UNICODE_STRING Name;
WCHAR Buffer[];
}MEMORY_SECTION_NAME,*PMEMORY_SECTION_NAME;

  前者返回内存的基本信息, 比如: 内存区的基址,大小以及页面的各种属性等等, 而后者则返回内存段的名字,  也就是我们所要找的模块名.
  利用前者我们可以过滤出类型为MEM_IMAGE的内存段并得到内存段的基址和属性, 利用后者我们可以得到模块名.

  代码如下:

VOID ListModuleThread(PVOID Context)
{
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
ULONG StepAddress;
ULONG Step2Address;
ULONG BufferSize = 0x200;
ULONG ReturnLength = ;
WCHAR LastImageName[] = { };
HANDLE HandleProcess;
PMEMORY_SECTION_NAME SectionName = NULL;
MEMORY_BASIC_INFORMATION BasicInformation;
PTHREAD_CONTEXT ThreadContext = Context;
PMODULE_INFO FoundModule = NULL;
pFnZwQueryVirtualMemory ZwQueryVirtualMemory = NULL; ZwQueryVirtualMemory = (pFnZwQueryVirtualMemory)
KeServiceDescriptorTable.ServiceTableBase[ServiceId_NtQueryVirtualMemory]; ntStatus = ObOpenObjectByPointer(ThreadContext->Process, OBJ_INHERIT,
NULL, , *PsProcessType,
ExGetPreviousMode(), &HandleProcess);
if (!NT_SUCCESS(ntStatus)) {
ExFreePoolWithTag(g_ModuleListHead, MEM_TAG);
g_ModuleListHead = NULL; goto _End;
} SectionName = ExAllocatePoolWithTag(PagedPool, BufferSize, MEM_TAG); for (StepAddress = ; StepAddress <= 0x7FFFFFFF; StepAddress += 0x10000)
{
ntStatus = ZwQueryVirtualMemory(HandleProcess,
(PVOID)StepAddress,
MemoryBasicInformation,
&BasicInformation,
sizeof(MEMORY_BASIC_INFORMATION),
&ReturnLength); if (!NT_SUCCESS(ntStatus) || BasicInformation.Type != SEC_IMAGE) continue;
_Retry:
ntStatus = ZwQueryVirtualMemory(HandleProcess,
(PVOID)StepAddress,
MemorySectionName,
SectionName,
BufferSize,
&ReturnLength); if (!NT_SUCCESS(ntStatus)) {
if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) {
ExFreePoolWithTag(SectionName, MEM_TAG);
SectionName = ExAllocatePoolWithTag(PagedPool, ReturnLength, MEM_TAG);
goto _Retry;
}
continue;
}
__try {
if (memcmp(LastImageName, SectionName->SectionFileName.Buffer,
SectionName->SectionFileName.Length) &&
SectionName->SectionFileName.Length < ) { memcpy(LastImageName, SectionName->SectionFileName.Buffer,
SectionName->SectionFileName.Length);
LastImageName[SectionName->SectionFileName.Length / ] = L'/0'; //
// Step into and get the image size
//
for (Step2Address = StepAddress + BasicInformation.RegionSize;
Step2Address < 0x7FFFFFFF;
Step2Address += BasicInformation.RegionSize) { ntStatus = ZwQueryVirtualMemory(HandleProcess,
(PVOID)Step2Address,
MemoryBasicInformation,
&BasicInformation,
sizeof(MEMORY_BASIC_INFORMATION),
&ReturnLength);
if (NT_SUCCESS(ntStatus) &&
BasicInformation.Type != SEC_IMAGE) break;
} FoundModule = ExAllocatePoolWithTag(NonPagedPool, sizeof(MODULE_INFO), MEM_TAG);
FoundModule->BaseAddress = StepAddress;
FoundModule->ImageSize = Step2Address - StepAddress;
RtlStringCbPrintfW(FoundModule->ImagePath, , L"%s", LastImageName); InsertTailList(&g_ModuleListHead->ModuleListHead, &FoundModule->ModuleLink);
g_ModuleListHead->NumberOfModules ++;
}
} __except (EXCEPTION_EXECUTE_HANDLER) { continue; }
}
ExFreePoolWithTag(SectionName, MEM_TAG);
ObCloseHandle(HandleProcess, ExGetPreviousMode());
_End:
KeSetEvent(&ThreadContext->SynEvent, IO_NO_INCREMENT, FALSE);
PsTerminateSystemThread(STATUS_SUCCESS);
}

  此时的模块名是NT Path需要转成Dos Path,代码如下

BOOLEAN NtPathToDosPathW(WCHAR* wzFullNtPath,WCHAR* wzFullDosPath);
extern
NTSTATUS
NTAPI
ZwQueryDirectoryObject (
__in HANDLE DirectoryHandle,
__out_bcount_opt(Length) PVOID Buffer,
__in ULONG Length,
__in BOOLEAN ReturnSingleEntry,
__in BOOLEAN RestartScan,
__inout PULONG Context,
__out_opt PULONG ReturnLength
); typedef struct _OBJECT_DIRECTORY_INFORMATION
{
UNICODE_STRING Name;
UNICODE_STRING TypeName;
} OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; ULONG
NtQueryDosDevice(WCHAR* wzDosDevice,WCHAR* wzNtDevice,
ULONG ucchMax);
BOOLEAN NtPathToDosPathW(WCHAR* wzFullNtPath,WCHAR* wzFullDosPath)
{
WCHAR wzDosDevice[] = {};
WCHAR wzNtDevice[] = {};
WCHAR *RetStr = NULL;
size_t NtDeviceLen = ;
short i = ;
if(!wzFullNtPath||!wzFullDosPath)
{
return FALSE;
}
for(i=;i<+;i++)
{
wzDosDevice[] = i;
wzDosDevice[] = L':';
if(NtQueryDosDevice(wzDosDevice,wzNtDevice,))
{
if(wzNtDevice)
{
NtDeviceLen = wcslen(wzNtDevice);
if(!_wcsnicmp(wzNtDevice,wzFullNtPath,NtDeviceLen))
{
wcscpy(wzFullDosPath,wzDosDevice);
wcscat(wzFullDosPath,wzFullNtPath+NtDeviceLen);
return TRUE;
}
}
}
}
} ULONG
NtQueryDosDevice(WCHAR* wzDosDevice,WCHAR* wzNtDevice,
ULONG ucchMax)
{
NTSTATUS Status;
POBJECT_DIRECTORY_INFORMATION ObjectDirectoryInfor;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString;
HANDLE hDirectory;
HANDLE hDevice;
ULONG ulReturnLength;
ULONG ulNameLength;
ULONG ulLength;
ULONG Context;
BOOLEAN bRestartScan;
WCHAR* Ptr = NULL;
UCHAR szBuffer[] = {};
RtlInitUnicodeString (&uniString,L"\\??");
InitializeObjectAttributes(&oa,
&uniString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenDirectoryObject(&hDirectory,DIRECTORY_QUERY,&oa);
if(!NT_SUCCESS(Status))
{
return ;
}
ulLength = ;
if (wzDosDevice != NULL)
{
RtlInitUnicodeString (&uniString,(PWSTR)wzDosDevice);
InitializeObjectAttributes(&oa,&uniString,OBJ_CASE_INSENSITIVE,hDirectory,NULL);
Status = ZwOpenSymbolicLinkObject(&hDevice,GENERIC_READ,&oa);
if(!NT_SUCCESS (Status))
{
ZwClose(hDirectory);
return ;
}
uniString.Length = ;
uniString.MaximumLength = (USHORT)ucchMax * sizeof(WCHAR);
uniString.Buffer = wzNtDevice;
ulReturnLength = ;
Status = ZwQuerySymbolicLinkObject (hDevice,&uniString,&ulReturnLength);
ZwClose(hDevice);
ZwClose(hDirectory);
if (!NT_SUCCESS (Status))
{
return ;
}
ulLength = uniString.Length / sizeof(WCHAR);
if (ulLength < ucchMax)
{
wzNtDevice[ulLength] = UNICODE_NULL;
ulLength++;
}
else
{
return ;
}
}
else
{
bRestartScan = TRUE;
Context = ;
Ptr = wzNtDevice;
ObjectDirectoryInfor = (POBJECT_DIRECTORY_INFORMATION)szBuffer;
while (TRUE)
{
Status = ZwQueryDirectoryObject(hDirectory,szBuffer,sizeof (szBuffer),TRUE,bRestartScan,&Context,&ulReturnLength);
if(!NT_SUCCESS(Status))
{
if (Status == STATUS_NO_MORE_ENTRIES)
{
*Ptr = UNICODE_NULL;
ulLength++;
Status = STATUS_SUCCESS;
}
else
{
ulLength = ;
}
break;
}
if (!wcscmp (ObjectDirectoryInfor->TypeName.Buffer, L"SymbolicLink"))
{
ulNameLength = ObjectDirectoryInfor->Name.Length / sizeof(WCHAR);
if (ulLength + ulNameLength + >= ucchMax)
{
ulLength = ;
break;
}
memcpy(Ptr,ObjectDirectoryInfor->Name.Buffer,ObjectDirectoryInfor->Name.Length);
Ptr += ulNameLength;
ulLength += ulNameLength;
*Ptr = UNICODE_NULL;
Ptr++;
ulLength++;
}
bRestartScan = FALSE;
}
ZwClose(hDirectory);
}
return ulLength;
}

0x03 参考

  http://www.cnblogs.com/kedebug/archive/2010/12/22/2791753.html

ZwQueryVirtualMemory暴力枚举进程模块的更多相关文章

  1. ZwQueryVirtualMemory枚举进程模块

    ZwQueryVirtualMemory算是枚举进程方法中的黑科技吧,主要是该方法可以检测出隐藏的模块(类似IceSword). 代码VS2015测试通过 再次奉上源码链接:https://githu ...

  2. pikachu学习-暴力破解模块

    安装好XAMPP,burpsuite,配置好pikachu我们就可以进行pikachu平台的漏洞学习 我这篇博客主要写暴力破解模块讲解,它分为4个小模块,分别是“基于表单的暴力破解”,“验证码绕过(o ...

  3. VadRoot枚举进程模块在Windows7下的完整实现

      原理小伟的小伟在http://bbs.pediy.com/showthread.php?t=66886说的挺清楚了,Windows7下有一些变化,使用NtQueryVirtualMemory来枚举 ...

  4. HookSSDT 通过HookOpenProcess函数阻止暴力枚举进程

    首先要知道Ring3层调用OpenProcess的流程 //当Ring3调用OpenProcess //1从自己的模块(.exe)的导入表中取值 //2Ntdll.dll模块的导出表中执行ZwOpen ...

  5. ring0 暴力枚举进程

    原理:遍历进程ID,然后openprocess,能打开的都枚举出来 ring0 : #include "EnumProcessByForce.h" extern char* PsG ...

  6. 由枚举模块到ring0内存结构 (分析NtQueryVirtualMemory)

    是由获得进程模块而引发的一系列的问题,首先,在ring3层下枚举进程模块有ToolHelp,Psapi,还可以通过在ntdll中获得ZwQuerySystemInformation的函数地址来枚举,其 ...

  7. 【旧文章搬运】再谈隐藏进程中的DLL模块

    原文发表于百度空间,2009-09-17========================================================================== 相当老的话 ...

  8. 枚举PEB获取进程模块列表

    枚举进程模块的方法有很多种,常见的有枚举PEB和内存搜索法,今天,先来看看实现起来最简单的枚举PEB实现获取进程模块列表. 首先,惯例是各种繁琐的结构体定义.需要包含 ntifs.h 和 WinDef ...

  9. 【web安全】第五弹:burpsuite proxy模块的一些理解

    作为一只小小小白的安全新手,只会简单的用sqlmap扫扫网站,用burpsuite的proxy模块拦截一些请求.最近又对proxy有点儿小理解,记录之. 1. 查看sqlmap注入的语句以及HTTP ...

随机推荐

  1. angular学习文章

    https://www.jianshu.com/p/86c6249a2069 angular.cn https://segmentfault.com/a/1190000008754631

  2. unix网络编程str_cli使用epoll实现

    unix网络编程str_cli使用epoll实现 unix环境高级编程中也有这个函数,都是为了讲解IO多路转接.从本质上来看epoll就是一个改善了的select和poll,本质没发生任何变化,对于构 ...

  3. rtabmap and rtabmap_ros make error(rtabmap编译错误)

    Build from source following README.nd in rtabmap_ros rtabmap make error Error 1 make[2]: *** No rule ...

  4. soapui

    webservice 的请求可使用工具:soapui 天气预报的接口地址:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsd ...

  5. luoguP2495 [SDOI2011]消耗战

    https://www.luogu.org/problemnew/show/P2495 Dp 方程很显然 设 Dp[u] 表示--使 u 不与其子树中任意一个关键点联通的最小代价 设 w[a, b] ...

  6. 通过html()的方法获取文本内容, form表单组件显示的值与获取到的值不一致的问题

    我在通过 html()获取对应节点的内容,发现一个问题,获取到的 form表单组件的内容值是初始加载的值,而不是经过用户修改后的值.例如页面加载时组件<input type="text ...

  7. 通用动态树(Link-Cut Tree)模板

    一个没有维护任何东西的动态树模板 忘了怎么写可以直接来粘 int ch[300010][2], fa[300010], st[300010]; bool lazy[300010]; bool nroo ...

  8. Mac的Parallels在启动Win的时候让它独立全屏窗口

    这里备忘一下,由于经常需要***,Win方法比较多少,所以使用Parallels在Win下***还是很有必要的,为了使用使用方便,一般让Parallels启动系统之后自动生成一个独立的全窗口,方便来回 ...

  9. js 封装一个均速动画函数

    //动画函数---任意一个元素移动到指定的目标位置 //element为元素 target为位置 function carToon(element, target) { //设置一个定时器让他循环去增 ...

  10. Hadoop Hive概念学习系列之什么是Hive?

    参考  <Hadoop大数据分析与挖掘实战>的在线电子书阅读                   http://yuedu.baidu.com/ebook/d128cf8e33687e21 ...