# Forum > World of Warcraft > World of Warcraft Bots and Programs > WoW Memory Editing >  [Sample Code] EndScene Hook with ASM and blackmagic

## RivaLfr

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:*


```
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:*


```
MyHook = new Hook(processId);
```

*Lua DoString:*


```
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:*


```
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:*


```
        public static int GetContainerNumFreeSlots()
        {
            LuaDoString("freeslots = GetContainerNumFreeSlots(0) + GetContainerNumFreeSlots(1) + GetContainerNumFreeSlots(2) + GetContainerNumFreeSlots(3) + GetContainerNumFreeSlots(4)");
            return Convert.ToInt32(GetLocalizedText("freeslots"));
        }
```

*Click To Move:*


```
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:*


```
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:*


```
      
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.*

----------


## Steveiwonder

Excellent, i need something like this to get started on injection (not that there isn't a million other things on ).

Ty

----------


## streppel

great post,thanks for this even tho my bot already had it,+rep  :Smile:

----------


## Cypher

"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)."

Actually, Warden COULD detect that if it wanted. Last time I checked, PunkBuster has a hook whitelist for 'known' legitimate software (Fraps, Xfire, etc) and kicks if your hook does not match an entry in the whitelist.

What you mean to say is that whilst it could, it doesn't.  :Wink:

----------


## namreeb

Interesting. What data does it use to check a hook against this whitelist? The code at the function it jumps to? That seems rather unreliable.

----------


## Chinchy

> Interesting. What data does it use to check a hook against this whitelist? The code at the function it jumps to? That seems rather unreliable.


It's reliable as it needs to be. There is a reason PB only kicks for it rather than bans.

----------


## RivaLfr

Thank for this info Cypher, but if the warden detect all endscene hook, a lot of video capture software not work by sample. They can not make a white list for all software that exists, and can not prohibit the capture of video.

To protect the code you need your random injection, so that the warden can not make a pattern.

The injection is always risky on the public projects, even if the injection is protected.

----------


## RivaLfr

> /facepalm
> 
> 
> 
> 10 points to Gryffindor!


I'm not saying I'm right, I said just my point of view, after listening to what you said.

I post this code because it can be useful.

----------


## Cypher

> I'm not saying I'm right, I said just my point of view, after listening to what you said.
> 
> I post this code because it can be useful.


Your 'opinion' is irrelevant though. I wasn't giving my opinion on the functionality being implemented into Warden, I was simply stating facts and correcting an error in your post (i.e. that such functionality DOES in fact exist in other live and widespread AC systems and it would be quite possible to implement it in Warden).

Tl;dr: Nobody cares. (Or at least, I don't.)

----------


## RivaLfr

Ok, no problem, thank you for your contribution Cypher.

----------


## Seifer

Basically what Cypher is saying is that it's about as secure as cheating on your wife in her bedroom, while she's asleep. Literally.

----------


## RivaLfr

Sample projet:

http://www.multiupload.com/TAWE0RFMWL

----------


## DamonT

> 


Did you ever notice the "MOV EDI,EDI" instruction in the beginning? It seems to be useless... but there's a reason for it.
I'd really like to see anybody using this to make a "cleaner" hook instead of overwriting the stackframe creation.

Here's the example:

Note: if you'll use a CALL, you have to change/increase the return address since it will end up in an infinite loop  :Wink: 

Also keep in mind that offset scanning is not warden's only way to detect hacks...

----------


## KuRIoS

Stop posting the pathetic pics we do not allow them for a reason. 
Only thing they are good for is starting spam - grow up.

----------


## RivaLfr

Stop spamming me of PM.

Go to this post for the last offset: http://www.mmowned.com/forums/world-...ml#post1977673

And added the addres of the Wow.exe module at all Wow function in asm code and at DX_DEVICE.

----------


## Ozius

The code turns out now should look so?:
*code:*


```
using System;
using System.Threading;
using Magic;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;

namespace ConsoleApplication2
{
    class Program
    {
        static Hook MyHook = null;
        static uint AddAdr;
        static void Main(string[] args)
        {
            Process[] Processes = Process.GetProcessesByName("Wow");
            if (Processes.Length > 0)
            {
                Console.WriteLine("Select wow process " + Processes[0].Id);

                AddAdr = (uint)BaseAdress((int)Processes[0].Id);

                MyHook = new Hook((uint)Processes[0].Id, AddAdr);
                Console.WriteLine("Hook statut: " + MyHook.threadHooked);
		
                if (MyHook.threadHooked)
                {
                    LuaDoString("DoEmote(\"Dance\");");//DoEmote("cry");
                    Console.WriteLine("INJECT LuaDoString(\"DoEmote(\"Dance\");\")");

                   // LuaDoString("freeslots = GetContainerNumFreeSlots(0) + GetContainerNumFreeSlots(1) + GetContainerNumFreeSlots(2) + GetContainerNumFreeSlots(3) + GetContainerNumFreeSlots(4)");
                   // Console.WriteLine("Free bag slots " + Convert.ToInt32(GetLocalizedText("freeslots")));

                    MyHook.DisposeHooking();
                    Console.WriteLine("Dispose Hooking");
                }
            }
            else
                Console.WriteLine("WoW process no found.");
            Console.ReadKey();
        }

        private static Int32 BaseAdress(Int32 IdProcess)
        {
            ProcessModuleCollection modules = Process.GetProcessById(IdProcess).Modules;
            for (int i = 0; i < modules.Count; i++)
            {
                if (modules[i].ModuleName.ToLower() == "wow.exe")
                {
                    return (int)modules[i].BaseAddress;
                }
            }
            return 0;
        }

        public static void LuaDoString(string command)
        {
            // Allocate memory
            uint DoStringArg_Codecave = MyHook.Memory.AllocateMemory(Encoding.UTF8.GetBytes(command).Length + 1);
            // offset:
            uint FrameScript__Execute = 0x395960 + AddAdr;


            // 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);
        }

        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 = 0x3480 + AddAdr;
            uint FrameScript__GetLocalizedText = 0x1C19F0 + AddAdr;

            // 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;
        }
    }

    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;
        uint AddAdr;
        public Hook(uint processId,uint Добавочный)
        {
            _processId = processId;
            this.AddAdr = Добавочный;//(uint)BaseAdress((int)_processId);
            Hooking();
        }
        
        public void Hooking()
        {
            // Offset:
            uint DX_DEVICE = 0x971094 + AddAdr;
            uint DX_DEVICE_IDX = 0x27B4;
            uint ENDSCENE_IDX = 0xAC;

            // Process Connect:
            if (!Memory.IsProcessOpen)
            {
                
                Memory = new BlackMagic((int)_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, ebx");
                        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 = 0x971094 + AddAdr;
                uint DX_DEVICE_IDX = 0x27B4;
                uint ENDSCENE_IDX = 0xAC;
            
                // 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)
        {
            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



                        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;
        }
    }
}
```

Has changed that that you have written, but there is a cycling:


```
while (Memory.ReadInt(addresseInjection) > 0) { Thread.Sleep(5); } // Wait to launch code
```

In what there can be a problem?

P.S.: I am sorry for my English  :Smile:

----------


## mongoosed

This example was amazingly helpful for showing me how hooking through C# and blackmagic is usually done, and how to hook into endscene. Thank you very much!

----------


## Millow

Tried to make it work, never managed to. Tried the other Endscene example, never managed to either, useless evening I guess, learned some things, but nothing works.


```

uint pDevice = Memory.ReadUInt(BaseAddress + DX_DEVICE);
uint pEnd = Memory.ReadUInt(pDevice + DX_DEVICE_IDX);
uint pScene = Memory.ReadUInt(pEnd);
uint pEndScene = Memory.ReadUInt(pScene + ENDSCENE_IDX);
```

Get a ReadUInt failed for pEnd, can't figure out why, shame....Anybody can give me a pointer ?

I saw miceiken do a double read in his MBot, I was wondering why you would ever do a double read ? I saw a post about it some times ago, can't seem to find it. Anyhow, amazing forum, but still, I progress slowly, but one day I hope to freakin be able to hook endscene and get some stuff done !

----------


## HeroXx

What offsets are you using?

----------


## fukmeimbroken

> What offsets are you using?




```
                uint DX_DEVICE = 0x971094;
                uint DX_DEVICE_IDX = 0x27B4;
                uint ENDSCENE_IDX = 0xAC;
```

This are the offsets I use i get no error at this part

uint pDevice = Memory.ReadUInt(BaseAddress + DX_DEVICE);
uint pEnd = Memory.ReadUInt(pDevice + DX_DEVICE_IDX);
uint pScene = Memory.ReadUInt(pEnd);
 uint pEndScene = Memory.ReadUInt(pScene + ENDSCENE_IDX);

but I get the same Loop as Ozius. Is there something else I have to Update in the source?

----------


## Flowerew

> ```
>                 uint DX_DEVICE = 0x971094;
>                 uint DX_DEVICE_IDX = 0x27B4;
>                 uint ENDSCENE_IDX = 0xAC;
> ```
> 
> This are the offsets I use i get no error at this part
> 
> uint pDevice = Memory.ReadUInt(BaseAddress + DX_DEVICE);
> ...


Isn't EndScene 0xA8 aka VMT[42]?!

----------


## _Mike

> Isn't EndScene 0xA8 aka VMT[42]?!


Yes. (filler)

----------


## Millow

```
public Hook(uint processId)
{
_processId = processId;
this.BaseAddress = (uint)_processId;
Hooking();
}
// Offset:
uint DX_DEVICE = BaseAddress + 0x971094;
uint DX_DEVICE_IDX = 0x27B4;
uint ENDSCENE_IDX = 0xA8;

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);
```

I still get a mistake at the pEnd line, anyone kind enough to enlighten me on this one ?

----------


## Chinchy

> ```
> public Hook(uint processId)
> {
> _processId = processId;
> this.BaseAddress = (uint)_processId;
> Hooking();
> }
> // Offset:
> uint DX_DEVICE = BaseAddress + 0x971094;
> ...


Your addresses are wrong for the current patch, if you're trying with 13287.

----------


## Millow

They should be right, used the new offsets from the 4.0.3 Wow - Offsets thread.

----------


## Chinchy

DevicePointer = 0x0097E7F4; //4.0.3.13287
_DevicePointer = 0x27B4; //4.0.3.13287
EndScene = 0xAC; //4.0.3.13287

The addresses in the quote are from 13205. Otherwise, make sure that the BaseAddress references the MainModule of the process.

Edit:
What the guy below me said.

----------


## _Mike

> ```
> this.BaseAddress = (uint)_processId;
> ```
> 
> I still get a mistake at the pEnd line, anyone kind enough to enlighten me on this one ?


That's your problem.

----------


## Millow

Thanx _Mike, I supposed that it was my problem, so I looked it up and dit this.

```

Process[] Processes = Process.GetProcessesByName("Wow");
ProcessModule pm = Processes[0].MainModule;
Console.WriteLine(pm.BaseAddress + ":" + Processes[0].Id);
Console.ReadLine();

```

Now I see the base address, I suppose it's the good one.


```

uint DX_DEVICE = BaseAddress + 0x971094;
uint DX_DEVICE_IDX = 0x27B4;
uint ENDSCENE_IDX = 0xA8;
```

Still no luck, can't get past the pEnd code described above, uint read failed. I tried looking in IDA for the DX_DEVICE_IDX offset, but with no luck, I need a few more tutorial, because aside from strings I can't find anything.

Edit: Finally got passed through the pEnd error, but now stuck at pScene....damn. used the addresses that Chinchy gave 
uint DX_DEVICE = BaseAddress + 0x0097E7F4;

Any pointers appreciated.

----------


## Chinchy

> Thanx _Mike, I supposed that it was my problem, so I looked it up and dit this.
> 
> ```
> 
> Process[] Processes = Process.GetProcessesByName("Wow");
> ProcessModule pm = Processes[0].MainModule;
> Console.WriteLine(pm.BaseAddress + ":" + Processes[0].Id);
> Console.ReadLine();
> 
> ...


Wrong addresses. I even posted the correct ones in this very thread...

----------


## Millow

Yes indeed, weird though, I had taken them from the Offset thread. Thx for the pointer. But still, something is wrong. Same problem. Device_IDX seems wrong, if you get this code working, hats off. Thanx for the help.

----------


## _Mike

> EndScene = 0xAC; //4.0.3.13287


EndScene is 0xA8. 0xAC is Clear

----------


## RivaLfr

public enum DirectX //4.0.3.13287
{
DX_DEVICE = 0x97E7F4,
DX_DEVICE_IDX = 0x27C4,
ENDSCENE_IDX = 0xA8,
}

----------


## Millow

Thx, it works now, with the new DX_Device_IDX it works. At least I was right about something !

----------


## Cypher

> EndScene is 0xA8. 0xAC is Clear


I think it's funny he has it tagged for the patch. Your WoW version means nothing, it's an offset which is tied to a D3D version, lol.

----------


## _Mike

> I think it's funny he has it tagged for the patch. Your WoW version means nothing, it's an offset which is tied to a D3D version, lol.


Indeed, and to be even more specific; The vmt indices are the same for all D3D9 versions.

----------


## fukmeimbroken

> Thx, it works now, with the new DX_Device_IDX it works. At least I was right about something !


Did you get the LuaDoString running too?

----------


## Millow

Nope,

Not yet, at this point, I will have to learn some IDA to learn how to replicate the lua dostring in ASM. Cypher I think, said that to find Dostring in IDA you has to look at the last function of Runscript, I've looked at runscript, no success yet. If anyone has pointers to help me learn how to find lua dostring in IDA, I'm all ears, I want to learn stuff so one day, like 1 year, I can post my first contribution....

fukmeimbroken, if you figure something out, pm me ! I'll do the same.

----------


## Scorpiona

> Nope,
> 
> Not yet, at this point, I will have to learn some IDA to learn how to replicate the lua dostring in ASM. Cypher I think, said that to find Dostring in IDA you has to look at the last function of Runscript, I've looked at runscript, no success yet. If anyone has pointers to help me learn how to find lua dostring in IDA, I'm all ears, I want to learn stuff so one day, like 1 year, I can post my first contribution....
> 
> fukmeimbroken, if you figure something out, pm me ! I'll do the same.


Try looking over my examples from back when I used ahook.

----------


## Millow

> Try looking over my examples from back when I used ahook.


Thx, I'll look into that, for your assembly code, did you look in IDA or you just based it on other people's code ?
Anybody knows if the assembly code could change from patch to patch (noob question) ?

----------


## Scorpiona

> Thx, I'll look into that, for your assembly code, did you look in IDA or you just based it on other people's code ?
> Anybody knows if the assembly code could change from patch to patch (noob question) ?


Yes, it's 100% copypasta, I not know of this 'IDA' you speak.

Read this and then look at the call sites of _FrameScript__Execute_. Like _lua_RunScript_ ...Yes, it can change from patch to patch

----------


## Chinchy

> I think it's funny he has it tagged for the patch. Your WoW version means nothing, it's an offset which is tied to a D3D version, lol.


I use 42*4. I fat fingered 43*4 into the calculator when I was posting that. =(

----------


## fukmeimbroken

> Yes, it's 100% copypasta, I not know of this 'IDA' you speak.
> 
> Read this and then look at the call sites of _FrameScript__Execute_. Like _lua_RunScript_ ...Yes, it can change from patch to patch


Ida is a well known disassembler  :Smile: . Thx looking into your link. Seem kinda harder then my old way of reading some memory hehe  :Smile: .




> fukmeimbroken, if you figure something out, pm me ! I'll do the same.


Okay I'll do.

----------


## Cypher

> Indeed, and to be even more specific; The vmt indices are the same for all D3D9 versions.


Yeah, lol. By "D3D versions" I meant 8, 9, 10, etc.




> I use 42*4. I fat fingered 43*4 into the calculator when I was posting that. =(


Slightly more correct:
42 * sizeof(void*)

 :Stick Out Tongue:

----------


## Ozius

I can not understand where I have committed an error, like have changed all offsets an.d have added BaseAddress but all the same doesn't work.
*Main:*


```
static void Main(string[] args)
        {
            Process[] Processes = Process.GetProcessesByName("Wow");
            ProcessModule pm = Processes[0].MainModule;
            
            Console.WriteLine(pm.BaseAddress);
            
            if (Processes.Length > 0)
            {
                Console.WriteLine("Select wow process " + Processes[0].Id);

                BaseAddress = (uint)pm.BaseAddress;

                MyHook = new Hook((uint)Processes[0].Id, BaseAddress);
                Console.WriteLine("Hook statut: " + MyHook.threadHooked);
		
                if (MyHook.threadHooked)
                {
                    LuaDoString("DoEmote(\"Dance\")");
                    Console.WriteLine("INJECT LuaDoString(\"DoEmote(\"Dance\")\")");

                    MyHook.DisposeHooking();
                    Console.WriteLine("Dispose Hooking");
                }
            }
            else
                Console.WriteLine("WoW process no found.");
            Console.ReadKey();
        }
```

*Offsets DirectX:*


```
            //4.0.3.13287
            uint DX_DEVICE = 0x97E7F4+BaseAddress;
            uint DX_DEVICE_IDX = 0x27C4;
            uint ENDSCENE_IDX = 0xA8;
```

*Other offsets:*


```
FrameScript__Execute = 0x39D7F0;
```

Doesn't dance. Help me plz....  :Frown:

----------


## Millow

Do you get it hooked ?

----------


## Ozius

Yes, Hook statut: true
The problem arises at performance LuaDoString->MyHook.InjectAndExecute(asm).
There is a cycling in line: while (Memory.ReadInt(addresseInjection) > 0) { Thread.Sleep(5); } // Wait to launch code

*LuaDoString*


```
public static void LuaDoString(string command)
        {
            // Allocate memory
            uint DoStringArg_Codecave = MyHook.Memory.AllocateMemory(Encoding.UTF8.GetBytes(command).Length + 1);
            // offset:
            uint FrameScript__Execute = 0x39D7F0;


            // 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);
        }
```

Tried to make so: uint FrameScript__Execute = 0x39D7F0 + BaseAdress;
Hasn't helped. ..
Thanks for the help.

----------


## CrimeTime

```
public static void LuaDoString(string command)
        {
            // Allocate memory
            uint DoStringArg_Codecave = MyHook.Memory.AllocateMemory(Encoding.UTF8.GetBytes(command).Length + 1);
            // offset:
            uint FrameScript__Execute = 0x39D7F0;


            // 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)BaseAdress+(uint)FrameScript__Execute), // Lua_DoString
                
                "call eax",
                "add esp, 0xC",
                "retn",    
            };

            // Inject
            MyHook.InjectAndExecute(asm);
            // Free memory allocated 
            MyHook.Memory.FreeMemory(DoStringArg_Codecave);
        }
```

should work now fine  :Smile:

----------


## Ozius

Doesn't work, already all has tried... 
Program.cs: http://dl.dropbox.com/u/7381029/Program.cs

----------


## CrimeTime

dont use 
uint ENDSCENE_IDX = 0xA8;*
use:
uint ENDSCENE_IDX = 0xAC;
( You have to change it two times!)
*

----------


## fukmeimbroken

> dont use 
> uint ENDSCENE_IDX = 0xA8;*
> use:
> uint ENDSCENE_IDX = 0xAC;
> ( You have to change it two times!)
> *


Still the same.

----------


## CrimeTime

no if i had use the 0xA8 it doesnt worked for me, then i've tried it with 0xAC and it work for me  :Wink:

----------


## fukmeimbroken

> no if i had use the 0xA8 it doesnt worked for me, then i've tried it with 0xAC and it work for me


Yes the Hook seems to work with both but Lua Do String doesn't works with both. Must be a mistake somewhere.

----------


## Millow

The address of endscene in the VMT is 42, 42*4 = 168 = 0xA8. I will have to try when I get home, but if it works with 0xAC and 0xA8, then there's something wrong for sure with the hook. CrimeTime, do you mean your hook works or that you saw your character dance on the screen ? Because I can't see how that's possible if you use 0xAC.

Anyhow, I might be wrong.

----------


## CrimeTime

tested before a Minute 

```
LuaDoString("DoEmote(\"Dance\")");
```

 works for me  :Wink:

----------


## fukmeimbroken

> tested before a Minute 
> 
> ```
> LuaDoString("DoEmote(\"Dance\")");
> ```
> 
>  works for me


Woot the ****? And if you check his Code http://dl.dropbox.com/u/7381029/Program.cs the only difference is the 0xA8 / 0xAC?

----------


## JuJuBoSc

> The address of endscene in the VMT is 42, 42*4 = 168 = 0xA8. I will have to try when I get home, but if it works with 0xAC and 0xA8, then there's something wrong for sure with the hook. CrimeTime, do you mean your hook works or that you saw your character dance on the screen ? Because I can't see how that's possible if you use 0xAC.
> 
> Anyhow, I might be wrong.


Because 0xAC is Clear func and can be hooked the same way, and is called every frame too.

----------


## Millow

> Because 0xAC is Clear func and can be hooked the same way, and is called every frame too.


All right, thx for the info.
But I've just tried his code and doesn't work for me, I will have to call this BS (the fact that he got this working) unless someone proves otherwise to me.

fukme ? Does it work for you ?

----------


## CrimeTime

have someone got the code to get a return of a DoString?

----------


## fukmeimbroken

No millow sry :/.




> have someone got the code to get a return of a DoString?


Me and millow doesn't even get the DoString to work may you share your Code with us.

----------


## CrimeTime

i've post all to fix it all what Millow and you got to do is put it in your code.
If there are still errors post it here.

now to my Problem:
i try to get a Return of the LuaDostring with this


```
                    LuaDoString("test = CanSendAuctionQuery()");
                    test = GetLocalizedText("test");
```

here the GetLocalizedText Function:


```
 public static string GetLocalizedText(string Commandline)
        {
            // Command to send using LUA
            String Command = Commandline;
            var proc = Process.GetProcessesByName("Wow");
            IntPtr WoWBase = proc[0].MainModule.BaseAddress;
            // Allocate memory for command
            uint Lua_GetLocalizedText_Space = MyHook.Memory.AllocateMemory(Encoding.UTF8.GetBytes(Command).Length + 1);

            // offset:
            uint ClntObjMgrGetActivePlayerObj = 0x93AD0;
            uint FrameScript__GetLocalizedText = 0x1C4190;

            // Write command in the allocated memory
            MyHook.Memory.WriteBytes(Lua_GetLocalizedText_Space, Encoding.UTF8.GetBytes(Command));

            String[] asm = new String[] 
            {
            "call " + ((uint)WoWBase + ClntObjMgrGetActivePlayerObj),
            "mov ecx, eax",
            "push -1",
            
            "mov edx, " + Lua_GetLocalizedText_Space,
            "push edx",
            
            "call " + ((uint)WoWBase + 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;
        }
```

Wow Crashes me after string sResult = Encoding.ASCII.GetString(MyHook.InjectAndExecute(asm));

----------


## sPeC!

> Because 0xAC is Clear func and can be hooked the same way, and is called every frame too.


I have spent some time debugging because of this one some days ago, only to find that using 0xAC was making CheckPermissions fail when trying to use protected lua functions. 
0xA8 is the correct index.

Cheers,
Edit: Posted wrong info!

----------


## CrimeTime

could kiss you, it works  :Big Grin:

----------


## _Mike

> Because 0xAC is Clear func and can be hooked the same way, and is called every frame too.


Yes it works, but there's 3 calls to Clear() per frame so the performance hit is bigger than hooking EndScene.

----------


## Millow

To whoever trying to get this to work and it does not work, http://www.mmowned.com/forums/world-...ne-hook-3.html go there.
I've used ahook and updated the console app to get it working ! I never managed to get the version of the hook in this thread working, so I used Ahook.
Credits goes to Juju for the DLL (source someday plz ? ) and RivaLFr for some of the the memory reading code !
Enjoy

PS: fukmeimbroken, ur pm box is full, tried pming you to no avail !  :Smile:

----------


## CrimeTime

still have Problems with the GetLocalizedText!
im trying to get data out of the Auctionhouse with this code:


```
                    LuaDoString("Totauctions = GetNumAuctionItems(\"list\")");
                    Totauctions = GetLocalizedText("Totauctions");
```

but all what i get back is "5" (i have search at AH before i have used the code)
i mean i should get much more data as only the "5" = 5 Auctions.

someone a Idea what im doing wrong?

Greets CrimeTime

----------


## miceiken

> still have Problems with the GetLocalizedText!
> im trying to get data out of the Auctionhouse with this code:
> 
> 
> ```
>                     LuaDoString("Totauctions = GetNumAuctionItems(\"list\")");
>                     Totauctions = GetLocalizedText("Totauctions");
> ```
> 
> ...




```
  numBatchAuctions, totalAuctions = GetNumAuctionItems("list")
```

GetNumAuctionItems - World of Warcraft Programming: A Guide and Reference for Creating WoW Addons

----------


## Ozius

Tried to use ENDSCENE_IDX = 0xAC;//0xA8;
Doesn't work. Can somehow influences that I use the russian wow?
edit file: http://dl.dropbox.com/u/7381029/Program2.cs

----------


## fukmeimbroken

> Tried to use ENDSCENE_IDX = 0xAC;//0xA8;
> Doesn't work. Can somehow influences that I use the russian wow?
> edit file: http://dl.dropbox.com/u/7381029/Program2.cs


We didn'T get it work too. Take a look into AHook http://www.mmowned.com/forums/world-...ne-hook-3.html ([C# DLL] aHook, use ASM through EndScene hook) like millow said, worked for us.

----------


## CrimeTime

> ```
>   numBatchAuctions, totalAuctions = GetNumAuctionItems("list")
> ```
> 
> GetNumAuctionItems - World of Warcraft Programming: A Guide and Reference for Creating WoW Addons


thanks that works, but i see i have write the wrong problem, the current problem is 


```
            LuaDoString("count = GetAuctionItemInfo(\"list\"," + index + ")");
            return GetLocalizedTextInt("count");
```

i get only the Name of the Item, and not the other Data, i've see that some people do Split the incoming Data but i cant Split something because i get only the Name and not the full Data String.

Edit: Got it workin, a shame that i didnt know how to do that ^^

----------


## Millow

Anyone knows what the step variable stands for ? It's equal to 0xE9 and is used to determine if the process is hooked.

----------


## Scorpiona

> Anyone knows what the step variable stands for ? It's equal to 0xE9 and is used to determine if the process is hooked.


0xE9 is JMP. It's checking if the detour has been applied.

----------


## reggggg

nevermind I worked it out  :Stick Out Tongue: 

Might as well post what my problem was. I couldn't figure out why the OP was adding 0xc to the stack pointer in DoString. Turns out you need to increment the sp by the size of the parameter list for the stack pointer to be in the right place and for code to to keep going smoothly, or something? I needed to do the same thing for ConsoleWriteA("lala", 4) and ended up adding 0x8 to esp for the char* and int, or execution would screw up afterwards.

----------


## Ozius

> nevermind I worked it out 
> 
> Might as well post what my problem was. I couldn't figure out why the OP was adding 0xc to the stack pointer in DoString. Turns out you need to increment the sp by the size of the parameter list for the stack pointer to be in the right place and for code to to keep going smoothly, or something? I needed to do the same thing for ConsoleWriteA("lala", 4) and ended up adding 0x8 to esp for the char* and int, or execution would screw up afterwards.


Hasn't understood, where it is necessary to add?
Specify please a line.  :Frown:

----------


## FenixTX2

The original 'Hooking()" function was wrong. There was an error in the ASM.



```
        application.Asm.Clear();

        application.Asm.AddLine("mov edi, edi");
        application.Asm.AddLine("push ebp");
        application.Asm.AddLine("mov ebp, esp");

        application.Asm.AddLine("pushfd");
        application.Asm.AddLine("pushad");
                    
        //Test for waiting code
        application.Asm.AddLine("mov eax, [" + addresseInjection + "]");
        application.Asm.AddLine("test eax, ebx");
        application.Asm.AddLine("je @out");

        //Execute waiting code
        application.Asm.AddLine("mov eax, [" + addresseInjection + "]");
        application.Asm.AddLine("call eax");

        //Copy pointer to return value
        application.Asm.AddLine("mov [" + retnInjectionAsm + "], eax");

        application.Asm.AddLine("mov edx, " + addresseInjection);
        application.Asm.AddLine("mov ecx, 0");
        application.Asm.AddLine("mov [edx], ecx");

        //Close Function
        application.Asm.AddLine("@out:");

        //Inject Code
        uint sizeAsm = (uint)(application.Asm.Assemble().Length);

        application.Asm.Inject(injected_code);

        int sizeJumpBack = 5;

        // create jump back stub
        application.Asm.Clear();
        application.Asm.AddLine("jmp " + (pEndScene + sizeJumpBack));
        application.Asm.Inject(injected_code + sizeAsm);// + (uint)sizeJumpBack);

        // create hook jump
        application.Asm.Clear(); // $jmpto
        application.Asm.AddLine("jmp " + (injected_code));
        application.Asm.Inject(pEndScene);
```

----------


## Ozius

*FenixTX2*, thx.
Has corrected the code as you have offered. Cycling in the same place: 


```
while (Memory.ReadInt(addresseInjection) > 0) { Thread.Sleep(5); } // Wait to launch code
```

The code entirely: http://dl.dropbox.com/u/7381029/Program.cs

----------


## FenixTX2

Just a quick glance at your code: 

In your LuaDoString code:


```
uint FrameScript__Execute = 0x3A2620;// +ba;
```



```
mov eax, " + (uint)FrameScript__Execute, // Lua_DoString
```

The FrameScript__Execute value you specify has been re-based. You need to add the wow main module base address to the address specified: 



```
mov eax, " + ((uint)MyHook.Memory.MainModule.BaseAddress + FrameScript__Execute), // Lua_DoString
```

Also, this line needs to be changed: 


```
"add esp, 0xC",// +(uint)command.Length,
```

In your GetLocalizedText method: 


```
uint ClntObjMgrGetActivePlayerObj = 0x3520;
uint FrameScript__GetLocalizedText = 0x1C2250;
```



```
"call " + (uint)ClntObjMgrGetActivePlayerObj,
```



```
"call " + (uint)FrameScript__GetLocalizedText,
```

Again, you need to add the MainModule.BaseAddress to these values.



```
"call " + ((uint)MyHook.Memory.MainModule.BaseAddress + (uint)ClntObjMgrGetActivePlayerObj),
```



```
"call " + ((uint)MyHook.Memory.MainModule.BaseAddress + (uint)FrameScript__GetLocalizedText),
```

----------


## Ozius

All has corrected that you have written. Goes in cycles in the same place. I will not understand where still there can be an error  :Frown: 
code: http://dl.dropbox.com/u/7381029/2Program.cs

----------


## FenixTX2

> All has corrected that you have written. Goes in cycles in the same place. I will not understand where still there can be an error 
> code: http://dl.dropbox.com/u/7381029/2Program.cs


When you run your program, do you have a character logged into WoW?
Is WoW running normally?
Do you have any other programs attached to wow already?

----------


## Ozius

Character logged. At use aHook.dll and iHook.dll, works. I will not understand why it doesn't work. The project: http://dl.dropbox.com/u/7381029/ConsoleApplication2.zip

----------


## FenixTX2

I'm attaching my working code. 
My implementation is slightly different than what was originally specified. 

My 'Hook' class is called HookManager and its default constructor requires an instance of BlackMagic.
The HookApplication and DisposeOfHook methods are private and used only within the InjectAndExecute method.

HookManager Code: 


```
    public struct Direct3D
    {
        public static uint Direct3D9__Device = 0x98BCDC;
        public static uint Direct3D9__Device__OffsetA = 0x27C4;
        public static uint Direct3D9__Device__OffsetB = 0xA8;
    }
    public class HookManager
    {
        private BlackMagic process;

        private bool mainThreadHooked;
        private bool ExecutingCode;

        private uint codeCave;
        private uint injectionAddress;
        private uint returnAddress;

        public HookManager(BlackMagic process)
        {
            this.process = process;

            this.mainThreadHooked = false;
            this.ExecutingCode = false;

            this.codeCave = 0;
            this.injectionAddress = 0;
            this.returnAddress = 0;
        }

        private void HookApplication()
        {
            if (!process.IsProcessOpen)
                throw new Exception("Process is not open");

            uint baseAddress = (uint)process.MainModule.BaseAddress;
            uint pDevice = process.ReadUInt(baseAddress + Direct3D.Direct3D9__Device);
            uint pEnd = process.ReadUInt(pDevice + Direct3D.Direct3D9__Device__OffsetA);
            uint pScene = process.ReadUInt(pEnd);
            uint pEndScene = process.ReadUInt(pScene + Direct3D.Direct3D9__Device__OffsetB);

            if (process.ReadUInt(pEndScene) == 0xE9 && (codeCave == 0 || injectionAddress == 0))
            {
                DisposeOfHook();
            }
            if (process.ReadUInt(pEndScene) != 0xE9)
            {
                try
                {
                    mainThreadHooked = false;

                    codeCave = process.AllocateMemory(2048);
                    injectionAddress = process.AllocateMemory(0x4);

                    process.WriteInt(injectionAddress, 0);

                    returnAddress = process.AllocateMemory(0x4);
                    process.WriteInt(returnAddress, 0);

                    process.Asm.Clear();

                    process.Asm.AddLine("mov edi, edi");
                    process.Asm.AddLine("push ebp");
                    process.Asm.AddLine("mov ebp, esp");

                    process.Asm.AddLine("pushfd");
                    process.Asm.AddLine("pushad");
                    
                    //Test for waiting code?
                    process.Asm.AddLine("mov eax, [" + injectionAddress + "]");
                    process.Asm.AddLine("test eax, ebx");
                    process.Asm.AddLine("je @out");

                    //Execute waiting code
                    process.Asm.AddLine("mov eax, [" + injectionAddress + "]");
                    process.Asm.AddLine("call eax");

                    //Copy pointer to return value
                    process.Asm.AddLine("mov [" + returnAddress + "], eax");

                    process.Asm.AddLine("mov edx, " + injectionAddress);
                    process.Asm.AddLine("mov ecx, 0");
                    process.Asm.AddLine("mov [edx], ecx");

                    //Close Function
                    process.Asm.AddLine("@out:");

                    //Inject Code
                    uint sizeAsm = (uint)(process.Asm.Assemble().Length);

                    process.Asm.Inject(codeCave);

                    int sizeJumpBack = 5;

                    // create jump back stub
                    process.Asm.Clear();
                    process.Asm.AddLine("jmp " + (pEndScene + sizeJumpBack));
                    process.Asm.Inject(codeCave + sizeAsm);// + (uint)sizeJumpBack);

                    // create hook jump
                    process.Asm.Clear(); // $jmpto
                    process.Asm.AddLine("jmp " + (codeCave));
                    process.Asm.Inject(pEndScene);

                }
                catch
                {
                    mainThreadHooked = false; return;
                }
                mainThreadHooked = true;
            }

        }
        private void DisposeOfHook()
        {
            if (!process.IsProcessOpen)
                throw new Exception("Process is not open");

            uint baseAddress = (uint)process.MainModule.BaseAddress;
            uint pDevice = process.ReadUInt(baseAddress + Direct3D.Direct3D9__Device);
            uint pEnd = process.ReadUInt(pDevice + Direct3D.Direct3D9__Device__OffsetA);
            uint pScene = process.ReadUInt(pEnd);
            uint pEndScene = process.ReadUInt(pScene + Direct3D.Direct3D9__Device__OffsetB);

            try
            {
                if (process.ReadByte(pEndScene) == 0xE9) // check if wow is already hooked and dispose Hook
                {
                    // Restore origine endscene:
                    process.Asm.Clear();
                    process.Asm.AddLine("mov edi, edi");
                    process.Asm.AddLine("push ebp");
                    process.Asm.AddLine("mov ebp, esp");
                    process.Asm.Inject(pEndScene);
                }

                // free memory:
                process.FreeMemory(codeCave);
                process.FreeMemory(injectionAddress);
                process.FreeMemory(returnAddress);
            }
            catch
            {
            }
        }

        public byte[] InjectAndExecute(string[] asm)
        {
            while (ExecutingCode)
            {
                System.Threading.Thread.Sleep(5);
            }

            ExecutingCode = true;

            HookApplication();

            byte[] tempsByte = new byte[0];

            // reset return value pointer
            process.WriteInt(returnAddress, 0);

            if (process.IsProcessOpen && mainThreadHooked)
            {
                // Write the asm stuff
                process.Asm.Clear();
                foreach (string tempLineAsm in asm)
                {
                    process.Asm.AddLine(tempLineAsm);
                }

                // Allocation Memory
                int codeSize = process.Asm.Assemble().Length;
                uint injectionAsm_Codecave = process.AllocateMemory(codeSize);


                try
                {
                    // Inject
                    process.Asm.Inject(injectionAsm_Codecave);
                    process.WriteInt(injectionAddress, (int)injectionAsm_Codecave);

                    // Wait to launch code
                    while (process.ReadInt(injectionAddress) > 0)
                    {
                        System.Threading.Thread.Sleep(5);
                    }

                    byte Buf = new Byte();
                    List<byte> retnByte = new List<byte>();
                    uint dwAddress = process.ReadUInt(returnAddress);
                    Buf = process.ReadByte(dwAddress);
                    while (Buf != 0)
                    {
                        retnByte.Add(Buf);
                        dwAddress = dwAddress + 1;
                        Buf = process.ReadByte(dwAddress);
                    }
                    tempsByte = retnByte.ToArray();
                }
                catch { }

                // Free memory allocated 
                process.FreeMemory(injectionAsm_Codecave);
            }

            DisposeOfHook();

            ExecutingCode = false;

            return tempsByte;
        }
    }
```

I also have a function manager class.
The default constructor takes an instance of BlackMagic as a parameter and creates an instance of HookManager.

FunctionManager Code: 


```
    public class FunctionManager
    {
        private BlackMagic process;
        private HookManager aHook;

        public FunctionManager(BlackMagic process)
        {
            this.process = process;
            this.aHook = new HookManager(process);
        }

        public void LuaDoString(string command)
        {
            int nSize = command.Length + 0x100;
            uint codeCave = process.AllocateMemory(nSize);
            uint moduleBase = (uint)process.MainModule.BaseAddress;

            process.WriteASCIIString(codeCave, command);
            
            process.Asm.Clear();

            String[] asm = new String[] 
            {
                "mov eax, " + codeCave,
                "push 0",
                "push eax",
              
                "push eax",
                "mov eax, " + (moduleBase + FrameScript__Execute),
                
                "call eax",
                "add esp, 0xC",
                "retn",    
            };

            aHook.InjectAndExecute(asm);
            process.FreeMemory(codeCave);
        }
}
```

Crappy Example Usage: 


```
        static void Main(string[] args)
        {
            BlackMagic application;
            FunctionManager functionManager;

            Process[] processes = Process.GetProcessesByName("Wow");

            application = new BlackMagic(processes[0].id);
            functionManager = new FunctionManager(application);

            functionManager.LuaDoString("print(\"Hello World\");");
            functionManager.LuaDoString("DoEmote(\"dance\");"); 
        }
```

----------


## FenixTX2

> *FenixTX2*, thx.
> Has corrected the code as you have offered. Cycling in the same place: 
> 
> 
> ```
> while (Memory.ReadInt(addresseInjection) > 0) { Thread.Sleep(5); } // Wait to launch code
> ```
> 
> The code entirely: http://dl.dropbox.com/u/7381029/Program.cs


I seem to have encountered the same error. 
The code works perfectly fine on my PC but fails to execute the command on my Laptop. 
The strange thing is that both machines are running windows 7 x64 and both have an i7 processor.

The error seems to stem from this section of code: 


```
        application.Asm.AddLine("mov eax, [" + addresseInjection + "]");
        application.Asm.AddLine("test eax, ebx");
        application.Asm.AddLine("je @out");
```



On the Laptop 'ebx' is always 0;

----------


## Xelper

Is your laptop's WoW running in something other than DX9? My new Dell Laptop that I freshly installed WoW onto defaulted to DX11.

edit: Incase you don't know how to check. Check your Config.WTF file, see if you have a line that looks like *SET gxApi "d3d11"* I don't know what the value would be to set it to DX9, however if you wipe out that line it should default to DX9.

----------


## FenixTX2

Both devices 'should' be running in d3d9 mode. That is to say that the gxApi cvar has not been set and I expect d3d9 to be default. 
I did try using d9d11 but tbh it didn't seem to make any difference...how on earth do you check the running state of a cvar anyway? print(cvarname) always returns nill.

----------


## Ozius

Thanx a lot!
The most funny thing is that my new project copypasted from FenixTX2's code appears to loop at the same point. 
I run it in d3d9 mode (The line SET gxApi "d3d11" isn't found):
DeskTop: cpu is Celeron, Win7 x86 platform;
Laptop: cpu i7, Win7 x64 platform.
Could you be so kind to run the project, in case it will run I'll try searching for error somwhere else rother then code.
project: http://dl.dropbox.com/u/7381029/Inj.zip

----------


## GameAssist

> Thanx a lot!
> project: http://dl.dropbox.com/u/7381029/Inj.zip


Works great - added the missing GetLocalizedText


```
public class FunctionManager
        {
            BlackMagic process;
            HookManager aHook;
            uint FrameScript__Execute = 0x3A2620;
            uint moduleBase { get { return (uint)process.MainModule.BaseAddress; } }

            public FunctionManager(BlackMagic process)
            {
                this.process = process;
                this.aHook = new HookManager(process);
            }

            public void LuaDoString(string command)
            {
                int nSize = command.Length + 0x100;
                uint codeCave = process.AllocateMemory(nSize);

                process.WriteASCIIString(codeCave, command);
                process.Asm.Clear();

                String[] asm = new String[] 
            {
                "mov eax, " + codeCave,
                "push 0",
                "push eax",
              
                "push eax",
                "mov eax, " + (moduleBase + FrameScript__Execute),
                
                "call eax",
                "add esp, 0xC",
                "retn",    
            };

                aHook.InjectAndExecute(asm);
                process.FreeMemory(codeCave);
            }

            public string GetLocalizedText(string command)
            {
                uint ClntObjMgrGetActivePlayerObj = moduleBase + 0x3520;
                uint FrameScript__GetLocalizedText= moduleBase + 0x1C2250;

                int nSize = command.Length + 0x100;
                uint codeCave = process.AllocateMemory(nSize);
                process.WriteASCIIString(codeCave, command);

                String[] asm = new String[] 
                {
                "call " + ClntObjMgrGetActivePlayerObj,
                "mov ecx, eax",
                "push -1",
                "mov edx, " + codeCave + "",
                "push edx",
                "call " + FrameScript__GetLocalizedText,
                "retn",
                };
                
                string sResult = Encoding.ASCII.GetString(aHook.InjectAndExecute(asm));
                process.FreeMemory(codeCave);

                return sResult;
            }
        }
```

----------


## MaiN

The line should read 'test eax, eax', not 'test eax, ebx'. You have not moved anything into ebx and it's actually completely random what ebx might be.
Long story short; learn ASM.

----------


## Ozius

> The line should read 'test eax, eax', not 'test eax, ebx'. You have not moved anything into ebx and it's actually completely random what ebx might be.
> Long story short; learn ASM.


*MaiN*, мany thanks, there was in it an error. Now works!  :Smile:

----------


## RivaLfr

> The line should read 'test eax, eax', not 'test eax, ebx'. You have not moved anything into ebx and it's actually completely random what ebx might be.
> Long story short; learn ASM.


I have not see this error, I edit my post

----------


## streppel

hey all
first of all, thanks RivaLfr for your amazing example,it works pretty well out of the box even in a non wow-related context,i would rep you but i can't currently

ok my reason for bumping this is that i encountered a problem with a boolean as returnvalue that was passed directly in the variable and not as a pointer
i changed the class a little


```
                    if (returnLength == 1)
                    {
                        tempsByte = Memory.ReadBytes(retnInjectionAsm, returnLength);
                    }
                    if (returnLength > 1)
                    {
                        tempsByte = Memory.ReadBytes(Memory.ReadUInt(retnInjectionAsm), returnLength);
                    }
                    if(returnLength == 0)
                    {
                        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();
                    }
```

this way it works just perfect, wanted to let you know...and this problem really got me hooked for about an hour before i finally fixed it...yay

----------


## Sye24

Hello, here is a way to return GetLocalizedText Variable with multiple types (String, int, float, bool etc.),

(No Code) id also recommend randomizing the ASM calls to make less detectable.



```
 public static T LuaDoString<T>(string LuaCode)
        {
            LuaDoString(LuaCode.Replace("return true", "R = 1").Replace("return false", "R = 0").Replace("return ", " R = ") + $" {Properties.Settings.Default.RandomString} = R");
            var LuaCallback = GetLocalizedText($"{Properties.Settings.Default.RandomString}");
            object Temp;

            if (typeof(T) == typeof(int))
            {
                Temp = Convert.ToInt32(LuaCallback);
            }
            else if (typeof(T) == typeof(string))
            {
                Temp = LuaCallback.ToString();
            }
            else if (typeof(T) == typeof(bool))
            {
                Temp = LuaCallback == "1";
            }
            else if (typeof(T) == typeof(List<string>))
            {
                List<char> Table = new List<char>();
                foreach(char i in LuaCallback)
                {
                    Table.Add(i);
                }
                Temp = Table.ToArray();
            }
            else if (typeof(T) == typeof(float))
            {
                Temp = float.Parse(LuaCallback);
            }
            else if (typeof(T) == typeof(double))
            {
                Temp = double.Parse(LuaCallback);
            }
            else
            {
                Temp = (T)Convert.ChangeType(0, typeof(T));
            }
            return (T)Temp;
        }  
    }
```

----------

