我们如何将某个位置的 RVA(相对虚拟地址)映射到 PE 文件偏移量?

发布于 2024-10-08 21:27:07 字数 132 浏览 3 评论 0原文

从磁盘位置读取 PE 文件时,我需要将 RVA(从 pdb 文件获取的相对虚拟地址)映射到 PE 文件(EXE)偏移量。为此,我需要将 RVA 转换为文件偏移量,以便我可以从该位置读出 GUIDS(CLSID、IID)。

问候 乌斯曼

I need to map RVA (Relative virtual address that's taken from pdb file) to PE file(EXE) offset when reading PE file from a disk location. For this I need to convert RVA to file offset so that I can read out GUIDS(CLSID,IID's) from that location.

Regards
Usman

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

赠我空喜 2024-10-15 21:27:07

您可以使用 ImageRvaToVa 函数。

You can use ImageRvaToVa function.

有木有妳兜一样 2024-10-15 21:27:07
template <class T> LPVOID GetPtrFromRVA(
   DWORD rva,
   T* pNTHeader,
   PBYTE imageBase ) // 'T' = PIMAGE_NT_HEADERS
{
   PIMAGE_SECTION_HEADER pSectionHdr;
   INT delta;

   pSectionHdr = GetEnclosingSectionHeader( rva, pNTHeader);
   if ( !pSectionHdr )
      return 0;

   delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
   return (PVOID) ( imageBase + rva - delta );
}

template <class T> PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(
   DWORD rva,
   T* pNTHeader)   // 'T' == PIMAGE_NT_HEADERS
{
    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
    unsigned i;

    for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
    {
      // This 3 line idiocy is because Watcom's linker actually sets the
      // Misc.VirtualSize field to 0.  (!!! - Retards....!!!)
      DWORD size = section->Misc.VirtualSize;
      if ( 0 == size )
         size = section->SizeOfRawData;

        // Is the RVA within this section?
        if ( (rva >= section->VirtualAddress) &&
             (rva < (section->VirtualAddress + size)))
            return section;
    }

    return 0;
}

应该做的伎俩...

template <class T> LPVOID GetPtrFromRVA(
   DWORD rva,
   T* pNTHeader,
   PBYTE imageBase ) // 'T' = PIMAGE_NT_HEADERS
{
   PIMAGE_SECTION_HEADER pSectionHdr;
   INT delta;

   pSectionHdr = GetEnclosingSectionHeader( rva, pNTHeader);
   if ( !pSectionHdr )
      return 0;

   delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
   return (PVOID) ( imageBase + rva - delta );
}

template <class T> PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(
   DWORD rva,
   T* pNTHeader)   // 'T' == PIMAGE_NT_HEADERS
{
    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
    unsigned i;

    for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
    {
      // This 3 line idiocy is because Watcom's linker actually sets the
      // Misc.VirtualSize field to 0.  (!!! - Retards....!!!)
      DWORD size = section->Misc.VirtualSize;
      if ( 0 == size )
         size = section->SizeOfRawData;

        // Is the RVA within this section?
        if ( (rva >= section->VirtualAddress) &&
             (rva < (section->VirtualAddress + size)))
            return section;
    }

    return 0;
}

should do the trick...

帝王念 2024-10-15 21:27:07

下面的代码片段将入口点地址的 RVA 转换为实际磁盘偏移量。发送任何 RVA 以将其转换为磁盘偏移量,而不是 AEP 的地址。

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

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 
        //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
        //suppose any one wants to know actual disk offset of "address of entry point" (AEP)

        sectionHeader = IMAGE_FIRST_SECTION(peHeader);
        UINT nSectionCount = peHeader->FileHeader.NumberOfSections;
        UINT i=0;
        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);
        }

        DWORD retAddr = ptr - (sectionHeader->VirtualAddress) +
                (sectionHeader->PointerToRawData);
        printf("\n Disk Offset : %x \n",retAddr+(PBYTE)lpFileBase);
        // retAddr + lpFileBase  contains the actual disk address 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;
}

Below code snippet converts RVA of address of entry point to actual disk offset. Instead of address of AEP send any RVA to convert it into disk offset.

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

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 
        //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
        //suppose any one wants to know actual disk offset of "address of entry point" (AEP)

        sectionHeader = IMAGE_FIRST_SECTION(peHeader);
        UINT nSectionCount = peHeader->FileHeader.NumberOfSections;
        UINT i=0;
        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);
        }

        DWORD retAddr = ptr - (sectionHeader->VirtualAddress) +
                (sectionHeader->PointerToRawData);
        printf("\n Disk Offset : %x \n",retAddr+(PBYTE)lpFileBase);
        // retAddr + lpFileBase  contains the actual disk address 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文