Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi Adresse von GetProcAddress OHNE GetProcAddress ermitteln ;) (https://www.delphipraxis.net/138858-adresse-von-getprocaddress-ohne-getprocaddress-ermitteln-%3B.html)

Aphton 18. Aug 2009 23:53


Adresse von GetProcAddress OHNE GetProcAddress ermitteln ;)
 
Hiermit möchte ich euch eine Routine beschreiben, mit der man ohne GetProcAddress die Adresse von GetProcAddress (und somit auch andere exportierte Funktionen) ermitteln kann.

Die Function _GetProcAddress() macht folgendes:
  • (1) Zuerst wird die Adresse von PEB (Process Enviroment Block) ermittelt
  • (2) Anschließend wird die doppelt verkettete Liste (LDR) abgearbeitet und nach dem Module "kernel32.dll" gesucht: wird sie gefunden, darfs weiter gehen
  • (3) die Funktion hangelt sich durch das Image-Format bis zur Export Table der DLL;
  • (4) hier werden alle Namen ausgelesen, verglichen und bei Übereinstimmung wird die Adresse der Funktion als Result zurück gegeben

Referenzen:
Undocumented.ntinternals - struct _PEB
msdn - PEB

MfG und viel Spaß damit ;)

Delphi-Quellcode:
{  --|  Code Snippet |--  }
uses
  Windows;

type
  _UNICODE_STRING = record
    Length: Word;
    MaximumLength: Word;
    Buffer: PWideChar;
  end;
  PUnicodeString = ^TUnicodeString;
  TUnicodeString = _UNICODE_STRING;

  PPEB_LDR_DATA = ^TPEB_LDR_DATA;
  TPEB_LDR_DATA = packed record
    Reserved1: Array[0..7] of Byte;
    Reserved2: Array[0..2] of Pointer;
    InMemoryOrderModuleList: LIST_ENTRY;
  end;

  PLDR_MODULE = ^LDR_MODULE;
  LDR_MODULE = packed record
    InLoadOrderModuleList: LIST_ENTRY;
    InMemoryOrderModuleList: LIST_ENTRY;
    InInitializationOrderModuleList: LIST_ENTRY;
    BaseAddress: Pointer;
    EntryPoint: Pointer;
    SizeOfImage: DWord;
    FullDllName: TUnicodeString;
    BaseDllName: TUnicodeString;
    Flags: DWord;
    LoadCount: Short;
    TlsIndex: SHort;
    HashTableEntry: LIST_ENTRY;
    TimeDateStamp: DWord;
  end;

  PPEB = ^PEB;
  PEB = record
    Reserved1: Array[0..1] of Byte;
    BeingDebugged: Byte;
    Spare: Byte;
    Mutant: DWord;
    ImageBase: Pointer;
    Ldr: PPEB_LDR_DATA;
    {REST NICHT IMPLEMENTIERT: WIRD FÜR >MEINE< ZWECKE NICHT BENÖTIGT}
  end;

function GetPEB(): PPEB;
asm
  mov eax, FS:[$30]
end;

function _GetProcAddress(): Pointer;
var
  _PEB: PPEB;
  _FirstItem, _CurrentItem: PListEntry;
  _Module: PLDR_MODULE;
  ModuleName: String;
  ModuleFound: Boolean;
  ImageBase: DWord;
  pDosHeader:  ^_IMAGE_DOS_HEADER;
  pNTHeaders:  ^_IMAGE_NT_HEADERS;
  pExportTable: ^_IMAGE_EXPORT_DIRECTORY;
  NameStartAddr: DWord;
  FuncStartAddr: DWord;
  ExportName: PChar;
  i: Integer;
const
  k32: PChar = 'kernel32.dll';
  GPA: PChar = 'GetProcAddress';
begin
// (1)
  Result       := NIL;
  _PEB         := GetPEB();
  _FirstItem   := @_PEB^.Ldr^.InMemoryOrderModuleList;
  if _FirstItem = NIL then
    Exit;
// (2)
  _CurrentItem := _FirstItem^.Flink;
  ModuleFound  := False;
  while ( _CurrentItem <> _FirstItem ) and ( not ModuleFound ) do
  begin
    _Module    := PLDR_MODULE( _CurrentItem );
    ModuleName := WideCharToString( _Module^.FullDllName.Buffer );
    ModuleFound := ModuleName = k32;
    _CurrentItem := _CurrentItem^.Flink;
  end;
// (3)
  if ModuleFound then
  begin
    ImageBase  := DWord( _Module^.InInitializationOrderModuleList.Flink );
    pDosHeader := Pointer( ImageBase );
    if pDosHeader^.e_magic = IMAGE_DOS_SIGNATURE then
    begin
      pNTHeaders := Pointer( ImageBase );
      inc( Cardinal( pNTHeaders ), pDosHeader^._lfanew );
      if pNTHeaders^.Signature = IMAGE_NT_SIGNATURE then
      begin
        pExportTable := Pointer( ImageBase +
          pNTHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress );
        NameStartAddr := ImageBase + DWord( pExportTable^.AddressOfNames );
        FuncStartAddr := ImageBase + DWord( pExportTable^.AddressOfFunctions );
// (4)
        for i := 0 to pExportTable^.NumberOfNames-1 do
        begin
          ExportName := pChar( ImageBase + PDWord( NameStartAddr + 4*i )^ );
          if String( ExportName ) = String( GPA ) then
          begin
            Result := Pointer( ImageBase + PDWord( FuncStartAddr + 4*(i+1) )^ );
            Exit;
          end;
        end;
      end;
    end;
  end;
end;
Delphi-Quellcode:
function _GetModuleAddress( ModuleName: PChar ): Pointer;
var
  _PEB: PPEB;
  _FirstItem, _CurrentItem: PListEntry;
  _Module: PLDR_MODULE;
  CurrentModule: String;
  ModuleFound: Boolean;
begin
  Result       := NIL;
  _PEB         := GetPEB();
  _FirstItem   := @_PEB^.Ldr^.InMemoryOrderModuleList;
  if _FirstItem = NIL then
    Exit;
  _CurrentItem := _FirstItem^.Flink;
  ModuleFound  := False;
  while ( _CurrentItem <> _FirstItem ) and ( not ModuleFound ) do
  begin
    _Module      := PLDR_MODULE( _CurrentItem );
    CurrentModule := WideCharToString( _Module^.FullDllName.Buffer );
    ModuleFound  := CurrentModule = ModuleName;
    _CurrentItem := _CurrentItem^.Flink;
  end;
  if ModuleFound then
    Result := _Module^.InInitializationOrderModuleList.Flink;
end;

function _GetProcAddress( ModuleAddress: Pointer; ProcName: PChar ): Pointer;
var
  pDosHeader:  ^_IMAGE_DOS_HEADER;
  pNTHeaders:  ^_IMAGE_NT_HEADERS;
  pExportTable: ^_IMAGE_EXPORT_DIRECTORY;
  NameStartAddr: DWord;
  FuncStartAddr: DWord;
  ExportName: PChar;
  i: Integer;
begin
  pDosHeader := ModuleAddress;
  if pDosHeader^.e_magic = IMAGE_DOS_SIGNATURE then
  begin
    pNTHeaders := ModuleAddress;
    inc( Cardinal( pNTHeaders ), pDosHeader^._lfanew );
    if pNTHeaders^.Signature = IMAGE_NT_SIGNATURE then
    begin
      pExportTable := Pointer( DWord( ModuleAddress ) +
        pNTHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress );
      NameStartAddr := DWord( ModuleAddress ) + DWord( pExportTable^.AddressOfNames );
      FuncStartAddr := DWord( ModuleAddress ) + DWord( pExportTable^.AddressOfFunctions );
      for i := 0 to pExportTable^.NumberOfNames-1 do
      begin
        ExportName := pChar( DWord( ModuleAddress ) + PDWord( NameStartAddr + 4*i )^ );
        if String( ExportName ) = String( ProcName ) then
        begin
          Result := Pointer( DWord( ModuleAddress ) + PDWord( FuncStartAddr + 4*(i+1) )^ );
          Exit;
        end;
      end;
    end;
  end;
end;

Dax 19. Aug 2009 00:19

Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
 
Ohne in Abrede zu stellen, dass das ein sehr interessante Stück Code ist - wozu soll das gut sein? :)

Aphton 19. Aug 2009 00:44

Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
 
Im Grunde wird sie genau dann benötigt, wenn einem GetProcAddress nicht zur Verfügung
steht - dh. Code-Injection, Shellcode Entwicklung ( Computer Sicherheit ) usw.

Natürlich kann man es auch für andere Zwecke missbrauchen :P

MfG

sx2008 19. Aug 2009 02:53

Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
 
Könntest du das nicht in zwei Funktionen zerlegen?
  • (1) Zuerst wird die Adresse von PEB (Process Enviroment Block) ermittelt
  • (2) Anschließend wird die doppelt verkettete Liste (LDR) abgearbeitet und nach dem Module "kernel32.dll" gesucht: wird sie gefunden, darfs weiter gehen
Diese beiden Punkte zusammen entsprechen ja der Funktion GetModuleAddress('kernel.dll').
Mit dieser Adresse und dem Namen der Funktion (hier: 'GetProcAddress') ruft man dann die zweite Funktion auf,
und erhält dann die Einsprungadresse.
Dies entspricht dann Punkt (3) und (4).

Nach dieser Zerlegung in zwei Funktionen versteht man den Code besser und kann auch mehr damit anfangen.

Aphton 19. Aug 2009 03:17

Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
 
Vorschlag angenommen; Siehe Beitrag #1

sx2008 19. Aug 2009 04:11

Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
 
Zitat:

Zitat von Aphton
Vorschlag angenommen; Siehe Beitrag #1

:thumb: Ok, und dann noch schnell die Früchte der Arbeit ernten:
Delphi-Quellcode:
function _GetProcAddress(): Pointer; overload;
begin
  Result := _GetModuleAddress('kernel.dll');
  if Assigned(result) then
    Result := _GetProcAddress(Result, 'GetProcAddress');
end;

Aphton 19. Aug 2009 04:54

Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
 
:warn:

:roll:

wicht 19. Aug 2009 07:58

Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
 
+1 Internets.
Auch wenn ich noch nicht weiß, ob ich es jemals gebrauchen kann...

OldGrumpy 19. Aug 2009 08:55

Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
 
Man kann damit auch die Leute etwas ärgern, die immer alles umsonst haben müssen :mrgreen: ;)

hitzi 19. Aug 2009 09:18

Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
 
Zitat:

Zitat von OldGrumpy
Man kann damit auch die Leute etwas ärgern, die immer alles umsonst haben müssen :mrgreen: ;)

Kannst du dazu bitte ein bissl mehr sagen? Würde mich interessieren.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:54 Uhr.
Seite 1 von 2  1 2      

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