17-09-2013, 13:28
Hvad går denne tutorial serie ud på?
Vi har et spil hvor der er runder. En runde er hvor mob angriber player, og player angriber mob. Vi er player. Det er tilfældigt hvem der vinder. Vi vil dog gerne vinde hver gang. Derfor injecter vi en selvskreven DLL ind i processen, hvor vi nu kan kalde funktionen attackMob() ubegrænset, og vinde hvergang.
Denne første del af GameHack serien, vil gå ud på at benytte reverse engineering til at opnå adressen på funktionen attackMob()
Den næste del vil gå ud på at injecte en DLL i GameHack.
Den sidste del vil være at skrive DLL'en så den kan benytte attackMob() funktionen så vi vinder hvergang
Det første er vores mobGame. Læs det, og forstå det. Hvis du ikke forstår det får du ikke noget ud af resten af denne tutorial
Jeg har compilet en version som i kan downloade her: https://mega.co.nz/#!WNph1Rra!HNQwn1ibkX...E9yOJGS-c4
Jeg vil anbefale jer at benytte denne version hvis i er helt nye på området.
Hvis ikke kan i skrive lidt om i koden så der ændres lidt, så i selv skal tænke lidt mere.
Da vores mål er at kunne angribe, uden at blive angrebet, skal vi finde funktionen som angriber mob. Denne kan vi hurtigt finde ved et kig på koden:
Det vi nu skal gøre er at finde ud af hvor denne funktion ligger i memory når programmet køres. Her vil vi benytte IDA.
Vi starter IDA op og vælger at vi godt vil rode med vores egen fil(Go: Work on your own):
Herefter trækker du blot filen mobGame.exe ind i IDA
Vi vil nu blive præsenteret for en anden skærm. Her trykker du blot "ok".
Vores .exe mobGame skulle nu gerne være loadet i IDA. Vælg graph view, da det efter min mening er det bedste(Højreklik midt i IDA og tryk graph view. Hvis muligheden ikke er der, er du allerede i graph view)
Det vi gør nu er at kigge på de forskellige ting og ser om vi kan finde noget som giver mening.
Vi kan hurtigt se vores if else statement hvor vi tjekker for hvilke valg der er truffet. Hvis der bliver trykket 1 så går vi til angreb, og hvis vi trykker 2 så flygter vi(programmet afsluttes)
Her kan vi tydeligt se hvad for et stykke kode den er igang med. Vi kan også se hvordan den sammenligner choice, med et nummer.
Først flyttes choice over i eax cpu registret.
Ellers fortsættes koden bare nedtil det spændende stykke. Nemlig inde i denne if statement:
Her ser vi et billed af funktionen i assembly:
Her ser vi et billed af funktionen i C++:
Her kan vi let se hvad det er der sker. Hvordan noget tekst i 2 omgange bliver push'et på stacken og herefter printet ved brug af cout.
Men længere nede ser vi 2 call's som går til attackPlayer og attackMob.
Dette er præcis hvad vi har ledt efter.
Vi kan nu se et call til attackMob. Vi klikker nu på attackMob for at se hvad der gemmer sig bag det call.
Meget hurtigt ved et lille kig kan vi se at det er den helt rigtige funktion vi har fat i. Vi klikker nu på den lille tilbage knap oppe i venstre hjørne af IDA for at komme tilbage til start.
Vi sætter nu et breakpoint ved attackMob ved at højreklikke på attackMob og klikke Add Breakpoint.
Det call til attackMob vil nu blive rødt.
Vi er nu klar til at køre vores program, så den kan stoppe ved breakpoint og fortælle den præcise lokation i memory.
I toppen af IDA, kan vi se en start button, samt pause og en stop
Her vælger vi Local Win32 debugger og trykker start
Et nyt vindue vil nu åbne, hvor vi kan se vores spil. Her vil vi trykke 1 for at angribe, så den rammer vores breakpoint ved attackMob
Her kan vi nu se at mob angriber player men så stopper/pauser programmet ved vores breakpoint
I IDA kan vi også se at den er stoppet ved det rigtige sted
Vi kan nu se den præcise lokation som er 003C1339 eller 0x003C1339
Vi har nu fundet funktionens præcise addresse. Denne vil blive brugt i den næste tutorial så følg med.
Vi har et spil hvor der er runder. En runde er hvor mob angriber player, og player angriber mob. Vi er player. Det er tilfældigt hvem der vinder. Vi vil dog gerne vinde hver gang. Derfor injecter vi en selvskreven DLL ind i processen, hvor vi nu kan kalde funktionen attackMob() ubegrænset, og vinde hvergang.
Denne første del af GameHack serien, vil gå ud på at benytte reverse engineering til at opnå adressen på funktionen attackMob()
Den næste del vil gå ud på at injecte en DLL i GameHack.
Den sidste del vil være at skrive DLL'en så den kan benytte attackMob() funktionen så vi vinder hvergang
Det første er vores mobGame. Læs det, og forstå det. Hvis du ikke forstår det får du ikke noget ud af resten af denne tutorial
mobGame.cpp (Click to View)
#include <iostream>
#include <Windows.h>
#include <cstdlib>
using namespace std;
void attackPlayer();
void attackMob();
void initialize();
struct playerInfo{
int life;
int damageFrom;
int damageTo;
}mob, player;
int main(char *args){
initialize();
int roundNum = 0;
while(true){
int choice;
cout << "What to do? Attack(1) Forfeit(2): ";
cin >> choice;
if(choice == 1){
cout << "Attacking!" << endl;
cout << "Round: " << roundNum << endl;
roundNum++;
attackPlayer();
attackMob();
}else if(choice == 2){
break;
}
}
}
void initialize(){
mob.life = 200;
mob.damageFrom = 10;
mob.damageTo = 50;
player.life = 210;
player.damageFrom = 18;
player.damageTo = 25;
}
void attackPlayer(){
int diff = mob.damageTo - mob.damageFrom;
int damageC = rand() % diff + mob.damageFrom;
cout << "Mob has engaged in attacking player. Mob does " << damageC << " damage" << endl;
player.life = player.life - damageC;
if(player.life <= 0){
cout << "Player died and mob won!";
int pauseVar;
cin >> pauseVar;
exit(1);
}
cout << "Player life: " << player.life << endl;
}
void attackMob(){
int diff = player.damageTo - player.damageFrom;
int damageC = rand() % diff + player.damageFrom;
cout << "Player is attacking mob. Player does " << damageC << " damage" << endl;
mob.life = mob.life - damageC;
if(mob.life <= 0){
cout << "Mob died and player won!";
int pauseVar;
cin >> pauseVar;
exit(1);
}
cout << "Mob life: " << mob.life << endl;
}
Jeg har compilet en version som i kan downloade her: https://mega.co.nz/#!WNph1Rra!HNQwn1ibkX...E9yOJGS-c4
Jeg vil anbefale jer at benytte denne version hvis i er helt nye på området.
Hvis ikke kan i skrive lidt om i koden så der ændres lidt, så i selv skal tænke lidt mere.
Da vores mål er at kunne angribe, uden at blive angrebet, skal vi finde funktionen som angriber mob. Denne kan vi hurtigt finde ved et kig på koden:
cout << "Attacking!" << endl;
cout << "Round: " << roundNum << endl;
roundNum++;
attackPlayer();
attackMob();
funktionen som angriber mob er så attackMob()Det vi nu skal gøre er at finde ud af hvor denne funktion ligger i memory når programmet køres. Her vil vi benytte IDA.
Vi starter IDA op og vælger at vi godt vil rode med vores egen fil(Go: Work on your own):
Herefter trækker du blot filen mobGame.exe ind i IDA
Vi vil nu blive præsenteret for en anden skærm. Her trykker du blot "ok".
Vores .exe mobGame skulle nu gerne være loadet i IDA. Vælg graph view, da det efter min mening er det bedste(Højreklik midt i IDA og tryk graph view. Hvis muligheden ikke er der, er du allerede i graph view)
Det vi gør nu er at kigge på de forskellige ting og ser om vi kan finde noget som giver mening.
Vi kan hurtigt se vores if else statement hvor vi tjekker for hvilke valg der er truffet. Hvis der bliver trykket 1 så går vi til angreb, og hvis vi trykker 2 så flygter vi(programmet afsluttes)
Her kan vi tydeligt se hvad for et stykke kode den er igang med. Vi kan også se hvordan den sammenligner choice, med et nummer.
Først flyttes choice over i eax cpu registret.
mov eax, [esp+8+choice]
så sammenlignes eax med 1cmp eax, 1
Så kommet jnz. Jump if not zerojnz short loc_401340
Der bliver hoppet til loc_401340 hvis eax ikke er lig 1Ellers fortsættes koden bare nedtil det spændende stykke. Nemlig inde i denne if statement:
if(choice==1)
og det er jo netop inde i denne if statement hvor de to funktioner attackMob og attackPlayer bliver kaldt.Her ser vi et billed af funktionen i assembly:
Her ser vi et billed af funktionen i C++:
Her kan vi let se hvad det er der sker. Hvordan noget tekst i 2 omgange bliver push'et på stacken og herefter printet ved brug af cout.
Men længere nede ser vi 2 call's som går til attackPlayer og attackMob.
Dette er præcis hvad vi har ledt efter.
Vi kan nu se et call til attackMob. Vi klikker nu på attackMob for at se hvad der gemmer sig bag det call.
Meget hurtigt ved et lille kig kan vi se at det er den helt rigtige funktion vi har fat i. Vi klikker nu på den lille tilbage knap oppe i venstre hjørne af IDA for at komme tilbage til start.
Vi sætter nu et breakpoint ved attackMob ved at højreklikke på attackMob og klikke Add Breakpoint.
Det call til attackMob vil nu blive rødt.
Vi er nu klar til at køre vores program, så den kan stoppe ved breakpoint og fortælle den præcise lokation i memory.
I toppen af IDA, kan vi se en start button, samt pause og en stop
Her vælger vi Local Win32 debugger og trykker start
Et nyt vindue vil nu åbne, hvor vi kan se vores spil. Her vil vi trykke 1 for at angribe, så den rammer vores breakpoint ved attackMob
Her kan vi nu se at mob angriber player men så stopper/pauser programmet ved vores breakpoint
I IDA kan vi også se at den er stoppet ved det rigtige sted
Vi kan nu se den præcise lokation som er 003C1339 eller 0x003C1339
Vi har nu fundet funktionens præcise addresse. Denne vil blive brugt i den næste tutorial så følg med.