Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getting offset in file from RVA

I'm trying to read a PE file.
The problems is that the data uses RVA pointers while I need offset within the file
to get what I need. How can I convert the RVA to offset in the file?

like image 597
Idov Avatar asked Mar 31 '12 12:03

Idov


People also ask

What is RVA and offset?

An RVA ("relative virtual offset") is used to describe a memory offset if the base address is unknown. So it's not the same like a file offset! If you have the section table it's easy to calculate a file offset from a RVA.

What is RVA in PE file?

A description of a field that indicates that the value of the field must be zero for generators and consumers must ignore the field. Relative virtual address (RVA) In an image file, this is the address of an item after it is loaded into memory, with the base address of the image file subtracted from it.

What is RVA in malware?

RVA = virtual address – base address (starting address in the memory) The address of the entry point is the address where the PE loader will begin execution; this is the address that is relative to image base when the executable is loaded into memory.

What is offset in malware analysis?

The file offset is actually a location within that particular file. To make it easier for you to understand it is actually the distance from the starting point either the start of the file or the start of a memory address. The offset value is added to the base value to determine the actual value.


2 Answers

To determine the file offset by RVA, you need:

  1. to determine in which section points RVA.
  2. subtract from your address relative virtual address of section
  3. add to result the file offset of section

You will receive a file offset that you need.

like image 51
Evgeny Avatar answered Sep 29 '22 17:09

Evgeny


Below example gives file offset of address of entry point from RVA. One can pass any pointer to get its disk offset from RVA.

Basically we need to find in which section the address belongs. Once the correct section is identified use below formula to get offset.

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

then add file base address to get physical address

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;
    }
like image 20
Nishikant Mokashi Avatar answered Sep 29 '22 15:09

Nishikant Mokashi