Array of bytes in DLL hack

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

Syperus

RTFM
Meme Tier VIP
Dank Tier Donator
Oct 29, 2012
432
2,638
7
Array Of Bytes Tutorial

Credits:
Agent Smith for showing me about AOBs.
Patrick for creating the Pattern and Compare functions.

Haven't contributed to the forums in awhile so I decided to write up a tutorial on how to obtain and use array of bytes in your hack. 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) //Provided in zip if you don't have it
A text editor of choice (Notepad++)
Game of choice (I'm doing Bioshock Infinite to show you how we did it. You can follow along with the source code if you like. I'm not getting into pointers and Reclass in this tutorial though. That'll be for another tutorial). Incase you wonder why I broke this into 2 parts it's because I exceeded the maximum allowed characters in a post.

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.
C++:
#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 imatge 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
C++:
0x01, 0x5F, 0x54 // Bytes before hack is activated

0xE9, 0xF9, 0xE2, 0x72, 0x0B // Bytes after hack is activated

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 // Bytes of our hack
I highlighted the 0xE9 because that's an important byte that we'll need to find later. 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 rememebr 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 you 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.

VirusTotal
Jotti
 

Attachments

Syperus

RTFM
Meme Tier VIP
Dank Tier Donator
Oct 29, 2012
432
2,638
7
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.
C++:
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
C++:
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)
C++:
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.

C++:
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 MSDN
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_RESERVE.

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

C++:
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.

C++:
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.

C++:
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.
C++:
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.

C++:
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.

C++:
*(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. The now you take that number and subtract it by 1 and write it out like I did with 13 + 5. The 5's will always be 5's. So if you came up with 28 your's would 27 + 5. Why 5 you ask? My answer is I honestly don't know. This part is a little vague to me. I'm not afraid to admit when I don't know something and this is one of those times. This is the one area I haven't been able to understand yet. See I'm still learning too. If anyone can shed some light on this for me please do because I would like to know. You will be properly credited. :)

C++:
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.
C++:
& 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.
 
Last edited:

till0sch

Respected Hacker
Dank Tier VIP
Dank Tier Donator
Oct 14, 2012
1,104
12,593
51
You should maybe consider checking if there's memory at the bytes you're checking on (in the Compare function), that caused crashes for me.

Thanks for sharing!
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,372
78,998
2,414
Excellent written Syperus!

Good job!
 

TastyHorror

Coder
Dank Tier Donator
Nobleman
Oct 11, 2012
179
2,268
8
A really well done tutorial mate, I hope you release more tutorials like this.

p.s. didn't look at it in depth, but will soon in a few days.
 

Syperus

RTFM
Meme Tier VIP
Dank Tier Donator
Oct 29, 2012
432
2,638
7
Thanks for the feedback guys. I started this tutorial awhile back, but had to put it on the back burner for awhile cause of some life events. Finally got around to finishing it. :)
 
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods