• PE文件RV转FOA及FOA转RVA


    /************************************************************************/
    /*
    功能:虚拟内存相对地址和文件偏移的转换
    参数:stRVA:    虚拟内存相对偏移地址
    lpFileBuf: 文件起始地址
    返回:转换后的文件偏移地址
    */
    /************************************************************************/
    size_t RVAToOffset(size_t stRVA, PVOID lpFileBuf)
    {
        PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpFileBuf;
        size_t stPEHeadAddr = (size_t)lpFileBuf + pDos->e_lfanew;
        PIMAGE_NT_HEADERS32 pNT = (PIMAGE_NT_HEADERS32)stPEHeadAddr;
        //区段数
        DWORD dwSectionCount = pNT->FileHeader.NumberOfSections;
        //内存对齐大小
        DWORD dwMemoruAil = pNT->OptionalHeader.SectionAlignment;
        PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNT);
        //距离命中节的起始虚拟地址的偏移值。
        DWORD  dwDiffer = 0;
        for (DWORD i = 0; i < dwSectionCount; i++)
        {
            //模拟内存对齐机制
            DWORD dwBlockCount = pSection[i].SizeOfRawData / dwMemoruAil;
            dwBlockCount += pSection[i].SizeOfRawData%dwMemoruAil ? 1 : 0;
    
            DWORD dwBeginVA = pSection[i].VirtualAddress;
            DWORD dwEndVA = pSection[i].VirtualAddress + dwBlockCount * dwMemoruAil;
            //如果stRVA在某个区段中
            if (stRVA >= dwBeginVA && stRVA < dwEndVA)
            {
                dwDiffer = stRVA - dwBeginVA;
                return pSection[i].PointerToRawData + dwDiffer;
            }
            else if (stRVA < dwBeginVA)//在文件头中直接返回
            {
                return stRVA;
            }
        }
        return 0;
    }
    /************************************************************************/
    /*
    功能:文件偏移地址和虚拟地址的转换
    参数:stOffset:文件偏移地址
    lpFileBuf:虚拟内存起始地址
    返回:转换后的虚拟地址
    */
    /************************************************************************/
    size_t Offset2VA(size_t stOffset, PVOID lpFileBuf)
    {
        //获取DOS头
        PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpFileBuf;
        //获取PE头
        //e_lfanew:PE头相对于文件的偏移地址
        size_t stPEHeadAddr = (size_t)lpFileBuf + pDos->e_lfanew;
        PIMAGE_NT_HEADERS32 pNT = (PIMAGE_NT_HEADERS32)stPEHeadAddr;
        //区段数
        DWORD dwSectionCount = pNT->FileHeader.NumberOfSections;
        //映像地址
        DWORD dwImageBase = pNT->OptionalHeader.ImageBase;
        //区段头
        PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNT);
    
        //相对大小
        DWORD  dwDiffer = 0;
        for (DWORD i = 0; i < dwSectionCount; i++)
        {
            //区段的起始地址和结束地址
            DWORD dwBeginVA = pSection[i].PointerToRawData;
            DWORD dwEndVA = pSection[i].PointerToRawData + pSection[i].SizeOfRawData;
            //如果文件偏移地址在dwBeginVA和dwEndVA之间
            if (stOffset >= dwBeginVA && stOffset < dwEndVA)
            {
                //相对大小
                dwDiffer = stOffset - dwBeginVA;
                //进程的起始地址 + 区段的相对地址 + 相对区段的大小
                return dwImageBase + pSection[i].VirtualAddress + dwDiffer;
            }
            else if (stOffset < dwBeginVA)    //如果文件偏移地址不在区段中
            {
                return dwImageBase + stOffset;
            }
        }
        return 0;
    }
  • 相关阅读:
    c# 方法重载
    c# propertyGrid下拉选项
    c# 枚举类型
    c# socket编程
    读书笔记之ado.net entity framework
    c# delegate的invoke和bejinInvoke的区别
    C# 读书笔记之类与结构体
    c#笔记之启动新线程
    c# listview的使用
    visual studio2013 改变匹配括号的颜色
  • 原文地址:https://www.cnblogs.com/wumac/p/5278853.html
Copyright © 2020-2023  润新知