Seite 1 von 2

Prozeduren von fremden Prozessen ausführen (Windows)

Verfasst: 19.05.2007 21:31
von Thorium
Da ich einige Tools für Spiele entwickle, stellt sich mir öfter die Problematik, das ich eine spielinterne Prozedur aufrufen will. Z.B. um Text auf den Screen des Spiels zu bekommen oder sonstiges.

Hier eine Prozedur mir der das ohne weiteres möglich ist.

hTarget: Handle des fremden Prozesses
ProcAddr: Adresse der Prozedur im fremden Prozess
Params: Long-Array mit beliebig vielen Parametern, die an die Prozedur übergeben werden sollen.
Wait: Wenn 1 dann wartet das Programm mit der weiteren Ausführung bis die fremde Prozedur komplett abgearbeitet ist.

Gibt die Prozedur 0 zurück ist sie gescheitert.

Code: Alles auswählen

;Written by Thorium
;PureBasic 4.02 Windows

Macro ArrayIndex(Array)
  PeekL(Array-8)-1
EndMacro

Procedure.l RemoteCallProc(hTarget.l,ProcAddr.l,Params.l(1),Wait.b)
  Define.l i,Position,ParamsCnt,hThread,BytesWritten,ProcCallAddr,CodeBuffer
  
  ParamsCnt = ArrayIndex(Params())
  CodeBuffer = AllocateMemory($1000)
  
  ;Parameter-Pushen generieren: push const
  For i = ParamsCnt To 0 Step -1
    PokeB(CodeBuffer + Position,$68)
    Position + 1
    PokeL(CodeBuffer + Position,Params(i))
    Position + 4
  Next
  
  ;Prozeduraufruf generieren: mov eax,const : call eax
  PokeB(CodeBuffer + Position,$B8)
  Position + 1
  PokeL(CodeBuffer + Position,ProcAddr)
  Position + 4
  PokeW(CodeBuffer + Position,$D0FF)
  Position + 2
  
  ;Rücksprung generieren: ret
  PokeB(CodeBuffer + Position,$C3)
  Position + 1
  
  ;Speicher für Code im Zielprozess allokieren
  ProcCallAddr = VirtualAllocEx_(hTarget,0,Position,#MEM_COMMIT | #MEM_RESERVE,#PAGE_EXECUTE_READWRITE)
  If ProcCallAddr = 0
    ProcedureReturn 0
  EndIf
  
  ;Code in den Zielprozess schreiben
  If WriteProcessMemory_(hTarget,ProcCallAddr,CodeBuffer,Position,@BytesWritten) = 0
    ProcedureReturn 0
  EndIf
  If WrittenBytes <> Position
    ProcedureReturn 0
  EndIf

  FreeMemory(CodeBuffer)

  ;Code ausführen indem ein Thread im Zielprozess erzeugt wird
  hThread.l = CreateRemoteThread_(hTarget,0,0,ProcCallAddr,0, 0, 0)
  If hThread = 0
    ProcedureReturn 0
  EndIf

  ;falls erwünscht warten bis der Thread beendet ist
  If Wait = 1
    WaitForSingleObject_(hThread,#INFINITE)
    ;Speicher im Zielprozess wieder freigeben
    VirtualFreeEx_(hTarget,ProcCallAddr,0,#MEM_RELEASE)
  EndIf

  ProcedureReturn 1
EndProcedure

Verfasst: 19.05.2007 21:38
von ts-soft
Du solltest Procedure.b gegen Procedure.l tauschen, Du sparst nicht ein Byte,
lediglich die Ausführung wird verlangsamt. Habs zwar schon mehrmals
erwähnt, aber irgendwie glaubt mir keiner :mrgreen:

Verfasst: 19.05.2007 21:42
von hardfalcon
Dass es nicht wirklich Speicher spart, ist klar, aber warum verlangsamt es das ganze denn? :?

Verfasst: 19.05.2007 21:51
von Thorium
ts-soft hat geschrieben:Du solltest Procedure.b gegen Procedure.l tauschen, Du sparst nicht ein Byte,
lediglich die Ausführung wird verlangsamt. Habs zwar schon mehrmals
erwähnt, aber irgendwie glaubt mir keiner :mrgreen:
Hab ich geändert, vielen Dank für den Hinweis wusste ich nicht. Mich würde aber auch interessieren warum das langsamer sein soll.

Verfasst: 19.05.2007 21:53
von AND51
> Habs zwar schon mehrmals erwähnt, aber irgendwie glaubt mir keiner
Doch ich! Ganz ehrlich!
Seit dem du das das erste Mal (mir gegenüber erwähnt hast), benutze ich nur noch Long und nichts darunter. Ja gut und ansonsten halt noch Quad, wenn nötig, und Floats/Dubbels. (Nein nicht Karl...^^)

> aber warum verlangsamt es das ganze denn
So wie TS'si es erklärt und ich verstanden habe ist das so, wei die Prozessorregister 4 Byte lang (oder groß?) sind. Ein Long ist auch 4 Byte groß. Das passt wie die Faust auf's Auge und somit ergibt sich die beste Performaz. Andere Typen (z. B. Byte) passen nicht, und sind dahere langsamer.

Korrigiert mich, wenn ich falsch liege. Schließlich geht in dem Fall auch meine Bildung den Bach runter. :lol:

Verfasst: 19.05.2007 21:58
von ts-soft
Bytes sind fast nur in Strukturen sinnvoll, wo sie tatsächlich nur ein Byte
belegen. Ein 32-Bit Betriebssystem kann auch 32-Bit Werte am schnellsten
verarbeiten, nämlich ohne Umwege, direkt unter Verwendung von 32-Bit
registern :mrgreen:
Ansonsten mal einen ASM-Freak fragen

Verfasst: 19.05.2007 22:01
von AND51
> Bytes sind fast nur in Strukturen sinnvoll
Fast oder immer? Wenn immer, dann weiß ich, ob ich in meine Strukturen von nun an Byte verwende.
Sind dort auch Word sinnvol? falls ich mal nen "halben Long" brauche?
Und was hat das für vorteile, wenn ich das mache anstatt nur mit Longs?

> Ein 32-Bit Betriebssystem kann auch 32-Bit Werte am schnellsten
verarbeiten
Und 64-Bit Systeme mit 64 Bit, also Quads? Muss ich dann immer Quads statt Longs nehmen?

Verfasst: 19.05.2007 22:04
von Thorium
AND51 hat geschrieben:> Bytes sind fast nur in Strukturen sinnvoll
Fast oder immer? Wenn immer, dann weiß ich, ob ich in meine Strukturen von nun an Byte verwende.
Sind dort auch Word sinnvol? falls ich mal nen "halben Long" brauche?
Und was hat das für vorteile, wenn ich das mache anstatt nur mit Longs?

> Ein 32-Bit Betriebssystem kann auch 32-Bit Werte am schnellsten
verarbeiten
Und 64-Bit Systeme mit 64 Bit, also Quads? Muss ich dann immer Quads statt Longs nehmen?
Ich denke das hat weniger mit dem Betriebssystem zutun als mehr mit der CPU. Weil an einem mov al,blub oder mov eax,blub ändert das Betriebssystem nix.

Naja bei Strukturen würde ich dann mal schwer davon ausgehen das es da eher um Strukturen in Verwendung mit Dateiformaten geht. Weil da alles als Longs zu speichern ist dann doch Speicherverschwendung. ^^

Verfasst: 19.05.2007 22:31
von ts-soft
PureBasic muß sich ja die Adresse zum Byte merken, die ist aber 32-Bit
gross, ersparnis 0, nur die CPU braucht länger.
Eine Strukture ist ja nur eine besondere Form von Speicherallokierung. Da
wird das Byte, Word oder sonstwas ja über die Strukture adressiert.

Verfasst: 20.05.2007 01:17
von Macros
Thorium hat geschrieben:hTarget: Handle des fremden Prozesses
ProcAddr: Adresse der Prozedur im fremden Prozess
Params: Long-Array mit beliebig vielen Parametern, die an die Prozedur übergeben werden sollen.
Und wie finde ich das alles raus?
Gibt es da Programme/Prozeduren dafür,
oder muss man mit Ollydbg ran
(wenn ichs denn könnte ^^)