hi,
Since I'm most likely leaving the scene of making these tools (apart from my macro if anyone is interested.), I'll be releasing a library that can be used to bypass all of GameGuard's protection methods on x64 Win7+.
I've document the 2 files in there as much as I could.
The source code also contains a rather useful header containing some native functions and some custom C and NT/WIN API functions.
Note that you need to compile in x86, I haven't tested it in x64 and most likely something will go wrong.
So this means that you need your AutoIt, C# or whatever other compiler to compile for x86 otherwise LdrLoadDll/LoadLibraryA won't return a handle.
Edit: I'll make a x64 version of this soon.
Edit 2: I forgot that VS Inline ASM does not support x64, so nevermind, 64bit wont be around.
If you don't want to compile the dll, you can go to Release/ and pick it up there.
The exported functions are:
Note that I called this DLL "GameGuard" but well that doesn't really matter at all. I'm not very creative.
Quick and simple example use for C# coming up.
Import the library exports.
Typedef some game addresses:
Declare our helper functions:
Declare our reading and writing functions for pointers.
And finally some example use for some things you might want to use in archlord.
In AutoIt it should work exactly the same, import the exports, and use them similarly how I presented them in C#.
For C/C++ you can just take a look at the source code and do whatever you like.
That'll be all, have fun; hope somebody makes tools out of this.
Update: added a nicer example for c#.
Since I'm most likely leaving the scene of making these tools (apart from my macro if anyone is interested.), I'll be releasing a library that can be used to bypass all of GameGuard's protection methods on x64 Win7+.
I've document the 2 files in there as much as I could.
The source code also contains a rather useful header containing some native functions and some custom C and NT/WIN API functions.
Note that you need to compile in x86, I haven't tested it in x64 and most likely something will go wrong.
So this means that you need your AutoIt, C# or whatever other compiler to compile for x86 otherwise LdrLoadDll/LoadLibraryA won't return a handle.
Edit: I'll make a x64 version of this soon.
Edit 2: I forgot that VS Inline ASM does not support x64, so nevermind, 64bit wont be around.
If you don't want to compile the dll, you can go to Release/ and pick it up there.
The exported functions are:
- extCloseHandle
- extGetCursorPos
- extGetProcessActive
- extGetProcessBaseAddress
- extGetProcessImageSize
- extGetWindowThreadProcessId
- extOpenProcess
- extPostMessageA/W
- extSendMessageA/W
- extWriteMemory
- extReadMemory
- extGetModuleHandleA/W
Note that I called this DLL "GameGuard" but well that doesn't really matter at all. I'm not very creative.
Quick and simple example use for C# coming up.
Import the library exports.
Code:
[DllImport("GameGuard.dll")] private static extern bool extSendMessageA(IntPtr hWnd, uint msg, uint wParam, IntPtr lParam); [DllImport("GameGuard.dll")] private static extern IntPtr extOpenProcess(uint processId); [DllImport("GameGuard.dll")] private static extern bool extReadMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesRead); [DllImport("GameGuard.dll")] private static extern bool extWriteMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int nSize, out IntPtr lpNumberOfBytesWritten); [DllImport("GameGuard.dll")] private static extern IntPtr extGetProcessBaseAddress(IntPtr hProcess); [DllImport("GameGuard.dll")] private static extern IntPtr extGetProcessImageSize(IntPtr hProcess); [DllImport("GameGuard.dll")] private static extern bool extCloseHandle(IntPtr hObject); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int MapVirtualKey(int uCode, int uMapType); [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern int VkKeyScan(char ch);
Code:
public static class Defines { public static IntPtr AddressTargetBase = new IntPtr(0xD00C84); /* VA */ public static IntPtr AddressCharacterBase = new IntPtr(0xD00B14); /* VA */ public static IntPtr LocalBar = new IntPtr(0x5412B0); /* RVA */ }
Code:
private static string GetString(byte[] buffer) { if (buffer.Length == 0 || buffer[0] == '\0') { return string.Empty; } var strBuilder = new StringBuilder(); foreach (var b in buffer) { if (b == '\0') { break; } strBuilder.Append((char)b); } return strBuilder.ToString(); } /* gets the VK equivalent of the '~' key. */ private static byte GetUpKey() { return (byte)MapVirtualKey(0x29, 1); } private static byte[] ToByteArray(object value, uint maxLength) { int rawsize = Marshal.SizeOf(value); byte[] rawdata = new byte[rawsize]; GCHandle gcHandle; if ((gcHandle = GCHandle.Alloc(rawdata, GCHandleType.Pinned)) == null) { throw new Exception("Not enough RAM memory available."); } Marshal.StructureToPtr(value, gcHandle.AddrOfPinnedObject(), false); gcHandle.Free(); if (maxLength < rawdata.Length) { byte[] temp = new byte[maxLength]; Array.Copy(rawdata, temp, maxLength); return temp; } else { return rawdata; } }
Code:
private static T Read<T>(IntPtr hProcess, IntPtr dwBaseAddress, int[] offsets = null, bool IsRVA = false) { int bytesRead; object ret; var size = typeof(T) != typeof(string) ? (uint)Marshal.SizeOf(typeof(T)) : 30; if (offsets == null) { offsets = new int[0]; } if (IsRVA) { IntPtr ImageBaseAddress; if ((ImageBaseAddress = extGetProcessBaseAddress(hProcess)) == IntPtr.Zero) { return default(T); } dwBaseAddress = IntPtr.Add(dwBaseAddress, (int)ImageBaseAddress); } var buffer = new byte[size]; extReadMemory(hProcess, dwBaseAddress, buffer, size, out bytesRead); foreach (int offset in offsets) { dwBaseAddress = new IntPtr(BitConverter.ToInt32(buffer, 0)); extReadMemory(hProcess, dwBaseAddress + offset, buffer, size, out bytesRead); } switch (Type.GetTypeCode(typeof(T))) { case TypeCode.Boolean: ret = BitConverter.ToBoolean(buffer, 0); break; case TypeCode.Char: ret = BitConverter.ToChar(buffer, 0); break; case TypeCode.Byte: ret = buffer[0]; break; case TypeCode.Int16: ret = BitConverter.ToInt16(buffer, 0); break; case TypeCode.UInt16: ret = BitConverter.ToUInt16(buffer, 0); break; case TypeCode.Int32: ret = BitConverter.ToInt32(buffer, 0); break; case TypeCode.UInt32: ret = BitConverter.ToUInt32(buffer, 0); break; case TypeCode.Int64: ret = BitConverter.ToInt64(buffer, 0); break; case TypeCode.UInt64: ret = BitConverter.ToUInt64(buffer, 0); break; case TypeCode.Single: ret = BitConverter.ToSingle(buffer, 0); break; case TypeCode.Double: ret = BitConverter.ToDouble(buffer, 0); break; case TypeCode.String: ret = GetString(buffer); break; default: throw new NotSupportedException( $"{typeof(T).FullName} is not currently supported by this function."); } return (T)ret; }
Code:
private static bool Write<T>(T value, IntPtr hProcess, IntPtr dwBaseAddress, int[] offsets, bool IsRVA = false) { int bytesRead; if (IsRVA) { IntPtr ImageBaseAddress; if ((ImageBaseAddress = extGetProcessBaseAddress(hProcess)) == IntPtr.Zero) { return false; } dwBaseAddress = IntPtr.Add(dwBaseAddress, (int)ImageBaseAddress); } var buffer = new byte[4]; extReadMemory(hProcess, dwBaseAddress, buffer, 4, out bytesRead); for (int i = 0; i < offsets.Length - 1; i++) { dwBaseAddress = new IntPtr(BitConverter.ToInt32(buffer, 0) + offsets[i]); extReadMemory(hProcess, dwBaseAddress, buffer, 4, out bytesRead); } dwBaseAddress = new IntPtr(BitConverter.ToInt32(buffer, 0) + offsets[offsets.Length - 1]); var size = (uint)Marshal.SizeOf(typeof(T)); byte[] val = ToByteArray(value, size); IntPtr lpBytesWritten; bool retn = extWriteMemory(hProcess, dwBaseAddress, val, val.Length, out lpBytesWritten); return retn; }
Code:
public static void Main(string[] args) { var alefClients = Process.GetProcessesByName("alefclient"); if (alefClients.Length == 0) { Console.WriteLine("Archlord is not running."); return; } var client = alefClients[0]; IntPtr windowHandle = client.MainWindowHandle; if (windowHandle == IntPtr.Zero) { Console.WriteLine($"Could not get window handle of {client.Id}"); return; } IntPtr hProcess; if ((hProcess = extOpenProcess((uint)client.Id)) == IntPtr.Zero) { Console.WriteLine($"Could not open the process {client.Id}"); return; } IntPtr ImageSize; if ((ImageSize = extGetProcessImageSize(hProcess)) == IntPtr.Zero) { Console.WriteLine($"Could not get image size {client.Id}"); extCloseHandle(hProcess); return; } IntPtr ImageBaseAddress; if ((ImageBaseAddress = extGetProcessBaseAddress(hProcess)) == IntPtr.Zero) { Console.WriteLine($"Could not get image base address {client.Id}"); extCloseHandle(hProcess); return; } int currentBarIndex = Read<int>(hProcess, Defines.LocalBar, new[] { 0x1440 }, true); Console.WriteLine($"Current bar number: {currentBarIndex + 1}."); /* let's go up 1 bar */ byte keyUp = GetUpKey(); extSendMessageA(windowHandle, 0x100, keyUp, new IntPtr((MapVirtualKey(keyUp, 0) << 16) & 0x00FF0000)); /* wait a bit */ Thread.Sleep(50); currentBarIndex = Read<int>(hProcess, Defines.LocalBar, new[] { 0x1440 }, true); Console.WriteLine($"new bar number: {currentBarIndex + 1}."); /* we can set back the number through memory, however this wont update it graphically */ bool success = Write(currentBarIndex - 1, hProcess, Defines.LocalBar, new[] { 0x1440 }, true); if (success) { currentBarIndex = Read<int>(hProcess, Defines.LocalBar, new[] { 0x1440 }, true); Console.WriteLine($"We're back on bar {currentBarIndex + 1}."); } else { Console.Write($"Couldn't write the memory."); } string targetName = Read<string>(hProcess, Defines.AddressTargetBase, new[] { 0xca4, 0x5c, 0x54, 0x74, 0xb8, 0x0 }); if (targetName == string.Empty) { /* monsters have this set to null so lets grab their name */ targetName = Read<string>(hProcess, Defines.AddressTargetBase, new[] { 0xc94, 0x34, 0x30 }); } if (targetName != string.Empty) { Console.WriteLine($"Your target's name is: {targetName}"); } else { Console.WriteLine("You have no target."); } /* cleanup */ extCloseHandle(hProcess); }
For C/C++ you can just take a look at the source code and do whatever you like.
That'll be all, have fun; hope somebody makes tools out of this.
Update: added a nicer example for c#.