Czesc, mam pytanie dotyczace przeliczenia adresu RVA (Real Vritual Address) na Offset w pliku.
Ma ktos moze jakis gotowy przyklad w postaci src?
Pozdrawiam.
Czesc, mam pytanie dotyczace przeliczenia adresu RVA (Real Vritual Address) na Offset w pliku.
Ma ktos moze jakis gotowy przyklad w postaci src?
Pozdrawiam.
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.
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 ;)
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;
Dziekuje! Bardzo mi pomogłeś :)
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