AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein DLL aus RES in Speicher laden und direkt verwenden.
Thema durchsuchen
Ansicht
Themen-Optionen

DLL aus RES in Speicher laden und direkt verwenden.

Ein Thema von Schorschi5566 · begonnen am 3. Aug 2010 · letzter Beitrag vom 6. Aug 2010
Antwort Antwort
Schorschi5566

Registriert seit: 6. Feb 2006
197 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#1

DLL aus RES in Speicher laden und direkt verwenden.

  Alt 3. Aug 2010, 21:14
Hallo DP,

in diesem Thread haben Himitsu und ich schon das Thema besprochen.

Es geht darum eine DLL direkt aus einer RES in den Speicher zu laden und dort zu verwenden. Der Umweg über das Filesystem würde also entfallen.

Hier habe ich das Thema gefunden und mal ausprobiert.

Es funktioniert fast.

Mit der libmysql.dll mit der ich es getestet habe, schafft er die ersten paar Funktionen aber dann scheppert's.

Code:
---------------------------
Zugriffsverletzung bei Adresse 776D8C19 in Modul 'ntdll.dll'. Schreiben von Adresse 00000014.
---------------------------
Ich habe folgenden Code aus obiger Quelle verwendet, der ja angeblich D2010-tauglich sein soll.

Delphi-Quellcode:
function BTMemoryLoadLibary(fp_data: Pointer;
  const f_size: int64): PBTMemoryModule;
var
  lp_result: PBTMemoryModule;
  l_dos_header: TImageDosHeader;
  l_old_header: TImageNtHeaders;
  l_code, l_headers: Pointer;
  l_locationdelta: Cardinal;
  lp_DllEntry: PDllEntryProc;
  l_successfull: boolean;
begin
  lp_result := nil;
  Result := nil;
  try
    CopyMemory(@l_dos_header, fp_data, SizeOf(_IMAGE_DOS_HEADER));
    if (l_dos_header.e_magic <> IMAGE_DOS_SIGNATURE) then
    begin
      lastErrStr := 'BTMemoryLoadLibary: dll dos header is not valid';
      exit;
    end;
    CopyMemory(@l_old_header, IncF(fp_data, l_dos_header._lfanew),
      SizeOf(_IMAGE_NT_HEADERS));
    if l_old_header.Signature <> IMAGE_NT_SIGNATURE then
    begin
      lastErrStr := 'BTMemoryLoadLibary: IMAGE_NT_SIGNATURE is not valid';
      exit;
    end;
    // reserve memory for image of library
    l_code := VirtualAlloc(Pointer(l_old_header.OptionalHeader.ImageBase),
      l_old_header.OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_READWRITE);
    if l_code = nil then
      // try to allocate memory at arbitrary position
      l_code := VirtualAlloc(nil, l_old_header.OptionalHeader.SizeOfImage,
        MEM_RESERVE, PAGE_READWRITE);
    if l_code = nil then
    begin
      lastErrStr := 'BTMemoryLoadLibary: VirtualAlloc failed';
      exit;
    end;
    // alloc space for the result record
    lp_result := PBTMemoryModule(HeapAlloc(GetProcessHeap(), 0,
        SizeOf(TBTMemoryModule)));
    lp_result^.codeBase := l_code;
    lp_result^.numModules := 0;
    lp_result^.modules := nil;
    lp_result^.initialized := false;
    // xy: is it correct to commit the complete memory region at once?
    // calling DllEntry raises an exception if we don't...
    VirtualAlloc(l_code, l_old_header.OptionalHeader.SizeOfImage, MEM_COMMIT,
      PAGE_READWRITE);
    // commit memory for headers
    l_headers := VirtualAlloc(l_code,
      l_old_header.OptionalHeader.SizeOfHeaders, MEM_COMMIT, PAGE_READWRITE);
    // copy PE header to code
    CopyMemory(l_headers, fp_data,
      (UInt64(l_dos_header._lfanew)
          + l_old_header.OptionalHeader.SizeOfHeaders));
    lp_result^.headers := PImageNtHeaders
      (UInt64(l_headers) + l_dos_header._lfanew);
    // update position
    lp_result^.headers^.OptionalHeader.ImageBase := UInt64(l_code);
    // copy sections from DLL file block to new memory location
    CopySections(fp_data, l_old_header, lp_result);
    // adjust base address of imported data
    l_locationdelta := Cardinal
      (UInt64(l_code) - l_old_header.OptionalHeader.ImageBase);
    if l_locationdelta <> 0 then
      PerformBaseRelocation(lp_result, l_locationdelta);
    // load required dlls and adjust function table of imports
    if not BuildImportTable(lp_result) then
    begin
      lastErrStr := lastErrStr + ' BTMemoryLoadLibary: BuildImportTable failed';
      Abort;
    end;
    // mark memory pages depending on section headers and release
    // sections that are marked as "discardable"
    FinalizeSections(lp_result);
    // get entry point of loaded library
    if (lp_result^.headers^.OptionalHeader.AddressOfEntryPoint) <> 0 then
    begin
      lp_DllEntry := Pointer
        (UInt64(l_code)
          + lp_result^.headers^.OptionalHeader.AddressOfEntryPoint);
      if lp_DllEntry = nil then
      begin
        lastErrStr := 'BTMemoryLoadLibary: Get DLLEntyPoint failed';
        Abort;
      end;
      l_successfull := TDllEntryProc(lp_DllEntry)(UInt64(l_code),
        DLL_PROCESS_ATTACH, nil);
      if not l_successfull then
      begin
        lastErrStr := 'BTMemoryLoadLibary: Can''t attach library';
        Abort;
      end;
      lp_result^.initialized := true;
    end;
  except
    BTMemoryFreeLibrary(lp_result);
    exit;
  end;
  Result := lp_result;
end;

function BTMemoryGetProcAddress(fp_module: PBTMemoryModule;
  const fp_name: PChar): Pointer;
var
  l_idx: Integer;
  l_i: DWORD;
  l_nameRef: PDWORD;
  l_ordinal: PWord;
  l_exports: PImageExportDirectory;
  l_directory: PImageDataDirectory;
begin
  Result := nil;
  l_idx := -1;
  l_directory := GetHeaderDictionary(fp_module, IMAGE_DIRECTORY_ENTRY_EXPORT);
  if l_directory^.Size = 0 then
  begin
    lastErrStr := 'BTMemoryGetProcAddress: no export table found';
    exit;
  end;
  l_exports := IncF(fp_module^.codeBase, l_directory^.VirtualAddress);
  if ((l_exports^.NumberOfNames = 0) or (l_exports^.NumberOfFunctions = 0)) then
  begin
    lastErrStr := 'BTMemoryGetProcAddress: DLL doesn''t export anything';
    exit;
  end;
  // search function name in list of exported names
  l_nameRef := IncF(fp_module^.codeBase, l_exports^.AddressOfNames);
  l_ordinal := IncF(fp_module^.codeBase, l_exports^.ADDressOfNameOrdinals);
  for l_i := 0 to l_exports^.NumberOfNames - 1 do
  begin
    if StrComp(fp_name, PAnsiCharToPChar(IncF(fp_module^.codeBase, l_nameRef^))
      ) = 0 then
    begin
      l_idx := l_ordinal^;
      break;
    end;
    Inc(l_nameRef);
    Inc(l_ordinal);
  end;
  if (l_idx = -1) then
  begin
    lastErrStr := 'BTMemoryGetProcAddress: exported symbol not found';
    exit;
  end;
  if (UInt64(l_idx) > l_exports^.NumberOfFunctions - 1) then
  begin
    lastErrStr :=
      'BTMemoryGetProcAddress: name <-> ordinal number don''t match';
    exit;
  end;
  // AddressOfFunctions contains the RVAs to the "real" functions
  Result := IncF(fp_module^.codeBase,
    PUInt64(IncF(fp_module^.codeBase, IncF(l_exports^.AddressOfFunctions,
          l_idx * 4)))^);
end;
Zum Debugging: Die AV kommt bei mir bei mysql_real_connect, es wurden also schon einige Funktionen erfolgreich durchlaufen (mysql_get_client_version, mysql_init, mysql_ssl_set). mysql_real_connect wird aber von BTMemoryGetProcAddress auch noch gefunden. Erst beim Aufruf von mysql_real_connect passiert's.

Hat jemand eine funktionierende Variante oder sieht einen offensichtlichen Fehler im Code?


Grüße,
Uwe

P.S.: Hat sich erledigt. Jetzt funktioniert es.
Uwe

Geändert von Schorschi5566 ( 4. Aug 2010 um 09:43 Uhr) Grund: Hat sich erledigt.
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#2

AW: DLL aus RES in Speicher laden und direkt verwenden.

  Alt 4. Aug 2010, 01:42
Wo lag der Fehler? Habe selbst mal versucht so eine funktion zu implementieren. Funktioniert auch wunderbar nur bei der ntdll.dll gibts ab und an auch mal ne Exception. Was mir aufgefallen ist, ist dass in deinem Code die Relocations gar nicht geparst werden.
  Mit Zitat antworten Zitat
Schorschi5566

Registriert seit: 6. Feb 2006
197 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#3

AW: DLL aus RES in Speicher laden und direkt verwenden.

  Alt 4. Aug 2010, 09:03
Hallo Zacherl,

es lag daran, dass ich nicht abgefangen hatte, dass BTMemoryLoadLibary mehrfach aufgerufen werden konnte.

Wenn die DLL nur einmal im Speicher ist, funktioniert es bisher einwandfrei.

Zitat von Zacherl:
Was mir aufgefallen ist, ist dass in deinem Code die Relocations gar nicht geparst werden.
Müsste man mal Martin Offenwanger fragen, der der Autor der Delphiversion ist.

Für D2010 habe ich nur einen Cast ändern müssen.

Ansonsten habe ich nur noch auf die aktuellste Version umgestellt. Die gibt es hier.


Grüße,
Uwe

[EDIT]Habe mal die verwendete Version ins erste Posting gestellt...[/EDIT]
Uwe

Geändert von Schorschi5566 ( 4. Aug 2010 um 09:44 Uhr)
  Mit Zitat antworten Zitat
Schorschi5566

Registriert seit: 6. Feb 2006
197 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#4

AW: DLL aus RES in Speicher laden und direkt verwenden.

  Alt 5. Aug 2010, 20:13
Kann mir jemand sagen, wie man die "Offene Frage"-Markierung weg bekommt?

Danke, schonmal.
Uwe
"Real programmers can write assembly code in any language." - Larry Wall
Delphi programming rocks
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.149 Beiträge
 
Delphi 12 Athens
 
#5

AW: DLL aus RES in Speicher laden und direkt verwenden.

  Alt 6. Aug 2010, 07:25
Schau mal nach, ob sich nicht da oben in den Themen-Optionen was versteckt,
ansonsten in den erweiterten Beitragseditor (oder 'nen neuen Beitrag/Post erstellen) und dann da unten das Häckchen wegmachen.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Schorschi5566

Registriert seit: 6. Feb 2006
197 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#6

AW: DLL aus RES in Speicher laden und direkt verwenden.

  Alt 6. Aug 2010, 21:59
Hmm, jetzt steht oben, dass es eine offene Frage von Dir ist.

Mal sehen, was jetzt passiert...

[EDIT]Ahh, hat geklappert...danke![/EDIT]
Uwe
"Real programmers can write assembly code in any language." - Larry Wall
Delphi programming rocks
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:34 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz