![]() |
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:
Referenzen: ![]() ![]() 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; |
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? :)
|
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 |
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
Könntest du das nicht in zwei Funktionen zerlegen?
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. |
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
Vorschlag angenommen; Siehe Beitrag #1
|
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
Zitat:
Delphi-Quellcode:
function _GetProcAddress(): Pointer; overload;
begin Result := _GetModuleAddress('kernel.dll'); if Assigned(result) then Result := _GetProcAddress(Result, 'GetProcAddress'); end; |
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
:warn:
:roll: |
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
+1 Internets.
Auch wenn ich noch nicht weiß, ob ich es jemals gebrauchen kann... |
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
Man kann damit auch die Leute etwas ärgern, die immer alles umsonst haben müssen :mrgreen: ;)
|
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
Zitat:
|
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
ich vermute mal, daß er es so meint, daß es über diese Funktionen schwerer sein wird, einfach irgendwelche Funktionen zu hocken und auf diese Weise z.B. etwas freizuschalten.
allerdings vermute ich mal, daß die entsprechenden APIs es auch nicht sehr viel anders machen. PS: ist wem schon aufgefallen, daß _GetModuleAddress im Grunde dem GetModuleHandle gleicht? (unter WinNT entspricht ja zufällig das Handle der Adresse) |
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
Bzgl GetProcAddress hatte Hagen
![]()
Delphi-Quellcode:
function GetProcAddr(Module: hModule; Name: PChar): Pointer;
asm XOR ECX,ECX // except frame PUSH OFFSET @@6 PUSH DWord Ptr FS:[ECX] MOV FS:[ECX],ESP PUSH EBP PUSH EBX MOV EBP,EDX AND EAX,not 3 PUSH EDI MOV EDX,[EAX + 03Ch] PUSH ESI TEST EBP,EBP JZ @@5 CMP Word Ptr [EAX + EDX],'EP' MOV EDX,[EAX + EDX + 078h] JNZ @@5 ADD EDX,EAX TEST EBP,0FFFF0000h MOV EBX,EAX JZ @@3 // import by ordinal ?? MOV EAX,[EDX + 018h] MOV ECX,[EDX + 020h] NOT EAX @@1: INC EAX MOV ESI,EBP JZ @@4 MOV EDI,[EBX + ECX] ADD ECX,4 ADD EDI,EBX @@2: CMPSB JNE @@1 CMP Byte Ptr [ESI - 1],0 JNE @@2 ADD EAX,[EDX + 018h] MOV ECX,[EDX + 024h] ADD ECX,EBX MOVZX EBP,Word Ptr [ECX + EAX * 2] INC EBP @@3: MOV ECX,[EDX + 01Ch] DEC EBP ADD ECX,EBX MOV EAX,[ECX + EBP * 4] ADD EAX,EBX @@4: POP ESI POP EDI POP EBX POP EBP POP DWord Ptr FS:[0] POP ECX RET @@5: XOR EAX,EAX JMP @@4 @@6: MOV EAX,[ESP + 00Ch] // except handler PUSH OFFSET @@5 POP DWord Ptr [EAX + 0B8h] SUB EAX,EAX end; |
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
Wie himitsu schon ganz richtig vermutete ist das halt ein Weg an OS-Funktionen zu kommen ohne die ganz offensichtlich statisch oder "konventionell dynamisch" zu linken. Insbesondere bei Shareware die für einen bestimmten Zeitraum voll funktionsfähig ist und sich dann totschaltet, ist es ja essentiell, ein halbwegs verlässliches Datum zu bekommen. Das kann man sich mit obiger Funktion holen ohne dass es auf den ersten Blick zu sehen ist. Stichwort Obfuskierung. Dass das keine wirkliche Hürde ist, sollte aber auch jedem klar sein, deswegen schrieb ich "etwas" und den :mrgreen: ;)
//Edit: In Zeiten des überall verfügbaren Internets hat die Bedeutung natürlich allgemein abgenommen, und die Bedeutung serverbasierter Authentifizierung stark zugenommen. Brauchemergarneddrübberredde ;) |
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
Zitat:
|
Re: Adresse von GetProcAddress OHNE GetProcAddress ermitteln
Fehlen aber noch Forwarded Functions und Ordinals
--> ![]() Und wenn du (laut Titel) nur GetProcAddress haben willst reicht das Handle des Kernel32.dll:
Delphi-Quellcode:
function GetKernelHandle: DWord; stdcall;
asm MOV EAX, DWORD PTR FS:[030H] TEST EAX, EAX JS @@W9X @@WNT: MOV EAX, DWORD PTR [EAX+00CH] MOV ESI, DWORD PTR [EAX+01CH] LODSD MOV EAX, DWORD PTR [EAX+008H] JMP @@K32 @@W9X: MOV EAX, DWORD PTR [EAX+034H] LEA EAX, DWORD PTR [EAX+07CH] MOV EAX, DWORD PTR [EAX+03CH] @@K32: end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz