Einzelnen Beitrag anzeigen

NicoDE
(Gast)

n/a Beiträge
 
#42

Re: vergleichen von zwei librarys im speicher

  Alt 8. Jul 2005, 12:00
Nützliches Zeug für das Einlesen der exportierten Funktionen aus der DLL (MMF) und der geladenen Version im Speicher (ohne GetProcAddress):

MMF: (todo: Anpassungen und spezielle Validierungen für dieses Projekt)
TDLLInfo.ReadExportDirectory

Mem: (todo: spezielle Validierungen für dieses Projekt)
Delphi-Quellcode:
function GetProcAddressPE32(Module: HMODULE; ProcName: LPCSTR): TFarProc;
type
  PWordArray = ^TWordArray;
  TWordArray = array [Word] of WORD;
  PDWordArray = ^TDWordArray;
  TDWordArray = array [Word] of DWORD;
var
  NtHeaders: PImageNtHeaders;
  ExpDatDir: PImageDataDirectory;
  ExportDir: PImageExportDirectory;
  Functions: PDWordArray;
  FuncIndex: DWORD;
  Ordinals: PWordArray;
  OrdIndex: DWORD;
  Names: PDWordArray;
  ModName: array [0..MAX_PATH] of AnsiChar;
  OrdStrLo: DWORD;
  OrdStrHi: DWORD;
  SCompare: Integer;
  function RvaToVa(Rva: DWORD): Pointer;
  begin
    Result := Pointer(Cardinal(Module) + Rva);
  end;
  function IsForwarderRva(Rva: DWORD): Boolean;
  begin
    Result := (Rva >= ExpDatDir.VirtualAddress) and
      (Rva < ExpDatDir.VirtualAddress + ExpDatDir.Size);
  end;
begin
  Result := nil;
  if HMODULE(nil) = Module then
  begin
    SetLastError(ERROR_INVALID_PARAMETER);
    Exit;
  end;
  with PImageDosHeader(Module)^ do
    if (IMAGE_DOS_SIGNATURE = e_magic) and (e_lfanew > 0) then
      NtHeaders := PImageNtHeaders(Cardinal(Module) + DWORD(e_lfanew))
    else
      NtHeaders := PImageNtHeaders(Module);
  with NtHeaders^, FileHeader, OptionalHeader do
    if (IMAGE_NT_SIGNATURE = Signature) and
      (SizeOfOptionalHeader >= SizeOf(TImageOptionalHeader) -
        SizeOf(DataDirectory) + SizeOf(TImageDataDirectory)) and
      (IMAGE_NT_OPTIONAL_HDR_MAGIC = Magic) then
    begin
      ExpDatDir := Addr(DataDirectory[0]);
      ExportDir := RvaToVa(ExpDatDir.VirtualAddress);
    end
    else
    begin
      SetLastError(ERROR_INVALID_DATA);
      Exit;
    end;
  if (0 = ExpDatDir.Size) or (nil = ExportDir) then
  begin
    SetLastError(ERROR_PROC_NOT_FOUND);
    Exit;
  end;
  Functions := RvaToVa(Cardinal(ExportDir.AddressOfFunctions));
  Ordinals := RvaToVa(Cardinal(ExportDir.AddressOfNameOrdinals));
  Names := RvaToVa(Cardinal(ExportDir.AddressOfNames));
  if nil = Functions then
  begin
    SetLastError(ERROR_PROC_NOT_FOUND);
    Exit;
  end;
  // Checks done ;)
  if Cardinal(ProcName) <= MAXWORD then
  begin
    // Import by Oridinal
    FuncIndex := Cardinal(ProcName) - Cardinal(ExportDir.Base);
    if (FuncIndex >= ExportDir.NumberOfFunctions) or
      (0 = Functions[FuncIndex]) then
      SetLastError(ERROR_PROC_NOT_FOUND)
    else
    begin
      if IsForwarderRva(Functions[FuncIndex]) then
      begin
        // Forwarder
        ProcName := lstrcpynA(PAnsiChar(Addr(ModName[0])),
          PAnsiChar(RvaToVa(Functions[FuncIndex])), MAX_PATH);
        while ProcName[0] <> #0 do
          if ProcName[0] <> '.then
            Inc(ProcName)
          else
          begin
            ProcName[0] := #0;
            Break;
          end;
        ProcName := PAnsiChar(Cardinal(RvaToVa(Functions[FuncIndex])) +
          Cardinal(lstrlenA(PAnsiChar(Addr(ModName[0])))));
        if ProcName[0] <> '.then
          SetLastError(ERROR_INVALID_DATA)
        else
        begin
          Inc(ProcName);
          Module := HMODULE(GetModuleHandleA(PAnsiChar(Addr(ModName[0]))));
          if HMODULE(nil) = Module then
            SetLastError(ERROR_MOD_NOT_FOUND)
          else
            Result := GetProcAddressPE32(Module, ProcName);
        end;
      end
      else
        // Function RVA
        Result := TFarProc(RvaToVa(Functions[FuncIndex]));
    end;
  end
  else
  begin
    // Import by Name
    OrdStrLo := 0;
    OrdStrHi := DWORD(Integer(ExportDir.NumberOfNames) - 1);
    while OrdStrLo <= OrdStrHi do
    begin
      OrdIndex := (OrdStrHi - OrdStrLo) div 2 + OrdStrLo;
      SCompare := lstrcmpA(ProcName, PAnsiChar(RvaToVa(Names[OrdIndex])));
      if 0 = SCompare then
      begin
        // Resolve by Ordinal
        Result := GetProcAddressPE32(Module,
          PAnsiChar(Ordinals[OrdIndex] + ExportDir.Base));
        Exit;
      end;
      if SCompare < 0 then
        OrdStrHi := OrdIndex - 1
      else
        OrdStrLo := OrdIndex + 1;
    end;
    SetLastError(ERROR_PROC_NOT_FOUND);
  end;
end;
Die beiden dürften als Vorlage relativ nützlich sein (der Code unterstützt auch Forwarder). Das ganze Projekt kann ich nicht veröffentlichen, da ich nicht das alleinige Copyright darauf habe... könnte also sein, dass ein paar Typen und Konstanten fehlen (sollten alle im MSDN/PSDK zu finden sein).

Gruß Nico
  Mit Zitat antworten Zitat