[Tutorial] Microsoft Detours

05/18/2009 19:37 schlurmann#1
Eine kleine .dll wird geschrieben, die mithilfe der Microsoft Detours Library die MessageBoxA Funktion detourt, und den Text ersetzt, sobald sie in einen Prozess injeziert wird. Ich hoffe ich konnte es einigermaßen verständlich erklären (mein Gedankenfluss ist manchmal etwas wirr).

Es ist auf Deutsch.

[Only registered and activated users can see links. Click Here To Register...]
05/18/2009 19:52 scbiz#2
Schick! :)
Gibt es einen Grund warum du dich gegen die Benutzung der 2.1'er Version entschieden hast?
05/18/2009 20:19 schlurmann#3
Quote:
Originally Posted by scripteur View Post
Schick! :)
Gibt es einen Grund warum du dich gegen die Benutzung der 2.1'er Version entschieden hast?
Ehrlich gesagt weiß ich gar nicht, ob Detours 2.1 vielleicht sogar im Hintergrund besser/sicherer arbeitet, allerdings, wenn du schon mal etwas mit Detours 2.1 gemacht hast: bei Detours 1.5 reicht eine Funktion. Bei Detours 2.1 musst du, wenn ich mich recht erinnere, mindestens 4 oder 5 Funktionen aufrufen, um dein Detour zu setzen. Also aus Bequemlichkeit.

Wenn es gute Argumente gegen 1.5 gibt, ich bin umstimmbar.
05/18/2009 21:28 __wadim#4
find ich sehr gut gemacht und ist auch alles bestens erklärt ;)
gj schlurmann!
05/18/2009 22:12 schlurmann#5
Freut mich. Danke. Dann kann ich ja mehr produzieren. Vorschläge? :)
05/18/2009 23:55 Bot_interesierter#6
Detours erzeugt keine Kopie von der Original Funktion, es werden lediglich die für den Sprung überschriebenen Opcodes kopiert und diese werden in eine "Trampolin"Funktion geschrieben, diese besteht aus den überschriebenen Bytes der Detourten Funktion und einem Sprung in die Original Funktion nach dem Detour Sprung, Detours achtet dabei auch auf eventuell überschriebene Sprung- und Callbefehle.
Und die Detours 1.5 Library ist nicht wirklich Thread sicher, es könnte passieren das der Scheduler während des Patchvorgangs in der DLLMain meint das ein Thread des Programms jetzt lieber weiterlaufen sollte und dann die nicht vollständig gepatchte Funktion aufgerufen wird und das Programm abschmiert, um das zu vermeiden benutzt man zur DLL injection am besten die CreateProcessWithDll (der Name ist eventuell anders) Funktion aus der Detours Library.
05/19/2009 00:12 RDTSC#7
Hm, als ich mir das Video angeschaut habe, hat der Bot Interessierte seine Chance ergriffen und mir die Berichtigung vorweg genommen... :-/

Damit mein Beitrag nicht nur aus Spam besteht:
So eine Detour-Funktion kann man auch leicht selber schreiben, siehe meinen kleinen Teeworlds Bot.
05/19/2009 00:18 schlurmann#8
Das wusste ich nicht. Danke. Ich habe allerdings keine Lust ein neues Video zu drehen, ich schreibe es darunter auf. :p

Edit: Ich habs berichtigt.
05/19/2009 12:41 Atheuz#9
Wird es nächstes mal auch ein Video geben wo du an einen einfachen Spiel erklärst wie man die typdef und argumente bekommt, falls es keine API ist?

<- Hat keine Ahnung, also nicht schlagen o,o
05/19/2009 12:54 schlurmann#10
Quote:
Originally Posted by Atheuz View Post
Wird es nächstes mal auch ein Video geben wo du an einen einfachen Spiel erklärst wie man die typdef und argumente bekommt, falls es keine API ist?

<- Hat keine Ahnung, also nicht schlagen o,o
Klar, kann ich machen.
05/19/2009 14:15 RDTSC#11
Nebenbei: JMPs kann man natürlich auch überall hinschreiben, es muss also nicht immer am Anfang einer Funktion sein.

@Atheuz:
Da geht an einer Analyse nichts vorbei.
Du müsstest den Prozess debuggen und dir den Stack anschauen, wenn in die Funktion gesprungen wird.
Das mit dem typedef kannst du auch ignorieren, wenn du auf Inline ASM zurückgreifst (Habe ich auch gemacht...).
05/19/2009 15:52 schlurmann#12
Nun ja, so eine grundlegende Vorgehensweise je nachdem was man finden möchte kann man schon vermitteln.

RDTSC: Schon, aber würde das nicht ggf. Probleme mit den Parametern nach sich ziehen, wenn vor dem Jump schon am Stack rumgewerkelt wurde?

Zum Thema Inline ASM: Inline ASM erleichtert oft einiges, allerdings ist das aufgrund der Anfängerfreundlichkeit die ich hier erzielen möchte wohl keine gute Idee für das Video.

Ich habe es doch noch ein mal neu aufgenommen und eine kleine Zeichnung zur Erklärung gemacht.
05/19/2009 18:57 RDTSC#13
"Nun ja, so eine grundlegende Vorgehensweise je nachdem was man finden möchte kann man schon vermitteln."
Jaja, klar.... halt den Stack begutachten ;-)

Ich meinte das eher so, dass man überall einfach so damit Code injizieren kann.
Auch irgendwo dort, wo deine Lebenspunkte dekrementiert werden.
Da packst du dann halt z.B. Code zu, der eine Nachricht ausgibt und deine LP um 30 erhöht.
Man sollte das nicht so HLL-like betrachten, dass man so Funktionen hookt...

Mitten in einer Funktion geht es natürlich auch und wenn die Funktion einen Stack Frame hat (Ich schätze mal, dass es da auch eine Konvention gibt, dass alle WinAPI Funktionen, die Parameter entgegen nehmen, einen standardisierten Stack Frame erstellen), wird man mit den Parametern keine Probleme haben.
05/20/2009 10:39 Atheuz#14
Quote:
Originally Posted by schlurmann View Post
[Only registered and activated users can see links. Click Here To Register...]
ಠ_ಠ
05/20/2009 15:27 RDTSC#15
War doch bestimmt Absicht :P
Aber geiler Smiley für diesen Kontext /no1

Ich habe mir gerade einmal die Zeichnung deines überarbeiteten Videos angeschaut:
In deinem Beispiel ist der Begriff 'springen' nicht falsch, auch wenn du es nicht tust...
Wenn du die Trampolinfunktion aufrufst, springt diese zum restlichen Teil der originalen Funktion und am Ende dieser wird beim Return wieder zu deiner gesprungen, in der nur noch ein Befehl folgt, der dahin springt, von wo MessageBoxA aufgerufen wurde (+ 5 wegen des relativen JMPs).
Der Stack wird also unnötig 2x mehr benutzt und ein Opcode ist auch zuviel...

Bei einem JMP und Parameter verändern (über Inline ASM) anstatt CALL und Parameter alle erneut pushen würde von deiner Funktion zur Trampolinfunktion, die zur originalen springt, von wo aus das Return den Instruction Pointer dann direkt auf den Caller setzt, gesprungen werden.


[ Was mir gerade mal so aufgefallen ist... ]
Der Compiler scheint das automatisch zu optimieren, und nicht zu knapp...
Das, was ich oben geschrieben habe, bringt ja nur etwas, wenn nach dem Sprung zur Trampolinfunktion nichts mehr kommen soll.
Da der Compiler aber automatisch den Stack updatet und dann zur Trampolinfunktion springt (anstatt noch einmal alles zu pushen und die Funktion dann mit einem CALL aufzurufen), ist es nichtig, was ich oben geschrieben habe, da es halt automatisch passiert...

Falls jemand mein Posting nicht versteht, weil es voll scheiße ist, einfach alles überlesen :x