Ich versuche, eine PE-Datei zu lesen.
Das Problem ist, dass die Daten RVA-Zeiger verwendet, während ich Offset innerhalb der Datei
brauche, um zu bekommen, was ich brauche. Wie kann ich die RVA in den Offset in der Datei konvertieren?bekomme Offset in Datei von RVA
Antwort
die Datei von RVA Offset Um zu bestimmen, benötigen Sie:
- in dem Abschnitt Punkte RVA zu bestimmen.
- subtrahieren von Ihrer Adresse relativ virtuelle Adresse des Abschnitts
- fügen Sie die Datei von Abschnitt versetzt führen
Sie eine Datei erhalten Offset, die Sie benötigen.
file Offset = RVAOfData - Virtual Offset + Raw Offset
Beispiel:
Unsere Ressource-Abschnitt (".rsrc") Details:
Virtuelle Offset: F000
Raw Offset: C600
Lässt auf einen der Ressource suchen wir haben:
Name: BIN
RVA von Daten: F0B0
Dateioffset:?
fileOffset = RVAOfData - Virtual Offset + Raw Offset
=> C6B0 = F0B0 - F000 + C600
Datei-Offset: C6B0
Referenz:
Understanding RVAs and Import Tables - by Sunshine
Funktion 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);
}
Das folgende Beispiel gibt den Dateioffset der Adresse des Eingangspunkts von RVA an. Man kann jeden Zeiger übergeben, um seinen Plattenoffset von RVA zu erhalten.
Grundsätzlich müssen wir herausfinden, in welchen Abschnitt die Adresse gehört. Sobald der richtige Abschnitt identifiziert wurde, verwenden Sie die Formel unten, um den Offset zu erhalten.
DWORD RetAddr = ptr - (sectionHeader-> VirtualAddress) +
(sectionHeader-> PointerToRawData);
dann Datei Basisadresse hinzufügen physikalische bekommen Adresse
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;
}
Können Sie Ihrem Code Kommentare hinzufügen? –
hinzugefügt eine Beschreibung sowie Kommentare. –
Angenommen, Sie es nicht aus der Datei lesen konnte, wie funktioniert der PE-Loader Arbeit? – harold
Ich weiß es nicht ... Zeigt es die Abwicklungsinfo? und wenn ich es aus der Datei lesen kann, was ist der Adressversatz von? – Idov
Nach meinen Informationen, sind sie relativ zu ImageBase (in der Kopfzeile) – harold