码迷,mamicode.com
首页 > 系统相关 > 详细

暴力枚举进程模块

时间:2016-03-22 18:53:15      阅读:752      评论:0      收藏:0      [点我收藏+]

标签:

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

后来在网上看到了一些内存暴力枚举的方法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[260];  
}MEMORY_SECTION_NAME,*PMEMORY_SECTION_NAME;

前者返回内存的基本信息, 比如: 内存区的基址,大小以及页面的各种属性等等, 而后者则返回内存段的名字,  
也就是我们所要找的模块名.

利用前者我们可以过滤出类型为MEM_IMAGE的内存段并得到内存段的基址和属性, 利用后者我们可以得到模块名.

此时的模块名是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[4] = {0};
    WCHAR wzNtDevice[64] = {0};
    WCHAR *RetStr = NULL;
    size_t NtDeviceLen = 0;
    short i = 0;
    if(!wzFullNtPath||!wzFullDosPath)
    {
        return FALSE;
    }
    for(i=65;i<26+65;i++)
    {
        wzDosDevice[0] = i;
        wzDosDevice[1] = L:;
        if(NtQueryDosDevice(wzDosDevice,wzNtDevice,64))
        {
            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[512] = {0};
    RtlInitUnicodeString (&uniString,L"\\??");
    InitializeObjectAttributes(&oa,
        &uniString,
        OBJ_CASE_INSENSITIVE,
        NULL,
        NULL); 
    Status = ZwOpenDirectoryObject(&hDirectory,DIRECTORY_QUERY,&oa);
    if(!NT_SUCCESS(Status))
    {
        return 0;
    }
    ulLength = 0;
    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 0;
        }
        uniString.Length = 0;
        uniString.MaximumLength = (USHORT)ucchMax * sizeof(WCHAR);
        uniString.Buffer = wzNtDevice;
        ulReturnLength = 0;
        Status = ZwQuerySymbolicLinkObject (hDevice,&uniString,&ulReturnLength);
        ZwClose(hDevice);
        ZwClose(hDirectory);
        if (!NT_SUCCESS (Status))
        {
            return 0;
        }
        ulLength = uniString.Length / sizeof(WCHAR);
        if (ulLength < ucchMax)
        {
            wzNtDevice[ulLength] = UNICODE_NULL;
            ulLength++;
        }
        else
        {
            return 0;
        }
    }
    else
    {
        bRestartScan = TRUE;
        Context = 0;
        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 = 0;
                }
                break;
            }
            if (!wcscmp (ObjectDirectoryInfor->TypeName.Buffer, L"SymbolicLink"))
            {
                ulNameLength = ObjectDirectoryInfor->Name.Length / sizeof(WCHAR);
                if (ulLength + ulNameLength + 1 >= ucchMax)
                {
                    ulLength = 0;
                    break;
                }
                memcpy(Ptr,ObjectDirectoryInfor->Name.Buffer,ObjectDirectoryInfor->Name.Length);
                Ptr += ulNameLength;
                ulLength += ulNameLength;
                *Ptr = UNICODE_NULL;
                Ptr++;
                ulLength++;
            }
            bRestartScan = FALSE;
        }
        ZwClose(hDirectory);
    }
    return ulLength;
}

 

网上都有代码我就不贴了,发个帖记录一下学习

这是别人的代码链接

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

 

暴力枚举进程模块

标签:

原文地址:http://www.cnblogs.com/aliflycoris/p/5307715.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!