Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


[Tutorial]Array of Bytes DLL Trainer Tut

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
Syperus
Advanced Cheater
Reputation: 1

Joined: 05 Jun 2011
Posts: 61

PostPosted: Tue Jul 07, 2015 1:54 pm    Post subject: [Tutorial]Array of Bytes DLL Trainer Tut Reply with quote

Wrote this tut awhile back for another game hacking website, but decided to share it here in case anyone wanted to use AOBs in their trainer as we do in our DLL trainers. This tutorial is for a DLL trainer for Bioshock Infinite.

Credits:
My boy Spock for showing me about AOBs.
Patrick for creating the Pattern and Compare functions.

Using AOB allows you to create a hack that will most likely work with any game updates so you don't have to keep going back and finding new addresses on every update. This isn't guaranteed to work. It just depends on what they release in the update. If they add new features then there's there a good chance it won't work. Just depends. Anyways

What you need:
Cheat Engine
Compiler of choice (I'm using VC++ 2010 Ultimate)
Ollydbg 1.10
SigMaker.dll (Ollydbg Plugin)
Text editor of choice (Notepad++)
Game of choice (I'm doing Bioshock Infinite. I'm not getting into pointers and Reclass in this tutorial though).

Part 1: Bytes and Signature
Your going to need to have your addresses already that you want. Once you have them load up your game, your cheat table, and attach CE to your game process. Done? Good! Lets start this off by creating a new cpp file. Were going to put in our headers and declare some variables.

Code:
#include <windows.h>
#include <conio.h>

DWORD BaseAddress, SilverHookAddress, SilverCCHookAddress;  /* Declare our variables. The SilverHookAddress will hold our hack function as you'll see later. The SilverCCHookAddress will allocates memory and reserves it for our specified function. */

BOOL SilverStatus; // Declares our status variable to check if the hack is on or off.

bool Compare(const BYTE* pData, const BYTE* bMask, const char* szMask)
{
   for(;*szMask;++szMask,++pData,++bMask)
      if(*szMask=='x' && *pData!=*bMask)   return 0;
   return (*szMask) == NULL;
}

DWORD Pattern(DWORD dwAddress,DWORD dwLen,BYTE *bMask,char * szMask)
{
   for(DWORD i=0; i<dwLen; i++)
      if (Compare((BYTE*)(dwAddress+i),bMask,szMask))  return (DWORD)(dwAddress+i);
   return 0;
}


Bytes
First thing we need is bytes of the original opcode. Were going to need 3 separate AOB's. First one is the bytes of the original opcode, second is the bytes of the jump to the hack, and third is the bytes of the hack. So go into CE, click on Memory View, You will see this window


Now go to the address of the code you want to change.
Once there right click on that line → Copy to Clipboard → Bytes only (no address). Paste those bytes in your text editor. Make a few return spaces in your text editor to not confuse the different bytes. Leave your Memory Viewer window open.

Note 1* You will need the address of these lines later so the easiest way to do that is once your on the line your going to change right click again, Go to Address, and copy the address shown in the textbox. Also make sure to keep it with the correct bytes to not confuse it. Otherwise the AOB won't work. For example the address that is selected in the image is "BioShockInfinite.exe"+371D02, but Olly can't read this address so when I click Go to Address I get 00771D02. That's the address I would need to save for later.

Now go back to CE and check the box to activate your hack. Notice now in your Memory Viewer window the code has changed to jmp address.



This tells the game where to read the modified code at. Same procedure has before right click on the jump line → Copy to Clipboard → Bytes only (no address). Paste this on a new line in your text editor. Now right click on the jump line again and this time select Follow. This takes you to the address where your hack is. From here you'll need to determine how many lines your hack is. Typically is 2 lines for a simple hack, but it will depend on the complexity of your hack. If you wrote a complex script you'll have several lines. In my case I have 21 lines. Select all the lines of your hack and copy the bytes to its own line in your text editor. Now you need to change all your bytes to hex. This is done by putting the 0x in front of the bytes and separate with commas. So 90 90 90 E9 would become 0x90, 0x90, 0x90, 0xE9. Mine looks like this

Code:
// Bytes before hack is activated
0x01, 0x5F, 0x54
// Bytes after hack is activated
0xE9, 0xF9, 0xE2, 0x72, 0x0B
// Bytes of our hack
0x58, 0x0F, 0x8D, 0x1E, 0x00, 0x00, 0x00, 0x51, 0x52, 0xBA, 0x04, 0x00, 0x00 0x00, 0x8B, 0xCB, 0x0F, 0xAF, 0xCA, 0x8B, 0xD9, 0x5A, 0x59, 0x01, 0x5F, 0x54, 0x8B, 0x0D, 0xDC, 0x88, 0x71, 0x01, 0xE9, 0xDD, 0x1C, 0x8D, 0xF4, 0x5A, 0x59, 0xC7, 0x47, 0x54, 0x9F, 0x86, 0x01, 0x00, 0x8B, 0x0D, 0xDC, 0x88, 0x71, 0x01, 0xE9, 0xC9, 0x1C, 0x8D, 0xF4

0xE9 is our hex byte for the jump to our hack. Just keep it in mind for now as we move on.

Now we have all our bytes and converted into hex. Now close out CE and the game (just to clear out memory so there's no confliction with multiple debuggers). Now we need to get the signatures.

Signatures
Now we need to get the AOB signature. Remember when I said you needed to save the address back at Note 1? This is where it comes into play. If you don't remember scroll back up and reread that part. Make sure you have the SigMaker.dll in Olly's Plugins directory. Load up Olly and load your game in Olly. Make sure you closed CE so you don't have multiple debuggers attached to the same process. This would crash the game. Once Olly is finished with its initial scans and is ready to go bring up your Go to Expression window (Ctrl+G) and put in the address of the original code.



Now, Olly will take you to the address that we just inputted. If it doesn't then you put in the wrong address. Now that your at that address we need to select a few lines before our address line and make note of that address. Take your original address (mine being 00771D02) and subtract it from the address of the line you just selected above the original address in a hex calculator and keep that value in your text editor. Were going to need it soon. Now select the address that you just made note of and highlight to a few lines past our original address.



Right click on the selected lines and select Make Sig → Code Style and paste this in your text editor. You can remove the first line which will be the full path of the executable and entry point. Now your left with the signature.


Part 2: Functions
Now we have our bytes and signature values so lets start coding. We need to create a function that'll hold the signature values and tell program how far between lines the orginial address and the top address is that we selected. I've bolded the areas that you need to change.

Code:
DWORD BSI_Silver (void)
{
    DWORD address = Pattern((DWORD)GetModuleHandleA("BioShockInfinite.exe"), 0xFFFFFFFF, (PBYTE)"\xE8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x2B\x44\x24\x18\x3B\xD8\x7E\x02\x8B\xD8\x01\x5F\x54\x8B\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x3C\x03\x74\x13\x8B\x86\x00\x00\x00\x00\x01\x98\x00\x00\x00\x00\x81\x48\x00\x00\x00\x00\x00\x6A\x10\x8B\xCE", "x????x????xxxxxxxxxxxxxxx????x????xxxxxx????xx????xx?????xxxx");
 
    if(address == 0)
    {
        return 0;
    }
 
    return address + 0x14; // Tells the program how far up the aob starts
}

We have our AOB function so lets create our bytes functions. You will need to create 3 functions for the bytes. One for the unhooked bytes, one for hooked bytes, and the last for our hack bytes. Here's what ours looks like in our trainer

Code:
BYTE SilverUnHookedBC [] =
{
    0x01, 0x5F, 0x54, 0x8B, 0x0D, 0xDC, 0x88, 0x71, 0x01
};
 
BYTE SilverHookedBC [] =
{
    0xE9, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90
};
 
BYTE SilverHackBC [] =
{
    0xC7, 0x47, 0x54, 0x9F, 0x86, 0x01, 0x00,
    0x8B, 0x0D, 0xDC, 0x88, 0x71, 0x01,
    0xE9, 0xF9, 0x1C, 0x37, 0xF6
};

Now our DllMain function (Pretty much the same as any dll hack)
Code:
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, PVOID lpvReserved)
{
    if(fdwReason == DLL_PROCESS_ATTACH)
    {
        CreateThread(NULL, NULL, MainThread, NULL, NULL, NULL);
    }
    return TRUE;

You will now need to create 2 functions. When your hack is on and when it's off and this is where we use our global variables that we created at the top.
Code:
void SilverHackON()
{
    DWORD oldProtect;
    VirtualProtect((void*)SilverHookAddress, sizeof(SilverHookedBC), PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy((void*)SilverHookAddress, SilverHookedBC, sizeof(SilverHookedBC));
    VirtualProtect((void*)SilverHookAddress, sizeof(SilverHookedBC), oldProtect, &oldProtect);
}
 
void SilverHackOFF()
{
    DWORD oldProtect;
    VirtualProtect((void*)SilverHookAddress, sizeof(SilverUnHookedBC), PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy((void*)SilverHookAddress, SilverUnHookedBC, sizeof(SilverUnHookedBC));
    VirtualProtect((void*)SilverHookAddress, sizeof(SilverUnHookedBC), oldProtect, &oldProtect);
}

If your wondering what's going on here let me explain. VirtualProtect() is used to change the permission of the addressed memory to allow us to modify. Memcpy() is used to to copy the bytes from sizeof to the memory address that we changed the protection for. Confusing? Lets take a look at the syntax and description of the parameters from [url=https://msdn.microsoft.com/en-us/library/windows/desktop/aa366898(v=vs.85).aspx]MSDN[/url]
MSDN wrote:
BOOL WINAPI VirtualProtect(
_In_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flNewProtect,
_Out_ PDWORD lpflOldProtect
);

lpAddress*[in]
A pointer an address that describes the starting page of the region of pages whose access protection attributes are to be changed.
All pages in the specified region must be within the same reserved region allocated when calling theVirtualAlloc*or*VirtualAllocEx*function using*MEM_RESERVE. The pages cannot span adjacent reserved regions that were allocated by separate calls to*VirtualAlloc*or*VirtualAllocEx*using*MEM_RESERV E.

dwSize*[in]
The size of the region whose access protection attributes are to be changed, in bytes. The region of affected pages includes all pages containing one or more bytes in the range from the*lpAddressparameter to*(lpAddress+dwSize). This means that a 2-byte range straddling a page boundary causes the protection attributes of both pages to be changed.

flNewProtect*[in]
The memory protection option. This parameter can be one of the*memory protection constants.
For mapped views, this value must be compatible with the access protection specified when the view was mapped (see*MapViewOfFile,*MapViewOfFileEx, and*MapViewOfFileExNuma).

lpflOldProtect*[out]
A pointer to a variable that receives the previous access protection value of the first page in the specified region of pages. If this parameter is*NULL*or does not point to a valid variable, the function fails.

So using my example
Code:
VirtualProtect((void*)SilverHookAddress, sizeof(SilverHookedBC), PAGE_EXECUTE_READWRITE, &oldProtect);

The first parameter is a pointer to address of our hack function. We actually haven't defined this yet, but don't worry we will. The second parameter grabs the byte size of our hooked bytecodes so the program knows the area of where the hack is going to start and the size of the area that needs to have the protection changed. The third parameter is the permission change. So we're changing the permission of that area to read, write, and execute (should be self explanatory to all the Linux lovers out there!). The last parameter holds the value of the previous protection level (permission) to revert to once our hack has copied the address with memcpy to the pointer of the hooked address.
Code:
memcpy((void*)SilverHookAddress, SilverHookedBC, sizeof(SilverHookedBC));

What this is doing is taking bytes from our hooked bytecodes and storing it into hook addresss. An easier way to read this is by parameter 2, parameter 3, then parameter one. Parameter 2 is the source of our hooked bytecodes. The third parameter is the size of our bytecodes which is copied into the first parameter.
Code:
VirtualProtect((void*)SilverHookAddress, sizeof(SilverHookedBC), oldProtect, &oldProtect);

This is changing the permission level back to its original state. I'm sure you can now follow the SilverHackOFF() function now, hopefully?

For this last part we need to call our define the rest of the hack, assign it a key, and have it turn the hack on or off based on its current state.
Code:
DWORD WINAPI MainThread(LPVOID lpThreadParameter)
{
    BaseAddress = (DWORD)GetModuleHandleA("BioShockInfinite.exe");
    SilverHookAddress = BSI_Silver();
    SilverCCHookAddress = (DWORD)VirtualAlloc(NULL, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
    *(DWORD*)(SilverHackBC + 14) = (DWORD)(( SilverHookAddress+ 5) - (SilverCCHookAddress + 13 + 5));
    memcpy((void*)SilverCCHookAddress, SilverHackBC , sizeof(SilverHackBC));
    *(DWORD*)(SilverHookedBC + 1) = (DWORD)((SilverCCHookAddress) - (SilverHookAddress + 5));
 
if(GetAsyncKeyState(VK_F1) & 1)
        {
            SilverStatus = !SilverStatus;
 
            if(SilverStatus)
            {
                SilverHackON();
            }
            else
            {
                SilverHackOFF();
            }
        }
 
}

Breakdown time! Ok the baseaddress should be pretty obvious by now on what it is.
Code:
SilverHookAddress = BSI_Silver();
    SilverCCHookAddress = (DWORD)VirtualAlloc(NULL, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

Remember earlier I said we would define the hookaddress later? Now we have defined the hookaddress. VirtualAlloc allocates the specified amount of memory for our hack (in bytes) specified in the second parameter. So in this case it allocates 1024 bytes of memory.

Code:
*(DWORD*)(SilverHackBC + 14) = (DWORD)(( SilverHookAddress+ 5) - (SilverCCHookAddress + 13 + 5));
    memcpy((void*)SilverCCHookAddress, SilverHackBC , sizeof(SilverHackBC));
    *(DWORD*)(SilverHookedBC + 1) = (DWORD)((SilverCCHookAddress) - (SilverHookAddress + 5));

Here we define our SilverHackBC function. In my example calculate it with 14 because that was how many lines I went up (remember in 2 bytes still) to start the array of byte at. So you'll input your own number that you got from your calculation. Now you take that number and subtract it by 1 and write it out like I did with 13 + 5

Code:
if(GetAsyncKeyState(VK_F1) & 1)
        {
            SilverStatus = !SilverStatus;
 
            if(SilverStatus)
            {
                SilverHackON();
            }
            else
            {
                SilverHackOFF();
            }
        }
 
}

If this isn't obvious i'll explain real quick. When the F1 key is pressed it'll check to see if the hack is on or off. Depending on the current state it'll call the other function. So if it's on, it'll call SilverHackOFF

Code:
& 1

This just prevents the program from registering the keypress more than once while it's still being held down. So when you press the F1 key it will only fire once until the key is unpressed and pressed again. Otherwise it might go through several cycles of SilverHackON and SilverHackOFF.

Well that's the end of this tutorial. Hope you learned something from it.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites