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/)
-   -   ...Methodenzeiger in Funktionszeiger konvertieren? (https://www.delphipraxis.net/97037-methodenzeiger-funktionszeiger-konvertieren.html)

Luckie 3. Aug 2007 09:59


...Methodenzeiger in Funktionszeiger konvertieren?
 
Bei den Schweizern gibt es folgenden Code, um einen Methodenzeiger in einen Funktionszeiger zu konvertieren:
Delphi-Quellcode:
function MakeProcInstance(M: TMethod): Pointer;
begin
  // allocate memory
  GetMem(Result, 15);
  asm
    // MOV ECX,
    MOV BYTE PTR [EAX], $B9
    MOV ECX, M.Data
    MOV DWORD PTR [EAX+$1], ECX
    // POP EDX
    MOV BYTE PTR [EAX+$5], $5A
    // PUSH ECX
    MOV BYTE PTR [EAX+$6], $51
    // PUSH EDX
    MOV BYTE PTR [EAX+$7], $52
    // MOV ECX,
    MOV BYTE PTR [EAX+$8], $B9
    MOV ECX, M.Code
    MOV DWORD PTR [EAX+$9], ECX
    // JMP ECX
    MOV BYTE PTR [EAX+$D], $FF
    MOV BYTE PTR [EAX+$E], $E1
  end;
end;
Dazu hätte ich noch Verständnisfragen:

1: Warum ist der Speicherbereich, der mit GetMem alloziiert wird ausführbar?
2: Warum werden 15 Bytes alloziiert? 4 Byte Code-Zeiger + 4 Byte Daten-Zeiger + 4 Byte Aufruf der Methode + 4 Byte Rückgabewert = 16 :gruebel:
3: Warum wird in dem Code alles mit MOV gemacht?
4: Könnte mal bitte jemand entsprechend Kommentare einfügen im Code an den Stellen an dem der Code-Zeiger, Daten-Zeiger, der Aufruf und der Rückgabewert in den Speicherbereich kopiert werden? Ich kann leider kein ASM.

Muetze1 3. Aug 2007 10:35

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Zitat:

Zitat von Luckie
1: Warum ist der Speicherbereich, der mit GetMem alloziiert wird ausführbar?

Schonmal ausgeführt auf einem Betriebssystem welches das NO-EXECUTION Flag (Intel's name, AMD nennts ein wenig anders) unterstützt? Ich wette, dass läuft dann nicht mehr. (Windows 2003 und aufwärts)

Zitat:

Zitat von Luckie
2: Warum werden 15 Bytes alloziiert? 4 Byte Code-Zeiger + 4 Byte Daten-Zeiger + 4 Byte Aufruf der Methode + 4 Byte Rückgabewert = 16 :gruebel:

In den 15 Bytes legt er mit dem MOV Befehlen 15 Bytes an Code ab, aber keine der o.g. Zeiger/Adressen.

Zitat:

Zitat von Luckie
3: Warum wird in dem Code alles mit MOV gemacht?

Der Code aus dem anderen Thread zeigt den Push/Pop der aktuell ausgeführt wird bei einem Aufruf. Dieser Code bewegt die Opcodes des (fast) gleichen Code in die 15 Bytes die alloziiert wurden und diese werden dann durchlaufen.

Zitat:

Zitat von Luckie
4: Könnte mal bitte jemand entsprechend Kommentare einfügen im Code an den Stellen an dem der Code-Zeiger, Daten-Zeiger, der Aufruf und der Rückgabewert in den Speicherbereich kopiert werden? Ich kann leider kein ASM.

Jo, kann ich gerne heute Abend mache, aber wegen den bewegten Opcodes kann ich dir diese nicht dekodieren, da ich die Unterlagen zu Hause habe...

Grundlegend macht der Code aber nur folgendes:

- 15 Bytes alloziieren
- in diesen nacheinander die Opcodes ablegen (welche Self vor dem Aufruf auf den Stack legen)
- Rückgabe der 15 Bytes als Ergebnis. D.h. er springt an den ersten abgelegten Befehl der 15 Bytes und macht genau dies (und im Endeffekt die Methode aufrufen).

Luckie 3. Aug 2007 10:40

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Danke, das reicht mir schon. In dem anderen Thread wurde mir auch schon geholfen. ;) Wie bekommt man das auch unter Os zum Laufen die den NO-EXECUTION Flag unterstützen?

sirius 3. Aug 2007 10:42

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Du tust Code implementieren, keine Daten speichern!
In deinen 15 Bytes steht folgendes (in Hex)
Code:
B9       (1 Byte)
[M.Data] (4 Bytes)
5A      (1 Byte)
51       (1 Byte)
52       (...)
B9
[M.Code] (4 Bytes)
FF
E1
Kannst du durchzählen .. ergibt 15.
Das sind OpCodes. Der Opcode B9 erwartet einfach eine 32bit-Zahl hintendrann,
also so in ASM:
Code:
B901020304     mov ecx,$04030201
5A            pop edx
51             push ecx
52             push edx
B900000000     mov ecx,$00000000
FFE1           jmp ecx
Und die 4 Bytes hinter B9 (was ja so viel heist wie mov ecx,...) füllst du mit sinnvolleren Werten aus TMethod.
Und EnumWindows ruft diese Funktion einfach auf, beginnend bei B901020304 ...

Man könnte MakeProcinstance, also das zusammensetzen der oben geschriebenen ASM Funktion, auch in Pascal schreiben. Aber das wäre nicht einfacher.

sirius 3. Aug 2007 10:47

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Zitat:

Zitat von Luckie
Danke, das reicht mir schon. In dem anderen Thread wurde mir auch schon geholfen. ;) Wie bekommt man das auch unter Os zum Laufen die den NO-EXECUTION Flag unterstützen?

Funktionieren müsste definitvi statt getmem virtualalloc und statt freemem virtualfree.
Delphi-Quellcode:
result:=virtualalloc(nil,15,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
und
Delphi-Quellcode:
virtualfree(ProcInstance,15,MEM_DECOMMIT);

evtl. statt MEM_commit mem_reserve und entspr. auch bei virtualfree. Das weis ich immer nicht. Schau mal bei msdn.

Luckie 3. Aug 2007 10:51

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also unter XP SP2 geht es immer noch mit VirtuallAlloc. Aber geht es auch unter OS mit diesen NO-EXECUTION Flag? Ich hänge das mal zum Test an.

SirThornberry 3. Aug 2007 11:03

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
wenn du ein kleines testprogramm anhängst könnte ich es unter windows server 2003 probieren.

Luckie 3. Aug 2007 11:09

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Liste der Anhänge anzeigen (Anzahl: 1)
OK, hier ist die Echse:

Gruber_Hans_12345 3. Aug 2007 11:16

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
unter vista funktioniert das demo exe auch

Leonard 3. Aug 2007 11:17

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
ich weiss nun nicht genau was passieren soll, aber im Anhang siehst du, was hier auf einem Windows2003 Standard Server mit SP2 ausgegeben wird.

mfg Leonard

Luckie 3. Aug 2007 11:18

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Hattest du als einzige Fenster nur zwei Explorer Fenster auf? Dann stimmt es. Das Demoprogramm soll alle sichtbaren Fenster auflisten bzw. deren Fenstertitel.

Leonard 3. Aug 2007 11:23

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Zitat:

Zitat von Luckie
Hattest du als einzige Fenster nur zwei Explorer Fenster auf? Dann stimmt es. Das Demoprogramm soll alle sichtbaren Fenster auflisten bzw. deren Fenstertitel.

Ja, das hatte ich. Habs mir jetzt nocheinmal mit mehreren Fenstern angeschaut und stelle fest, dass einige Programme 2 mal in der Liste stehen, obwohl sie nur einmal gestartet sind.

sirius 3. Aug 2007 12:10

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
XP SP2
Ich muss mal ein paar Fentser schließen, hier ziehts.

@Leonard: Versteckte Fenster vielleicht?

Leonard 3. Aug 2007 13:33

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Zitat:

Zitat von sirius
@Leonard: Versteckte Fenster vielleicht?

Bei mir ist es das "Advantage Configuration Utility", welches doppelt in der Liste steht. Ob das ein verstecktes Fenster hat weiss ich nicht. Hat vielleicht jemand anderes das Programm installiert und kann das bestätigen?

Muetze1 3. Aug 2007 13:52

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Die App läuft auf unserem Server. Dort mussten Delphi 5 & 7 explizit bei der "Datenausführungsverhinderung" ausgeschlossen werden, damit sie liefen.

Luckie 3. Aug 2007 13:57

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Das heißt selbst mit VirtualAlloc angeforderter Speicher ist nicht ausführbar? Kann man da noch was machen? Quellcode findest du hier im Thread.

Muetze1 3. Aug 2007 14:00

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Zitat:

Zitat von Luckie
Das heißt selbst mit VirtualAlloc angeforderter Speicher ist nicht ausführbar?

Es läuft doch?! Er würde schliesslich eine Exception bekommen bzw. beendet werden, wenn es nicht laufen würde. Es klappt aber alles - also nichts zu meckern. (Du musst das dicke nicht in deinen Gedanken streichen :lol: )

Luckie 3. Aug 2007 14:07

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Na ja du hattest doch geschrieben, dass du Delphi von dem Schutz ausschliessen musstest. Deswegen dachte ich, es würde nicht laufen. Aber OK, dann geht das jetzt.

Aber jetzt: wies sieht es aus wenn der 32-Bit Code unter 64-Bit ausgeführt wird. Funktioniert es dann immer noch?

Gruber_Hans_12345 3. Aug 2007 14:37

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Zitat:

Zitat von Luckie
Na ja du hattest doch geschrieben, dass du Delphi von dem Schutz ausschliessen musstest. Deswegen dachte ich, es würde nicht laufen. Aber OK, dann geht das jetzt.

Aber jetzt: wies sieht es aus wenn der 32-Bit Code unter 64-Bit ausgeführt wird. Funktioniert es dann immer noch?

also mein vista ultimate, wos läuft ist 64 bittig

Luckie 3. Aug 2007 14:41

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Ok, das hätte ich jetzt nicht erwartet, aber gut. Danke fürs testen.

shmia 3. Aug 2007 15:19

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Hier kommt der Knaller ;-)
Das gibts es doch schon in der VCL
Unit Forms
Delphi-Quellcode:
function MakeObjectInstance(Method: TWndMethod): Pointer;
procedure FreeObjectInstance(ObjectInstance: Pointer);

sirius 3. Aug 2007 15:55

Re: ...Methodenzeiger in Funktionszeiger konvertieren?
 
Zitat:

Zitat von shmia
Hier kommt der Knaller ;-)
Das gibts es doch schon in der VCL
Unit Forms
Delphi-Quellcode:
function MakeObjectInstance(Method: TWndMethod): Pointer;
procedure FreeObjectInstance(ObjectInstance: Pointer);

Und, hast du dich auch schon mal gefragt was dieses blöde Wnd zwischen dem T und dem Method sucht? :wink:
Der springt erstmal standardmäßig auf die Stdwndproc und hätte da auch gerne die angegebenen Parameter einer TWndProc :zwinker:

Allerdings hast du Recht. Es ist das gleiche/ähnliche Prinzip, man kann sich da einiges abgucken, wie es auch ohne ASM geht. Wobei hier auch noch ein bisschen mehr passiert. Ich hab grad keine Lust mich da weiter reinzudenken


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