Autor |
Beitrag |
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 24.09.04 21:35
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
MrSaint
      
Beiträge: 1033
Erhaltene Danke: 1
WinXP Pro SP2
Delphi 6 Prof.
|
Verfasst: Fr 24.09.04 22:27
Zeile 3 sieht mir nach einem Parameter für den Kontruktor aus. ist das $irgendwas vielleicht ein Zeiger auf einen String oder sowas in der Art? Wenn der Konstruktor stdcall wäre, dann müsste an dieser Stelle glaube ich ein "mov eax, [$irgendwas]; push eax" stehen, aber ich glaube Delphi übergibt Variablen über die Register, sofern man "the delphi way of calling functions" benutzt *g* (bin mir da aber grad net so sicher; ich mein des hätt ich mal in meim quellcode gelesen)
Was Zeile 2 soll, weiß ich net genau, aber wenn du sagst, dass das der Konstruktor braucht, dann glaub ich dir das vom Felck weg
Und Zeile 1 is mir auch absolut unbegreiflich...
MrSaint
_________________ "people knew how to write small, efficient programs [...], a skill that has subsequently been lost"
Andrew S. Tanenbaum - Modern Operating Systems
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Fr 24.09.04 22:49
nach nem bisl decompilen
mov ecx, xxx
ist das offset des textes als pchar
so dann in eax:
[eax - $c] muss die adresse von tobject.NewInstance sein
[eax -$1c] muss die adresse von tobject.AfterConstrucion (oder ne funktion mit nem simplen ret)
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Sa 25.09.04 00:21
Zeile 1 verwundert mich aber:
Wenn ich in meinem Source
Delphi-Quelltext 1:
| MOV ECX, OFFSET FmtInvalidDim |
schreib, kommt was total anderes raus, als das was Delphi geproggt hat.
@EAX: Also müsste EAX der Zeiger auf die zu erzeugende Objekt-Klasse sein?
@DL: Muss eins sein, damit der Konstruktor eine Objekt-Referenz erzeugt. Ist bei jedem (internen) folgenden Aufruf 0, damit kein neues Objekt angelegt wird.
Aber wo ich besonders dran Scheitere ist die Sache mit dem Raise-en dieser erzeugten Exception ... Wie gesagt kann ich diese Routine @RaiseExcept ja leider nicht direkt aufrufen ... 
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: So 26.09.04 12:51
hab da mal nen bisl probiert
hier das was ich rausgefunden habe
der text der angezeigt werden soll
Delphi-Quelltext 1: 2:
| mov ecx, offset FmtInvalidDim mov ecx, [ecx] |
wobei FmtInvalidDim nen string ist
in eax wird nen offset von ne mstruct geschrieben
wo eax-$28 die länge des textes steht
in eax-$3c steht die adresse für den text der unit EMathbla
wobei am ersten byte die länge des textes steht
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| unittext^ := 4; unittext := pointer(integer(unittext)+1); unittext^ := byte('H'); unittext := pointer(integer(unittext)+1); unittext^ := byte('E'); unittext := pointer(integer(unittext)+1); unittext^ := byte('H'); unittext := pointer(integer(unittext)+1); unittext^ := byte('E');
p := pointer(integer(p)+$2c); |
bei der excpetion würde nun stehen
"bla bla fehler in der unit: HEHE"
hier mal alle funktionen nachgebaut, trotzdem funzt es nbet weil ich ncoh net den aufbau der struktur kenne
am besten mal kernel32.RaiseException angucken weil damit kann man die std exceptions machen, um aber selbst nen text festzulegene muss du dich mal damit auseinandersetzen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246:
| var FmtInvalidDim: string = 'hallo kleines';
procedure classcreate; asm PUSH EDX PUSH ECX PUSH EBX TEST DL,DL JL @jmp1 CALL tobject.newinstance; @jmp1: XOR EDX,EDX LEA ECX,DWORD PTR SS:[ESP+$10] MOV EBX,DWORD PTR FS:[EDX] MOV DWORD PTR DS:[ECX],EBX MOV DWORD PTR DS:[ECX+$8],EBP MOV DWORD PTR DS:[ECX+$4], offset @hae MOV DWORD PTR DS:[ECX+$C],EAX MOV DWORD PTR FS:[EDX],ECX POP EBX POP ECX POP EDX RETN @hae: end;
procedure error; begin end;
procedure GetMemx; asm PUSH EBX TEST EAX,EAX JLE @jmp1 CALL SysGetMem MOV EBX,EAX TEST EBX,EBX JNZ @jmp2 MOV AL,1 CALL Error JMP @jmp2 @jmp1: XOR EBX,EBX @jmp2: MOV EAX,EBX POP EBX RETN end;
procedure NewAnsiString; asm TEST EAX,EAX JLE @jmp1 PUSH EAX ADD EAX,$0A AND EAX,$FFFFFFFE PUSH EAX CALL GetMemx POP EDX MOV WORD PTR DS:[EDX+EAX-$2],0 ADD EAX,8 POP EDX MOV DWORD PTR DS:[EAX-$4],EDX MOV DWORD PTR DS:[EAX-$8],1 RETN XOR EAX,EAX @jmp1: RETN end;
procedure Move; asm PUSH ESI PUSH EDI MOV ESI,EAX MOV EDI,EDX MOV EAX,ECX CMP EDI,ESI JA @jmp1 JE @jmp2 SAR ECX,$2 JS @jmp2 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] MOV ECX,EAX AND ECX,$3 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] POP EDI POP ESI RETN @jmp1: LEA ESI,DWORD PTR DS:[ECX+ESI-$4] LEA EDI,DWORD PTR DS:[ECX+EDI-$4] SAR ECX,$2 JS @jmp2 STD REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] MOV ECX,EAX AND ECX,$3 ADD ESI,$3 ADD EDI,$3 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] CLD @jmp2: POP EDI POP ESI RETN end;
procedure FreeMem; begin end;
procedure lstrasg; asm TEST EDX,EDX JE @jmp1 MOV ECX, DWORD PTR DS:[EDX-$8] INC ECX JG @jmp1 PUSH EAX PUSH EDX MOV EAX,DWORD PTR DS:[EDX-$4] CALL NewAnsiString MOV EDX,EAX POP EAX PUSH EDX MOV ECX,DWORD PTR DS:[EAX-$4] CALL Move POP EDX POP EAX JMP @jmp1 LOCK INC DWORD PTR DS:[EDX-$8] @jmp1: XCHG DWORD PTR DS:[EAX],EDX TEST EDX,EDX JE @jmp2 MOV ECX,DWORD PTR DS:[EDX-$8] DEC ECX JL @jmp2 LOCK DEC DWORD PTR DS:[EDX-$8] JNZ @jmp2 LEA EAX,DWORD PTR DS:[EDX-$8] CALL FreeMem @jmp2: RETN end;
procedure AfterConstruction; asm PUSH EBX MOV EBX,EAX MOV EAX,EBX MOV EDX,DWORD PTR DS:[EAX] MOV EAX,EBX POP EBX RETN end;
procedure exceptcreate; asm PUSH EBX PUSH ESI PUSH EDI TEST DL,DL JE @jmp1 ADD ESP,-$10 CALL classcreate @jmp1: MOV ESI,ECX MOV EBX,EDX MOV EDI,EAX LEA EAX,DWORD PTR DS:[EDI+$4] MOV EDX,ESI CALL Lstrasg MOV EAX,EDI TEST BL,BL JE @jmp2 CALL AfterConstruction POP DWORD PTR FS:[0] ADD ESP,$C @jmp2: MOV EAX,EDI POP EDI POP ESI POP EBX RETN end;
procedure showexcept; asm OR EAX,EAX JNZ @jmp1 MOV EAX,$0D8 POP EDX @jmp1: PUSH ESP PUSH EBP PUSH EDI PUSH ESI PUSH EBX PUSH EAX PUSH EDX PUSH ESP PUSH $7 PUSH $1 PUSH $0EEDFADE PUSH EDX JMP RaiseException end;
procedure TForm1.Button1Click(Sender: TObject); var p: pointer; i: ^integer; unittext: ^byte; begin getmem(p,$800); zeromemory(p,$800); copymemory(p,pointer($00406ff0-$2c),$2c);
getmem(unittext,10);
i := p; i^ := integer(unittext);
unittext^ := 4; unittext := pointer(integer(unittext)+1); unittext^ := byte('H'); unittext := pointer(integer(unittext)+1); unittext^ := byte('E'); unittext := pointer(integer(unittext)+1); unittext^ := byte('H'); unittext := pointer(integer(unittext)+1); unittext^ := byte('E');
p := pointer(integer(p)+$2c);
asm mov ecx, offset FmtInvalidDim mov ecx, [ecx] mov dl, $1 mov eax, [p] call exceptcreate call showexcept end; end; |
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 26.09.04 19:09
Gut, soviel zum Construieren der Exception. Und das eigentliche Aufrufen? Die Function RaiseException, die in der System.pas aus der Kernel32.dll eingebunden wird wird wohl auf eher weniger was damit zu tun haben, da die für Win32-Exceptions gedacht ist, nicht für die Delphi-Exceptions.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: So 26.09.04 21:42
doch die hat was damit zu tun
der parameter muss $0EEDFADE sein bei kernel.RaiseExcpetion, dann kann man selbst über parameter bestimmten welcher text ausgegeben werden soll
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 07.10.04 17:36
Hab jetzt auch ne Möglichkeit gefunden, die EIGENTLICH funktionieren sollte.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| asm MOV ECX, [FmtInvalidDim] MOV DL, $01 MOV EAX, [EMathError] CALL Exception.Create CALL _RaiseExcept end; |
Das einzige Problem, was es mit diesem Source gibt, ist hier beschrieben.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Fr 08.10.04 10:50
also ich habe mir das nochmal genauer angeguckt,
folgendermaßen:
die wichtige funktion ist RaiseException
aus der kernel32.dll
diese funktion hat als
1. parameter die art der exception, eine delphi exception hat den wert
$0EEDFADE alle weiteren findest du bei msdn.microsoft.com/l...getexceptioncode.asp
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| const cContinuable = 0; cNonContinuable = 1; cUnwinding = 2; cUnwindingForExit = 4; cUnwindInProgress = cUnwinding or cUnwindingForExit; cDelphiException = $0EEDFADE; cDelphiReRaise = $0EEDFADF; cDelphiExcept = $0EEDFAE0; cDelphiFinally = $0EEDFAE1; cDelphiTerminate = $0EEDFAE2; cDelphiUnhandled = $0EEDFAE3; cNonDelphiException = $0EEDFAE4; cDelphiExitFinally = $0EEDFAE5; cCppException = $0EEFFACE; EXCEPTION_CONTINUE_SEARCH = 0; EXCEPTION_EXECUTE_HANDLER = 1; EXCEPTION_CONTINUE_EXECUTION = -1; |
der 2. parameter sollte EXCEPTION_EXECUTE_HANDLER sein, d.h. die excpeion geht an den handler
der 3. parameter ist die anzahl der parameter der exception handler bekommt
der 4. parameter ist die adresse wo die einzelnen parameter für den exception handler stehen
delphi hat einen eigenen SEH, der am anfang installiert wird, eine 'cDelphiException = $0EEDFADE' benötigt 7 parameter ->
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| TRaisedException = packed record RefCount: Integer; ExceptObject: TObject; ExceptionAddr: Pointer; HandlerEBP: LongWord; Flags: LongWord; Cleanup: Pointer; Prev: PRaisedException; ReleaseProc: Pointer; end; |
PS: frag mich net warum das 8 sind delphi übergibt der kernel funktion nen $07 ;>
aber um eine eigene exception aufzurufen kannst dir besser nen eigenen exception handler installieren
das geht über
Delphi-Quelltext 1: 2: 3: 4: 5:
| asm push fs:[0] push esp mov fs:[0], offset myexceptionhandler end; |
der eigentlich exception handler hat folgenden aufbau:
Delphi-Quelltext 1: 2: 3: 4: 5:
| function except_handler( ExceptionRecord: P_EXCEPTION_RECORD; EstablisherFrame: pointer; ContextRecord: P_CONTEXT; DispatcherContext: pointer): integer; cdecl; |
aus dem exception handler kannste dann selber die parameter auslesen über ExceptionRecord
für $0EEDFADE solltest dir dann selbst ne eigene zahl nehmen
-> also was delphi macht ist genau
nen exception handler installieren
bei ner raise exception vom user wird dann CreateException oder wie funktion heißt aufgerufen
dann kernel32.dll Raisexception mit den 7 parametern
der eigentliche delphi SEH bekommt dann diese exception und macht nichts anderes als zu schauen ob der parmeter $0EEDFADE, wenn so weiß der delphi SEH das es eine delphi raise exception ist, es werden die 7 parmeter auslesen und dann einfach ne messagebox angezeigt
also im endeffekt ist -> raise einfach ne msg box
bsp.:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure raiseerror(oo: tobject; s: string); stdcall; var retn: integer; begin asm mov eax, [ebp+4] mov [retn], eax end; dec(retn,5); messagebox(0,pchar('In der Unit: "'+oo.ClassName+'" an adresse: 0x'+inttohex(retn,8)+ ' mit der meldung: "'+s+'" aufgetreten'),'Exception',MB_ABORTRETRYIGNORE); end;
procedure TForm1.FormCreate(Sender: TObject); begin raiseerror(EMathError.NewInstance,'bla'); end; |
|
|
BenBE 
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 09.09.05 19:39
Manchmal sind die Dinge doch soooo einfach:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| asm MOV ECX, [FmtInvalidDim] MOV DL, $01 MOV EAX, [EMathError] CALL Exception.Create CALL System.@RaiseExcept end; |
Dann funktioniert es!!!
Auszug aus der Hilfe bzgl. Assembler-Direktiven:
Zitat: | Zwei zusätzliche Direktiven ermöglichen dem Assembler-Code den Zugriff auf dynamische und virtuelle Methoden: VMTOFFSET und DMTINDEX.
VMTOFFSET ruft den Byte-Offset des Tabelleneintrags mit dem virtuellen Methodenzeiger des virtuellen Methodenarguments vom Anfang der virtuellen Methodentabelle (VMT) ab. Diese Direktive benötigt einen vollständig angegebenen Klassennamen mit einem Methodennamen als Parameter (beispielsweise TExample.VirtualMethod) oder einen Schnittstellennamen und einen Schnittstellenmethodennamen.
DMTINDEX ruft den dynamischen Methodentabellenindex der übergebenen dynamischen Methode ab. Diese Direktive benötigt ebenfalls einen vollständig angegebenen Klassennamen mit einem Methodennamen als Parameter, (z. B. TExample.DynamicMethod). Sie rufen die dynamische Methode mit System.@CallDynaInst mit dem (E)SI-Register auf, das den von DMTINDEX abgerufenen Wert enthält.
Hinweis
Methoden mit der message-Direktive werden als dynamische Methoden implementiert und können auch mit DMTINDEX aufgerufen werden. Beispiel:
Delphi-Quelltext 1: 2: 3:
| TMyClass = class procedure x; message MYMESSAGE; end; |
Das folgende Beispiel verwendet sowohl DMTINDEX als auch VMTOFFSET für den Zugriff auf dynamische und virtuelle Methoden:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60:
| program Project2;
type TExample = class procedure DynamicMethod; dynamic; procedure VirtualMethod; virtual; end;
procedure TExample.DynamicMethod; begin
end;
procedure TExample.VirtualMethod; begin
end;
procedure CallDynamicMethod(e: TExample); asm PUSH ESI
MOV EAX, e
MOV ESI, DMTINDEX TExample.DynamicMethod CALL System.@CallDynaInst
POP ESI end;
procedure CallVirtualMethod(e: TExample); asm MOV EAX, e
MOV EDX, [EAX]
CALL DWORD PTR [EDX + VMTOFFSET TExample.VirtualMethod]
end;
var e: TExample;
begin e := TExample.Create; try CallDynamicMethod(e); CallVirtualMethod(e); finally e.Free; end; end. | |
Damit wäre wieder einmal ein Rätsel entmystifiziert ...
Habs getestet, der Source funzt so wirklich. Bin heut nur durch Zufall drauf gestoßen, hab eigentlich was ganz anderes gesucht ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|