RVA to Offset

0

Czesc, mam pytanie dotyczace przeliczenia adresu RVA (Real Vritual Address) na Offset w pliku.
Ma ktos moze jakis gotowy przyklad w postaci src?

Pozdrawiam.

0
miker napisał(a)

Czesc, mam pytanie dotyczace przeliczenia adresu RVA (Real Vritual Address) na Offset w pliku.
Ma ktos moze jakis gotowy przyklad w postaci src?

Pozdrawiam.

do uses rxtypes jest w %DELPHI%\Demos\ResXplor

FileBase uzyskujesz funkcją MapViewOfFile chyba wiesz jak a jak nie to pisz.

function RVAToOffset(FileBase: Pointer;RVA: Cardinal): Cardinal;
var
  DosHeader: PIMAGE_DOS_HEADER;
  NTHeader: PIMAGE_NT_HEADERS;
  SecHeader: PIMAGE_SECTION_HEADER;
  i: Word;
begin
  result:= 0;
  DosHeader := PIMAGE_DOS_HEADER(FileBase);
  if not DosHeader.e_magic = IMAGE_DOS_SIGNATURE then exit;
  NTHeader := PIMAGE_NT_HEADERS(Longint(DosHeader) + DosHeader.e_lfanew);
  if IsBadReadPtr(NTHeader, sizeof(IMAGE_NT_HEADERS)) or
     (NTHeader.Signature <> IMAGE_NT_SIGNATURE) then exit;
  SecHeader := PIMAGE_SECTION_HEADER(NTHeader);
  Inc(PIMAGE_NT_HEADERS(SecHeader));
  for i:= 0 to NTHeader.FileHeader.NumberOfSections - 1 do
  begin
   if (RVA >= SecHeader.VirtualAddress) and
         (RVA < (SecHeader.VirtualAddress + SecHeader.SizeOfRawData)) then
      result:= (SecHeader.VirtualAddress - RVA) + SecHeader.PointerToRawData;
    inc(SecHeader);
  end;
end;

Chyba działa bo kod wydarłem ze starego (z przed 3 lat) mojego programu tylko go troszkę zoptymalizowalem.

0

do uses rxtypes jest w %DELPHI%\Demos\ResXplor

FileBase uzyskujesz funkcją MapViewOfFile chyba wiesz jak a jak nie to pisz.

Wielkie dzieki. nie mam u siebie w delpih rxtypes.dcu na torry.net tez nie moge znaleŹĆ wiec jak bys mogl wystawic gdzies albo wrzucic na mytempdir.com bylbym wdzieczny.

Kod na oko dobrze wyglada, z tym MapViewOfFile mozesz rowzniesz napisac, przyda sie. Dziekuje raz jeszcze za pomoc ;)

0

Ok, wrzuciłem rxtypes.pas umieść go w katalogu programu lub %Delphi%\Lib

Zmienne:
fBase: Pointer;
fHandle: Cardinal;
fMapping: Cardinal;

To wykonujesz na początku aby pobrać FileBase (zmienna fBase), funkcja zwraca false jeżeli wystąpi błąd.

function MapFile(fName: PChar): Boolean;
begin
  result:= False;
  fBase:= nil;
  fHandle := CreateFile(fName, GENERIC_READ, FILE_SHARE_READ,
      nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  if fHandle = INVALID_HANDLE_VALUE then exit;
  fMapping := CreateFileMapping(fHandle, nil, PAGE_READONLY, 0, 0, nil);
  if fMapping > 0 then
    fBase := MapViewOfFile(fMapping, FILE_MAP_READ, 0, 0, 0)
  else
    CloseHandle(fHandle);
  result:= (fBase <> nil);
end;

A to na końcu:

procedure UnMapFile;
begin
  UnmapViewOfFile(fBase);
  CloseHandle(fMapping);
  CloseHandle(fHandle);
end;
0

Dziekuje! Bardzo mi pomogłeś :)

0

Masz jeszcze

function VAToOffset(FileBase: Pointer;VA: Cardinal): Cardinal;
var
  DosHeader: PIMAGE_DOS_HEADER;
  NTHeader: PIMAGE_NT_HEADERS;
  SecHeader: PIMAGE_SECTION_HEADER;
  ImageBase: Cardinal;
  i: Word;
  tmpOffset, tmp: Cardinal;
begin
  result:= 0;
  DosHeader := PIMAGE_DOS_HEADER(FileBase);
  if not DosHeader.e_magic = IMAGE_DOS_SIGNATURE then exit;
  NTHeader := PIMAGE_NT_HEADERS(Longint(DosHeader) + DosHeader.e_lfanew);
  if IsBadReadPtr(NTHeader, sizeof(IMAGE_NT_HEADERS)) or
     (NTHeader.Signature <> IMAGE_NT_SIGNATURE) then exit;
  SecHeader := PIMAGE_SECTION_HEADER(NTHeader);
  Inc(PIMAGE_NT_HEADERS(SecHeader));
  ImageBase:= NTHeader.OptionalHeader.ImageBase;
  for i:= 0 to NTHeader.FileHeader.NumberOfSections - 1 do
  begin
    tmpOffset:= RVAToOffset(FileBase, SecHeader.VirtualAddress);
    tmp:= ImageBase + SecHeader.VirtualAddress;
    Inc(SecHeader);
    if (ImageBase + SecHeader.VirtualAddress) > VA then
    begin
      result:= (VA - tmp) + tmpOffset;
      break;
    end;
  end;
end;

function OffsetToVA(FileBase: Pointer;Offset: Cardinal): Cardinal;
var
  DosHeader: PIMAGE_DOS_HEADER;
  NTHeader: PIMAGE_NT_HEADERS;
  SecHeader: PIMAGE_SECTION_HEADER;
  ImageBase: Cardinal;
  i: Word;
  tmpOffset, tmp: Cardinal;
begin
  result:= 0;
  DosHeader := PIMAGE_DOS_HEADER(FileBase);
  if not DosHeader.e_magic = IMAGE_DOS_SIGNATURE then exit;
  NTHeader := PIMAGE_NT_HEADERS(Longint(DosHeader) + DosHeader.e_lfanew);
  if IsBadReadPtr(NTHeader, sizeof(IMAGE_NT_HEADERS)) or
     (NTHeader.Signature <> IMAGE_NT_SIGNATURE) then exit;
  SecHeader := PIMAGE_SECTION_HEADER(NTHeader);
  Inc(PIMAGE_NT_HEADERS(SecHeader));
  ImageBase:= NTHeader.OptionalHeader.ImageBase;
  for i:= 0 to NTHeader.FileHeader.NumberOfSections - 1 do
  begin
    tmpOffset:= RVAToOffset(FileBase, SecHeader.VirtualAddress);
    tmp:= ImageBase + SecHeader.VirtualAddress;
    inc(SecHeader);
    result:= (Offset + tmp) - tmpOffset;
    if Offset < SecHeader.VirtualAddress then
      begin
        break;
      end;
  end;
end;

moze ci sie przyda

1 użytkowników online, w tym zalogowanych: 0, gości: 1