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;
}

 

posted @ 2016-03-15 12:04  疯陈演义  阅读(1725)  评论(1编辑  收藏  举报