Sto provando a leggere un file PE.
Il problema è che i dati utilizzano puntatori RVA mentre ho bisogno di offset all'interno del file
per ottenere ciò di cui ho bisogno. Come posso convertire l'RVA in offset nel file?ottenere offset in file da RVA
risposta
per determinare il file compensato da RVA, è necessario:
- per determinare in cui i punti di sezione RVA.
- sottrarre dal tuo indirizzo virtuale relativo di sezione
- aggiungere al risultato il file di offset della sezione
Riceverai compensato un file di cui avete bisogno.
file Offset = RVAOfData - Virtual Offset + Raw Offset
Esempio:
nostra sezione delle risorse (".rsrc") particolari:
virtuale Offset: F000 compensato
Raw: C600
lascia lo sguardo su una delle risorse abbiamo:
Nome: BIN
RVA di dati: F0B0
Offset file:?
fileOffset = RVAOfData - Virtual Offset + Raw Offset
=> C6B0 = F0B0 - F000 + C600
compensare File: C6B0
Riferimento:
Understanding RVAs and Import Tables - by Sunshine
funzione in 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);
}
Nell'esempio seguente viene fornito l'offset del file dell'indirizzo del punto di ingresso da RVA. Si può passare qualsiasi puntatore per ottenere il suo offset del disco da RVA.
Fondamentalmente abbiamo bisogno di trovare in quale sezione appartiene l'indirizzo. Una volta identificata la sezione corretta, utilizzare sotto la formula per ottenere l'offset.
DWORD RetAddr = ptr - (sectionHeader-> VirtualAddress) +
(sectionHeader-> PointerToRawData);
quindi aggiungere l'indirizzo di base di file per ottenere l'indirizzo fisico
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;
}
Puoi aggiungere alcuni commenti al tuo codice? –
aggiunto qualche descrizione e commenti. –
Supponiamo non si poteva leggere dal file, come fa il caricatore PE lavoro? – harold
Non so ... Mostra le informazioni per lo svolgimento? e se posso leggerlo dal file, qual è l'offset dell'indirizzo? – Idov
Secondo le mie informazioni, sono relativi a ImageBase (nell'intestazione) – harold