C++中通过指针获取结构体

问题描述 投票:0回答:1

我正在尝试从

NtQuerySystemInformation()
函数获取有关进程中句柄的信息。我有以下代码:

#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include <process.h>

#define SystemHandleInformation 0x10
#define SystemHandleInformationSize 1024 * 1024 * 2

using fNtQuerySystemInformation = NTSTATUS(WINAPI*)(
    ULONG SystemInformationClass,
    PVOID SystemInformation,
    ULONG SystemInformationLength,
    PULONG ReturnLength
);

typedef struct _DEVICE_OBJECT* PDEVICE_OBJECT;
typedef struct _PVPB* PVPB;
typedef struct _KEVENT* PKEVENT;
typedef struct _IO_COMPLETION_CONTEXT* PIO_COMPLETION_CONTEXT;

typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
    USHORT UniqueProcessId;
    USHORT CreatorBackTraceIndex;
    UCHAR ObjectTypeIndex;
    UCHAR HandleAttributes;
    USHORT HandleValue;
    PVOID Object;
    ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;

typedef struct _SYSTEM_HANDLE_INFORMATION
{
    ULONG NumberOfHandles;
    SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;

typedef struct _SECTION_OBJECT_POINTERS
{
    PVOID DataSectionObject;
    PVOID SharedCacheMap;
    PVOID ImageSectionObject;
} SECTION_OBJECT_POINTERS, * PSECTION_OBJECT_POINTERS;

typedef struct _FILE_OBJECT
{
    SHORT Type;
    SHORT Size;
    PDEVICE_OBJECT DeviceObject;
    PVPB Vpb;
    PVOID FsContext;
    PVOID FsContext2;
    PSECTION_OBJECT_POINTERS SectionObjectPointer;
    PVOID PrivateCacheMap;
    LONG FinalStatus;
    struct _FILE_OBJECT *RelatedFileObject;
    UCHAR LockOperation;
    UCHAR DeletePending;
    UCHAR ReadAccess;
    UCHAR WriteAccess;
    UCHAR DeleteAccess;
    UCHAR SharedRead;
    UCHAR SharedWrite;
    UCHAR SharedDelete;
    ULONG Flags;
    UNICODE_STRING FileName;
    LARGE_INTEGER CurrentByteOffset;
    ULONG Waiters;
    ULONG Busy;
    PVOID LastLock;
    PKEVENT Lock;
    PKEVENT Event;
    PIO_COMPLETION_CONTEXT CompletionContext;
    ULONG IrpListLock;
    LIST_ENTRY IrpList;
    PVOID FileObjectExtension;
} FILE_OBJECT, * PFILE_OBJECT;


int main() {
    HANDLE hFile = CreateFileA("C:\\Users\\user\\Documents\\test.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    ULONG returnLenght = 0;
    fNtQuerySystemInformation NtQuerySystemInformation = (fNtQuerySystemInformation)GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation");
    PSYSTEM_HANDLE_INFORMATION handleTableInformation = (PSYSTEM_HANDLE_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SystemHandleInformationSize);
    NtQuerySystemInformation(SystemHandleInformation, handleTableInformation, SystemHandleInformationSize, &returnLenght);
    int PID = _getpid();

    for (int i = 0; i < handleTableInformation->NumberOfHandles; i++)
    {
        SYSTEM_HANDLE_TABLE_ENTRY_INFO handleInfo = (SYSTEM_HANDLE_TABLE_ENTRY_INFO)handleTableInformation->Handles[i];

        if (handleInfo.UniqueProcessId == PID && handleInfo.ObjectTypeIndex == 37)
        {
            printf_s("Handle 0x%x at 0x%p, PID: %x\n", handleInfo.HandleValue, handleInfo.Object, handleInfo.UniqueProcessId);

            PFILE_OBJECT fileObj = (PFILE_OBJECT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1024 * 1024 * 2);
            memcpy(&fileObj, &handleInfo.Object, sizeof(fileObj));
            printf_s("%d\n", fileObj->Type);
        }
    }
    
    return 0;
}

IF
条件下,我正在检查
handleInfo
的PID以及对象类型是否为37,这意味着它是一个文件对象(这是Windows 10中的正确索引。在其他操作系统中可能有所不同) 。在这个
IF
块中,我需要通过存储在
PFILE_OBJECT
中的指针来获取
handleInfo.Object
。但是当我调用
memcpy()
函数将此结构分配给变量时,我收到了
Access violation of reading location
错误。

我做错了什么?如何访问这个结构?我需要获取它的 Type、ReadAccess、WriteAccess、FileName 等。

c++ winapi
1个回答
0
投票

我运行了代码,

printf_s("%d\n", fileObj->Type);
行抛出了
read access violation
异常。
fileObj
的地址是
0xFFFF800D0F4C3940

根据虚拟地址空间

进程可用的虚拟地址范围是已知的 作为进程的虚拟地址空间。每个用户模式进程都有其 自己的私有虚拟地址空间。

  • 32 位进程的虚拟地址空间通常在 2 GB 范围内 0x00000000 到 0x7FFFFFFF。

  • 64 位 Windows 上的 64 位进程具有 128 TB 范围内的虚拟地址空间 0x000'00000000 到 0x7FFF'FFFFFFFF。

在用户模式下运行的代码可以访问用户空间,但不能访问系统空间。 此限制可防止用户模式代码读取或更改 受保护的操作系统数据结构。

尝试访问大于

0x7FFF'FFFFFFFF
的地址将导致读访问冲突。

© www.soinside.com 2019 - 2024. All rights reserved.