as I previously stated I use BlackMagic by Shynd to interact with other processes. When I started with the whole topic I used it without even knowing what this great dll was doing in detail (which is bad in my opinion).
In this post I want to take a step back and write the current tickcount into LastHardwareAction without any kind of tool.
What is required?
- WoW v1.12.1
- Cheat Engine (to control if we do our job good)
- Basic C#
Lets go!
1. First of all: LastHardwareAction address is 0x00CF0BC8
2. Attach Cheat Engine to your WoW instance and add the address manually by Add Address Manually. The type is 4 byte (UInt / Int -> 4 byte)
3. To modify memory of another process we need WriteProcessMemory which is provided by Kernel32.dll. We follow the suggestion of pinvoke (http://www.pinvoke.net/default.aspx/kernel32.writeprocessmemory) and define our prototype like this:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
IntPtr lpBuffer,
int nSize,
out IntPtr lpNumberOfBytesWritten);
4. To verify our MemoryWrite we also want to read the memory. Once again we define another prototype for ReadProcessMemory:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[Out] byte[] lpBuffer,
int dwSize,
out IntPtr lpNumberOfBytesRead);
5. Now that we got Read and WriteProcessMemory defined we need a simple UInt which we will convertert into a byte array and write to memory later
uint exTickCount = 1;
byte[] bCurTickCount = BitConverter.GetBytes(exTickCount);
6. Lets break up this little snippet:
Process WoW = Process.GetProcessesByName("WoW")[0];
IntPtr bytesWritten = IntPtr.Zero;
IntPtr lpBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(bCurTickCount[0]) * 4);
Marshal.Copy(bCurTickCount, 0, lpBuffer, bCurTickCount.Length);
WriteProcessMemory(WoW.Handle, (IntPtr)0x00CF0BC8, lpBuffer, bCurTickCount.Length, out bytesWritten);
We obtain all Processes with the name WoW and pick the first one (Since this is just an example ... who gives a fuck)
We initialise bytesWritten with IntPtr.Zero
We use Marshal.AllochGlobal to allocate the needed size of bytes in the unmanaged address space of our program (http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.allochglobal(v=vs.100).aspx)
With Marshal.SizeOf we get the size of bytes a managed object has unmanaged:
You can use this method when you do not have a structure. The layout must be sequential or explicit.
The size returned is the size of the unmanaged type. The unmanaged and managed sizes of an object can differ. For character types, the size is affected by the CharSet value applied to that class. (source)
Since all elements of our array are from the same type we just multiple the value we get from Marshal.SizeOf with our count of elements and get the value of bytes we need to allocate.
Next step is about copying our managed byte array in unmanaged memory with the help of Marshal.Copy:
1. parameter -> Our byte array
2. parameter -> The element where we begin to copy
3. parameter -> Pointer to the beginning of our previously allocated unmanaged space
4. parameter -> The length of bytes to copy into unmanaged memory
Finally we call WriteProcessMemory:
1. parameter -> Handle to our process
2. Parameter -> Address of LastHardwareAction
3. parameter -> Pointer to our previously allocated unmanaged bytes now storing the byte array
4. parameter -> The length of bytes to write
5. parameter -> Will hold the values of bytes we successfully wrote into the address space of WoW
Want to know more about unmanaged and managed memory? I found a great post on stackoverflow explaining this topic (stackoverflow).
6. Everything worked? Great! Lets view LastHardwareAction in Cheat Engine (this time as: Array of byte (size 4))
Following this tutorial you will most likely see the result I saw:
Windows stores bytes in little endian which means that the little end (our last element) is stored first.
Short version: Bytes are reversed (if you calculate the value you start of with the first left byte instead of the first right)
Long version: http://support.microsoft.com/kb/102025
Reading from memory is pretty much the same game. Create an empty array with the size of bytes you want to read. Pass handle, address, aswell the empty array to ReadProcessMemory and enjoy the results.
If you have problems, questions or suggestions for further posts I would be glad to have a chat over skype (cmwts9) or IRC (#FeenixED on quakenet).
Moreover I want to point to an OwnedCore-thread collecting links to all kind of memory manipulation librarys:
http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/331363-memory-hacking-library-list.html
Keine Kommentare:
Kommentar veröffentlichen