从RVA获取文件偏移量

时间:2012-03-31 12:13:16

标签: 64-bit portable-executable

我试图读取PE文件 问题是数据使用RVA指针,而我需要文件中的偏移量  得到我需要的东西。 如何将RVA转换为文件中的偏移?

3 个答案:

答案 0 :(得分:4)

要通过RVA确定文件偏移量,您需要:

  1. 确定哪个部分指向RVA。
  2. 从您的地址减去部分
  3. 的相对虚拟地址
  4. 添加结果
  5. 的文件偏移量

    您将收到所需的文件偏移量。

答案 1 :(得分:0)

file Offset = RVAOfData - Virtual Offset + Raw Offset  

例:
我们的资源部分(" .rsrc")详细信息:
虚拟偏移:F000
原始抵消:C600

https://developer.mozilla.org/es/docs/Web/API/Console/clear

让我们看看我们拥有的资源之一:
姓名:BIN
数据的RVA:F0B0
文件偏移量:?

enter image description here

fileOffset = RVAOfData - Virtual Offset + Raw Offset   
=>  C6B0   = F0B0      - F000           + C600 

文件偏移:C6B0

enter image description here

参考:
enter image description here

C#中的功能:

// Example:
//   RVA: F0B0
//   Virtual offset: F000 ("RVA" in PEview)
//   Raw offset: C600 ("Pointer to Raw Data" in PEview)
//   fileOffset = F0B0 - F000 + C600 = C6B0
private static uint rvaToFileOffset(uint i_Rva, uint i_VirtualOffset, uint i_RawOffset)
{
    return (i_Rva - i_VirtualOffset + i_RawOffset);
}

答案 2 :(得分:0)

下面的示例给出了RVA入口点地址的文件偏移量。可以传递任何指针以从RVA获取其磁盘偏移量。

基本上我们需要找到地址所属的部分。确定正确的部分后,使用以下公式来获得抵消。

  

DWORD retAddr = ptr - (sectionHeader-> VirtualAddress)+
       (sectionHeader->的PointerToRawData);

然后添加文件基地址以获取物理地址

  

retAddr +(PBYTE)lpFileBase

    LPCSTR fileName="exe_file_to_parse";
    HANDLE hFile; 
    HANDLE hFileMapping;
    LPVOID lpFileBase;
    PIMAGE_DOS_HEADER dosHeader;
    PIMAGE_NT_HEADERS peHeader;
    PIMAGE_SECTION_HEADER sectionHeader;

    hFile = CreateFileA(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

    if(hFile==INVALID_HANDLE_VALUE)
    {
        printf("\n CreateFile failed in read mode \n");
        return 1;
    }

    hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);

    if(hFileMapping==0)
    {
        printf("\n CreateFileMapping failed \n");
        CloseHandle(hFile);
        return 1;
    }

    lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0); // Base pointer to file

    if(lpFileBase==0)
    {
        printf("\n MapViewOfFile failed \n");
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        return 1;
    }

    dosHeader = (PIMAGE_DOS_HEADER) lpFileBase;  //pointer to dos headers

    if(dosHeader->e_magic==IMAGE_DOS_SIGNATURE)
    {
        //if it is executable file print different fileds of structure
        //dosHeader->e_lfanew : RVA for PE Header
        printf("\n DOS Signature (MZ) Matched");

        //pointer to PE/NT header
        peHeader = (PIMAGE_NT_HEADERS) ((u_char*)dosHeader+dosHeader->e_lfanew);

        if(peHeader->Signature==IMAGE_NT_SIGNATURE)
        {
            printf("\n PE Signature (PE) Matched \n");
            // valid executable so we can proceed

            //address of entry point
            DWORD ptr = peHeader->OptionalHeader.AddressOfEntryPoint;

            //instead of AEP send any pointer to get actual disk offset of it
            printf("\n RVA : %x \n",ptr); // this is in memory address i.e. RVA
            //suppose any one wants to know actual disk offset of "address of entry point" (AEP)

            sectionHeader = IMAGE_FIRST_SECTION(peHeader); //first section address
            UINT nSectionCount = peHeader->FileHeader.NumberOfSections;
            UINT i=0;
            //check in which section the address belongs
            for( i=0; i<=nSectionCount; ++i, ++sectionHeader )
            {
                if((sectionHeader->VirtualAddress) > ptr)
                {
                    sectionHeader--;
                    break;
                }
            }

            if(i>nSectionCount)
            {
                sectionHeader = IMAGE_FIRST_SECTION(peHeader);
                UINT nSectionCount = peHeader->FileHeader.NumberOfSections;
                for(i=0; i<nSectionCount-1; ++i,++sectionHeader);
            }

            //once the correct section is found below formula gives the actual disk offset 
            DWORD retAddr = ptr - (sectionHeader->VirtualAddress) +
                    (sectionHeader->PointerToRawData);
            printf("\n Disk Offset : %x \n",retAddr+(PBYTE)lpFileBase);
            // retAddr+(PBYTE)lpFileBase contains the actual disk offset of address of entry point

        }
        UnmapViewOfFile(lpFileBase);
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        //getchar();
        return 0;
    }
    else
    {
        printf("\n DOS Signature (MZ) Not Matched \n");
        UnmapViewOfFile(lpFileBase);
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        return 1;
    }