6.2 遍历重定位表

本节我们将编写一个遍历重定位表的示例程序,打印重定位表。

本节必须掌握的知识点:

        遍历重定位表

6.2.1 遍历重定位表

实验四十三:遍历重定位表

Image_093

以下代码实现打印"c:\\notepad64.exe"进程重定位表的所有信息。

/*------------------------------------------------------------------------

 FileName:PrintImportDescriptor.c

 实验43:遍历重定位表(支持32位和64位PE)

 (c) bcdaren, 2024

-----------------------------------------------------------------------*/

#include <stdio.h>

#include <windows.h>

#include <winnt.h>

#define WIN64



PBYTE creatfilemap(LPCWSTR szFile);

VOID printReloc(PBYTE lpvResult);

DWORD RvaToFoa(PIMAGE_NT_HEADERS ntHeaders, DWORD rva);



int main(int argc, char* argv[])

{

    //LPCWSTR szFileName = TEXT("c:\\winResult.dll");

    LPCWSTR szFileName = TEXT("c:\\notepad64.exe");

    PBYTE lpAddress = NULL; //PE文件内存映射文件地址



    lpAddress = creatfilemap(szFileName);

    if (lpAddress)

    {

        printf("%ls\n", szFileName);

        printReloc(lpAddress);

    }

    system("pause");

    return 0;

}



//创建PE文件映射对象

PBYTE creatfilemap(LPCWSTR szFile)

{

    HANDLE hFile;

    HANDLE hMapFile = NULL;

    PBYTE lpMemory = NULL;  //PE文件内存映射文件地址

    char buffer[16] = { 0 };

    DWORD dwFileSize;

    DWORD dwBytesRead = 0;

    PIMAGE_DOS_HEADER lpstDOS = NULL;

    PIMAGE_NT_HEADERS lpstNT = NULL;



    hFile = CreateFile(szFile,

        GENERIC_READ,          // 只读打开

        FILE_SHARE_READ,       // 允许其他进程以读取方式打开文件

        NULL,                  // 默认安全属性

        OPEN_EXISTING,         // 打开已存在的文件

        FILE_ATTRIBUTE_NORMAL, // 普通文件

        NULL);



    if (hFile == INVALID_HANDLE_VALUE)

        printf("打开文件失败!\n");

    else

    {

        dwFileSize = GetFileSize(hFile, 0);//获得文件大小可通过结构体获取

        //创建内存映射文件

        if (dwFileSize)

        {

            if (hMapFile = CreateFileMapping(hFile, NULL,

PAGE_READONLY, 0, 0, NULL))

            {

                //获得文件在内存的映象起始位置

                lpMemory = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);

                if (!lpMemory)

                    printf("获取映像起始地址失败!\n");



                //检查PE文件是否有效

                lpstDOS = (PIMAGE_DOS_HEADER)lpMemory;

                if (lpstDOS->e_magic != IMAGE_DOS_SIGNATURE)

                    printf("非PE格式文件!\n");



                lpstNT = (PIMAGE_NT_HEADERS)(lpMemory + lpstDOS->e_lfanew);



                if (lpstNT->Signature != IMAGE_NT_SIGNATURE)

                    printf("非PE格式文件!\n");

            }

        }

    }

    return lpMemory;

}



//32位PE文件

VOID printReloc(PBYTE lpvResult)

{

    PIMAGE_DOS_HEADER pImageDOSHeader = (PIMAGE_DOS_HEADER)lpvResult;

#ifdef WIN64

    PIMAGE_NT_HEADERS64 psImageNTHeader = (PIMAGE_NT_HEADERS64)(lpvResult + pImageDOSHeader->e_lfanew);

#else

    PIMAGE_NT_HEADERS32 psImageNTHeader = (PIMAGE_NT_HEADERS32)(lpvResult + pImageDOSHeader->e_lfanew);

#endif

    //重定位表RVA

    DWORD RelocRVA = psImageNTHeader->OptionalHeader.DataDirectory[5].VirtualAddress;

    DWORD dwTemp = 0;

    //获取重定位表FOA地址

    PIMAGE_BASE_RELOCATION pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)RvaToFoa((PIMAGE_NT_HEADERS)psImageNTHeader, RelocRVA);

    dwTemp = (DWORD)pImageDOSHeader + (DWORD)pImageBaseRelocation;



    for(DWORD i = 0; (DWORD*)(((PIMAGE_BASE_RELOCATION)dwTemp)->VirtualAddress ) != 0; i++)

    {

        printf("virtual address : 0x%08x\n", ((PIMAGE_BASE_RELOCATION)dwTemp)->VirtualAddress);

        printf("size of block   : 0x%08x\n", ((PIMAGE_BASE_RELOCATION)dwTemp)->SizeOfBlock);

        for (DWORD j = 0; j < ((PIMAGE_BASE_RELOCATION)dwTemp)->SizeOfBlock - 8; j += 2)

        {

            printf("%4x\t", *(WORD*)(dwTemp + 8 + j));

        }

        dwTemp += ((PIMAGE_BASE_RELOCATION)dwTemp)->SizeOfBlock;

        printf("\n");

    }

}



//RVA转FOA

DWORD RvaToFoa(PIMAGE_NT_HEADERS ntHeaders, DWORD rva) {

    //ntHeaders+4+sizeof(IMAGE_FILE_HEADER)+FileHeader.SizeOfOptionalHeader(32或64位PE)

    PIMAGE_SECTION_HEADER sectionHeader = IMAGE_FIRST_SECTION(ntHeaders);

    WORD numberOfSections = ntHeaders->FileHeader.NumberOfSections;



    for (WORD i = 0; i < numberOfSections; i++) {

        DWORD sectionStartRva = sectionHeader->VirtualAddress;

        DWORD sectionEndRva = sectionStartRva + sectionHeader->SizeOfRawData;



        if (rva >= sectionStartRva && rva < sectionEndRva) {

            DWORD foa = sectionHeader->PointerToRawData + (rva –

sectionStartRva);

            return foa;

        }

        sectionHeader++;

    }

    return 0;  // RVA not found

}

图6-3 打印notepad64.exe重定位表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值