驱动中实现兼容x86/x64的GetProcAddress

本文阅读 1 分钟
首页 驱动开发 正文
    //************************************
    // 函数名: GetProcAddressA
    // 返回值: 函数在模块中的地址
    // 功能:  查找函数在模块中的地址
    // 参数1: 模块地址
    // 参数2: 函数名称
    //************************************
    PVOID GetProcAddressA(HANDLE Module, PCHAR ProcName)
    {
        if (!Module)
        {
            return NULL;
        }
        PIMAGE_DOS_HEADER ImageDosHeader = (PIMAGE_DOS_HEADER)Module;
        if (ImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
        {
            return NULL;
        }

        PIMAGE_NT_HEADERS32 ImageNtHeader32 = (PIMAGE_NT_HEADERS32)((DWORD_PTR)Module + ImageDosHeader->e_lfanew);
        PIMAGE_NT_HEADERS64 ImageNtHeader64 = (PIMAGE_NT_HEADERS64)((DWORD_PTR)Module + ImageDosHeader->e_lfanew);
        if (ImageNtHeader64->Signature != IMAGE_NT_SIGNATURE)
        {
            return NULL;
        }
        PIMAGE_DATA_DIRECTORY ImageDataDirectory = NULL;
        if (ImageNtHeader64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
        {
            ImageDataDirectory = &ImageNtHeader64->OptionalHeader.
                DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
        }
        else if (ImageNtHeader64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
        {
            ImageDataDirectory = &ImageNtHeader32->OptionalHeader.
                DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
        }
        else
        {
            return NULL;
        }

        PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)Module + ImageDataDirectory->VirtualAddress);
        ULONG ImageExportDirectorySize = ImageDataDirectory->Size;
        if (ImageExportDirectory == NULL)
        {
            return NULL;
        }

        // 函数地址数组
        PULONG AddressOfFunctions = (PULONG)((DWORD_PTR)Module + ImageExportDirectory->AddressOfFunctions);
        // 名称方式导出函数名称数组
        PULONG AddressOfNames = (PULONG)((DWORD_PTR)Module + ImageExportDirectory->AddressOfNames);
        // 名称方式导出函数序号数组
        PUSHORT AddressOfNameOrdinals = (PUSHORT)((DWORD_PTR)Module + ImageExportDirectory->AddressOfNameOrdinals);

        PVOID ProcAddress = NULL;
        if ((DWORD_PTR)ProcName >> 16 == 0)
        {
            WORD Ordinal = LOWORD(ProcName);
            ULONG OrdinalBase = ImageExportDirectory->Base;
            if (Ordinal < OrdinalBase || Ordinal >= OrdinalBase + ImageExportDirectory->NumberOfFunctions)
            {
                return NULL;
            }
            ProcAddress = (PVOID)((DWORD_PTR)Module + AddressOfFunctions[Ordinal - OrdinalBase]);
        }
        else
        {
            for (size_t i = 0; i < ImageExportDirectory->NumberOfNames; i++)
            {
                char* FunctionName = (char*)((DWORD_PTR)Module + AddressOfNames[i]);
                if (strcmp(ProcName, FunctionName) == 0)
                {
                    ProcAddress = (PVOID)((DWORD_PTR)Module + AddressOfFunctions[AddressOfNameOrdinals[i]]);
                    break;
                }
            }
        }

        // 转发函数
        if ((ULONG_PTR)ProcAddress >= (ULONG_PTR)ImageExportDirectory && (ULONG_PTR)ProcAddress <= (ULONG_PTR)ImageExportDirectory + ImageExportDirectorySize)
        {
            char LibraryName[MAX_PATH] = { 0 };
            char FunctionName[MAX_PATH] = { 0 };
            strcpy(LibraryName, ProcAddress);
            char* p = strchr(LibraryName, '.');
            if (!p)
            {
                return NULL;
            }
            *p = 0;
            strcpy(FunctionName, p + 1);
            strcat(LibraryName, ".dll");
            HMODULE Library = LoadLibraryA(LibraryName);
            if (Library == NULL)
            {
                return NULL;
            }
            return  GetProcAddressA(Library, FunctionName);
        }
        return ProcAddress;
    }
本文来自投稿,不代表本站立场,如若转载,请注明出处:
虚拟机使用的是此版本 VMware Workstation 不支持的硬件版本解决方案
« 上一篇 01-20
驱动中获取当前进程名的方法
下一篇 » 01-25