DelphiXE2测试:从内存加载64位Dll

unit NtResDll;

interface

uses

  {$IFDEF DELPHI16}Winapi.Windows{$ELSE}Windows{$ENDIF}, {$IFDEF DELPHI16}System.SysUtils{$ELSE}SysUtils{$ENDIF}, {$IFDEF DELPHI16}System.Classes{$ELSE}Classes{$ENDIF};

function IsWinNT: boolean;
function LoadMyResDll(FileBuffer: Pointer; var EntryPoint: Pointer): Pointer;
function FindMyResFunc(pBaseAddress: Pointer; FuncName: PAnsiChar): Pointer;
function FreeMyResDll(BaseAddress: Pointer; EntryPoint: Pointer): Boolean;

implementation

{$WARNINGS OFF}

const
  FD_READ                            = $01;
  FD_WRITE                           = $02;
  FD_OOB                             = $04;
  FD_ACCEPT                          = $08;
  FD_CONNECT                         = $10;
  FD_CLOSE                           = $20;
{$IFDEF WIN64}
  ORDINAL_MASK                       = $7FFFFFFFFFFFFFFF;
{$ELSE}
  ORDINAL_MASK                       = $7FFFFFFF;
{$ENDIF}
  IMAGE_REL_BASED_ABSOLUTE           = 0;
  IMAGE_REL_BASED_HIGH               = 1;
  IMAGE_REL_BASED_LOW                = 2;
  IMAGE_REL_BASED_HIGHLOW            = 3;
  IMAGE_REL_BASED_HIGHADJ            = 4;
  IMAGE_REL_BASED_MIPS_JMPADDR       = 5;
  IMAGE_REL_BASED_MIPS_JMPADDR16     = 9;
  IMAGE_REL_BASED_IA64_IMM64         = 9;
  IMAGE_REL_BASED_DIR64              = 10;

{$WARNINGS OFF}


type
  PShort    = ^Short;
  TShortArr = array of Short;
  PShortArr = ^TShortArr;
  TDWORDArr = array of DWORD;
  PDWORDArr = ^TDWORDArr;

  // PE file header structures used to parse the dll for correct dll loading.
  // For detailed infromation about this sructures refer to MSDN library

  TIIDUnion = record
    case Integer of
      0: (Characteristics: DWORD);
      1: (OriginalFirstThunk: DWORD);
  end;

  TImgSecHdrMisc = record
    case Integer of
      0: (PhysicalAddress: DWORD);
      1: (VirtualSize: DWORD);
  end;

  _IMAGE_SECTION_HEADER = record
    Name: array[0..IMAGE_SIZEOF_SHORT_NAME - 1] of Byte;
    Misc: TImgSecHdrMisc;
    VirtualAddress: DWORD;
    SizeOfRawData: DWORD;
    PointerToRawData: DWORD;
    PointerToRelocations: DWORD;
    PointerToLinenumbers: DWORD;
    NumberOfRelocations: WORD;
    NumberOfLinenumbers: WORD;
    Characteristics: DWORD;
  end;

  IMAGE_SECTION_HEADER = _IMAGE_SECTION_HEADER;
  PIMAGE_SECTION_HEADER = ^IMAGE_SECTION_HEADER;

  PIMAGE_IMPORT_DESCRIPTOR = ^IMAGE_IMPORT_DESCRIPTOR;
  _IMAGE_IMPORT_DESCRIPTOR = record
    Union: TIIDUnion;
    TimeDateStamp: DWORD;
    ForwarderChain: DWORD;
    Name: DWORD;
    FirstThunk: DWORD;
  end;
  IMAGE_IMPORT_DESCRIPTOR = _IMAGE_IMPORT_DESCRIPTOR;

  PIMAGE_THUNK_DATA32 = ^IMAGE_THUNK_DATA32;
  _IMAGE_THUNK_DATA32 = record
    case Integer of
      0: (ForwarderString: DWORD);
      1: (Function_: DWORD);
      2: (Ordinal: DWORD);
      3: (AddressOfData: DWORD);
  end;
  IMAGE_THUNK_DATA32 = _IMAGE_THUNK_DATA32;

{$IFDEF WIN64}
  PIMAGE_THUNK_DATA64 = ^IMAGE_THUNK_DATA64;
  _IMAGE_THUNK_DATA64 = record
    case Integer of
      0: (ForwarderString: DWORD64);
      1: (Function_: DWORD64);
      2: (Ordinal: DWORD64);
      3: (AddressOfData: DWORD64);
  end;
  IMAGE_THUNK_DATA64 = _IMAGE_THUNK_DATA64;
{$ENDIF}

  PIMAGE_IMPORT_BY_NAME = ^IMAGE_IMPORT_BY_NAME;
  _IMAGE_IMPORT_BY_NAME = record
    Hint: WORD;
    Name: array[0..0] of Byte;
  end;
  IMAGE_IMPORT_BY_NAME = _IMAGE_IMPORT_BY_NAME;

  PIMAGE_EXPORT_DIRECTORY = ^IMAGE_EXPORT_DIRECTORY;
  _IMAGE_EXPORT_DIRECTORY = record
    Characteristics: DWORD;
    TimeDateStamp: DWORD;
    MajorVersion: WORD;
    MinorVersion: WORD;
    Name: DWORD;
    Base: DWORD;
    NumberOfFunctions: DWORD;
    NumberOfNames: DWORD;
    AddressOfFunctions: DWORD;
    AddressOfNames: DWORD;
    AddressOfNameOrdinals: DWORD;
  end;

  IMAGE_EXPORT_DIRECTORY = _IMAGE_EXPORT_DIRECTORY;
{$IFDEF WIN64}
  PIMAGE_NT_HEADERS = ^_IMAGE_NT_HEADERS64;
  IMAGE_THUNK_DATA  = IMAGE_THUNK_DATA64;
  PIMAGE_THUNK_DATA = ^IMAGE_THUNK_DATA64;
  MY_POINTER        = DWORD64;
  PMY_POINTER       = ^DWORD64;
{$ELSE}
  PIMAGE_NT_HEADERS = ^_IMAGE_NT_HEADERS;
  IMAGE_THUNK_DATA  = IMAGE_THUNK_DATA32;
  PIMAGE_THUNK_DATA = ^IMAGE_THUNK_DATA32;
  MY_POINTER        = DWORD;
  PMY_POINTER       = ^DWORD;
{$ENDIF}
  TEntryPointProc = function(hinstDll: HINST; fdwReason: DWORD; lpvREserved: Pointer): Boolean; stdcall; // the dll entry point procedure type

function IsWinNT : Boolean;
var
   osv : TOSVERSIONINFO;
begin
   osv.dwOSVersionInfoSize := sizeOf(OSVERSIONINFO);
   GetVersionEx(osv);
   result := (osv.dwPlatformId = VER_PLATFORM_WIN32_NT);
end;

function LoadMyResDll(FileBuffer: Pointer; var EntryPoint: Pointer): Pointer;
var
  peHeader: PIMAGE_NT_HEADERS;
  peSectHeader: PIMAGE_SECTION_HEADER;
  peSectRelocHeader: PIMAGE_SECTION_HEADER;
  DllBuffer: Pointer;
  DllHandle: THandle;
  TempBuffer: Pointer;
  i: DWORD;
  j: DWORD;
  k: MY_POINTER;
  ImportDesc: PIMAGE_IMPORT_DESCRIPTOR;
  ThunkData: PIMAGE_THUNK_DATA;
  ImportByName: PIMAGE_IMPORT_BY_NAME;
  AddresOfEntryPoint: DWORD;
  Offset: DWORD;
  Address: PDWORD;
  DllName: PAnsiChar;
  DllModule: HMODULE;
  AddresTable: Pointer;
  ProcAddress: Pointer;
  Ordinal: Boolean;
  MoveAddr: Pointer;
  Entry: WORD;
  EntryType: WORD;
  EntryOffset: WORD;
{$IFDEF WIN64}
  Address64: PDWORD64;
{$ENDIF}
begin
  Result := nil;
  peSectRelocHeader := nil;
  if not IsWinNT then begin
    DllHandle := 0;
    //ShowMessage('LoadResDll is not support Windows 95/98/Me.');
    Result := Pointer(DllHandle);
    exit;
  end;
  if Assigned(FileBuffer) then
    begin
      peHeader := PIMAGE_NT_HEADERS(DWORD(FileBuffer) + PDWORD(DWORD(FileBuffer) + $3C)^);
      if (PDWORD(peHeader)^ = $4550) then
        begin
          DllBuffer := VirtualAlloc(nil, peHeader.OptionalHeader.SizeOfImage,
            MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
          if Assigned(DllBuffer) then
            begin
              Move(FileBuffer^, DllBuffer^, peHeader.OptionalHeader.SizeOfHeaders);
              peSectHeader := Pointer(MY_POINTER(DllBuffer) + MY_POINTER(@peHeader.OptionalHeader) - MY_POINTER(FileBuffer) + peHeader.FileHeader.SizeOfOptionalHeader);
              for i := 0 to Pred(peHeader.FileHeader.NumberOfSections) do
                begin
                  if strcomp(PAnsiChar(@peSectHeader.Name), '.reloc') = 0 then
                    peSectRelocHeader := peSectHeader;
                  TempBuffer := Pointer(MY_POINTER(DllBuffer) + peSectHeader.VirtualAddress);
                  MoveAddr := Pointer(MY_POINTER(FileBuffer) + peSectHeader.PointerToRawData);
                  Move(MoveAddr^, TempBuffer^, peSectHeader.SizeOfRawData);
                  peSectHeader.Misc.PhysicalAddress := DWORD(TempBuffer);
                  peSectHeader := PIMAGE_SECTION_HEADER(MY_POINTER(peSectHeader) + sizeof(IMAGE_SECTION_HEADER));
                end;
              if Assigned(peSectRelocHeader) then
                begin
                  TempBuffer := Pointer(MY_POINTER(FileBuffer) + peSectRelocHeader.PointerToRawData);
                  i := 0;
                  while i < peSectRelocHeader.SizeOfRawData do
                    begin
                      j := 8;
                      while j < PDWORD(MY_POINTER(TempBuffer) + 4)^ do
                        begin
                          Entry := PShort(MY_POINTER(TempBuffer) + j)^;
                          EntryType := (Entry Shr 12) and $F;
                          EntryOffset := Entry and $FFF;
                          case EntryType of
                            IMAGE_REL_BASED_HIGHLOW:
                            begin
                              Offset := EntryOffset + PDWORD(MY_POINTER(TempBuffer))^;
                              Address := PDWORD(MY_POINTER(DllBuffer) + Offset);
                              Address^ := Address^ - peHeader.OptionalHeader.ImageBase + MY_POINTER(DllBuffer);
                            end;
{$IFDEF WIN64}
                            IMAGE_REL_BASED_DIR64:
                            begin
                              Offset := EntryOffset + PDWORD(MY_POINTER(TempBuffer))^;
                              Address64 := PDWORD64(MY_POINTER(DllBuffer) + Offset);
                              Address64^ := Address64^ - peHeader.OptionalHeader.ImageBase + MY_POINTER(DllBuffer);
                            end;
{$ENDIF}
                          end;
                          Inc(j, 2);
                        end;
                      TempBuffer := Pointer(MY_POINTER(TempBuffer) + PDWORD(MY_POINTER(TempBuffer) + 4)^);
                      i := i + j;
                    end;
                  if peHeader.OptionalHeader.DataDirectory[1].VirtualAddress <> 0 then
                    begin
                      ImportDesc := PIMAGE_IMPORT_DESCRIPTOR(DWORD(DllBuffer) + peHeader.OptionalHeader.DataDirectory[1].VirtualAddress);
                      while (ImportDesc.Union.OriginalFirstThunk <> 0) do
                        begin
                          DllName := PAnsiChar(DWORD(DllBuffer) + ImportDesc.Name);
                          AddresTable := Pointer(MY_POINTER(DllBuffer) + ImportDesc.FirstThunk);
                          DllModule := GetModuleHandleA(DllName);
                          if DllModule = 0 then
                            begin
                              DllModule := LoadLibraryA(DllName);
                              if DllModule = 0 then
                                Exit;
                            end;
                          ThunkData := PIMAGE_THUNK_DATA(DWORD(DllBuffer) + ImportDesc.Union.OriginalFirstThunk);
                          while PDWORD(ThunkData)^ <> 0 do
                            begin
                              Ordinal := False;
                              k := ThunkData.Ordinal;
                              if ((k and ORDINAL_MASK) <> k) then
                                begin
                                  Ordinal := True;
                                  k := k and ORDINAL_MASK;
                                end;
                              if not Ordinal then
                                begin
                                  ImportByName := PIMAGE_IMPORT_BY_NAME(DWORD(DllBuffer) + k);
                                  ProcAddress := GetProcAddress(DllModule, PAnsiChar(@ImportByName.Name));
                                end
                              else
                                ProcAddress := GetProcAddress(DllModule, PAnsiChar(k));
                              PMY_POINTER(AddresTable)^ := MY_POINTER(ProcAddress);
                              AddresTable := PMY_POINTER(MY_POINTER(AddresTable) + sizeof(MY_POINTER));
                              ThunkData := PIMAGE_THUNK_DATA(MY_POINTER(ThunkData) + sizeof(IMAGE_THUNK_DATA));
                            end;
                          ImportDesc := PIMAGE_IMPORT_DESCRIPTOR(MY_POINTER(ImportDesc) + sizeof(IMAGE_IMPORT_DESCRIPTOR));
                        end;
                    end;
                end;
              AddresOfEntryPoint := peHeader.OptionalHeader.AddressOfEntryPoint + MY_POINTER(DllBuffer);
              if not TEntryPointProc(AddresOfEntryPoint)(HINST(DllBuffer), DLL_PROCESS_ATTACH, nil) then
                Exit;
              EntryPoint := Pointer(AddresOfEntryPoint);
              Result := DllBuffer;
            end;
        end;
    end;
end;

function FreeMyResDll(BaseAddress: Pointer; EntryPoint: Pointer): Boolean;
begin
  Result := False;
  if not IsWinNT then begin
   if Assigned(BaseAddress) then FreeLibrary(THandle(BaseAddress));
   exit;
  end;
  if Assigned(BaseAddress) and Assigned(EntryPoint) then
    if TEntryPointProc(EntryPoint)(HINST(BaseAddress), DLL_PROCESS_DETACH, nil) then
      Result := VirtualFree(BaseAddress, 0, MEM_RELEASE);
end;

function FindMyResFunc(pBaseAddress: Pointer; FuncName: PAnsiChar): Pointer;
var
  pinth: PIMAGE_NT_HEADERS;
  pied: PIMAGE_EXPORT_DIRECTORY;
  k: Integer;
  FuncAddr: Pointer;
  dwBaseAddress: MY_POINTER;
begin
  FuncAddr := nil;
  Result := nil;
  if not IsWinNT then begin
    Result := GetProcAddress(THandle(pBaseAddress), FuncName);
    exit;
  end;
  dwBaseAddress := MY_POINTER(pBaseAddress);
  if (dwBaseAddress <> 0) then
    begin
      pinth := PIMAGE_NT_HEADERS(dwBaseAddress + PDWORD(dwBaseAddress + $3C)^);
      pied := PIMAGE_EXPORT_DIRECTORY(pinth.OptionalHeader.DataDirectory[0].VirtualAddress + dwBaseAddress);
      for k := 0 to Pred(pied.NumberOfNames) do
        begin
          if strcomp(PAnsiChar(TDWORDArr(pied.AddressOfNames + dwBaseAddress)[k] + dwBaseAddress), FuncName) = 0 then
            begin
              FuncAddr := Pointer(TDWORDArr(pied.AddressOfFunctions + dwBaseAddress)
                    [TShortArr(pied.AddressOfNameOrdinals + dwBaseAddress)[k]]);
              FuncAddr := Pointer(MY_POINTER(FuncAddr) + dwBaseAddress);
            end;
        end;
      Result := FuncAddr;
    end;
end;

end.

转载于:https://www.cnblogs.com/wuan/archive/2011/09/27/2193574.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值