Register for your free account! | Forgot your password?

You last visited: Today at 19:39

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



[C++]Hooks

Discussion on [C++]Hooks within the Coding Tutorials forum part of the General Coding category.

Reply
 
Old   #1
 
Tyrar's Avatar
 
elite*gold: 0
Join Date: Oct 2008
Posts: 1,637
Received Thanks: 1,119
[C++]Hooks

so... ich denke mal, dass ich euch eine der wichtigsten teile in sachen gamehacking hier erklären kann, oder zumindest versuchen zu erklären

fangen wir mal damit an, was ich benutze:
-Visual Studio 2008 Professional + Visual Assist X
-IDA Pro Free
-ein game

los gehts:
erstellt euch eine struktur, wodrin ihr informationen über einen hook speichert.
bei mir sieht das so aus:
Code:
[...]
typedef struct
{
BYTE* pBackup;
LPVOID* lpOriginal;
LPVOID* lpHook;
LPVOID* lpSub;
LPVOID* lpReturn;
}SHOOKINFO,*LPSHOOKINFO;
[...]
pBackup ist die kopie von dem überschriebenen speicher (später mehr)
lpOriginal ist die original funktions adresse
lpHook ist die funktion, die wir anspringen wollen!
lpSub ist eine zwischenfunktion, die lpHook ausführt, und auf lpReturn zurück springt.
lpReturn ist eine backup funktion, die den überschriebenen speicher ausführt, und zu der adresse von originalen+überschriebene byte länge springt.
als nächstes sollte ein globale variable erstellt werden, in der wir ALLE hook informationen speichern (auch mehrere). dazu nehme ich std::vector<typename>. das sieht so aus:
Code:
#include <vector>
[...]
std::vector<SHOOKINFO> hooks;
[...]
jetzt kommen wir zum interessanten teil, dem eigentlichen hook!
ein hook funktioniert so:
er überschreibt die ersten bytes einer funktion, mit den bytes die dafür sorgen dass die funktion als erstes an eine andere funktions adresse springt.
von dieser funktionsadresse KANN man die überschriebenen bytes ausführen, und an die original adresse + überschriebene byte länge springen, um die originale funktion aufzurufen.
da ich noch eine subfunktion habe die das alles für mich übernimmt (an neue adresse springen, und hinterher das backup ausführen), wird der letztere teil eher unnötig!
die subfunktion sieht bei mir so aus:
Code:
__declspec(naked) void hkSub()
{
__asm
{
pushfd //register backup
pushad //register backup
call 0xDEADBEEF //platzhalter für die neue funktion
popad //register backup laden
popfd //register backup laden
jmp 0xDEADBEEF //platzhalter für die backup funktion
}
}
die platzhalter werden später durch die "richtigen" adressen ersetzt.
Code:
[...]
#define ASM_JMP 0xE9 //byte-op-code für den JMP befehl!
[...]
SHOOKINFO AttachHook(LPVOID lpOriginal,LPVOID lpNew)
{
DWORD dwOldProtect;
SHOOKINFO info;
info.lpSub = VirtualAlloc(NULL,sizeof(&hkSub),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
info.lpReturn = VirtualAlloc(NULL,10,MEM_COMMIT,PAGE_EXECUTE_READWRITE); //wie ich auf 10 komme? überschriebene bytes(5)+jmp(1)+DWORD(4)
VirtualProtect(lpOriginal,5,PAGE_EXECUTE_READWRITE,&dwOldProtect); //wie ich auf 5 komme? jmp(1)+DWORD(4)
info.pBackup = new BYTE[5];
memcpy(&info.pBackup[0],lpOriginal,5);
memcpy(lpOriginal,(void*)ASM_JMP,1); //jmp an den anfang schreiben
memcpy((void*)((DWORD)lpOriginal+1),info.lpSub,4); //adresse hinterher schreiben!
VirtualProtect(lpOriginal,5,dwOldProtect,0);
memcpy(info.lpSub,&hkSub,sizeof(&hkSub));
memcpy((void*)((DWORD)info.lpSub+3),lpNew,4); //das erste 0xDEADBEEF durch lpNew ersetzen!
memcpy((void*)((DWORD)info.lpSub+10),info.lpReturn,4); //das zweite 0xDEADBEEF durch info.lpReturn ersetzen!
memcpy(info.lpReturn,&info.pBuffer[0],5); //die überschriebenen bytes in die backup funktion schreiben
memcpy((void*)((DWORD)info.lpReturn+5),(void*)ASM_JMP,1); //jmp schreiben
memcpy((void*)((DWORD)info.lpReturn+6),(void*)((DWORD)lpOriginal+5),4); //die adresse hinterher schreiben, wo der jmp befehl auf die sub funktion zuende ist!
return info;
}
startet jetzt IDA, und analysiert das spiel! (könnte etwas dauern)
wenn IDA fertig ist, guckt mal in die register karte "Functions", und sucht nach einer funktion die interessant sein könnte. Ob die funktion euch interessiert, könnt ihr am namen lesen (wenn sie einen hat).
nehmen wir mal an, die funktion liegt an adresse 0x00618942.
dann muss euer code so aussehen:
Code:
__declspec(naked) void hkNothing()
{
//do something
}
[...]
AttachHook((void*)0x00618942,&hkNothing);
ich hoffe da sind keine fehler drin, und dass es hilfreich war
Tyrar is offline  
Thanks
6 Users
Old 03/21/2010, 23:50   #2
 
flo8464's Avatar
 
elite*gold: 0
Join Date: Nov 2008
Posts: 161
Received Thanks: 38
Der Code ist leserlich wie Spaghetti und du gibst einen Scheiß auf 64bit-Kompatibilität, aber trotzdem mal was brauchbares, netter Beitrag

Wenn wir langweilig ist, werde ich deinen Code mal in schöneres C++ mitsamt x64-Unterstützung portieren, mal sehen.
flo8464 is offline  
Old 03/22/2010, 04:06   #3
 
P-a-i-n's Avatar
 
elite*gold: 0
Join Date: Nov 2009
Posts: 1,258
Received Thanks: 396
Quote:
Originally Posted by flo8464 View Post
Der Code ist leserlich wie Spaghetti und du gibst einen Scheiß auf 64bit-Kompatibilität, aber trotzdem mal was brauchbares, netter Beitrag

Wenn wir langweilig ist, werde ich deinen Code mal in schöneres C++ mitsamt x64-Unterstützung portieren, mal sehen.
so ein quatsch das wird sogar unter 64 bit unterstützt arbeite genauso wie er und hab nie probleme

das ist kein hook d3 hook wo sich die adressen ändern dies aber auch im system32 nimmt man den devicepointer von spielen so ändert der sich nicht

also läuft auf 32bit so wie 64bit
wenn man weiß wie und wo man es anwenden muss ist der source klasse
P-a-i-n is offline  
Old 03/22/2010, 06:43   #4
 
flo8464's Avatar
 
elite*gold: 0
Join Date: Nov 2008
Posts: 161
Received Thanks: 38
Quote:
Originally Posted by P-a-i-n View Post
so ein quatsch das wird sogar unter 64 bit unterstützt arbeite genauso wie er und hab nie probleme

das ist kein hook d3 hook wo sich die adressen ändern dies aber auch im system32 nimmt man den devicepointer von spielen so ändert der sich nicht

also läuft auf 32bit so wie 64bit
wenn man weiß wie und wo man es anwenden muss ist der source klasse
Viel Spaß mit pushad/popad unter 64bit

Unde der Rest deines Postings macht irgendwie keinen Sinn.
flo8464 is offline  
Old 03/22/2010, 08:13   #5
 
Tyrar's Avatar
 
elite*gold: 0
Join Date: Oct 2008
Posts: 1,637
Received Thanks: 1,119
Quote:
Originally Posted by flo8464 View Post
Viel Spaß mit pushad/popad unter 64bit

Unde der Rest deines Postings macht irgendwie keinen Sinn.
argh >.<
is eben für 32 bit XD

naja ich wusste schon immer dass ich sowas nich kann XD

egal versuch war es wert
Tyrar is offline  
Old 03/22/2010, 12:32   #6
 
P-a-i-n's Avatar
 
elite*gold: 0
Join Date: Nov 2009
Posts: 1,258
Received Thanks: 396
das man das nicht 1 zu 1 verwenden kann ist klar
aber aus der erklärung kann man sich vieles ableiten
ich arbeite eh anders wenn ich es schreibe dann würd es so aussehen
und das geht ganz sicher unter 64bit
nur als bsp

DWORD funktion= 0x0XXXXXX;

_asm
{
XOR EAX,EAX;
PUSH Ent;
CALL funktion;
add esp, 4
MOV Ret, AL;
}
P-a-i-n is offline  
Old 03/22/2010, 13:21   #7
 
flo8464's Avatar
 
elite*gold: 0
Join Date: Nov 2008
Posts: 161
Received Thanks: 38
Quote:
DWORD funktion= 0x0XXXXXX;

_asm
{
XOR EAX,EAX;
PUSH Ent;
CALL funktion;
add esp, 4
MOV Ret, AL;
}
Das ist gleich mehrfach falsch

1. Passen 64bit-Addressen nicht in ein DWORD (4byte unsigned long). Hier würde sich DWORD_PTR anbieten, das ist ein typedef auf unsigned long bei 32bit und ein unsigned long long bei 64bit.

2. Das du mit den 32bit Registern bei 64bit Programmen recht blöd dastehst sollte auch klar sein

3. Deine Return-Value ist sogar unter 32bit falsch, die gängigen Calling Conventions nutzen prinzipiell bei 32bit den ganzen EAX-Register zur Rückgabe, nur AL zu nutzen ist nicht gerade geschickt.
flo8464 is offline  
Thanks
2 Users
Old 03/22/2010, 14:21   #8


 
MrSm!th's Avatar
 
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,909
Received Thanks: 25,409
Quote:
Originally Posted by HeavyHacker View Post
ganz nett in der theorie, aber du hast etwa vergessen.
nämlich wenn am anfang der funktion nur eine instruction mit 1 byte ist und du damit auch eine zweite zum teil überschreibst.
oder wenn die instruction größer als 5 bytes ist.
dann wird das in die hose gehen, da dadurch entweder keine gültigen oder einfach die falschen instructions entstehen.
klar, bei api funktionen gibts normalerweise am anfang eine sinnlose instruction wie mov edi,edi aber bei anderen funktionen, wo sofort am anfang push ebp steht, haste ein problem.
da klappt das so nicht, denn in diesem falle müsste man die opcodes parsen und dann die richtige länge an bytes sichern. d.h. du nimmst entweder eine fertige disassembler lib, wie die von Olly oder BeaEngine oder du schreibst deine eigene Wenn du wirklich nur vor hast, den Hook am Anfang zu platzieren, kannste die meisten opcodes vernachlässigen und nur nach den gängigsten am anfang einer funktion suchen (unwahrscheinlich dass direkt am anfang zb. gecalled wird). aber wie gesagt, ganz ohne gehts nur bei api funktionen
MrSm!th is offline  
Old 03/22/2010, 15:29   #9
 
P-a-i-n's Avatar
 
elite*gold: 0
Join Date: Nov 2009
Posts: 1,258
Received Thanks: 396
Quote:
Originally Posted by flo8464 View Post
Das ist gleich mehrfach falsch

1. Passen 64bit-Addressen nicht in ein DWORD (4byte unsigned long). Hier würde sich DWORD_PTR anbieten, das ist ein typedef auf unsigned long bei 32bit und ein unsigned long long bei 64bit.

2. Das du mit den 32bit Registern bei 64bit Programmen recht blöd dastehst sollte auch klar sein

3. Deine Return-Value ist sogar unter 32bit falsch, die gängigen Calling Conventions nutzen prinzipiell bei 32bit den ganzen EAX-Register zur Rückgabe, nur AL zu nutzen ist nicht gerade geschickt.
geht es zu 100% außerdem ist es nur ein teil von einer weit größeren funktion vergess nicht das ist nicht das 1x1
beim programmieren führen viele wege nach oben ich hab dir nur gezeigt wie ich es aufrufe die komplette funktion hab ich nicht kopiert es ist nur ein kleiner teil von weit mehr
das ist von CoD4 checkt ob ein gegener unsichtbar ist und färbt dann das boxesp um damit kannst dur die denken was da noch alles nötig ist das es klappt
da hängt noch eine riesige struct dran und es funktioniert ohne probleme

nur weil du ein wegfährst muss ich den nicht auch fahren wenn es noch andere gibt

und ruf es so auf
BOOL funktion( CEntity* Ent )
und nicht mit

__declspec

das macht schon unterschiede so nu genug diskutiert jeder macht es anderes wichtig ist das es geht
P-a-i-n is offline  
Old 03/22/2010, 15:38   #10
 
flo8464's Avatar
 
elite*gold: 0
Join Date: Nov 2008
Posts: 161
Received Thanks: 38
COD 4 gibt es doch gar nicht als 64bit Binary?

Und nein, die physikalischen Gesetze verbieten es, "andere Wege" zu gehen.
flo8464 is offline  
Old 03/22/2010, 16:47   #11
 
P-a-i-n's Avatar
 
elite*gold: 0
Join Date: Nov 2009
Posts: 1,258
Received Thanks: 396
wir machen es so du hast recht und ich meine ruhe sonst endet das hier nie
P-a-i-n is offline  
Old 03/24/2010, 16:26   #12


 
MrSm!th's Avatar
 
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,909
Received Thanks: 25,409
Mein erwähntes Problem am Source kümmert wohl niemanden >.<
MrSm!th is offline  
Old 03/25/2010, 09:33   #13
 
Tyrar's Avatar
 
elite*gold: 0
Join Date: Oct 2008
Posts: 1,637
Received Thanks: 1,119
Quote:
Originally Posted by MrSm!th View Post
ganz nett in der theorie, aber du hast etwa vergessen.
nämlich wenn am anfang der funktion nur eine instruction mit 1 byte ist und du damit auch eine zweite zum teil überschreibst.
oder wenn die instruction größer als 5 bytes ist.
dann wird das in die hose gehen, da dadurch entweder keine gültigen oder einfach die falschen instructions entstehen.
klar, bei api funktionen gibts normalerweise am anfang eine sinnlose instruction wie mov edi,edi aber bei anderen funktionen, wo sofort am anfang push ebp steht, haste ein problem.
da klappt das so nicht, denn in diesem falle müsste man die opcodes parsen und dann die richtige länge an bytes sichern. d.h. du nimmst entweder eine fertige disassembler lib, wie die von Olly oder BeaEngine oder du schreibst deine eigene Wenn du wirklich nur vor hast, den Hook am Anfang zu platzieren, kannste die meisten opcodes vernachlässigen und nur nach den gängigsten am anfang einer funktion suchen (unwahrscheinlich dass direkt am anfang zb. gecalled wird). aber wie gesagt, ganz ohne gehts nur bei api funktionen
ich habe dabei ziemlich allgemein gedacht
natürlich wenn man ganz am anfang z.b.
Code:
mov edi, edi
call 0x00000001
kommt am ende nur scheisse raus!

das sollte eigendlich nur eine grundanleitung sein
Tyrar is offline  
Reply


Similar Threads Similar Threads
[c++]hooks
11/02/2009 - C/C++ - 2 Replies
brauche hilfe bei meinen hooks! ms detours will ich nich benutzen (vorallem weil die nich für meine zwecke laufen :D), ausserdem um weiterzu lernen eigenes system schreiben! mein problem is wenn ich in einer funktion die ersten 5 bytes mit jmp dword überschreibe, und z.b. das 2 byte auch nen jmp dword ist, bleibt am ende 1 byte über! in meiner subfunc speicher ich die register mit pushad, call , popad, den überschriebenen code hier einfügen, und dann jmp ....
Hooks mit VB?
04/22/2007 - .NET Languages - 21 Replies
Nabend, Ich versuch mich momentan den Tinytoon Hook hiermit zum implementieren, da mich Forceshock langsam.... :eek: Wär nett wenn jemand noch sinnvolle Beispiele dazu hätte, ua. selbst Erfahrung damit hat. Option Explicit Private Declare Function FindWindow Lib &#34;user32&#34; Alias &#34;FindWindowA&#34; &#40;ByVal lpClassName As String, ByVal lpWindowName As String&#41; As Long Private Declare Function GetWindowThreadProcessId Lib &#34;user32&#34; &#40;ByVal hwnd As Long, lpdwProcessId As Long&#41; As Long ...



All times are GMT +1. The time now is 19:39.


Powered by vBulletin®
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2026 elitepvpers All Rights Reserved.