none
如何得到某个进程的GDI对象句柄列表? RRS feed

全部回复

  • 你好,

    感谢你在这里发帖。

    查询GDI对象句柄表,因为所有进程共享GDI对象句柄表,所以需要根据进程标识符筛选。此方法需要gdi32.dll的支持。底下demo实现了这个方法,根据进程ID从系统GDI对象句柄表中筛选出所有符合要求的GDI对象句柄,并根据句柄类型分类。仅供参考。

    //process.cpp
    #include <iostream>
    #include <TCHAR.h>
    #include "Header.h"
    
    int main()
    {
    
    	// get process id
    	DWORD dwId = 16888;//process ID
    
    	// open the process
    	HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwId);
    	DWORD err = 0;
    	if (hProcess == NULL)
    	{
    		printf("OpenProcess %u failed\n", dwId);
    		err = GetLastError();
    		return -1;
    	}
    	DWORD a=NULL;
    	
    	GetProcessHandleCount(hProcess, &a);
    	std::cout << a<<std::endl;
    	// determine if 64 or 32-bit processor
    	SYSTEM_INFO si;
    	GetNativeSystemInfo(&si);
    
    	// NOTE: as this is undocumented, it *may vary* depending on bitness (32/64) and on Windows version.
    	// use WinDbg "dt ntdll!_PEB" command and search for GdiSharedHandleTable offset to find the truth out
    	DWORD GdiSharedHandleTableOffset = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ? 0xF8 : 0x94;
    	DWORD tableCount = 16384; // count of GDI table cells
    
    	// determine if this process is running on WOW64
    	BOOL wow;
    	IsWow64Process(GetCurrentProcess(), &wow);
    
    	// read basic info to get PEB address, we only need the beginning of PEB
    	DWORD pebSize = GdiSharedHandleTableOffset + 8;
    	LPBYTE peb = (LPBYTE)malloc(pebSize);
    	ZeroMemory(peb, pebSize);
    
    	if (wow)
    	{
    		// we're running as a 32-bit process in a 64-bit process
    		PROCESS_BASIC_INFORMATION_WOW64 pbi;
    		ZeroMemory(&pbi, sizeof(pbi));
    
    		// get process information from 64-bit world
    		_NtQueryInformationProcess query = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtWow64QueryInformationProcess64");
    		err = query(hProcess, 0, &pbi, sizeof(pbi), NULL);
    		if (err != 0)
    		{
    			printf("NtWow64QueryInformationProcess64 failed\n");
    			CloseHandle(hProcess);
    			return -1;
    		}
    
    		// read PEB from 64-bit address space
    		_NtWow64ReadVirtualMemory64 read = (_NtWow64ReadVirtualMemory64)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtWow64ReadVirtualMemory64");
    		err = read(hProcess, pbi.PebBaseAddress, peb, pebSize, NULL);
    		if (err != 0)
    		{
    			printf("NtWow64ReadVirtualMemory64 PEB failed\n");
    			CloseHandle(hProcess);
    			return -1;
    		}
    
    		// get GDI table ptr from PEB
    		GDICELL_WOW64* gdiTable = (GDICELL_WOW64*) * (LPVOID*)(peb + GdiSharedHandleTableOffset); // address in remote process adress space
    		if (gdiTable == NULL)
    		{
    			printf("GDI32.DLL is not loaded in the process\n");
    			CloseHandle(hProcess);
    			return -1;
    		}
    		free(peb);
    		DWORD tableSize = sizeof(GDICELL_WOW64) * tableCount; // size of GDI table
    		GDICELL_WOW64* table = (GDICELL_WOW64*)malloc(tableSize); // local table copied over to our address space
    
    		// copy GDI table
    		err = read(hProcess, gdiTable, table, tableSize, NULL);
    		if (err != 0)
    		{
    			printf("NtWow64ReadVirtualMemory64 GdiTable failed\n");
    			free(table);
    			CloseHandle(hProcess);
    			return -1;
    		}
    
    		for (DWORD i = 0; i < tableCount; i++)
    		{
    			GDICELL_WOW64 cell = table[i];
    			if (cell.wProcessId == dwId)
    			{
    				HGDIOBJ gdiHandle = (HGDIOBJ)((cell.wUpper << 16) + i);
    				WORD type = cell.wType & 0x7F;
    				switch (type)
    				{
    				case 1:
    					printf("DC handle:0x%08X\n", gdiHandle);
    					break;
    
    				case 4:
    					printf("Region handle:0x%08X\n", gdiHandle);
    					break;
    
    				case 5:
    					printf("Bitmap handle:0x%08X\n", gdiHandle);
    					break;
    
    				case 8:
    					printf("Palette handle:0x%08X\n", gdiHandle);
    					break;
    
    				case 10:
    					printf("Font handle:0x%08X\n", gdiHandle);
    					break;
    
    				case 16:
    					printf("Brush handle:0x%08X\n", gdiHandle);
    					break;
    
    				case 48:
    					printf("Pen handle:0x%08X\n", gdiHandle);
    					break;
    
    				default:
    					printf("Unknown type handle:0x%08X\n", gdiHandle);
    					break;
    				}
    			}	
    		}
    		free(table);
    	}
    	else
    	{
    		// we're running as a 32-bit process in a 32-bit OS, or as a 64-bit process in a 64-bit OS
    		PROCESS_BASIC_INFORMATION pbi;
    		ZeroMemory(&pbi, sizeof(pbi));
    
    		// get process information
    		_NtQueryInformationProcess query = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
    		err = query(hProcess, 0, &pbi, sizeof(pbi), NULL);
    		if (err != 0)
    		{
    			printf("NtQueryInformationProcess failed\n");
    			CloseHandle(hProcess);
    			return -1;
    		}
    
    		// read PEB
    		_NtReadVirtualMemory read = (_NtReadVirtualMemory)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtReadVirtualMemory");
    		err = read(hProcess, pbi.PebBaseAddress, peb, pebSize, NULL);
    		if (err != 0)
    		{
    			printf("NtReadVirtualMemory PEB failed\n");
    			CloseHandle(hProcess);
    			return -1;
    		}
    
    		// get GDI table ptr
    		GDICELL* gdiTable = (GDICELL*) * (LPVOID*)(peb + GdiSharedHandleTableOffset); // address in remote process adress space
    		if (gdiTable == NULL)
    		{
    			printf("GDI32.DLL is not loaded in the process\n");
    			CloseHandle(hProcess);
    			return -1;
    		}
    		free(peb);
    
    		DWORD tableSize = sizeof(GDICELL) * tableCount; // size of GDI table
    		GDICELL* table = (GDICELL*)malloc(tableSize); // local table copied over to our address space
    
    		// read GDI table
    		err = read(hProcess, gdiTable, table, tableSize, NULL);
    		if (err != 0)
    		{
    			printf("NtReadVirtualMemory GdiTable failed\n");
    			free(table);
    			CloseHandle(hProcess);
    			return -1;
    		}
    
    		for (DWORD i = 0; i < tableCount; i++)
    		{
    			GDICELL cell = table[i];
    			if (cell.wProcessId != dwId)
    				continue;
    
    			HGDIOBJ gdiHandle = (HGDIOBJ)((cell.wUpper << 16) + i);
    			WORD type = cell.wType & 0x7F;
    			switch (type)
    			{
    			case 1:
    				printf("DC handle:0x%08X\n", gdiHandle);
    				break;
    
    			case 4:
    				printf("Region handle:0x%08X\n", gdiHandle);
    				break;
    
    			case 5:
    				printf("Bitmap handle:0x%08X\n", gdiHandle);
    				break;
    
    			case 8:
    				printf("Palette handle:0x%08X\n", gdiHandle);
    				break;
    
    			case 10:
    				printf("Font handle:0x%08X\n", gdiHandle);
    				break;
    
    			case 16:
    				printf("Brush handle:0x%08X\n", gdiHandle);
    				break;
    
    			case 48:
    				printf("Pen handle:0x%08X\n", gdiHandle);
    				break;
    
    			default:
    				printf("Unknown type handle:0x%08X\n", gdiHandle);
    				break;
    			}
    		}
    		free(table);
    	}
    	CloseHandle(hProcess);
    }
    //Header.h
    #pragma once
    #include <Windows.h>
    
    // defines a GDI CELL
    typedef struct
    {
    	LPVOID pKernelAddress;
    	USHORT wProcessId;
    	USHORT wCount;
    	USHORT wUpper;
    	USHORT wType;
    	LPVOID pUserAddress;
    } GDICELL;
    
    // defines a GDI CELL for WOW64
    typedef struct
    {
    	PVOID64 pKernelAddress;
    	USHORT wProcessId;
    	USHORT wCount;
    	USHORT wUpper;
    	USHORT wType;
    	PVOID64 pUserAddress;
    } GDICELL_WOW64;
    
    // NtQueryInformationProcess for pure 32 and 64-bit processes
    typedef NTSTATUS(NTAPI* _NtQueryInformationProcess)(
    	IN HANDLE ProcessHandle,
    	ULONG ProcessInformationClass,
    	OUT PVOID ProcessInformation,
    	IN ULONG ProcessInformationLength,
    	OUT PULONG ReturnLength OPTIONAL
    	);
    
    typedef NTSTATUS(NTAPI* _NtReadVirtualMemory)(
    	IN HANDLE ProcessHandle,
    	IN PVOID BaseAddress,
    	OUT PVOID Buffer,
    	IN SIZE_T Size,
    	OUT PSIZE_T NumberOfBytesRead);
    
    // NtQueryInformationProcess for 32-bit process on WOW64
    typedef NTSTATUS(NTAPI* _NtWow64ReadVirtualMemory64)(
    	IN HANDLE ProcessHandle,
    	IN PVOID64 BaseAddress,
    	OUT PVOID Buffer,
    	IN ULONG64 Size,
    	OUT PULONG64 NumberOfBytesRead);
    
    // PROCESS_BASIC_INFORMATION for pure 32 and 64-bit processes
    typedef struct _PROCESS_BASIC_INFORMATION {
    	PVOID Reserved1;
    	PVOID PebBaseAddress;
    	PVOID Reserved2[2];
    	ULONG_PTR UniqueProcessId;
    	PVOID Reserved3;
    } PROCESS_BASIC_INFORMATION;
    
    // PROCESS_BASIC_INFORMATION for 32-bit process on WOW64
    // The definition is quite funky, as we just lazily doubled sizes to match offsets...
    typedef struct _PROCESS_BASIC_INFORMATION_WOW64 {
    	PVOID Reserved1[2];
    	PVOID64 PebBaseAddress;
    	PVOID Reserved2[4];
    	ULONG_PTR UniqueProcessId[2];
    	PVOID Reserved3[2];
    } PROCESS_BASIC_INFORMATION_WOW64;

    Best Regards,

    Suarez Zhou


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2019年11月25日 7:11
  • 非常感谢.
    2019年11月29日 9:53
  • 你好,

    如果你的问题解决了,请标记有价值的回复为答案,这会对社区其他成员有帮助。

    Best Regards,

    Suarez Zhou


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2019年12月11日 8:52
  • 你好,非常感谢.

    我编译不过去.

    我把文件加入到VC DOS 支持MFC的新工程中,出现了下列错误.

    --------------------Configuration: dosgdi0 - Win32 Debug--------------------
    Compiling...
    dosgdi0.cpp
    D:\temp\dosgdi0\dosgdi0.cpp(51) : error C2059: syntax error : '__stdcall'
    D:\temp\dosgdi0\dosgdi0.cpp(57) : error C2091: function returns function
    D:\temp\dosgdi0\dosgdi0.cpp(64) : error C2091: function returns function
    D:\temp\dosgdi0\dosgdi0.cpp(72) : error C2091: function returns function
    D:\temp\dosgdi0\dosgdi0.cpp(79) : error C2146: syntax error : missing ';' before identifier 'UniqueProcessId'
    D:\temp\dosgdi0\dosgdi0.cpp(79) : error C2501: 'ULONG_PTR' : missing storage-class or type specifiers
    D:\temp\dosgdi0\dosgdi0.cpp(79) : error C2501: 'UniqueProcessId' : missing storage-class or type specifiers
    D:\temp\dosgdi0\dosgdi0.cpp(89) : error C2146: syntax error : missing ';' before identifier 'UniqueProcessId'
    D:\temp\dosgdi0\dosgdi0.cpp(89) : error C2501: 'ULONG_PTR' : missing storage-class or type specifiers
    D:\temp\dosgdi0\dosgdi0.cpp(89) : error C2501: 'UniqueProcessId' : missing storage-class or type specifiers
    D:\temp\dosgdi0\dosgdi0.cpp(110) : error C2065: 'GetProcessHandleCount' : undeclared identifier
    D:\temp\dosgdi0\dosgdi0.cpp(114) : error C2065: 'GetNativeSystemInfo' : undeclared identifier
    D:\temp\dosgdi0\dosgdi0.cpp(118) : error C2065: 'PROCESSOR_ARCHITECTURE_AMD64' : undeclared identifier
    D:\temp\dosgdi0\dosgdi0.cpp(123) : error C2065: 'IsWow64Process' : undeclared identifier
    D:\temp\dosgdi0\dosgdi0.cpp(137) : error C2065: '_NtQueryInformationProcess' : undeclared identifier
    D:\temp\dosgdi0\dosgdi0.cpp(137) : error C2146: syntax error : missing ';' before identifier 'query'
    D:\temp\dosgdi0\dosgdi0.cpp(137) : error C2065: 'query' : undeclared identifier
    D:\temp\dosgdi0\dosgdi0.cpp(137) : error C2146: syntax error : missing ';' before identifier 'GetProcAddress'
    D:\temp\dosgdi0\dosgdi0.cpp(148) : error C2440: '=' : cannot convert from 'int (__cdecl *(__cdecl *)(void))(void *,unsigned long,void *,unsigned long,unsigned long *)' to 'unsigned long'
            This conversion requires a reinterpret_cast, a C-style cast or function-style cast
    D:\temp\dosgdi0\dosgdi0.cpp(169) : error C2440: '=' : cannot convert from 'int (__cdecl *(__cdecl *)(void))(void *,unsigned long,void *,unsigned long,unsigned long *)' to 'unsigned long'
            This conversion requires a reinterpret_cast, a C-style cast or function-style cast
    D:\temp\dosgdi0\dosgdi0.cpp(230) : error C2146: syntax error : missing ';' before identifier 'query'
    D:\temp\dosgdi0\dosgdi0.cpp(230) : error C2146: syntax error : missing ';' before identifier 'GetProcAddress'
    D:\temp\dosgdi0\dosgdi0.cpp(241) : error C2440: '=' : cannot convert from 'int (__cdecl *(__cdecl *)(void))(void *,unsigned long,void *,unsigned long,unsigned long *)' to 'unsigned long'
            This conversion requires a reinterpret_cast, a C-style cast or function-style cast
    D:\temp\dosgdi0\dosgdi0.cpp(263) : error C2440: '=' : cannot convert from 'int (__cdecl *(__cdecl *)(void))(void *,unsigned long,void *,unsigned long,unsigned long *)' to 'unsigned long'
            This conversion requires a reinterpret_cast, a C-style cast or function-style cast
    Error executing cl.exe.

    dosgdi0.exe - 24 error(s), 0 warning(s)
    下面是我的源代码

    // dosgdi0.cpp : Defines the entry point for the console application.
    //

    #include "stdafx.h"
    #include <Windows.h>

    #include "dosgdi0.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // The one and only application object

    CWinApp theApp;

    using namespace std;
    //process.cpp
    #include <iostream>
    #include <TCHAR.h>
    //#include "Header.h"



    // defines a GDI CELL
    typedef struct
    {
        LPVOID pKernelAddress;
        USHORT wProcessId;
        USHORT wCount;
        USHORT wUpper;
        USHORT wType;
        LPVOID pUserAddress;
    } GDICELL;

    // defines a GDI CELL for WOW64
    typedef struct
    {
        PVOID64 pKernelAddress;
        USHORT wProcessId;
        USHORT wCount;
        USHORT wUpper;
        USHORT wType;
        PVOID64 pUserAddress;
    } GDICELL_WOW64;

    // NtQueryInformationProcess for pure 32 and 64-bit processes
    typedef NTSTATUS(NTAPI* _NtQueryInformationProcess)(
        IN HANDLE ProcessHandle,
        ULONG ProcessInformationClass,
        OUT PVOID ProcessInformation,
        IN ULONG ProcessInformationLength,
        OUT PULONG ReturnLength OPTIONAL
        );

    typedef NTSTATUS(NTAPI* _NtReadVirtualMemory)(
        IN HANDLE ProcessHandle,
        IN PVOID BaseAddress,
        OUT PVOID Buffer,
        IN SIZE_T Size,
        OUT PSIZE_T NumberOfBytesRead);

    // NtQueryInformationProcess for 32-bit process on WOW64
    typedef NTSTATUS(NTAPI* _NtWow64ReadVirtualMemory64)(
        IN HANDLE ProcessHandle,
        IN PVOID64 BaseAddress,
        OUT PVOID Buffer,
        IN ULONG64 Size,
        OUT PULONG64 NumberOfBytesRead);

    // PROCESS_BASIC_INFORMATION for pure 32 and 64-bit processes
    typedef struct _PROCESS_BASIC_INFORMATION {
        PVOID Reserved1;
        PVOID PebBaseAddress;
        PVOID Reserved2[2];
        ULONG_PTR UniqueProcessId;
        PVOID Reserved3;
    } PROCESS_BASIC_INFORMATION;

    // PROCESS_BASIC_INFORMATION for 32-bit process on WOW64
    // The definition is quite funky, as we just lazily doubled sizes to match offsets...
    typedef struct _PROCESS_BASIC_INFORMATION_WOW64 {
        PVOID Reserved1[2];
        PVOID64 PebBaseAddress;
        PVOID Reserved2[4];
        ULONG_PTR UniqueProcessId[2];
        PVOID Reserved3[2];
    } PROCESS_BASIC_INFORMATION_WOW64;

    int f0(DWORD dwId)
    {

        // get process id
        //DWORD dwId = 16888;//process ID

        // open the process
        HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwId);
        DWORD err = 0;
        if (hProcess == NULL)
        {
            printf("OpenProcess %u failed\n", dwId);
            err = GetLastError();
            return -1;
        }
        DWORD a=NULL;
        
        GetProcessHandleCount(hProcess, &a);
        std::cout << a<<std::endl;
        // determine if 64 or 32-bit processor
        SYSTEM_INFO si;
        GetNativeSystemInfo(&si);

        // NOTE: as this is undocumented, it *may vary* depending on bitness (32/64) and on Windows version.
        // use WinDbg "dt ntdll!_PEB" command and search for GdiSharedHandleTable offset to find the truth out
        DWORD GdiSharedHandleTableOffset = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ? 0xF8 : 0x94;
        DWORD tableCount = 16384; // count of GDI table cells

        // determine if this process is running on WOW64
        BOOL wow;
        IsWow64Process(GetCurrentProcess(), &wow);

        // read basic info to get PEB address, we only need the beginning of PEB
        DWORD pebSize = GdiSharedHandleTableOffset + 8;
        LPBYTE peb = (LPBYTE)malloc(pebSize);
        ZeroMemory(peb, pebSize);

        if (wow)
        {
            // we're running as a 32-bit process in a 64-bit process
            PROCESS_BASIC_INFORMATION_WOW64 pbi;
            ZeroMemory(&pbi, sizeof(pbi));

            // get process information from 64-bit world
            _NtQueryInformationProcess query = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtWow64QueryInformationProcess64");
            err = query(hProcess, 0, &pbi, sizeof(pbi), NULL);
            if (err != 0)
            {
                printf("NtWow64QueryInformationProcess64 failed\n");
                CloseHandle(hProcess);
                return -1;
            }

            // read PEB from 64-bit address space
            _NtWow64ReadVirtualMemory64 read = (_NtWow64ReadVirtualMemory64)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtWow64ReadVirtualMemory64");
            err = read(hProcess, pbi.PebBaseAddress, peb, pebSize, NULL);
            if (err != 0)
            {
                printf("NtWow64ReadVirtualMemory64 PEB failed\n");
                CloseHandle(hProcess);
                return -1;
            }

            // get GDI table ptr from PEB
            GDICELL_WOW64* gdiTable = (GDICELL_WOW64*) * (LPVOID*)(peb + GdiSharedHandleTableOffset); // address in remote process adress space
            if (gdiTable == NULL)
            {
                printf("GDI32.DLL is not loaded in the process\n");
                CloseHandle(hProcess);
                return -1;
            }
            free(peb);
            DWORD tableSize = sizeof(GDICELL_WOW64) * tableCount; // size of GDI table
            GDICELL_WOW64* table = (GDICELL_WOW64*)malloc(tableSize); // local table copied over to our address space

            // copy GDI table
            err = read(hProcess, gdiTable, table, tableSize, NULL);
            if (err != 0)
            {
                printf("NtWow64ReadVirtualMemory64 GdiTable failed\n");
                free(table);
                CloseHandle(hProcess);
                return -1;
            }

            for (DWORD i = 0; i < tableCount; i++)
            {
                GDICELL_WOW64 cell = table[i];
                if (cell.wProcessId == dwId)
                {
                    HGDIOBJ gdiHandle = (HGDIOBJ)((cell.wUpper << 16) + i);
                    WORD type = cell.wType & 0x7F;
                    switch (type)
                    {
                    case 1:
                        printf("DC handle:0x%08X\n", gdiHandle);
                        break;

                    case 4:
                        printf("Region handle:0x%08X\n", gdiHandle);
                        break;

                    case 5:
                        printf("Bitmap handle:0x%08X\n", gdiHandle);
                        break;

                    case 8:
                        printf("Palette handle:0x%08X\n", gdiHandle);
                        break;

                    case 10:
                        printf("Font handle:0x%08X\n", gdiHandle);
                        break;

                    case 16:
                        printf("Brush handle:0x%08X\n", gdiHandle);
                        break;

                    case 48:
                        printf("Pen handle:0x%08X\n", gdiHandle);
                        break;

                    default:
                        printf("Unknown type handle:0x%08X\n", gdiHandle);
                        break;
                    }
                }    
            }
            free(table);
        }
        else
        {
            // we're running as a 32-bit process in a 32-bit OS, or as a 64-bit process in a 64-bit OS
            PROCESS_BASIC_INFORMATION pbi;
            ZeroMemory(&pbi, sizeof(pbi));

            // get process information
            _NtQueryInformationProcess query = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
            err = query(hProcess, 0, &pbi, sizeof(pbi), NULL);
            if (err != 0)
            {
                printf("NtQueryInformationProcess failed\n");
                CloseHandle(hProcess);
                return -1;
            }

            // read PEB
            _NtReadVirtualMemory read = (_NtReadVirtualMemory)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtReadVirtualMemory");
            err = read(hProcess, pbi.PebBaseAddress, peb, pebSize, NULL);
            if (err != 0)
            {
                printf("NtReadVirtualMemory PEB failed\n");
                CloseHandle(hProcess);
                return -1;
            }

            // get GDI table ptr
            GDICELL* gdiTable = (GDICELL*) * (LPVOID*)(peb + GdiSharedHandleTableOffset); // address in remote process adress space
            if (gdiTable == NULL)
            {
                printf("GDI32.DLL is not loaded in the process\n");
                CloseHandle(hProcess);
                return -1;
            }
            free(peb);

            DWORD tableSize = sizeof(GDICELL) * tableCount; // size of GDI table
            GDICELL* table = (GDICELL*)malloc(tableSize); // local table copied over to our address space

            // read GDI table
            err = read(hProcess, gdiTable, table, tableSize, NULL);
            if (err != 0)
            {
                printf("NtReadVirtualMemory GdiTable failed\n");
                free(table);
                CloseHandle(hProcess);
                return -1;
            }

            for (DWORD i = 0; i < tableCount; i++)
            {
                GDICELL cell = table[i];
                if (cell.wProcessId != dwId)
                    continue;

                HGDIOBJ gdiHandle = (HGDIOBJ)((cell.wUpper << 16) + i);
                WORD type = cell.wType & 0x7F;
                switch (type)
                {
                case 1:
                    printf("DC handle:0x%08X\n", gdiHandle);
                    break;

                case 4:
                    printf("Region handle:0x%08X\n", gdiHandle);
                    break;

                case 5:
                    printf("Bitmap handle:0x%08X\n", gdiHandle);
                    break;

                case 8:
                    printf("Palette handle:0x%08X\n", gdiHandle);
                    break;

                case 10:
                    printf("Font handle:0x%08X\n", gdiHandle);
                    break;

                case 16:
                    printf("Brush handle:0x%08X\n", gdiHandle);
                    break;

                case 48:
                    printf("Pen handle:0x%08X\n", gdiHandle);
                    break;

                default:
                    printf("Unknown type handle:0x%08X\n", gdiHandle);
                    break;
                }
            }
            free(table);
        }
        CloseHandle(hProcess);
    }
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
        int nRetCode = 0;

        // initialize MFC and print and error on failure
        if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
        {
            // TODO: change error code to suit your needs
            cerr << _T("Fatal Error: MFC initialization failed") << endl;
            nRetCode = 1;
        }
        else
        {
            // TODO: code your application's behavior here.
            f0(1);
            CString strHello;
            strHello.LoadString(IDS_HELLO);
            cout << (LPCTSTR)strHello << endl;
        }

        return nRetCode;
    }

    stdafx.h代码:

    // stdafx.h : include file for standard system include files,
    //  or project specific include files that are used frequently, but
    //      are changed infrequently
    //

    #if !defined(AFX_STDAFX_H__48940212_4EA5_466F_8D02_505DEE438573__INCLUDED_)
    #define AFX_STDAFX_H__48940212_4EA5_466F_8D02_505DEE438573__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000

    #define VC_EXTRALEAN        // Exclude rarely-used stuff from Windows headers

    #include <afx.h>
    #include <afxwin.h>         // MFC core and standard components
    #include <afxext.h>         // MFC extensions
    #include <afxdtctl.h>        // MFC support for Internet Explorer 4 Common Controls
    #ifndef _AFX_NO_AFXCMN_SUPPORT
    #include <afxcmn.h>            // MFC support for Windows Common Controls
    #endif // _AFX_NO_AFXCMN_SUPPORT

    #include <iostream>

    // TODO: reference additional headers your program requires here

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_STDAFX_H__48940212_4EA5_466F_8D02_505DEE438573__INCLUDED_)

    非常感谢.

    谢谢.



    • 已编辑 张新波 2019年12月24日 10:04
    2019年12月24日 10:01