function RVAToFileOffset(FileName:string; RVA: Cardinal): Cardinal;

var

  MemPE: TFileStream;

  PEDosHead: TImageDosHeader;

  PENtHead: TImageNtHeaders;

  Section : TImageSectionHeader;

  i, SectionsCount: Integer;

begin

  Result := RVA;

  MemPE:=TFileStream.Create(FileName,fmOpenReadWrite);

  try

    MemPE.Seek(0, soFromBeginning);

    MemPE.Read(PEDosHead, SizeOf(PEDosHead));

    MemPE.Seek(PEDosHead._lfanew, soFromBeginning);

    MemPE.Read(PENtHead, SizeOf(PENtHead));


    SectionsCount := PENtHead.FileHeader.NumberOfSections;


    if SectionsCount <> 0 then

      for i := 0 to SectionsCount - 1 do

      begin

        MemPE.Read(Section, SizeOf(Section));

        if (RVA >= Section.VirtualAddress) and (RVA < Section.VirtualAddress + Section.SizeOfRawData) then

        begin

          Result := RVA - Section.VirtualAddress + Section.PointerToRawData;

          Break;

        end;

      end;

  finally

    FreeAndNil(MemPE);

  end;

end;



function FileOffsetToRVA(FileName:string; Offset: Cardinal): Cardinal;

var

  MemPE: TFileStream;

  PEDosHead: TImageDosHeader;

  PENtHead: TImageNtHeaders;

  Section : TImageSectionHeader;

  i, SectionsCount: Integer;

begin 

  Result :=Offset;

  MemPE:=TFileStream.Create(FileName,fmOpenReadWrite);

  try

    MemPE.Seek(0, soFromBeginning);

    MemPE.Read(PEDosHead, SizeOf(PEDosHead));

    MemPE.Seek(PEDosHead._lfanew, soFromBeginning);

    MemPE.Read(PENtHead, SizeOf(PENtHead));


    SectionsCount := PENtHead.FileHeader.NumberOfSections;


    if SectionsCount <> 0 then

      for i := 0 to SectionsCount - 1 do

      begin

        MemPE.Read(Section, SizeOf(Section));

        if (Offset >= Section.PointerToRawData) and (Offset < Section.PointerToRawData + Section.SizeOfRawData) then

        begin

          Result := Offset - Section.PointerToRawData + Section.VirtualAddress;

          Break;

        end;

      end;

  finally

    FreeAndNil(MemPE);

  end;

end;

程序源代码:

unit Unit1;


interface


uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls;


type

  TForm1 = class(TForm)

    Button1: TButton;

    Edit1: TEdit;

    Edit2: TEdit;

    Edit3: TEdit;

    Edit4: TEdit;

    Button2: TButton;

    Edit5: TEdit;

    Label1: TLabel;

    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

  private

    { Private declarations }

  public

    { Public declarations }

  end;


var

  Form1: TForm1;


implementation


{$R *.dfm}


function FileOffsetToRVA(FileName:string; Offset: Cardinal): Cardinal;

var

  MemPE: TFileStream;

  PEDosHead: TImageDosHeader;

  PENtHead: TImageNtHeaders;

  Section : TImageSectionHeader;

  i, SectionsCount: Integer;

begin

  Result :=Offset;

  MemPE:=TFileStream.Create(FileName,fmOpenReadWrite);

  try

    MemPE.Seek(0, soFromBeginning);

    MemPE.Read(PEDosHead, SizeOf(PEDosHead));

    MemPE.Seek(PEDosHead._lfanew, soFromBeginning);

    MemPE.Read(PENtHead, SizeOf(PENtHead));


    SectionsCount := PENtHead.FileHeader.NumberOfSections;


    if SectionsCount <> 0 then

      for i := 0 to SectionsCount - 1 do

      begin

        MemPE.Read(Section, SizeOf(Section));

        if (Offset >= Section.PointerToRawData) and (Offset < Section.PointerToRawData + Section.SizeOfRawData) then

        begin

          Result := Offset - Section.PointerToRawData + Section.VirtualAddress;

          Break;

        end;

      end;

  finally

    FreeAndNil(MemPE);

  end;

end;


procedure TForm1.Button1Click(Sender: TObject);

begin

Edit2.Text := string(FileOffsetToRVA(Edit5.Text,Cardinal(Edit1.Text)));

end;


function RVAToFileOffset(FileName:string; RVA: Cardinal): Cardinal;

var

  MemPE: TFileStream;

  PEDosHead: TImageDosHeader;

  PENtHead: TImageNtHeaders;

  Section : TImageSectionHeader;

  i, SectionsCount: Integer;

begin

  Result := RVA;

  MemPE:=TFileStream.Create(FileName,fmOpenReadWrite);

  try

    MemPE.Seek(0, soFromBeginning);

    MemPE.Read(PEDosHead, SizeOf(PEDosHead));

    MemPE.Seek(PEDosHead._lfanew, soFromBeginning);

    MemPE.Read(PENtHead, SizeOf(PENtHead));


    SectionsCount := PENtHead.FileHeader.NumberOfSections;


    if SectionsCount <> 0 then

      for i := 0 to SectionsCount - 1 do

      begin

        MemPE.Read(Section, SizeOf(Section));

        if (RVA >= Section.VirtualAddress) and (RVA < Section.VirtualAddress + Section.SizeOfRawData) then

        begin

          Result := RVA - Section.VirtualAddress + Section.PointerToRawData;

          Break;

        end;

      end;

  finally

    FreeAndNil(MemPE);

  end;

end;


procedure TForm1.Button2Click(Sender: TObject);

begin

Edit4.Text := string(RVAToFileOffset(Edit5.Text,Cardinal(Edit3.Text)));

end;


end.


程序界面:

RVA与Offset的换算函数_RVA与Offset的换算函数