zoukankan      html  css  js  c++  java
  • Windows Pe 第三章 PE头文件-EX-相关编程-2(RVA_FOA转换)

    RVA-FOA之间转换

     

    1.首先PE头加载到内存之后是和文件头内容一样的,就算是偏移不同,一个是磁盘扇区大小(400H)另一个是内存页大小(1000H),但是因为两个都是开头位置,所以相同。

     

    2.看下IMAGE_SECTION_HEADER定义

     

    也就是这样:

     

    然后就可以算了(RVA->FOA)

     

    (1) RVA20 < RVA < RVA30 可以知道在第二节

    (2) 然后 off = RVA - RVA20 ,得出距离第二节的偏移off

    (3) FOA = FOA 20 + off 求出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;  
    return  pSection[i].VirtualAddress + dwDiffer;
            }  
            else if (stOffset < dwBeginVA)    //如果文件偏移地址不在区段中  
            {  
                return dwImageBase + stOffset;  
            }  
        }  
        return 0;  
    }  
     

    测试了上面两个函数,没发现什么问题,测试结果:

     

    随手写了个简单的工具,直接控制台写的,功能简单,懒得写界面了。源码在:

    http://download.csdn.net/detail/u013761036/9643230

    运行效果:


  • 相关阅读:
    JavaScript的数据类型
    php字符串操作
    PHP快速入门
    JavaScript简介与使用方法
    《技术大牛的养成指南》--读书笔记
    Java并发编程-多线程
    分布式锁的实现方式和优缺点&Java代码实现
    Java操作Zookeeper
    排序二叉树、平衡二叉树、红黑树
    HashMap&Hashtable&LinkedHashMap&ConcurrentHashMap&Collections.synchronizedMap
  • 原文地址:https://www.cnblogs.com/csnd/p/12062236.html
Copyright © 2011-2022 走看看