Hi all,
I post the source code for hook the endscene with blackmagic only on ASM injec, as GetName, Interact, Ctm, Lua doString inject.
This inject is not secure!!!
I do not guarantee operation to 100%
(Offset for WoW 3.3.5a)
Hook EndScene:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Magic;
using System.Threading;
namespace WowManager.Memory
{
public class Hook
{
// Addresse Inection code:
uint injected_code = 0;
uint addresseInjection = 0;
public bool threadHooked = false;
uint retnInjectionAsm = 0;
bool InjectionUsed = false;
public BlackMagic Memory = new BlackMagic();
public uint _processId = 0;
public Hook(uint processId)
{
_processId = processId;
Hooking();
}
public void Hooking()
{
// Offset:
uint DX_DEVICE = 0xC5DF88;
uint DX_DEVICE_IDX = 0x397C;
uint ENDSCENE_IDX = 0xA8;
// Process Connect:
if (!Memory.IsProcessOpen)
{
Memory.OpenProcessAndThread(_processId);
}
if (Memory.IsProcessOpen)
{
// Get address of EndScene
uint pDevice = Memory.ReadUInt(DX_DEVICE);
uint pEnd = Memory.ReadUInt(pDevice + DX_DEVICE_IDX);
uint pScene = Memory.ReadUInt(pEnd);
uint pEndScene = Memory.ReadUInt(pScene + ENDSCENE_IDX);
if (Memory.ReadByte(pEndScene) == 0xE9 && (injected_code == 0 || addresseInjection == 0)) // check if wow is already hooked and dispose Hook
{
DisposeHooking();
}
if (Memory.ReadByte(pEndScene) != 0xE9) // check if wow is already hooked
{
try
{
threadHooked = false;
// allocate memory to store injected code:
injected_code = Memory.AllocateMemory(2048);
// allocate memory the new injection code pointer:
addresseInjection = Memory.AllocateMemory(0x4);
Memory.WriteInt(addresseInjection, 0);
// allocate memory the pointer return value:
retnInjectionAsm = Memory.AllocateMemory(0x4);
Memory.WriteInt(retnInjectionAsm, 0);
// Generate the STUB to be injected
Memory.Asm.Clear(); // $Asm
// save regs
Memory.Asm.AddLine("pushad");
Memory.Asm.AddLine("pushfd");
// Test if you need launch injected code:
Memory.Asm.AddLine("mov eax, [" + addresseInjection + "]");
Memory.Asm.AddLine("test eax, eax");
Memory.Asm.AddLine("je @out");
// Launch Fonction:
Memory.Asm.AddLine("mov eax, [" + addresseInjection + "]");
Memory.Asm.AddLine("call eax");
// Copie pointer return value:
Memory.Asm.AddLine("mov [" + retnInjectionAsm + "], eax");
// Enter value 0 of addresse func inject
Memory.Asm.AddLine("mov edx, " + addresseInjection);
Memory.Asm.AddLine("mov ecx, 0");
Memory.Asm.AddLine("mov [edx], ecx");
// Close func
Memory.Asm.AddLine("@out:");
// load reg
Memory.Asm.AddLine("popfd");
Memory.Asm.AddLine("popad");
// injected code
uint sizeAsm = (uint)(Memory.Asm.Assemble().Length);
Memory.Asm.Inject(injected_code);
// Size asm jumpback
int sizeJumpBack = 5;
// copy and save original instructions
Memory.Asm.Clear();
Memory.Asm.AddLine("mov edi, edi");
Memory.Asm.AddLine("push ebp");
Memory.Asm.AddLine("mov ebp, esp");
Memory.Asm.Inject(injected_code + sizeAsm);
// create jump back stub
Memory.Asm.Clear();
Memory.Asm.AddLine("jmp " + (pEndScene + sizeJumpBack));
Memory.Asm.Inject(injected_code + sizeAsm + (uint)sizeJumpBack);
// create hook jump
Memory.Asm.Clear(); // $jmpto
Memory.Asm.AddLine("jmp " + (injected_code));
Memory.Asm.Inject(pEndScene);
}
catch { threadHooked = false; return; }
}
threadHooked = true;
}
}
public void DisposeHooking()
{
try
{
// Offset:
uint DX_DEVICE = 0xC5DF88;
uint DX_DEVICE_IDX = 0x397C;
uint ENDSCENE_IDX = 0xA8;
// Get address of EndScene:
uint pDevice = Memory.ReadUInt(DX_DEVICE);
uint pEnd = Memory.ReadUInt(pDevice + DX_DEVICE_IDX);
uint pScene = Memory.ReadUInt(pEnd);
uint pEndScene = Memory.ReadUInt(pScene + ENDSCENE_IDX);
if (Memory.ReadByte(pEndScene) == 0xE9) // check if wow is already hooked and dispose Hook
{
// Restore origine endscene:
Memory.Asm.Clear();
Memory.Asm.AddLine("mov edi, edi");
Memory.Asm.AddLine("push ebp");
Memory.Asm.AddLine("mov ebp, esp");
Memory.Asm.Inject(pEndScene);
}
// free memory:
Memory.FreeMemory(injected_code);
Memory.FreeMemory(addresseInjection);
Memory.FreeMemory(retnInjectionAsm);
} catch {}
}
public byte[] InjectAndExecute(string[] asm, int returnLength = 0)
{
while (InjectionUsed)
{ Thread.Sleep(5); }
InjectionUsed = true;
// Hook Wow:
Hooking();
byte[] tempsByte = new byte[0];
// reset return value pointer
Memory.WriteInt(retnInjectionAsm, 0);
if (Memory.IsProcessOpen && threadHooked)
{
// Write the asm stuff
Memory.Asm.Clear();
foreach (string tempLineAsm in asm)
{
Memory.Asm.AddLine(tempLineAsm);
}
// Allocation Memory
uint injectionAsm_Codecave = Memory.AllocateMemory(Memory.Asm.Assemble().Length);
try
{
// Inject
Memory.Asm.Inject(injectionAsm_Codecave);
Memory.WriteInt(addresseInjection, (int)injectionAsm_Codecave);
while (Memory.ReadInt(addresseInjection) > 0) { Thread.Sleep(5); } // Wait to launch code
if (returnLength > 0)
{
tempsByte = Memory.ReadBytes(Memory.ReadUInt(retnInjectionAsm), returnLength);
}
else
{
byte Buf = new Byte();
List<byte> retnByte = new List<byte>();
uint dwAddress = Memory.ReadUInt(retnInjectionAsm);
Buf = Memory.ReadByte(dwAddress);
while (Buf != 0)
{
retnByte.Add(Buf);
dwAddress = dwAddress + 1;
Buf = Memory.ReadByte(dwAddress);
}
tempsByte = retnByte.ToArray();
}
}
catch { }
// Free memory allocated
Memory.FreeMemory(injectionAsm_Codecave);
}
InjectionUsed = false;
// return
return tempsByte;
}
}
}
Create new instance:
Code:
MyHook = new Hook(processId);
Lua DoString:
Code:
public static void LuaDoString(string command)
{
// Allocate memory
uint DoStringArg_Codecave = MyHook.Memory.AllocateMemory(Encoding.UTF8.GetBytes(command).Length + 1);
// offset:
FrameScript__Execute = 0x819210;
// Write value:
MyHook.Memory.WriteBytes(DoStringArg_Codecave, Encoding.UTF8.GetBytes(command));
// Write the asm stuff for Lua_DoString
String[] asm = new String[]
{
"mov eax, " + DoStringArg_Codecave,
"push 0",
"push eax",
"push eax",
"mov eax, " + (uint)FrameScript__Execute, // Lua_DoString
"call eax",
"add esp, 0xC",
"retn",
};
// Inject
MyHook.InjectAndExecute(asm);
// Free memory allocated
MyHook.Memory.FreeMemory(DoStringArg_Codecave);
}
GetLocalizedText:
Code:
public static string GetLocalizedText(string Commandline)
{
// Command to send using LUA
String Command = Commandline;
// Allocate memory for command
uint Lua_GetLocalizedText_Space = MyHook.Memory.AllocateMemory(Encoding.UTF8.GetBytes(Command).Length + 1);
// offset:
uint ClntObjMgrGetActivePlayerObj = 0x4038F0;
uint FrameScript__GetLocalizedText = 0x7225E0;
// Write command in the allocated memory
MyHook.Memory.WriteBytes(Lua_GetLocalizedText_Space, Encoding.UTF8.GetBytes(Command));
String[] asm = new String[]
{
"call " + (uint)ClntObjMgrGetActivePlayerObj,
"mov ecx, eax",
"push -1",
"mov edx, " + Lua_GetLocalizedText_Space + "",
"push edx",
"call " + (uint)FrameScript__GetLocalizedText,
"retn",
};
// Inject the shit
string sResult = Encoding.ASCII.GetString(MyHook.InjectAndExecute(asm));
// Free memory allocated for command
MyHook.Memory.FreeMemory(Lua_GetLocalizedText_Space);
// Uninstall the hook
return sResult;
}
Use Lua DoString + GetLocalizedText:
Code:
public static int GetContainerNumFreeSlots()
{
LuaDoString("freeslots = GetContainerNumFreeSlots(0) + GetContainerNumFreeSlots(1) + GetContainerNumFreeSlots(2) + GetContainerNumFreeSlots(3) + GetContainerNumFreeSlots(4)");
return Convert.ToInt32(GetLocalizedText("freeslots"));
}
Click To Move:
Code:
public static void CGPlayer_C__ClickToMove(Single x, Single y, Single z, UInt64 guid, Int32 action, Single precision)
{
// Allocate Memory:
UInt32 Pos_Codecave = MyHook.Memory.AllocateMemory(0x4 * 3);
UInt32 GUID_Codecave = MyHook.Memory.AllocateMemory(0x8);
UInt32 Precision_Codecave = MyHook.Memory.AllocateMemory(0x4);
// Offset:
uint CGPlayer_C__ClickToMove = 0x727400;
uint ClntObjMgrGetActivePlayerObj = 0x4038F0;
// Write value:
MyHook.Memory.WriteUInt64(GUID_Codecave, guid);
MyHook.Memory.WriteFloat(Precision_Codecave, precision);
MyHook.Memory.WriteFloat(Pos_Codecave, x);
MyHook.Memory.WriteFloat(Pos_Codecave + 0x4, y);
MyHook.Memory.WriteFloat(Pos_Codecave + 0x8, z);
// BOOL __thiscall CGPlayer_C__ClickToMove(WoWActivePlayer *this, CLICKTOMOVETYPE clickType, WGUID *interactGuid, WOWPOS *clickPos, float precision)
string[] asm = new string[]
{
"mov edx, [" + Precision_Codecave + "]",
"push edx",
"call " + (uint)ClntObjMgrGetActivePlayerObj,
"mov ecx, eax",
"push " + Pos_Codecave,
"push " + GUID_Codecave,
"push " + action,
"call " + (uint)CGPlayer_C__ClickToMove,
"retn",
};
MyHook.InjectAndExecute(asm);
MyHook.Memory.FreeMemory(Pos_Codecave);
MyHook.Memory.FreeMemory(GUID_Codecave);
MyHook.Memory.FreeMemory(Precision_Codecave);
}
GetName:
Code:
public static string GetName(uint BaseAddress)
{
GetNameVMT = 54;
string sResult = "";
uint VMT = MyHook.Memory.ReadUInt((MyHook.Memory.ReadUInt(BaseAddress) + ((uint)GetNameVMT * 4)));
string[] asm = new string[]
{
"mov ecx, " + BaseAddress,
"mov eax, " + VMT,
"call eax",
"retn",
};
sResult = Encoding.ASCII.GetString(MyHook.InjectAndExecute(asm));
return sResult;
}
Interact:
Code:
public static void InteractGameObject(uint baseAddress)
{
uint InteractVMT = 44;
if (baseAddress > 0)
{
uint VMT44 = MyHook.Memory.ReadUInt(MyHook.Memory.ReadUInt(baseAddress) + ((uint)InteractVMT * 4));
var objectManagerBase = 0x2ED0;
string[] asm = new string[]
{
"fs mov eax, [0x2C]",
"mov eax, [eax]",
"add eax, 0x10",
"mov dword [eax], " + objectManagerBase,
"mov ecx, " + baseAddress,
"call " + VMT44,
"retn",
};
MyHook.InjectAndExecute(asm);
}
}
Sample projet: http://www.multiupload.com/TAWE0RFMWL
Why is the hook endscene?
To not do detect on public project, because if you want you can hook any function that it will work. Programs other than the bot Hook endscene like Fraps for video capture, Ventrilo to see who speaks in the game, xfire ... and also make a jmp, so the warden can not tell whether the jmp to this function and to jmp a legal software or not (this is the software required to hook the endscene to add graphic elements to the game).
I want to thank Jujuboss and mdperdu for their help.