Sunday 14 June 2015

Introdoction to Game Hacking: AssaultCube External Memory Hacks

AssaultCube External Memory Hacks- picateshackz.com

Today i am going to be showing you how to hack AssaultCube shooter game, in this tutorial you will learn how to create a simple external memory hack.

The concept of memory hacks is fairly easy to grasp especially with a demonstration. So the idea of a Memory hack is generally, to access the games process memory in order to change values therefore affecting the status of the player in game or to read values in order to gain an unfair advantage. Memory hacks can do things such as give health or ammo, change the players position, or give other players positions (depending on the game).

Things you need:


Good to have:

  • aadp4olly (for getting by anti debugging solutions that might be implemented on commercial games) 

Before we get started I would also recommend adding this to your arguments inside the assaultcube.bat file "-t -w 800 -h 600", just because we are going to be messing around with a bunch of windows.


Things you should probably know (not completely necessary I suppose)

Hacking AssaultCube:



The first step in creating a memory hack is to find the adressess that you need to write to. For this we are going to use Cheat Engine. So open up assault Cube and Cheat Engine then attach Cheat Engine to ac_client.exe. The first address I am going to show how to find is the adress for the variable holding your ammo count. To do this first start a new scan, then search for the amount of ammo you currently have. Next take two shots and do another search with your new ammo count(click next scan). Continue this process until you have narrowed it down to two addresses. Add the top value (double click on it). Change the value by double click on the value column of the memory record in the record window. Make this value some number and see if it changes your ammo ingame. If it does change ingame then the top one was the correct address otherwise add the bottom address from the search and try it with that address. Great we have found the address of the variable holding the ammo count. Unfortunately this address will constantly change because of how virtual memory works so now we have to find a permanent pointer to this value.

Cheat Engine makes finding this pointer relatively easy. Right click on the memory record and select find what access this address. There will be a couple of asm instructions in the debugger window but these are not what we are looking for these are just used for displaying the value. To find the value we want take a shot then return to the window. The decrement instruction is the one we are looking for. This instruction decrements your ammo when you take a shot double click on it. (As a side note record the address of the decrement instruction for later.) Cheat engine will find the value of a pointer to this address. So we search this value in Cheat Engine. Add the address manually and make sure to check the box designating it a pointer and add no offset because there is none in the instruction. Continue to repeat this process on the pointer until you reach a static address(green). Record the address and its offsets.

Now the process needs to be repeated for the health variable. Unfortunately assault cube dos not provide a command to hurt yourself so you have to hurt yourself by ingame means such as standing by a grenade. So do a first scan for 100 and then find a grenade on the map you were loaded into and hurt yourself with it. Do the next scan with your new health value. Continue to do this until you have two values once again add the top one and change the value.

Repeat the process of finding a static pointer.


Explained using pictures for visual learners:

First we search our starting value for ammo which if you are using the assault rifle is 20



Next in game take three shots and search the new ammo value with next scan.



In some cases you will need to repeat that process to get two results. Since we narrowed it down to two add the top one and change the ammo value, then see if it changes in game.



It did in this case if it had not we would have tried the other value.



Next right click the record then click find what accesses this address; do not select the instructions that appear. First take a couple of shots then select the decrement instruction. After doing that you will be presented with a screen like this. Notice that the offset for this address is 0 (nothing added to esi). Record the offset then copy the value that is needed to find the address.



Search the value, make sure to check the hex box.



Since there is only one add it as a pointer.



Now find what accesses this pointer, record the offset(14), and copy the value.



Search the value.



Since there are multiple addresses start by adding the top address with both offsets.



This pointer turned out to be a dead end.



Therefore we move on to the next address found.



Once again find what accesses it after shooting.



Record the offset in your list(374,14,0). Now search this new value.



Alright we have found a stable address.



0051E20C offsets: 374,14,0



Repeat this for health: 0x00509B74 offsets: F8 (yours will probably be different depending on architecture etcc).


Programming the Hack:


The first thing we need to do to gain control of the game is to gain a handle linked to the process. To do this I wrote a method called getHandle.

Code: C

  1. /*
  2. * Returns a Handle for process matching pname
  3. */
  4. HANDLE getHandle(char pname[])
  5. {
  6.     DWORD dwPid=0;
  7.     HANDLE proc, hProc;
  8.     PROCESSENTRY32 pe32 = {sizeof(PROCESSENTRY32)};
  9.         while(!dwPid)
  10.         {
  11.         printf("Searching for ac process...\n");
  12.         printf("Make sure the game is running!\n");
  13.         hProc=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  14.         if(Process32First(hProc, &pe32))//place process in pe32
  15.         {
  16.             do
  17.             {
  18.                
  19.                 if(!strcmp(pe32.szExeFile,pname))//compare pe32 pname to the pname
  20.                 {
  21.                     dwPid=pe32.th32ProcessID;//set pid to the pid of the process if the process names matched
  22.                     break;
  23.                 }
  24.             }while(Process32Next(hProc,&pe32));//move to next process
  25.         }
  26.         sleep(10);
  27.     }
  28.     proc=OpenProcess (PROCESS_ALL_ACCESS,FALSE,dwPid);//open process Handle
  29.     return proc;//return the Handle
  30. }



After we have a handle of the process we will need to calculate the dynamic adressess for this I wrote the method offCalc.

Code: C

  1. DWORD offCalc(DWORD b, DWORD offs[], int size, HANDLE proc)
  2. {
  3.     DWORD base=b;
  4.     DWORD ptemp;
  5.     int i;
  6.     for(i=0;i<size;i++)//loops through offsets
  7.     {
  8.         ReadProcessMemory(proc, (LPCVOID)base,&ptemp,sizeof(ptemp),NULL);//reads the next adress into ptemp
  9.         base=ptemp+offs;//adds ptemp to the offset
  10.         printf("0x%x+%x=%x\n",ptemp, offs, base);//prints debugging info
  11.     }
  12.    
  13.     return base;//return address
  14. }



After we have the dynamic adressess all that is left is to write the values into their addresses.

Code: C

  1. int writeVal(HANDLE proc, DWORD addr,BYTE *val)
  2. {
  3.     return WriteProcessMemory(proc,(BYTE*)addr,val,4,NULL);//write the value to the proc at addr
  4. }


This is all tied together in main.

Code: C


  1. int main()
  2. {
  3.     BYTE setval[]={0x64,0x00,0x00,0x00};//100 in hex because of little endian
  4.     HANDLE proc=NULL;//handle for the process
  5.     DWORD health={0x00509B74};//static adress for health
  6.     DWORD haddr;
  7.     DWORD offh[]={0xF8};//offsets health
  8.     DWORD ammo={0x0051E20C};//static adress for ammo
  9.     DWORD aaddr;
  10.     DWORD offa[]={0x374, 0x14, 0x00};//offsets for ammo
  11.     char gameName[]="ac_client.exe";//name of the process
  12.     proc=getHandle(gameName);//set proc to the Handle gained by get Handle
  13.     if(proc!=0)//check if proc was retrieved
  14.     {
  15.         haddr=offCalc(health,offh,1,proc);//calculate  the dynamic address and set haddrr
  16.         aaddr=offCalc(ammo,offa,3,proc);//calculate the dynamic adress of and set aaddr
  17.         int check1;//bool for write status
  18.         int check2;//bool for write status
  19.     while(1==1)//infinite loop cause im lazy
  20.             {
  21.             check1=writeVal(proc,haddr,setval);//write the val for health and place the status in check 1
  22.             check2=writeVal(proc,aaddr,setval);//write the val for ammo and place the status in check 2
  23.             if(!check1&&!check2)//print error adressess if write returns 0
  24.             {
  25.                 if(!check1)
  26.                     printf("Error writing to 0x%x",haddr);
  27.                 if(!check2)
  28.                     printf("Error writing to 0x%x",aaddr);
  29.             }
  30.         }
  31.     }
  32. }



Final Code:

Code: C

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <tlhelp32.h>
  6. //function prototypes
  7. DWORD offCalc(DWORD b, DWORD offs[], int size, HANDLE proc);
  8. HANDLE getHandle(char windowname[]);
  9. int writeVal(HANDLE proc, DWORD addr,BYTE *val);
  10. int main()
  11. {
  12.     BYTE setval[]={0x64,0x00,0x00,0x00};//100 in hex because of little endian
  13.     HANDLE proc=NULL;//handle for the process
  14.     DWORD health={0x00509B74};//static adress for health
  15.     DWORD haddr;
  16.     DWORD offh[]={0xF8};//offsets health
  17.     DWORD ammo={0x0051E20C};//static adress for ammo
  18.     DWORD aaddr;
  19.     DWORD offa[]={0x374, 0x14, 0x00};//offsets for ammo
  20.     char gameName[]="ac_client.exe";//name of the process
  21.     proc=getHandle(gameName);//set proc to the Handle gained by get Handle
  22.     if(proc!=0)//check if proc was retrieved
  23.     {
  24.         haddr=offCalc(health,offh,1,proc);//calculate  the dynamic address and set haddrr
  25.         aaddr=offCalc(ammo,offa,3,proc);//calculate the dynamic adress of and set aaddr
  26.         int check1;//bool for write status
  27.         int check2;//bool for write status
  28.     while(1==1)//infinite loop cause im lazy
  29.             {
  30.             check1=writeVal(proc,haddr,setval);//write the val for health and place the status in check 1
  31.             check2=writeVal(proc,aaddr,setval);//write the val for ammo and place the status in check 2
  32.             if(!check1&&!check2)//print error adressess if write returns 0
  33.             {
  34.                 if(!check1)
  35.                     printf("Error writing to 0x%x",haddr);
  36.                 if(!check2)
  37.                     printf("Error writing to 0x%x",aaddr);
  38.             }
  39.         }
  40.     }
  41. }
  42. int writeVal(HANDLE proc, DWORD addr,BYTE *val)
  43. {
  44.     return WriteProcessMemory(proc,(BYTE*)addr,val,4,NULL);//write the value to the proc at addr
  45. }
  46. /*
  47. * Returns a Handle for process matching pname
  48. */
  49. HANDLE getHandle(char pname[])
  50. {
  51.     DWORD dwPid=0;
  52.     HANDLE proc, hProc;
  53.     PROCESSENTRY32 pe32 = {sizeof(PROCESSENTRY32)};
  54.         while(!dwPid)
  55.         {
  56.         printf("Searching for ac process...\n");
  57.         printf("Make sure the game is running!\n");
  58.         hProc=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  59.         if(Process32First(hProc, &pe32))//place process in pe32
  60.         {
  61.             do
  62.             {
  63.                
  64.                 if(!strcmp(pe32.szExeFile,pname))//compare pe32 pname to the pname
  65.                 {
  66.                     dwPid=pe32.th32ProcessID;//set pid to the pid of the process if the process names matched
  67.                     break;
  68.                 }
  69.             }while(Process32Next(hProc,&pe32));//move to next process
  70.         }
  71.         sleep(10);
  72.     }
  73.     proc=OpenProcess (PROCESS_ALL_ACCESS,FALSE,dwPid);//open process Handle
  74.     return proc;//return the Handle
  75. }
  76. /*
  77. * Returns the adress with calculated offsets
  78. */
  79. DWORD offCalc(DWORD b, DWORD offs[], int size, HANDLE proc)
  80. {
  81.     DWORD base=b;
  82.     DWORD ptemp;
  83.     int i;
  84.     for(i=0;i<size;i++)//loops through offsets
  85.     {
  86.         ReadProcessMemory(proc, (LPCVOID)base,&ptemp,sizeof(ptemp),NULL);//reads the next adress into ptemp
  87.         base=ptemp+offs;//adds ptemp to the offset
  88.         printf("0x%x+%x=%x\n",ptemp, offs, base);//prints debugging info
  89.     }
  90.    
  91.     return base;//return address
  92. }



You are done, Thanks for reading.




No comments:

Post a Comment