Patrickssj6
August 27th, 2007, 09:59 AM
Some people asked me...well I guess here it goes...usual excuses apply here to German ppl...no Blitzkrieg and no comments about the errors or my english.
------------------------------------------------------
Table of Content:
Part I. (Easy)
Memory System
Modifying Halo's Memory
Simple Memory Programming (VB.NET)Part II. (Intermediate)
Pointers / Offsets
Advanced Memory Programming (VB.NET)Part I.I Memory System
I'm not go into depth with this because...A. it changes occasionally B. I don't know everything about it...and I guess that's vital for explaining it.
Anyway I hope Korn & Co. don't find that many mistakes in here but I think I can try to explain the basic idea or at least get it across :)
Each byte (a byte consists of 8 bits..for example in Hex a byte would be "00" or "FF") has it's own address assigned to it. How big is the memory? Let's take a look...
Range: 0x00000000 to 0x7FFFE000
Wait, what does that mean? 0x is a syntax to display an offset. So 0x00 means it's 00 away from the starting index. So RAM ranges from 00000000 to 7FFFE000? Wait....7FFFE000(Hex) = 2147475456(Dec)...and each byte has it's own address? So we have 2147475456 bytes...roughly 2147475 kilo bytes...2147...mega bytes...2 giga bytes...of Random Access Memory(RAM)?
How can that be if not all computer have that amount? And why does Halo's Memory start at 0x00400000...and my other processes have the same starting index?
Magic?...it's Microsoft after all...no..no...Windows uses a Virtual Mapping system to assign chunks of memory to each individual process and hides the real memory address (which we don't care about anyway).
As you may notice memory informations like addresses or their corresponding bytes are displayed in Hex(imal). How to count Hex?
There are mathematical ways of doing it...but I wouldn't bother since everyone with Windows XP has a nifty tool called the calculator that already includes Hex calculating and conversion.
But to get back to the stone age and to start from the beginning....
Humans have 10 numbers to display all of the rest...0123456789...but why 10? No one knows for sure but we have 10 fingers after all right?
Well for Hex you just have to imagine that we have 16 fingers...ranging from 0123456789ABCDEF...and the counting is the same....
Hex : 00 01 02 ... 09 0A 0B 0C 0D 0E 0F 10 11...1F..20
Dec : 00 01 02 ... 09 10 11 12 13 14 15 16 17...31 32
So 20 in Hex is....32 in Dec. Seems easy doesn't it? Well it is...
http://img177.imageshack.us/img177/4152/memorytutap5.png
Part I.II Modifying Halo's Memory
Can we plz build an aimbot now, plzplz? Nope sorry. Even though there is so much irony in that sentence...someone who wants to build an aimbot needs some kind of mathematical skills (except if he is copy pasting source or tutorial) and that requires some level of intelligence...
We are going to do simple things...so no vehicle hijacking or whatever you want to imagine...we gonna modify....the ubber amazing death count of a player! Cool or? Actually...there are 2 reasons why this isn't cool.
1. It doesn't work if you join a server *CRY*
2. It's the death count who cares anyway? *Hint*Kill Count Lawl*Hint*
And please...don't EVER ever think of memory hacking the ping....
Ok let's get started...take Notepad and open up Haloce.exe with it...
no please don't. For memory hacking we need special programs that are dedicated to us...to do this nerdy crap.
Here are the 2 main ones:
ArtMoney (http://www.artmoney.ru/e_download.htm)
CheatEngine (http://cheatengine.org/download.php)
Let's go back to the drawing board...all values or basically everything you see on screen is stored somewhere in the memory...let's stick to something visible and easy like the death count...I assume by know you know how to open up a process (haloce.exe,Halo) in one of those programs...it's not very hard really.
So let's start to search for the death count...ok we haven't died yet in game so let's search for 0! ...no...no.... let's not...it's a waste of time searching for 0...so try to avoid them if you can and always start with a higher number( even if it is 1)...so die once...yay press F1 in game and you see that you have died once! Now go into CheatEngine or ArtMoney and go to search...ok value? 1 obviously....type?
I guess I have to explain some basics things again.
Memory values are stored in Hex amiright? Yes I am.
But there are different ways of reading them...or using them for different types of data. So let's take a simple but effective example...
Hex:3E
Dec: 62
Datatypes: Integer (1 to 10 bytes) , Float (aka Single/ 1 to 10 bytes), ASCII (1 byte?), Unicode (4 bytes?).
If we would read that address to ASCII it would be ">"
ASCII Table (just use google) (http://www.ecowin.org/aulas/resources/tables/asciitable.jpg)
So what's the basic (I say basic cause Microsoft says different) difference between floats and integer? You guys are lucky that you are English native because it took me 2 years to figure out the German word even though I knew what an Integer basically was regarding memory hacking (ger.= ganze Zahl).
Type Range Comment
Integer 1 byte 0 .. 255 Usually health, lifes, number of stuffes
Integer 2 bytes 0 .. 65535 Usually money, number of stuffes, resources
Integer 3 bytes 0 .. 16777215 Use this type for ePSXe, ZSNES and ROCKNES emulators
Integer 4 bytes 0 .. 4294967295 Usually money,experience
Integer 8 bytes 0 .. 18446744073709551616 Usually money, if more then 4 milliardes
Float 4 bytes 1.5e-45 .. 3.4e+38 Some games uses it. Microsoft likes to use it.
Float 6 bytes 2.9e-39 .. 1.7e+38 Only for DOS games, that was created in Turbo Pascal
Float 8 bytes 5.0e-324 .. 1.7e+308 Macromedia Flash games
Float 10 bytes 3.4e-4951 .. 1.1e+4932 Only for mathematical programs
How do they know this numbers? Cheesecake...1 Byte can be 00 to FF...FF= 16 *16 = 256 so 255 numbers (because you start with 0)
1 Byte: 255
2 Bytes: Roughly 255*255
4 Bytes: Roughly 255*255*255*255
...
That's for integers.
Ok let's go back to our death count...as you may notice Floats are 2.3421 or whatever...I don't think the Bungie/GBX programmer would have wanted that would he?Player #1 died 2.5 times...No...Death Count is an Integer with 4 bytes (because Halo likes 4 bytes)...we can tell that from try & error or...experience.
No let's assume you died once (and make sure the game didn't restart while reading this ^^) go ahead and search for 1 - Integer...ok few secs later yay we have over 1 Mill Addresses with the value of 1...great...
What we need to do is filter...so either we search for the same value again and dismiss those that changed in the mean time or....we die again and filter 2...go on until we have a few addresses left.
Make sure you get the right address...one address might store the value and the other one just displays it...so if you have 2 addresses changing simultaneously make sure you test them by giving them a value of their own.
So there we have it...you know can change the death count by hand!
But wait? Why doesn't this work on other servers again?
Because for security reasons and to avoid stupidity all the vital memory memory data like positions, team indexes, kill/death/whatever count are stored ON THE FUCKING SERVER. And that's why you CANT I repeat YOU CANT hack your way trough RUNESCAPE or any other MMORPG. (Actually...nevermind I won't bother)
Part I.III Simple Memory Programming (VB.NET)
Alright now let's do one of the more funnier parts! Writing a trainer in VB.NET (yes no VB6 so Limited go into your corner :P, just kidding I love you ^^)
Let's get started...wait...how? Well either you take my source I released or let's create one step by step!
I assume that you have a basic knowledge on VB.NET by now. I'm going to use Visual Studio 2005 .NET Framework 3.0...but that doesn't really matter ^^.
THIS WILL HELP YOU ALL THE TIME: http://msdn2.microsoft.com/en-us/default.aspx
So we start of with a function and take a look on it how it works....the functions are called:
Public Declare Function GetWindowThreadProcessId Lib "User32" (ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As Integer) As Integer
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
Public Declare Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal Classname As String, ByVal WindowName As String) As Integer
'For Reading and Writing Process Memory
Public Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
Public Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
'Disable Memory Protection
Public Declare Function VirtualProtectEx Lib "kernel32" (ByVal hProcess As Integer, ByRef lpAddress As Object, ByVal dwSize As Integer, ByVal flNewProtect As Integer, ByRef lpflOldProtect As Integer) As IntegerThe first 3 Functions are for Process Handling...that means getting the process information, getting access to it and in the end close the access again.
The next 3 are vital for our memory purposes. Like the name says ReadProcessMemory/WriteProcessMemory. The next one is important too.
It changes the memory protection so we can write to it. You don't need this if you are only reading from memory and the memory is already set to "read". We are going to change it to "Read/Write" later on.
Let's add these constants:
Const PAGE_NOACCESS = &H1&
Const PAGE_READONLY = &H2&
Const PAGE_READWRITE = &H4&
Const PAGE_WRITECOPY = &H8&
Const PAGE_EXECUTE = &H10&
Const PAGE_EXECUTE_READ = &H20&
Const PAGE_EXECUTE_READWRITE = &H40&
Const PAGE_EXECUTE_WRITECOPY = &H80&
Const PAGE_GUARD = &H100&
Const PAGE_NOCACHE = &H200&
Const PROCESS_ALL_ACCESS = &H1F0FFF
The functions and constants have to go on top of all other code or inside a module.
Now let's actually write some code and no more copy paste 'n shit.
So let's create create our Sub/Method:
Public Sub ChangeDeathCount(ByVal DeathCount as Integer)
End Sub
Cool amIright? So to call this Sub/Method we just have to type:
ChangeDeathCount(Value)
Sweet. Now let's add some code.
Dim myProcesses As Process() = Process.GetProcessesByName("haloce")
If myProcesses.Length = 0 Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
Dim processHandle As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, myProcesses(0).Id)
If processHandle = IntPtr.Zero Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
So with the first variable we check for the process if it exists...the process is inside the "...". Haloce.exe -> Haloce | Halo.exe -> Halo etc....
If the Process = 0...so it actually doesn't exist...it just exists the sub and doesn't execute anymore code.
The second variable + code opens the process for you by setting it to Process_All_Access (check the constant at the top!).
So we have something like this:
Public Sub ChangeDeathCount(ByVal DeathCount as Integer)
Dim myProcesses As Process() = Process.GetProcessesByName("haloce")
If myProcesses.Length = 0 Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
Dim processHandle As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, myProcesses(0).Id)
If processHandle = IntPtr.Zero Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
End Sub
So we have a Sub/Method that checks for the process Haloce.exe...great. Now let's do something! We need a few variables:
Dim Address(0 To 1) As Integer
Dim vBuffer(0 To 1) As Long
Dim convert(0 To 1) As Integer
Dim byte_array0 As Byte() = Nothing
So the first is the address we need...the vbuffer stores our memory bytes....bytearray get's the bytearray from the vbuffer for us...convert converts it to an Integer so our actual DeathCount.
So let's add the DeathCount Address we have from ArtMoney/CheatEngine...
Address(0) = &H402AB07A (HEXIMAL)
OR
Address(0) = 1076539514 (DECIMAL)
Now let's read the memory from it:
ReadProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
byte_array0 = BitConverter.GetBytes(vBuffer(0))
convert(0) = BitConverter.ToInt32(byte_array0, 0)
'Textbox1.Text=convert(0)
vBuffer(0) = DeathCount 'The DeathCount we want to write (Method)
VirtualProtectEx(processHandle, Address(0), 4, PAGE_READWRITE, 0)
WriteProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
ReadProcessMemory(AtTheProcessHaloCE,FromTheAddres s,WritingTheValueToVbuffer,ByteSize(you don'tt need to change this reall),StartingIndex(this netiher))
Read byte array from the vbuffer and convert that to integer...
If you have the convert(0) you can display your death count anywhere on your app.
Now to write a custom DeathCount you just give vbuffer(0) a value and write the memory...we gave it a DeathCount Variable because we can insert any custom value when using the method (ChangeDeathCount(Value here) remember).
Finished yay! We just need to call the method:
ChangeDeathCount(1337)
Public Sub ChangeDeathCount(ByVal DeathCount as Integer)
Dim myProcesses As Process() = Process.GetProcessesByName("haloce")
If myProcesses.Length = 0 Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
Dim processHandle As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, myProcesses(0).Id)
If processHandle = IntPtr.Zero Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
Dim Address(0 To 1) As Integer
Dim vBuffer(0 To 1) As Long
Dim convert(0 To 1) As Integer
Dim byte_array0 As Byte() = Nothing
Address(0) = &H402AB07A (HEXIMAL)
'OR
Address(0) = 1076539514 (DECIMAL)
ReadProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
byte_array0 = BitConverter.GetBytes(vBuffer(0))
convert(0) = BitConverter.ToInt32(byte_array0, 0)
'Textbox1.Text=convert(0)
vBuffer(0) = DeathCount 'The DeathCount we want to write (Method)
VirtualProtectEx(processHandle, Address(0), 4, PAGE_READWRITE, 0)
WriteProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
End Sub
Part II.I Pointers and Offsets
Offsets:
I think I'm going to start off with Offsets since they are easier to understand and more common really. An Offset is like the name says...a offset from one point to the next one. So how does this help us? I'm going to give you 2 examples so you get a basic idea...
Regarding Halo 2 Vista:
If you tried to memory hack Halo 2 Vista you may have noticed that the addresses change on restart...first we thought this would be due to pointers but they also seemed to change. Like I said above every process has something like a starting memory index...we realized that the offset from the starting index stays the same but that the starting index always changes...So Halo2.exe + Offset always works...but a single address like 40092E42 won't. So when programming you have to get the base index first and then add the offset on top of it. Here are 2 ways on finding out the base address of the process....
Either you have an app that tells you the base address so you just take the address and substract the base index so we have the actual offset. Like 40000001 (Address), 40000000 (Starting Index)...so 40000001-40000000 = 1 so Base Index (40000000) + 1 = Our Address (40000001)
or if you use CheatEngine it gives you most of the time something like this:
"Halo2.exe + 1" (Double click on the address for this)
So Halo2.exe is the base index and 1 is the offset.
Regarding Memory Chunks:
Let's take the player informations as an example...they are memory chunks with a fixed size and every player in the server has one of his own...so let's pretend the memory chunk for the player starts with the player name....
[[PL1Name][PL1TeamIndex][Pl1Score][PL1Kills][PL1Assists][PL1Deaths]...]
[[PL2Name][PL2TeamIndex][Pl2Score][PL2Kills][PL2Assists][PL2Deaths]...]
[[PL3Name][PL3TeamIndex][Pl3Score][PL3Kills][PL3Assists][PL3Deaths]...]
The size of those memory chunks in Halo never change...so the offset from PL1Name to PL2Name is always constant (if I remember correctly it's 0x200).
So you basically need 1 address to get all of the rest...time saving right? I'm gonna use this information for the a little bit more complex VB.NET code later on...
Pointers:
*to be continued*
Part II.II Advanced Memory Programming (VB.NET)
I'm going to explain some of my sources I made in the past. Some or most of them have a simple mathematical fact behind them. Maybe this can give you some inspiritation.
BlueArrow Hack:
!!This shouldn't be used for cheating purposes. I hope the people that can follow this are smart enough not to misuse this information!!
This Hack changes the team you are on...so you can see the enemies arrows above their heads. The server doesn't see this because this data doesn't get sent from the client to the server.
T06xN9Y7UZQ
Basically each player has it's own Team Index...I bet there is a address that shows you what player index you are but I like to do this the hard way. Remember that each player has a specific offset? So does the playername and the player team index. So what I did I read the profile name and checked each player ingame for their names until the names matched with the profile name and changed according to that the team index.
We can write this pretty complex:
For i = 0 To 10
Address(0) += 2
ReadProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
ret0 = BitConverter.GetBytes(vBuffer(0))
TextBox1.Text &= System.Text.Encoding.ASCII.GetString(ret0)
Next
For i is a loop...it loops from 0 to 10 so 11 times. Why? Because a profile name in Halo has 11 chars. So Textbox1.Text &= System.Text.Encoding.ASCII.GetString(ret0) (which is Textbox1.Text = Textbox1.Text & the new char).
So Textbox1.Text holds the name for us.
For ia = 0 To 15
For i = 0 To 10
ReadProcessMemory(processHandle, Address(1), vBuffer(1), 2, 0)
ret0 = BitConverter.GetBytes(vBuffer(1))
TextBox2.Paste(System.Text.Encoding.Unicode.GetStr ing(ret0))
Address(1) = Address(1) + 2
Next
If TextBox1.Text = TextBox2.Text Then
ChangeTeams(ia)
Exit Sub
Else
Address(1) += &H1EA
TextBox2.Clear()
End If
Next
So this thing has 2 loops...a loop inside a loop..the loop is checks for each player 0 to 15..because a halo game can hold up to 16 players.
The next loop (i) get's the player name again....and stores the name into Textbox2. If Textbox1(ProfileName) and Textbox2(CurrentInGameName) match then it executes the method ChangeTeams(ia) where ia is the current player...if they don't match the offset goes to the next playername and this whole thing repeats itself.
Let's take a look at the other method:
Public Sub ChangeTeams(ByVal PlayerNumber As Integer)
Address(2) = AddressHereCencored 'Team Index PL1
Address(2) += PlayerNumber * 512
ReadProcessMemory(processHandle, Address(2), vBuffer(0), 4, 0)
ret0 = BitConverter.GetBytes(vBuffer(0))
convert(0) = BitConverter.ToInt32(ret0, 0)
If convert(0) = 1 Then
vBuffer(0) = 0
VirtualProtectEx(processHandle, Address(2), 4, PAGE_READWRITE, 0)
WriteProcessMemory(processHandle, Address(2), vBuffer(0), 4, 0)
End If
If convert(0) = 0 Then
vBuffer(0) = 1
VirtualProtectEx(processHandle, Address(2), 4, PAGE_READWRITE, 0)
WriteProcessMemory(processHandle, Address(2), vBuffer(0), 4, 0)
End If
So we had ChangeTeams(ia) before...ia is our playerindex. Address(0) += PlayerIndex * 512..so if we are PlayerIndex 0 then 0*512 = 0 so Address(0) += 0 so we are the first player inside the game :D
The next thing is to toggle the team. If we are on Team 0 then we are going to be on Team 1 and vice versa.
And there you have it...coding time about 1 hour and debugging with the help of Skyline :)
Halo CE FlyCam:
How to make a smooth transition.
8Ry5kUf75MI
Try
For motherloop = 0 To ListBox1.Items.Count - 1
Sensitivity = ListBox7.SelectedItem.ToString
ListBox1.SelectedIndex = line
X1 = ListBox1.SelectedItem.ToString
Y1 = ListBox2.SelectedItem.ToString
Z1 = ListBox3.SelectedItem.ToString
XL1 = ListBox4.SelectedItem.ToString
YL1 = ListBox5.SelectedItem.ToString
FoV1 = ListBox6.SelectedIndex.ToString
ListBox1.SelectedIndex = line + 1
X2 = ListBox1.SelectedItem.ToString
Y2 = ListBox2.SelectedItem.ToString
Z2 = ListBox3.SelectedItem.ToString
XL2 = ListBox4.SelectedItem.ToString
YL2 = ListBox5.SelectedItem.ToString
FoV2 = ListBox6.SelectedIndex.ToString
XDif = (X1 - X2) / Sensitivity
YDif = (Y1 - Y2) / Sensitivity
ZDif = (Z1 - Z2) / Sensitivity
XLDif = (XL1 - XL2) / Sensitivity
YLDif = (YL1 - YL2) / Sensitivity
FoVDif = (FoV1 - FoV2) / Sensitivity
For daloop = 0 To (Sensitivity - 1)
X = X1 - (XDif * (daloop + 1))
vBuffer(0) = X
Y = Y1 - (YDif * (daloop + 1))
vBuffer(1) = Y
Z = Z1 - (ZDif * (daloop + 1))
vBuffer(2) = Z
XL = XL1 - (XLDif * (daloop + 1))
vBuffer(3) = XL
YL = YL1 - (YLDif * (daloop + 1))
vBuffer(4) = YL
FoV = FoV1 - (FoVDif * (daloop + 1))
vBuffer(5) = FoV
VirtualProtectEx(processHandle, Address(0), 4, PAGE_READWRITE, 0)
VirtualProtectEx(processHandle, Address(1), 4, PAGE_READWRITE, 0)
VirtualProtectEx(processHandle, Address(2), 4, PAGE_READWRITE, 0)
VirtualProtectEx(processHandle, Address(3), 4, PAGE_READWRITE, 0)
VirtualProtectEx(processHandle, Address(4), 4, PAGE_READWRITE, 0)
VirtualProtectEx(processHandle, Address(6), 4, PAGE_READWRITE, 0)
WriteProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
WriteProcessMemory(processHandle, Address(1), vBuffer(1), 4, 0)
WriteProcessMemory(processHandle, Address(2), vBuffer(2), 4, 0)
WriteProcessMemory(processHandle, Address(3), vBuffer(3), 4, 0)
WriteProcessMemory(processHandle, Address(4), vBuffer(4), 4, 0)
If CheckBox1.Checked = True Then
WriteProcessMemory(processHandle, Address(6), vBuffer(5), 4, 0) 'This is the optional FoV
End If
System.Threading.Thread.Sleep(Sleep)
Next
line += 1
Next
Catch ex As Exception
End Try
X1 is the first X-position point of the camera, X2 obviously the second one. Now we calculate the difference bewteen those. So if X1 =1 and X2 = 2 then XDif = -1.
Now we don't want it to jump from X1 to X2 immedatly so we divide it by the user given sensitivity...let's say 10...so -1 / 10 = -0.1.
Now the next step is a bit harder to understand...X1 + 0.1 = 1.1...+ 0.1 again 1.2...until we have 2.0 (X2). We divided by 10 (sensitivity) so we have to add those again to make a smooth transition.
X = X1 - (XDif * (daloop + 1)) means that X1 - XDif (-0.1 remember?) * daloop (which is basically the sensitivity)...
so X= 1 - (-0.1) = 1.1...1.2...1.3......1.9...2.0 (X2).
If the loop is done it takes the next 2 lines in the application and has a new X1 and X2.
I admit that this code is not that easy to understand. ^^
to be continued....
------------------------------------------------------
Table of Content:
Part I. (Easy)
Memory System
Modifying Halo's Memory
Simple Memory Programming (VB.NET)Part II. (Intermediate)
Pointers / Offsets
Advanced Memory Programming (VB.NET)Part I.I Memory System
I'm not go into depth with this because...A. it changes occasionally B. I don't know everything about it...and I guess that's vital for explaining it.
Anyway I hope Korn & Co. don't find that many mistakes in here but I think I can try to explain the basic idea or at least get it across :)
Each byte (a byte consists of 8 bits..for example in Hex a byte would be "00" or "FF") has it's own address assigned to it. How big is the memory? Let's take a look...
Range: 0x00000000 to 0x7FFFE000
Wait, what does that mean? 0x is a syntax to display an offset. So 0x00 means it's 00 away from the starting index. So RAM ranges from 00000000 to 7FFFE000? Wait....7FFFE000(Hex) = 2147475456(Dec)...and each byte has it's own address? So we have 2147475456 bytes...roughly 2147475 kilo bytes...2147...mega bytes...2 giga bytes...of Random Access Memory(RAM)?
How can that be if not all computer have that amount? And why does Halo's Memory start at 0x00400000...and my other processes have the same starting index?
Magic?...it's Microsoft after all...no..no...Windows uses a Virtual Mapping system to assign chunks of memory to each individual process and hides the real memory address (which we don't care about anyway).
As you may notice memory informations like addresses or their corresponding bytes are displayed in Hex(imal). How to count Hex?
There are mathematical ways of doing it...but I wouldn't bother since everyone with Windows XP has a nifty tool called the calculator that already includes Hex calculating and conversion.
But to get back to the stone age and to start from the beginning....
Humans have 10 numbers to display all of the rest...0123456789...but why 10? No one knows for sure but we have 10 fingers after all right?
Well for Hex you just have to imagine that we have 16 fingers...ranging from 0123456789ABCDEF...and the counting is the same....
Hex : 00 01 02 ... 09 0A 0B 0C 0D 0E 0F 10 11...1F..20
Dec : 00 01 02 ... 09 10 11 12 13 14 15 16 17...31 32
So 20 in Hex is....32 in Dec. Seems easy doesn't it? Well it is...
http://img177.imageshack.us/img177/4152/memorytutap5.png
Part I.II Modifying Halo's Memory
Can we plz build an aimbot now, plzplz? Nope sorry. Even though there is so much irony in that sentence...someone who wants to build an aimbot needs some kind of mathematical skills (except if he is copy pasting source or tutorial) and that requires some level of intelligence...
We are going to do simple things...so no vehicle hijacking or whatever you want to imagine...we gonna modify....the ubber amazing death count of a player! Cool or? Actually...there are 2 reasons why this isn't cool.
1. It doesn't work if you join a server *CRY*
2. It's the death count who cares anyway? *Hint*Kill Count Lawl*Hint*
And please...don't EVER ever think of memory hacking the ping....
Ok let's get started...take Notepad and open up Haloce.exe with it...
no please don't. For memory hacking we need special programs that are dedicated to us...to do this nerdy crap.
Here are the 2 main ones:
ArtMoney (http://www.artmoney.ru/e_download.htm)
CheatEngine (http://cheatengine.org/download.php)
Let's go back to the drawing board...all values or basically everything you see on screen is stored somewhere in the memory...let's stick to something visible and easy like the death count...I assume by know you know how to open up a process (haloce.exe,Halo) in one of those programs...it's not very hard really.
So let's start to search for the death count...ok we haven't died yet in game so let's search for 0! ...no...no.... let's not...it's a waste of time searching for 0...so try to avoid them if you can and always start with a higher number( even if it is 1)...so die once...yay press F1 in game and you see that you have died once! Now go into CheatEngine or ArtMoney and go to search...ok value? 1 obviously....type?
I guess I have to explain some basics things again.
Memory values are stored in Hex amiright? Yes I am.
But there are different ways of reading them...or using them for different types of data. So let's take a simple but effective example...
Hex:3E
Dec: 62
Datatypes: Integer (1 to 10 bytes) , Float (aka Single/ 1 to 10 bytes), ASCII (1 byte?), Unicode (4 bytes?).
If we would read that address to ASCII it would be ">"
ASCII Table (just use google) (http://www.ecowin.org/aulas/resources/tables/asciitable.jpg)
So what's the basic (I say basic cause Microsoft says different) difference between floats and integer? You guys are lucky that you are English native because it took me 2 years to figure out the German word even though I knew what an Integer basically was regarding memory hacking (ger.= ganze Zahl).
Type Range Comment
Integer 1 byte 0 .. 255 Usually health, lifes, number of stuffes
Integer 2 bytes 0 .. 65535 Usually money, number of stuffes, resources
Integer 3 bytes 0 .. 16777215 Use this type for ePSXe, ZSNES and ROCKNES emulators
Integer 4 bytes 0 .. 4294967295 Usually money,experience
Integer 8 bytes 0 .. 18446744073709551616 Usually money, if more then 4 milliardes
Float 4 bytes 1.5e-45 .. 3.4e+38 Some games uses it. Microsoft likes to use it.
Float 6 bytes 2.9e-39 .. 1.7e+38 Only for DOS games, that was created in Turbo Pascal
Float 8 bytes 5.0e-324 .. 1.7e+308 Macromedia Flash games
Float 10 bytes 3.4e-4951 .. 1.1e+4932 Only for mathematical programs
How do they know this numbers? Cheesecake...1 Byte can be 00 to FF...FF= 16 *16 = 256 so 255 numbers (because you start with 0)
1 Byte: 255
2 Bytes: Roughly 255*255
4 Bytes: Roughly 255*255*255*255
...
That's for integers.
Ok let's go back to our death count...as you may notice Floats are 2.3421 or whatever...I don't think the Bungie/GBX programmer would have wanted that would he?Player #1 died 2.5 times...No...Death Count is an Integer with 4 bytes (because Halo likes 4 bytes)...we can tell that from try & error or...experience.
No let's assume you died once (and make sure the game didn't restart while reading this ^^) go ahead and search for 1 - Integer...ok few secs later yay we have over 1 Mill Addresses with the value of 1...great...
What we need to do is filter...so either we search for the same value again and dismiss those that changed in the mean time or....we die again and filter 2...go on until we have a few addresses left.
Make sure you get the right address...one address might store the value and the other one just displays it...so if you have 2 addresses changing simultaneously make sure you test them by giving them a value of their own.
So there we have it...you know can change the death count by hand!
But wait? Why doesn't this work on other servers again?
Because for security reasons and to avoid stupidity all the vital memory memory data like positions, team indexes, kill/death/whatever count are stored ON THE FUCKING SERVER. And that's why you CANT I repeat YOU CANT hack your way trough RUNESCAPE or any other MMORPG. (Actually...nevermind I won't bother)
Part I.III Simple Memory Programming (VB.NET)
Alright now let's do one of the more funnier parts! Writing a trainer in VB.NET (yes no VB6 so Limited go into your corner :P, just kidding I love you ^^)
Let's get started...wait...how? Well either you take my source I released or let's create one step by step!
I assume that you have a basic knowledge on VB.NET by now. I'm going to use Visual Studio 2005 .NET Framework 3.0...but that doesn't really matter ^^.
THIS WILL HELP YOU ALL THE TIME: http://msdn2.microsoft.com/en-us/default.aspx
So we start of with a function and take a look on it how it works....the functions are called:
Public Declare Function GetWindowThreadProcessId Lib "User32" (ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As Integer) As Integer
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer
Public Declare Function FindWindow Lib "User32" Alias "FindWindowA" (ByVal Classname As String, ByVal WindowName As String) As Integer
'For Reading and Writing Process Memory
Public Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
Public Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByRef lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer
'Disable Memory Protection
Public Declare Function VirtualProtectEx Lib "kernel32" (ByVal hProcess As Integer, ByRef lpAddress As Object, ByVal dwSize As Integer, ByVal flNewProtect As Integer, ByRef lpflOldProtect As Integer) As IntegerThe first 3 Functions are for Process Handling...that means getting the process information, getting access to it and in the end close the access again.
The next 3 are vital for our memory purposes. Like the name says ReadProcessMemory/WriteProcessMemory. The next one is important too.
It changes the memory protection so we can write to it. You don't need this if you are only reading from memory and the memory is already set to "read". We are going to change it to "Read/Write" later on.
Let's add these constants:
Const PAGE_NOACCESS = &H1&
Const PAGE_READONLY = &H2&
Const PAGE_READWRITE = &H4&
Const PAGE_WRITECOPY = &H8&
Const PAGE_EXECUTE = &H10&
Const PAGE_EXECUTE_READ = &H20&
Const PAGE_EXECUTE_READWRITE = &H40&
Const PAGE_EXECUTE_WRITECOPY = &H80&
Const PAGE_GUARD = &H100&
Const PAGE_NOCACHE = &H200&
Const PROCESS_ALL_ACCESS = &H1F0FFF
The functions and constants have to go on top of all other code or inside a module.
Now let's actually write some code and no more copy paste 'n shit.
So let's create create our Sub/Method:
Public Sub ChangeDeathCount(ByVal DeathCount as Integer)
End Sub
Cool amIright? So to call this Sub/Method we just have to type:
ChangeDeathCount(Value)
Sweet. Now let's add some code.
Dim myProcesses As Process() = Process.GetProcessesByName("haloce")
If myProcesses.Length = 0 Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
Dim processHandle As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, myProcesses(0).Id)
If processHandle = IntPtr.Zero Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
So with the first variable we check for the process if it exists...the process is inside the "...". Haloce.exe -> Haloce | Halo.exe -> Halo etc....
If the Process = 0...so it actually doesn't exist...it just exists the sub and doesn't execute anymore code.
The second variable + code opens the process for you by setting it to Process_All_Access (check the constant at the top!).
So we have something like this:
Public Sub ChangeDeathCount(ByVal DeathCount as Integer)
Dim myProcesses As Process() = Process.GetProcessesByName("haloce")
If myProcesses.Length = 0 Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
Dim processHandle As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, myProcesses(0).Id)
If processHandle = IntPtr.Zero Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
End Sub
So we have a Sub/Method that checks for the process Haloce.exe...great. Now let's do something! We need a few variables:
Dim Address(0 To 1) As Integer
Dim vBuffer(0 To 1) As Long
Dim convert(0 To 1) As Integer
Dim byte_array0 As Byte() = Nothing
So the first is the address we need...the vbuffer stores our memory bytes....bytearray get's the bytearray from the vbuffer for us...convert converts it to an Integer so our actual DeathCount.
So let's add the DeathCount Address we have from ArtMoney/CheatEngine...
Address(0) = &H402AB07A (HEXIMAL)
OR
Address(0) = 1076539514 (DECIMAL)
Now let's read the memory from it:
ReadProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
byte_array0 = BitConverter.GetBytes(vBuffer(0))
convert(0) = BitConverter.ToInt32(byte_array0, 0)
'Textbox1.Text=convert(0)
vBuffer(0) = DeathCount 'The DeathCount we want to write (Method)
VirtualProtectEx(processHandle, Address(0), 4, PAGE_READWRITE, 0)
WriteProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
ReadProcessMemory(AtTheProcessHaloCE,FromTheAddres s,WritingTheValueToVbuffer,ByteSize(you don'tt need to change this reall),StartingIndex(this netiher))
Read byte array from the vbuffer and convert that to integer...
If you have the convert(0) you can display your death count anywhere on your app.
Now to write a custom DeathCount you just give vbuffer(0) a value and write the memory...we gave it a DeathCount Variable because we can insert any custom value when using the method (ChangeDeathCount(Value here) remember).
Finished yay! We just need to call the method:
ChangeDeathCount(1337)
Public Sub ChangeDeathCount(ByVal DeathCount as Integer)
Dim myProcesses As Process() = Process.GetProcessesByName("haloce")
If myProcesses.Length = 0 Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
Dim processHandle As IntPtr = OpenProcess(PROCESS_ALL_ACCESS, 0, myProcesses(0).Id)
If processHandle = IntPtr.Zero Then
'Optional Stuff Goes Here...like Label displaying some kind of text
Exit Sub
End If
Dim Address(0 To 1) As Integer
Dim vBuffer(0 To 1) As Long
Dim convert(0 To 1) As Integer
Dim byte_array0 As Byte() = Nothing
Address(0) = &H402AB07A (HEXIMAL)
'OR
Address(0) = 1076539514 (DECIMAL)
ReadProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
byte_array0 = BitConverter.GetBytes(vBuffer(0))
convert(0) = BitConverter.ToInt32(byte_array0, 0)
'Textbox1.Text=convert(0)
vBuffer(0) = DeathCount 'The DeathCount we want to write (Method)
VirtualProtectEx(processHandle, Address(0), 4, PAGE_READWRITE, 0)
WriteProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
End Sub
Part II.I Pointers and Offsets
Offsets:
I think I'm going to start off with Offsets since they are easier to understand and more common really. An Offset is like the name says...a offset from one point to the next one. So how does this help us? I'm going to give you 2 examples so you get a basic idea...
Regarding Halo 2 Vista:
If you tried to memory hack Halo 2 Vista you may have noticed that the addresses change on restart...first we thought this would be due to pointers but they also seemed to change. Like I said above every process has something like a starting memory index...we realized that the offset from the starting index stays the same but that the starting index always changes...So Halo2.exe + Offset always works...but a single address like 40092E42 won't. So when programming you have to get the base index first and then add the offset on top of it. Here are 2 ways on finding out the base address of the process....
Either you have an app that tells you the base address so you just take the address and substract the base index so we have the actual offset. Like 40000001 (Address), 40000000 (Starting Index)...so 40000001-40000000 = 1 so Base Index (40000000) + 1 = Our Address (40000001)
or if you use CheatEngine it gives you most of the time something like this:
"Halo2.exe + 1" (Double click on the address for this)
So Halo2.exe is the base index and 1 is the offset.
Regarding Memory Chunks:
Let's take the player informations as an example...they are memory chunks with a fixed size and every player in the server has one of his own...so let's pretend the memory chunk for the player starts with the player name....
[[PL1Name][PL1TeamIndex][Pl1Score][PL1Kills][PL1Assists][PL1Deaths]...]
[[PL2Name][PL2TeamIndex][Pl2Score][PL2Kills][PL2Assists][PL2Deaths]...]
[[PL3Name][PL3TeamIndex][Pl3Score][PL3Kills][PL3Assists][PL3Deaths]...]
The size of those memory chunks in Halo never change...so the offset from PL1Name to PL2Name is always constant (if I remember correctly it's 0x200).
So you basically need 1 address to get all of the rest...time saving right? I'm gonna use this information for the a little bit more complex VB.NET code later on...
Pointers:
*to be continued*
Part II.II Advanced Memory Programming (VB.NET)
I'm going to explain some of my sources I made in the past. Some or most of them have a simple mathematical fact behind them. Maybe this can give you some inspiritation.
BlueArrow Hack:
!!This shouldn't be used for cheating purposes. I hope the people that can follow this are smart enough not to misuse this information!!
This Hack changes the team you are on...so you can see the enemies arrows above their heads. The server doesn't see this because this data doesn't get sent from the client to the server.
T06xN9Y7UZQ
Basically each player has it's own Team Index...I bet there is a address that shows you what player index you are but I like to do this the hard way. Remember that each player has a specific offset? So does the playername and the player team index. So what I did I read the profile name and checked each player ingame for their names until the names matched with the profile name and changed according to that the team index.
We can write this pretty complex:
For i = 0 To 10
Address(0) += 2
ReadProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
ret0 = BitConverter.GetBytes(vBuffer(0))
TextBox1.Text &= System.Text.Encoding.ASCII.GetString(ret0)
Next
For i is a loop...it loops from 0 to 10 so 11 times. Why? Because a profile name in Halo has 11 chars. So Textbox1.Text &= System.Text.Encoding.ASCII.GetString(ret0) (which is Textbox1.Text = Textbox1.Text & the new char).
So Textbox1.Text holds the name for us.
For ia = 0 To 15
For i = 0 To 10
ReadProcessMemory(processHandle, Address(1), vBuffer(1), 2, 0)
ret0 = BitConverter.GetBytes(vBuffer(1))
TextBox2.Paste(System.Text.Encoding.Unicode.GetStr ing(ret0))
Address(1) = Address(1) + 2
Next
If TextBox1.Text = TextBox2.Text Then
ChangeTeams(ia)
Exit Sub
Else
Address(1) += &H1EA
TextBox2.Clear()
End If
Next
So this thing has 2 loops...a loop inside a loop..the loop is checks for each player 0 to 15..because a halo game can hold up to 16 players.
The next loop (i) get's the player name again....and stores the name into Textbox2. If Textbox1(ProfileName) and Textbox2(CurrentInGameName) match then it executes the method ChangeTeams(ia) where ia is the current player...if they don't match the offset goes to the next playername and this whole thing repeats itself.
Let's take a look at the other method:
Public Sub ChangeTeams(ByVal PlayerNumber As Integer)
Address(2) = AddressHereCencored 'Team Index PL1
Address(2) += PlayerNumber * 512
ReadProcessMemory(processHandle, Address(2), vBuffer(0), 4, 0)
ret0 = BitConverter.GetBytes(vBuffer(0))
convert(0) = BitConverter.ToInt32(ret0, 0)
If convert(0) = 1 Then
vBuffer(0) = 0
VirtualProtectEx(processHandle, Address(2), 4, PAGE_READWRITE, 0)
WriteProcessMemory(processHandle, Address(2), vBuffer(0), 4, 0)
End If
If convert(0) = 0 Then
vBuffer(0) = 1
VirtualProtectEx(processHandle, Address(2), 4, PAGE_READWRITE, 0)
WriteProcessMemory(processHandle, Address(2), vBuffer(0), 4, 0)
End If
So we had ChangeTeams(ia) before...ia is our playerindex. Address(0) += PlayerIndex * 512..so if we are PlayerIndex 0 then 0*512 = 0 so Address(0) += 0 so we are the first player inside the game :D
The next thing is to toggle the team. If we are on Team 0 then we are going to be on Team 1 and vice versa.
And there you have it...coding time about 1 hour and debugging with the help of Skyline :)
Halo CE FlyCam:
How to make a smooth transition.
8Ry5kUf75MI
Try
For motherloop = 0 To ListBox1.Items.Count - 1
Sensitivity = ListBox7.SelectedItem.ToString
ListBox1.SelectedIndex = line
X1 = ListBox1.SelectedItem.ToString
Y1 = ListBox2.SelectedItem.ToString
Z1 = ListBox3.SelectedItem.ToString
XL1 = ListBox4.SelectedItem.ToString
YL1 = ListBox5.SelectedItem.ToString
FoV1 = ListBox6.SelectedIndex.ToString
ListBox1.SelectedIndex = line + 1
X2 = ListBox1.SelectedItem.ToString
Y2 = ListBox2.SelectedItem.ToString
Z2 = ListBox3.SelectedItem.ToString
XL2 = ListBox4.SelectedItem.ToString
YL2 = ListBox5.SelectedItem.ToString
FoV2 = ListBox6.SelectedIndex.ToString
XDif = (X1 - X2) / Sensitivity
YDif = (Y1 - Y2) / Sensitivity
ZDif = (Z1 - Z2) / Sensitivity
XLDif = (XL1 - XL2) / Sensitivity
YLDif = (YL1 - YL2) / Sensitivity
FoVDif = (FoV1 - FoV2) / Sensitivity
For daloop = 0 To (Sensitivity - 1)
X = X1 - (XDif * (daloop + 1))
vBuffer(0) = X
Y = Y1 - (YDif * (daloop + 1))
vBuffer(1) = Y
Z = Z1 - (ZDif * (daloop + 1))
vBuffer(2) = Z
XL = XL1 - (XLDif * (daloop + 1))
vBuffer(3) = XL
YL = YL1 - (YLDif * (daloop + 1))
vBuffer(4) = YL
FoV = FoV1 - (FoVDif * (daloop + 1))
vBuffer(5) = FoV
VirtualProtectEx(processHandle, Address(0), 4, PAGE_READWRITE, 0)
VirtualProtectEx(processHandle, Address(1), 4, PAGE_READWRITE, 0)
VirtualProtectEx(processHandle, Address(2), 4, PAGE_READWRITE, 0)
VirtualProtectEx(processHandle, Address(3), 4, PAGE_READWRITE, 0)
VirtualProtectEx(processHandle, Address(4), 4, PAGE_READWRITE, 0)
VirtualProtectEx(processHandle, Address(6), 4, PAGE_READWRITE, 0)
WriteProcessMemory(processHandle, Address(0), vBuffer(0), 4, 0)
WriteProcessMemory(processHandle, Address(1), vBuffer(1), 4, 0)
WriteProcessMemory(processHandle, Address(2), vBuffer(2), 4, 0)
WriteProcessMemory(processHandle, Address(3), vBuffer(3), 4, 0)
WriteProcessMemory(processHandle, Address(4), vBuffer(4), 4, 0)
If CheckBox1.Checked = True Then
WriteProcessMemory(processHandle, Address(6), vBuffer(5), 4, 0) 'This is the optional FoV
End If
System.Threading.Thread.Sleep(Sleep)
Next
line += 1
Next
Catch ex As Exception
End Try
X1 is the first X-position point of the camera, X2 obviously the second one. Now we calculate the difference bewteen those. So if X1 =1 and X2 = 2 then XDif = -1.
Now we don't want it to jump from X1 to X2 immedatly so we divide it by the user given sensitivity...let's say 10...so -1 / 10 = -0.1.
Now the next step is a bit harder to understand...X1 + 0.1 = 1.1...+ 0.1 again 1.2...until we have 2.0 (X2). We divided by 10 (sensitivity) so we have to add those again to make a smooth transition.
X = X1 - (XDif * (daloop + 1)) means that X1 - XDif (-0.1 remember?) * daloop (which is basically the sensitivity)...
so X= 1 - (-0.1) = 1.1...1.2...1.3......1.9...2.0 (X2).
If the loop is done it takes the next 2 lines in the application and has a new X1 and X2.
I admit that this code is not that easy to understand. ^^
to be continued....