Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi MakeProcInstance & Priviligierte Anweisung (https://www.delphipraxis.net/135272-makeprocinstance-priviligierte-anweisung.html)

Corelgott 8. Jun 2009 10:30


MakeProcInstance & Priviligierte Anweisung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi @ all,

ich habe ein Problem: Bekanntlicher weise sparen plagiate ja zeit... somit habe bei diesem Code bzw. bei Lucky's Code bedient um eine Methode zu einer Regulären Procedure zu casten.

Das ganze hat den Hintergrund, dass ich gerne Lua in einem meiner Projekte verwenden möchte, die buissness logic aber gerne in Objekten haben will und nicht in einer riesen unit mit lauter proceduren (Gäbe auch sonst ein paar Thread Problematiken, da ich auf asyncone Rs232-Communikation angewiesen bin)...

Nun kommt folgendes Problem: Wenn ich die Methode durch LUA aufrufe, wird dies wunderschön ausgeführt, bis er wieder aus der funktion zurückspringen soll... Ich denk mal, dass es etwas mit der Art und Weise zu tun hat, wie die MakeProcInstance per Assambler die Methode regisiert, und dass hier der Rücksprungpunkt nicht richtig eingetragen wird (Ist mal nur geraten). Leider habe ich von Assambler gar keinen Plan.

Ich hänge mal das gesammte Projekt inkl, der LUA-Bins an.

Hat jemand ne idee? Oder nen Tipp für mich (außer: Lern halt assambler...)

Vielen Dank im Vorraus!

Gruß

Corelgott

sirius 8. Jun 2009 10:48

Re: MakeProcInstance & Priviligierte Anweisung
 
Das liegt definitv an der Aufrufkonvention. Ich schau mal was man ändern müsste. (die Funktion MakeProcInstance ist nur für stdcall gedacht)

Edit: Und ich weiß auch warum. Bei cdecl ist der Aufrufer für das Aufräumen des Stacks verantwortlich. Da der Aufrufer aber in der Annahme ist eine normale procedure aufzurufen räumt er nur seine Parameter vom Stack. Eine Methode hat aber noch einen versteckten Parameter, der bleibt dann leider stehen (und wurde von MakeProcInstance hinzugefügt = Method.data).

Corelgott 8. Jun 2009 11:52

Re: MakeProcInstance & Priviligierte Anweisung
 
Ah, hervorragen... Das klingt sehr plausibel!

Es ist gut da schon mal einen Ansatzpunkt zu haben! Für weitere Hilfe wäre ich extrem Dankbar, da wie gesagt meine Assembler Kenntnisse = 0 sind...

Vielen Dank schon mal in Vorraus!
Ich freue mich auf eine umgeschriebene Version...

Gruß & Danke

Corelgott

sirius 8. Jun 2009 12:18

Re: MakeProcInstance & Priviligierte Anweisung
 
Das ist komplizierter als ich dachte.
Ich habe jetzt die Version 0 fertig. Die funktioniert aber nur solange du keinen Mehrfachaufruf machst:
Delphi-Quellcode:
function MakeProcInstance(M: TMethod): Pointer;
  begin
    // Ausführbaren Speicher alloziieren
    Result := VirtualAlloc(nil, $27, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    asm
      // POP EDX (bisherige Rücksprungadresse nach edx)
      MOV BYTE PTR [EAX], $5A
      // CALL +4 (4 Bytes Platz für Speicherung der Rücksprungaddresse)
      MOV BYTE PTR [EAX+$01], $E8
      MOV BYTE PTR [EAX+$02], $04
      MOV BYTE PTR [EAX+$03], $00
      MOV BYTE PTR [EAX+$04], $00
      MOV BYTE PTR [EAX+$05], $00
      // DD 0
      MOV DWORD PTR [EAX+$06], $00000000
      // POP ECX (Addresse vonn "DD 0" nach ECX)
      MOV BYTE PTR [EAX+$0A], $59
      // MOV [ECX], EDX (Rücksprungaddresse bei "DD 0" speichern)
      MOV BYTE PTR [EAX+$0B], $89
      MOV BYTE PTR [EAX+$0C], $11
      // MOV ECX, (Self nach ECX)
      MOV BYTE PTR [EAX+$0D], $B9
      MOV ECX, M.Data
      MOV DWORD PTR [EAX+$0E], ECX
      // PUSH ECX (self als Parameter 0 anfügen)
      MOV BYTE PTR [EAX+$12], $51
      // MOV ECX, (Adresse nach ecx laden)
      MOV BYTE PTR [EAX+$13], $B9
      MOV ECX, M.Code
      MOV DWORD PTR [EAX+$14], ECX
      // CALL ECX (Sprung an den ersten abgelegten Befehl und Methode aufrufen)
      MOV BYTE PTR [EAX+$18], $FF
      MOV BYTE PTR [EAX+$19], $D1
      // POP ECX (Self vom Stack löschen)
      MOV BYTE PTR [EAX+$1A], $59
      // CALL +0 (aktuelle Addresse ermitteln)
      MOV BYTE PTR [EAX+$1B], $E8
      MOV DWORD PTR [EAX+$1C], $00000000
      // POP ECX (aktuelle Addresse nach ECX)
      MOV BYTE PTR [EAX+$20], $59
      // ADD ECX, -19 (Addresse von "DD 0" errechnen)
      MOV BYTE PTR [EAX+$21], $83
      MOV BYTE PTR [EAX+$22], $C1
      MOV BYTE PTR [EAX+$23], $E6
      // MOV EDX, [ECX] (Rücksprungadresse von "DD 0" nach EDX)
      MOV BYTE PTR [EAX+$24], $8B
      MOV BYTE PTR [EAX+$25], $11
      // PUSH EDX (Rücksprungadresse zurück auf den Stack)
      MOV BYTE PTR [EAX+$26], $52
      //RET
      MOV BYTE PTR [EAX+$27], $C3
    end;
  end;
Edit: Vergiss nicht, dass zu jedem VirtualAlloc ein VirtualFree gehört (müsste Lucki auch in seinem Code haben), wenn du die Klasse nicht mehr benötigst.

Corelgott 8. Jun 2009 12:27

Re: MakeProcInstance & Priviligierte Anweisung
 
Wow!

Perfekt! Das ist echt super!
Aller, aller besten Dank! Das mit dem FreeMem werde ich dann in meine Klasse einbauen!

Danke nochmal!

Gruß

Corelgott

sirius 8. Jun 2009 12:46

Re: MakeProcInstance & Priviligierte Anweisung
 
Zitat:

Zitat von Corelgott
Wow!

Perfekt! Das ist echt super!
Aller, aller besten Dank! Das mit dem FreeMem werde ich dann in meine Klasse einbauen!

Danke nochmal!

Gruß

Corelgott

Nicht FreeMem, sondern VirtualFree.

Aber wie gesagt, Wenn der Aufruf parallel (über Threads) oder verschachtelt (bspw. Rekursion) mehrfach gemacht wird, geht die Funktion schief.

sirius 8. Jun 2009 13:40

Re: MakeProcInstance & Priviligierte Anweisung
 
Hier noch eine Version (MakeProcInstance für Aufrufkonvention "cdecl"):
Delphi-Quellcode:
function MakeProcInstance(M: TMethod): Pointer;
  begin
    // Ausführbaren Speicher alloziieren
    Result := VirtualAlloc(nil, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    asm
      // POP EDX (bisherige Rücksprungadresse nach edx)
      MOV BYTE PTR [EAX], $5A
      // CALL +0 (aktuelle Addresse ermitteln)
      MOV BYTE PTR [EAX+$01], $E8
      MOV DWORD PTR [EAX+$02], $00000000
      // POP ECX (Addresse nach ECX)
      MOV BYTE PTR [EAX+$06], $59
      // ADD ECX, $31 (Addresse von Liste errechnen)
      MOV BYTE PTR [EAX+$07], $83
      MOV BYTE PTR [EAX+$08], $C1
      MOV BYTE PTR [EAX+$09], $31
      // MOV EAX, [ECX] (Listenindex nach EAX)
      MOV BYTE PTR [EAX+$0A], $8B
      MOV BYTE PTR [EAX+$0B], $01
      // INC EAX (Listenindex erhöhen)
      MOV BYTE PTR [EAX+$0C], $40
      // MOV [ECX+EAX*4], EDX (Rücksprungaddresse in Liste eintragen)
      MOV BYTE PTR [EAX+$0D], $89
      MOV BYTE PTR [EAX+$0E], $14
      MOV BYTE PTR [EAX+$0F], $81
      // MOV [ECX], EAX (Index speichern)
      MOV BYTE PTR [EAX+$10], $89
      MOV BYTE PTR [EAX+$11], $01
      // MOV ECX, (Self nach ECX)
      MOV BYTE PTR [EAX+$12], $B9
      MOV ECX, M.Data
      MOV DWORD PTR [EAX+$13], ECX
      // PUSH ECX (self als Parameter 0 anfügen)
      MOV BYTE PTR [EAX+$17], $51
      // MOV ECX, (Addresse nach ecx laden)
      MOV BYTE PTR [EAX+$18], $B9
      MOV ECX, M.Code
      MOV DWORD PTR [EAX+$19], ECX
      // CALL ECX (Sprung an den ersten abgelegten Befehl und Methode aufrufen)
      MOV BYTE PTR [EAX+$1D], $FF
      MOV BYTE PTR [EAX+$1E], $D1
      // POP ECX (Self vom Stack löschen)
      MOV BYTE PTR [EAX+$1F], $59
      // CALL +0 (aktuelle Addresse ermitteln)
      MOV BYTE PTR [EAX+$20], $E8
      MOV DWORD PTR [EAX+$21], $00000000
      // POP ECX (aktuelle Addresse nach ECX)
      MOV BYTE PTR [EAX+$25], $59
      // ADD ECX, $12 (Addresse von Liste errechnen)
      MOV BYTE PTR [EAX+$26], $83
      MOV BYTE PTR [EAX+$27], $C1
      MOV BYTE PTR [EAX+$28], $12
      // MOV EDX, [ECX] (Listenindex nach EDX)
      MOV BYTE PTR [EAX+$29], $8B
      MOV BYTE PTR [EAX+$2A], $11
      // PUSH EAX (Funktionsresult retten)
      MOV BYTE PTR [EAX+$2B], $50
      // MOV EAX, [ECX+EDX*4] (Rücksprungaddresse nach EAX)
      MOV BYTE PTR [EAX+$2C], $8B
      MOV BYTE PTR [EAX+$2D], $04
      MOV BYTE PTR [EAX+$2E], $91
      // DEC EDX (Listenindex dekrementieren)
      MOV BYTE PTR [EAX+$2F], $4A
      // MOV [ECX], EDX (Listenindex speichern)
      MOV BYTE PTR [EAX+$30], $89
      MOV BYTE PTR [EAX+$31], $11
      // POP EDX (Funktionsresult nach EDX)
      MOV BYTE PTR [EAX+$32], $5A
      // PUSH EAX (Rücksprungadresse auf Stack)
      MOV BYTE PTR [EAX+$33], $50
      // MOV EAX, EDX (Funktionsresult zurück nach EAX)
      MOV BYTE PTR [EAX+$34], $89
      MOV BYTE PTR [EAX+$35], $D0
      // RET (End;)
      MOV BYTE PTR [EAX+$36], $C3
      // DD 0 (Anfang der Liste mit Index=0)
      MOV DWORD PTR [EAX+$37], $00000000
    end;
  end;
Hier wird am Ende eine Liste geführt mit mehreren Rücksprungadressen. Dadurch kann ein verschachtelter Aufruf erfolgen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:40 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