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 getthreadcontext verständnisfrage (https://www.delphipraxis.net/63659-getthreadcontext-verstaendnisfrage.html)

smc 21. Feb 2006 11:26


getthreadcontext verständnisfrage
 
Hallo an alle, ich bins mal wieder :)

ich bin zuletzt über die windows api getthreadcontext gestolpert und habe da so meine Probleme diese API zu verstehen.
So wie ich das im moment verstehe kann man mit dieser API die register eines opcode offsets auslesen lassen.

Für mich bedeutet das das man in dieser Funktion das Handle, das Betreffende Offset und ein Pointer auf TContext (ablagestelle für eax, ecx etc.) angeben muss.

Nun habe ich mir das ganze auf msdn angesehen um muss zu meinem erstaunen feststellen das das ganz anders aussieht.

Code:
BOOL GetThreadContext(
  HANDLE hThread,
  LPCONTEXT lpContext
);
Handle to the thread whose context is to be retrieved. <- Hä? O_o eigentlich habe ich ein HANDLE hProcess erwartet, aber wie zeige ich auf einen hThread? *verwirrt*

[in, out] Pointer to the CONTEXT structure that receives the appropriate context of the specified thread. <- wieso Context struktur? muss ich hier das Offset angeben aus dem ich die register lesen will? oder betrifft dies das TContext? wenn TContext damit angesprochen wird verstehe ich nicht auf welches Offset die funktion zugreifen soll.

Mit dieser Funktion will ich ereichen das mein Programm aus einem anderen laufenden Prozess von einem opcode offset ein bestimmtes register ausliest (eax).

Ist das damit überhaupt möglich?

Im moment verstehe ich das nicht wirklich, eventuell kann mir jemand von euch weiterhelfen, würde mich freuen!

grüße

NicoDE 21. Feb 2006 11:56

Re: getthreadcontext verständnisfrage
 
Delphi-Quellcode:
function GetThreadContext(hThread: THandle; var lpContext: TContext): BOOL; stdcall; external kernel32;
hThread - Handle auf ein Thread-Objekt (siehe: CreateThread, OpenThread, ...)
lpContext - Struktur die durch die Funktion gefüllt wird (platformspezifische Struktur, die den 'Zustand' eines Threads wiederspiegelt - unter x86 sind das einige Prozessor-Register)

smc 21. Feb 2006 14:13

Re: getthreadcontext verständnisfrage
 
ok, danke.

lpContext verstehe ich nun.
Habe jetzt nur noch meine Probleme mit hThread.

Ich will ein Statistik Programm für ein spiel schreiben, dieses Programm muss Werte aus verschiedenen offsets auslesen.
Da die offsets durch DMA sich bei jedem neustart des Spiels ändern will ich mit getthreadcontext das register eines opcode auslesen welche die position des neuen offsets beinhaltet.

Ich verstehe einfach nicht wieso die api's keine pointer zu dem prozess von dem ich eigentl. was will beinhalten, woher soll den mein programm wissen worauf es zugreifen soll wenn ich nur threadspezifische infos bereitstellen kann?

In etwa so hab ich mir das anfangs gedacht:
1. Handle suchen und finden
2. api zum register lesen benutzen
->>> (handle, opcodeoffset, register(z.b. EAX), pointer wo der inhalt von eax übermittelt wird)
3. readprocessmemory von dem eaxpointer wert
4. ergebniss von readprocessmemory (nach floattostr) in einem lable anzeigen

scheint so aber nicht zu funktionieren, hm? :-)

p.s. vll. machts bei mir bei diesem thema doch noch "klick" :cheers:

Robert Marquardt 21. Feb 2006 14:26

Re: getthreadcontext verständnisfrage
 
Also so wie du mit unpassenden Begriffen um dich wirfst, hast du keine Ahnung, aber davon recht viel.

DMA hat nur im Kernel irgendeine Bedeutung. Im Userspace ist es voellig unbekannt.
Wie kommst du eigentlich auf die Idee das das Thread API etwas zur Loesung deines Problems beitragen kann?
Speziell GetThreadContext ist praktisch nur fuer einen Debugger interessant.

Es waere auch mal praktisch zu erklaeren was du wirklich machen willst.
Bestimmte Speicherzellen aus dem virtuellen Adressraum eines anderen Prozesses auszulesen ist durchaus moeglich.
Die Funktion dazu heisst ReadProcessMemory.

smc 21. Feb 2006 14:40

Re: getthreadcontext verständnisfrage
 
Zitat:

Zitat von Robert Marquardt
Also so wie du mit unpassenden Begriffen um dich wirfst, hast du keine Ahnung, aber davon recht viel.

danke :( ich bin leider noch Anfänger.

Zitat:

DMA hat nur im Kernel irgendeine Bedeutung. Im Userspace ist es voellig unbekannt.
Wie kommst du eigentlich auf die Idee das das Thread API etwas zur Loesung deines Problems beitragen kann?
habe ich daraus so verstanden: hThread - Handle auf ein Thread-Objekt (siehe: CreateThread, OpenThread, ...)


Zitat:

Speziell GetThreadContext ist praktisch nur fuer einen Debugger interessant.
Das ist im grunde der springende punkt, debugger wie ollydbg können ja register von opcodes lesen, genau das will ich meinem Programm beibringen.

Zitat:

Es waere auch mal praktisch zu erklaeren was du wirklich machen willst.
hab ich doch :)
### Ich will ein Statistik Programm für ein spiel schreiben, dieses Programm muss Werte aus verschiedenen offsets auslesen.
Da die offsets durch DMA sich bei jedem neustart des Spiels ändern will ich mit getthreadcontext das register eines opcode auslesen welche die position des neuen offsets beinhaltet. ###

Zitat:

Bestimmte Speicherzellen aus dem virtuellen Adressraum eines anderen Prozesses auszulesen ist durchaus moeglich.
Die Funktion dazu heisst ReadProcessMemory.
ReadProcessMemory bringt mir leider erst dann etwas sobald ich das Zieloffset weiss, und genau das wechselt immer bei einem Prozessneustart!
Das Zieloffset will ich eben aus dem opcode welcher das Zieloffset (für rpm) übermittelt mit einer api bekommen.

Sorry wenn ich mit meiner Fragerei nerve.

Robert Marquardt 21. Feb 2006 15:19

Re: getthreadcontext verständnisfrage
 
Bevor du nicht verstehst wie ein Windows-Programm/Prozess ueberhaupt funktioniert kannst du keinen Erfolg haben.
Ein Prozess hat einen virtuellen Adressraum ganz fuer sich allein. Dort wird er normalerweise immer an die gleiche Adresse geladen.
DLLs landen im gleichen Adressraum, aber sie muessen moeglicherweise reloziert werden, falls schon eine andere DLL an der gewuenschten Basisadresse steht.

Du willst vermutlich globale Variablen des Programms auslesen.
Dazu dient ReadProcessMemory. Die Besonderheit bei dieser Funktion ist das die Leseadresse aus dem Adressraum des zu lesenden Prozesses und die Adresse des Zielpuffers aus dem Adressraum des lesenden Prozesses ist.

Was du ermitteln ist die Leseadresse.

smc 21. Feb 2006 15:49

Re: getthreadcontext verständnisfrage
 
Nennen wir es halt Leseadresse, fakt ist das ich mit ReadProcessMemory nicht allzuweit komme da ich keinen Static Pointer finden kann der zu der Adresse zeigt welche den Wert welchen ich dem User übermitteln will hält.

Das Offset welches z.B. die Anzahl von Holz beinhaltet wechselt bei jedem Spielneustart.

Für mich gibt es nun 3 möglichkeiten:
1. DMA Stealing - will ich nicht machen weil das mit codeinjections verbunden ist welche das jetzige offset in ein codecave kopiert.
2. Static Pointer finden - ist normalerweise der beste weg, kann man bei manchen programmen auch recht einfach finden, nur bei diesem nicht (sind sicher über 5 lvl *würg*).
3. getthreadcontext - habe ich bisher noch nie angewand, sollte aber funktionieren, die debugger können es ja auch.

Irgendwie reden wir aneinander vorbei...

Mal ein Beispiel:

0056ac15 - mov eax,[eax+10]

in eax befindet sich das offset von holz

Ich will nun 0056ac15 auslesen und den wert von EAX einsehen

danach addiere ich 0x10 zu dem gewonnen wert, der wert sollte dann meine _Leseadresse_ sein.

Die Leseadresse lese ich mit ReadProcessMemory.

NicoDE 21. Feb 2006 16:01

Re: getthreadcontext verständnisfrage
 
Zitat:

Zitat von smc
Mal ein Beispiel:
0056ac15 - mov eax,[eax+10]
in eax befindet sich das offset von holz
Ich will nun 0056ac15 auslesen und den wert von EAX einsehen

An Adresse 0x0056ac15 steht nur die Prozessoranweisung für "mov eax,[eax+10]" - du müsstest genau in dem Moment den Context auslesen, in welchem ein/der Thread diesen Code ausführt -> womit wir wieder beim Debugger wären...

ps@robert: mit 'DMA stealing' meint er wahrscheinlich das Überwachen von 'Dynamic Memory Allocations' (hoch leben die unverstandenen Abkürzungen ;))

smc 21. Feb 2006 16:09

Re: getthreadcontext verständnisfrage
 
genau das will ich :) nur wie stell ich das an?
Ich weiss das die Anweisung sehr oft aufgerufen wird, daher ist das kein Problem!


DMA Stealing würde wie folgt aussehen:

0056ac15 - mov eax,[eax+10] ändern wir in einen JMP zu einem CodeCave um.

das CodeCave beinhaltet dann den original opcode und ein lea eax+mov eax opcode welcher den wert von eax läd und in ein weiteres CodeCave schiebt.
In dem letzten CodeCave findet man dann immer das aktuelle Offset (auch nach einem neustart) :)

Dachte eigentlich das "DMA Stealing" so bekannt ist, da ich es schon öfters gelesen habe, naja so kann man sich irren.

NicoDE 21. Feb 2006 16:19

Re: getthreadcontext verständnisfrage
 
Zitat:

Zitat von smc
0056ac15 - mov eax,[eax+10] ändern wir in einen JMP

Das sind nur drei Bytes ($8B $40 $0A)...
- das reicht nur für einen short jump (127 Bytes)
- du müsstest also das Code-Segment patchen (Erfahrung mit Assembler unter Windows x86 scheinen ja zu fehlen...)

Zitat:

Zitat von smc
zu einem CodeCave um.

Ein was?

Zitat:

Zitat von smc
Dachte eigentlich das "DMA Stealing" so bekannt ist, da ich es schon öfters gelesen habe, naja so kann man sich irren.

Ich kenne mich damit nicht so sehr aus...

smc 21. Feb 2006 16:45

Re: getthreadcontext verständnisfrage
 
Zitat:

Das sind nur drei Bytes ($8B $40 $0A)...
- das reicht nur für einen short jump (127 Bytes)
- du müsstest also das Code-Segment patchen (Erfahrung mit Assembler unter Windows x86 scheinen ja zu fehlen...)
ist mir klar, war ja auch nur ein Beispiel :)

Zitat:

Ein was?
Ein CodeCave ist normalerweise eine größere Sektion voller nops oder 0x00 Bytes in einem Modul in dem man eigene Codes injecten kann.

Zitat:

Ich kenne mich damit nicht so sehr aus...
muss man auch nicht wirklich

p.s. ich will hier kein was ist richtig, was ist falsch, spiel spielen.
Ich weiss auch das ich kein Profi in den ganzen sachen bin, allerdings will ich lernen wie das was wir oben schon teilweise angesprochen haben zu realisieren ist.

NicoDE 21. Feb 2006 16:52

Re: getthreadcontext verständnisfrage
 
Zitat:

Zitat von smc
allerdings will ich lernen wie das was wir oben schon teilweise angesprochen haben zu realisieren ist.

Wurde doch schon erwähnt: a) Schreibe einen Debugger, setze einen Haltepunkt und hole dir den Thread-Context b) Patche den Remote-Code
Ist beides genauso aufwändig; spielt also IMHO keine Rolle wofür du dich entscheidest.

brechi 21. Feb 2006 16:54

Re: getthreadcontext verständnisfrage
 
smc, das was du vorhast kann mit GetThreadContext / WriteProcessMemory nicht sauber (ohne Hänger) lösen.

Willst du keine Injection / Hooking machen musst du folgendermaßen vorgehen:

Du überschreibst die Stelle mit Hilfe von WriteProcessMemory in dem du einen "jmp -2" dort hinschreibst. (EB FE)
Dadurch bleibt der Zielprozess beim nächsten Aufruf dort stehen (das Programm wird hängen). Wenn du aber dauerhaft immer GetThreadContext in deinem Programm auf den richtigen Thread (Haupthread des Spiels) aufrufst bis der EIP von dem zurückgelieferten Context = der Stelle ist wo du den short jump hingeschrieben hast, dann steht die richtige Adresse in lpContext.EAX. Danach kannst du den richtigen Opcode wieder hinschreiben, das Spiel wird dann weiterlaufen. Nun hast du den EAX Wert den du weiter benutzen kannst.

Codeinjection / Hooking wäre auch kein Problem ist aber für den Fall nicht direkt nötig, da du EAX bzw globale Adressen ja nicht verändern musst.

hierzu: http://cvs.sourceforge.net/viewcvs.p...uallCollection

btw
0056ac15 - mov eax,[eax+10]
ist nicht $8B $40 $0A sondern $8B $40 $10 da Ollydbg des immer in hex anzeigt *grossmaul*

brechi 21. Feb 2006 17:08

Re: getthreadcontext verständnisfrage
 
Delphi-Quellcode:
const DEINE_ADDR = $00441234;
var dwProcessID: DWord;
    dwThreadID: DWord;
    wBuf: Word;
    dwRead: DWord;
    wJmp: Word;
    Context: TContext;
    bFound: Boolean;
begin
  dwProcessID := uallProcess.FindProcess('solitär.exe');
  wJmp := $FEEB;

  if dwProcessID <> 0 then
  begin
    dwThreadID := uallProcess.GetThread(dwProcessID);
    dwProcessID := OpenProcess(PROCESS_ALL_ACCESS,false,dwProcessID);
    if ReadProcessMemory(dwProcessID,pointer(DEINE_ADDR),@wbuf,SizeOf(wBuf),dwRead) and
      (dwRead = SizeOf(wBuf)) then
    if WriteProcessMemory(dwProcessID,pointer(DEINE_ADDR),@wJmp,SizeOf(wJmp),dwRead) and
      (dwRead = SizeOf(wJmp)) then
    begin
      bFound := false;
      repeat
        if GetThreadContext(dwThreadID,Context) then
        begin
          if (Context.Eip = DEINE_ADDR) then
          begin
            WriteProcessMemory(dwProcessID,pointer(DEINE_ADDR),@wBuf,SizeOf(wBuf),dwRead);
            bFound := true;
            // Context.Eax hat den Wert
          end;
        end;
        Sleep(100);
      until bFound;
    end;

    CloseHandle(dwProcessID);
  end;
end;
Sollte als Beispiel genügen.

smc 22. Feb 2006 09:42

Re: getthreadcontext verständnisfrage
 
Hi brechi,

vielen dank für deine antwort, das hilft mir schon um einiges weiter!

Noch eine kleine Frage, könnte man nicht auch den thread mit SuspendThread anhalten anstatt mit einem EB FE?
Der opcode von dem ich den wert haben will wird so gut wie durchgängig ausgeführt, bin auch sicher das meine Adresse da durchgehend übermittelt wird.

Auf die uall sachen hätte ich früher stoßen sollen, ziemlich praktisch die funktionen. :)

brechi 22. Feb 2006 10:14

Re: getthreadcontext verständnisfrage
 
Mit Suspendthread stoppst du den Thread. WO der allerdings stehen bleibt kannst du nicht festlegen. Im schlechtesten Fall wird der nie genau an der Stelle stehen bleiben.

Suspendthread sollte man jedoch immer vor GetThreadContext aufrufen. Auch in meinem Beispiel. Wird zwar keine große Auswirkung haben, aber sicher ist sicher.

NicoDE 22. Feb 2006 11:08

Re: getthreadcontext verständnisfrage
 
Zitat:

Zitat von brechi
Du überschreibst die Stelle mit Hilfe von WriteProcessMemory in dem du einen "jmp -2" dort hinschreibst. (EB FE)
Dadurch bleibt der Zielprozess beim nächsten Aufruf dort stehen (das Programm wird hängen).

Bleibt nur zu hoffen, dass die Zielanwendung keinen WatchDog-Thread hat...
(juhu, mein erstes Schlagwort in diesem Thread *g*)

smc 22. Feb 2006 11:20

Re: getthreadcontext verständnisfrage
 
okay ich werd dann mal ein bisschen rumtesten sobald ich dazu komme, melde mich dann nochmal :)

Das einzigste was mich jetzt noch stört ist die CodeInjection von EB FE, aber ohne wird es wahrscheinlich nur mit Static Pointern gehen (hab ich schon erwähnt das ich Static Pointer suchen hasse?).

Gefällt mir so aber schon um einiges besser als dma stealing!

Zitat:

Bleibt nur zu hoffen, dass die Zielanwendung keinen WatchDog-Thread hat...
(juhu, mein erstes Schlagwort in diesem Thread *g*)
:thumb:

brechi 23. Feb 2006 09:40

Re: getthreadcontext verständnisfrage
 
Das Finden einer statischen Adresse, dauert (wenn man das Programm debuggen kann) nicht mal 5 Minuten. Das ist das beste/sicherste was du für deinen Einsatz benutzen kannst.

falls es einen "WatchDog-Thread" bekommst das das schnell mt Hilfe von den HW-BP raus
generell benutzen die neuen Cheats eben diese HW-BP kombiniert mit PAGE_GUARD um Funktionen abzufangen usw. was relativ schwer entdeckt werden kann

smc 23. Feb 2006 14:20

Re: getthreadcontext verständnisfrage
 
dann mache ich eindeutig was falsch, kennst du vielleicht ein gutes tutorial welches erklärt wie man Static-Pointer findet? habe bisher nur im cheatengine forum etwas darüber gefunden

und wie genau funktioniert ein hardware breakpoint mithilfe PAGE_GUARD? (höre ich jetzt zum ersten mal)


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