Calling Lua Functions from DLL menu

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 20
  1. #1
    Viano's Avatar Active Member
    Reputation
    37
    Join Date
    May 2008
    Posts
    172
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Calling Lua Functions from DLL

    Hi everyone,

    I finally managed to use EasyHook to inject DLLs in some processes and now I was trying to use it for WoW. My DLL gets injected but I am not able to call DoString(). I am just testing DoEmote("dance"); currently but nothing happens. I was logging the steps in my DLL and everything seems fine. Any advice on this would be great.

    This is the content of the class from my DLL.

    Code:
    private static uint Lua;
            private static Lua_DoStringDelegate Lua_DoString;
            private static Lua_GetStateDelegate Lua_GetState;
            private static Lua_RegisterDelegate Lua_Register;
            private static Lua_GetTopDelegate Lua_GetTop;
            private static Lua_ToStringDelegate Lua_ToString;
            public static List<string> Values = new List<string>();    
    
            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
            private delegate void Lua_DoStringDelegate(string command, string fileName, uint luaState);
    
            [UnmanagedFunctionPointer(CallingConvention.StdCall)]
            private delegate void Lua_RegisterDelegate(string name, IntPtr function);
    
            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
            private delegate uint Lua_GetStateDelegate();
    
            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
            private delegate uint Lua_GetTopDelegate(uint luaState);
    
            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
            private delegate string Lua_ToStringDelegate(uint luaState, uint idx, uint length);
    
            [DllImport("kernel32.dll")]
            static extern uint SuspendThread(IntPtr hThread);
    
            [DllImport("kernel32.dll")]
            static extern uint ResumeThread(IntPtr hThread);
    
            [DllImport("kernel32.dll")]
            private static extern IntPtr GetCurrentProcess();
    
            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
            private delegate int CommandHandlerDelegate(uint luaState);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten);
    
            private static int ReturnBytes;
            private static readonly CommandHandlerDelegate CmdHandler = InputHandler;
            public static IntPtr CmdHandlerPtr = Marshal.GetFunctionPointerForDelegate(CmdHandler);
    
            Hooker.MyInterface Interface;
    
            public static IntPtr WowProcessHandle;
            public static IntPtr WowThreadHandle;
    
            public MyDLL(RemoteHooking.IContext InContext, String InChannelName,
                IntPtr processHandle,
                IntPtr threadHandle)
            
                
            {
                WowProcessHandle = processHandle;
                WowThreadHandle = threadHandle;
                Interface = RemoteHooking.IpcConnectClient<Hooker.MyInterface>(InChannelName);
            }
    
            public void Run(RemoteHooking.IContext InContext, String InChannelName,
                IntPtr processHandle,
                IntPtr threadHandle)
            {
                Lua_Register =
                        (Lua_RegisterDelegate)
                        Marshal.GetDelegateForFunctionPointer((IntPtr)Constants.Lua_Register, typeof(Lua_RegisterDelegate));
                Lua_DoString =
                       (Lua_DoStringDelegate)
                       Marshal.GetDelegateForFunctionPointer((IntPtr)Constants.Lua_DoString, typeof(Lua_DoStringDelegate));
                Lua_GetState =
                        (Lua_GetStateDelegate)
                        Marshal.GetDelegateForFunctionPointer((IntPtr)Constants.Lua_GetState, typeof(Lua_GetStateDelegate));
                Lua_GetTop =
                        (Lua_GetTopDelegate)
                        Marshal.GetDelegateForFunctionPointer((IntPtr)Constants.Lua_GetTop, typeof(Lua_GetTopDelegate));
                Lua_ToString =
                        (Lua_ToStringDelegate)
                        Marshal.GetDelegateForFunctionPointer((IntPtr)Constants.Lua_ToString, typeof(Lua_ToStringDelegate));
    
                Lua = Lua_GetState();
                Lua_Register("InputHandler", (IntPtr)Constants.PatchOffset);
    
    		PatchPointer(CmdHandlerPtr);
    	
    		// NOW TRY TO DANCE
                DoString("DoEmote(\"dance\");");
            }
    
            public static int InputHandler(uint luaState)
            {
                lock (Values)
                {
                    Values.Clear();
                    uint n = Lua_GetTop(luaState);
                    for (uint i = 1; i <= n; i++)
                    {
                        string res = Lua_ToString(luaState, i, 0);
                        Values.Add(res);
                    }
                }
                return 0;
            }
    
            public static void DoString(string command)
            {
                try
                {
                    string cmd = string.Format("{0}", command);
                    SuspendThread(WowThreadHandle);
                    Lua_DoString(cmd, "MyLUA.lua", Lua);
                    ResumeThread(WowThreadHandle);
                }
                catch (SEHException e)
                {
                    // log this later
                }
            }
    
            public static int PatchPointer(IntPtr pointer)
            {
                bool ReturnVal;
                uint p = (uint)pointer - Constants.PatchOffset - 5;
                var buffer1 = new byte[4];
                var buffer2 = new byte[1];
                buffer2[0] = 0xE9;
                buffer1[3] = (byte)((p & 0xFF000000) >> 24);
                buffer1[2] = (byte)((p & 0xFF0000) >> 16);
                buffer1[1] = (byte)((p & 0xFF00) >> 8);
                buffer1[0] = (byte)((p & 0xFF));
    
                IntPtr hProcess = GetCurrentProcess();
    
                ReturnVal = WriteProcessMemory(hProcess, (IntPtr)Constants.PatchOffset, buffer2, 1, out ReturnBytes);
                ReturnVal = WriteProcessMemory(hProcess, (IntPtr)(Constants.PatchOffset + 1), buffer1, 4, out ReturnBytes);
                return ReturnBytes;
            }
    Last edited by Viano; 07-28-2009 at 02:07 AM.
    Viano

    Calling Lua Functions from DLL
  2. #2
    vulcanaoc's Avatar Member
    Reputation
    31
    Join Date
    Jul 2008
    Posts
    125
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Although I can't directly help you, I have some notes:

    If you're in process, you should not need to use WriteProcessMemory. You can use pointers (even in C# as you hopefully know) to access memory.

    Also, I don't see the point in suspending WoW's main thread when you call DoString. Its not like you're running it on the main thread. Oh wait, that could be part of why it doesn't work.

    Also
    Code:
    string cmd = string.Format("{0}", command);
    doesn't do anything useful.

  3. #3
    flo8464's Avatar Active Member
    Reputation
    30
    Join Date
    Apr 2009
    Posts
    434
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah, hook EndScene to execute your code.

  4. #4
    Quarters's Avatar Member
    Reputation
    16
    Join Date
    May 2009
    Posts
    38
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You should take a look at Project BabBot and see how they did it as they use EasyHook AFAIK, it will give you ideas anyway, I tend to find looking at how others did it really good learning

  5. #5
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Don't take his advice of using pointers to read memory in C#... It doesn't work all the time. Most of the time it doesn't, actually. Annoying, but, it IS microsoft.

  6. #6
    alek900's Avatar Contributor
    Reputation
    103
    Join Date
    Nov 2007
    Posts
    101
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by lanman92 View Post
    Don't take his advice of using pointers to read memory in C#... It doesn't work all the time. Most of the time it doesn't, actually. Annoying, but, it IS microsoft.
    uhm, what? :confused:
    19+4 that means i score

  7. #7
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Volcanaoc said you can read memory inprocess with C# and pointers. You can, but it sucks. They throw exceptions constantly. The microsoft comment was just for laughs on my part.

  8. #8
    Viano's Avatar Active Member
    Reputation
    37
    Join Date
    May 2008
    Posts
    172
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by vulcanaoc View Post
    ...
    If you're in process, you should not need to use WriteProcessMemory. You can use pointers (even in C# as you hopefully know) to access memory.

    Also, I don't see the point in suspending WoW's main thread when you call DoString. Its not like you're running it on the main thread. Oh wait, that could be part of why it doesn't work.

    Also
    Code:
    string cmd = string.Format("{0}", command);
    doesn't do anything useful.
    Thanks for pointing the suspending part out. But I think WriteMemory is a lot safer and will work for sure. There is nothing wrong with using the function.

    And with "string cmd = string.Format("{0}", command);" you are right. I was using that for s.th. else.

    Originally Posted by Quarters View Post
    You should take a look at Project BabBot and see how they did it as they use EasyHook AFAIK, it will give you ideas anyway, I tend to find looking at how others did it really good learning
    Actually I was looking at BabBot and the main idea is from it. Nevertheless I was going through API docs of EasyHook and wanted to get some simple things going so I understand what I am doing. Unfortunately I am at that tricky part where I do not get why DoString is not called correctly. Hopefully it's just the thread suspension part mentioned above.
    Viano

  9. #9
    kynox's Avatar Account not activated by Email
    Reputation
    830
    Join Date
    Dec 2006
    Posts
    888
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    ..why not just use Marshal?

  10. #10
    Viano's Avatar Active Member
    Reputation
    37
    Join Date
    May 2008
    Posts
    172
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by kynox View Post
    ..why not just use Marshal?
    For which part? Where? What? Why?
    Viano

  11. #11
    Viano's Avatar Active Member
    Reputation
    37
    Join Date
    May 2008
    Posts
    172
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Hyru View Post
    Babbot hooks Direct3DCreate9, which is only called once immediately after WoW launches, and when that's called they hook EndScene. I tried this method for a few hours over the weekend but never got it working. I might look at it again soon. IRL is a debuff for me.
    Ok, so to sum it up. The recipe is:

    1. Inject DLL.
    2. Hook Direct3dCreate9.
    3. Hook EndScene.
    4. Execute LUA.

    I just don't understand the Hooking D3D and EndScene part. Why do I have to do this? For what D3D? Here I was thinking that registrating lua functions

    Code:
    Lua_DoString = (Lua_DoStringDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)Constants.Lua_DoString, typeof(Lua_DoStringDelegate));
    is enough.

    Ok, crawling back and reading ...
    Last edited by Viano; 07-28-2009 at 08:40 AM.
    Viano

  12. #12
    vulcanaoc's Avatar Member
    Reputation
    31
    Join Date
    Jul 2008
    Posts
    125
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by lanman92 View Post
    Volcanaoc said you can read memory inprocess with C# and pointers. You can, but it sucks. They throw exceptions constantly. The microsoft comment was just for laughs on my part.
    Alright, alright, you're right, anyone who's curious should google IsBadReadPtr or IsBadWritePtr and you'll know what he means.

    Alternatively, you could try using memset, but that would not get past the memory access problems.

    Unless you do something like:

    Code:
    MEMORY_BASIC_INFORMATION mbi;
    			if(VirtualQuery((LPCVOID)currentAddress, &mbi, sizeof(mbi)) > 0)
    			{
    				unsigned long endOfRegion = ((unsigned long)mbi.BaseAddress + mbi.RegionSize);
    
    				if(mbi.State != MEM_COMMIT ||
    					mbi.Protect == PAGE_NOACCESS ||
    					mbi.Protect == PAGE_GUARD)
    				{
    					//char sendBuffer[scanChunkSize] = "failpacket";
    					//WriteFile(hPipe, sendBuffer, sizeof(sendBuffer), &cbRead, NULL);
    					currentAddress = (endOfRegion);
    				}
    				else
    				{
    					VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect);
    
    					currentAddress = (unsigned long)mbi.BaseAddress;
    					while(currentAddress < endOfRegion && !g_bClosing)
    					{
    						char sendBuffer[scanChunkSize] = "failpacket";
    
    						//if(!IsBadReadPtr((LPCVOID)currentAddress, scanChunkSize))
    						//{
    							//memcpy_s(sendBuffer, sizeof(sendBuffer), (void*)currentAddress, sizeof(sendBuffer));
    							for(int i = 0; i < sizeof(sendBuffer); i++)
    								sendBuffer[i] = *(char*)(currentAddress + i);
    						//}
    
    						WriteFile(hPipe, sendBuffer, sizeof(sendBuffer), &cbRead, NULL);
    
    						char addr[32];
    						sprintf(addr, "%u", currentAddress);
    						WriteFile(hPipe, addr, sizeof(addr)+1, &cbRead, NULL);
    
    						currentAddress += scanChunkSize;
    					}
    					VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect);
    				}
    			}
    (excuse the code, it is old from when I was learning [strikethrough]C++[/strikethrough] Spaghetti C)
    Last edited by vulcanaoc; 07-28-2009 at 09:39 AM.

  13. #13
    vulcanaoc's Avatar Member
    Reputation
    31
    Join Date
    Jul 2008
    Posts
    125
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Viano View Post
    Ok, so to sum it up. The recipe is:

    1. Inject DLL.
    2. Hook Direct3dCreate9.
    3. Hook EndScene.
    4. Execute LUA.

    I just don't understand the Hooking D3D and EndScene part. Why do I have to do this? For what D3D? Here I was thinking that registrating lua functions

    Code:
    Lua_DoString = (Lua_DoStringDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)Constants.Lua_DoString, typeof(Lua_DoStringDelegate));
    is enough.

    Ok, crawling back and reading ...

    Now to actually be helpful.

    To put it simply, it is a very good idea to run your injected code on WoW's main thread.

    EndScene, and other D3D APIs (such as Present, Reset) are called on every frame at a predictable point in time (in relation to the frame).

    Unless you want to do some drawing to WoW's screen, you DON'T need to hook Direct3DDeviceCreate. The reason you would do that is to grab the pointer to WoW's main Direct3DDevice. You can do this on-the-fly by hooking Present or Reset, since they are "thiscall"s and are therefore passed an argument containing a pointer to the Direct3DDevice on which they are called.

    However, you are *still* going to need to put a jmp or call to your code so that it can execute in WoW's main thread on every frame.

    Hope that helps..

    Edit: Another (small) reason that hooking D3D is a "good" idea is that it is commonly hooked by legitimate applications like Fraps. This means that Blizzard is that much less likely to look for your hook there, as it could be a legitimate program that is hooking it.
    Last edited by vulcanaoc; 07-28-2009 at 09:37 AM. Reason: forgot to say some shit!

  14. #14
    Maserrail's Avatar Member
    Reputation
    1
    Join Date
    Jul 2009
    Posts
    14
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nice....................

  15. #15
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I heard you can find the device pointer + endscene etc... from calling D3D9Create again. Not sure. Never tried it, but I've heard stuff about calling it and then destructing it after you get the device pointer.
    Last edited by lanman92; 07-28-2009 at 11:14 AM.

Page 1 of 2 12 LastLast

Similar Threads

  1. Executing WoW Lua functions from C#
    By kisjaksi in forum WoW Bots Questions & Requests
    Replies: 1
    Last Post: 09-02-2010, 10:22 AM
  2. Call Lua callback in DLL cause some Error
    By rafaelcn in forum WoW Memory Editing
    Replies: 3
    Last Post: 08-04-2010, 03:32 AM
  3. Calling LUA Functions
    By cloud_wizard in forum WoW Memory Editing
    Replies: 7
    Last Post: 01-04-2009, 08:24 AM
  4. Call lua function and get result
    By starfish99 in forum WoW Memory Editing
    Replies: 4
    Last Post: 12-26-2008, 05:15 AM
  5. Replies: 1
    Last Post: 08-26-2008, 10:49 PM
All times are GMT -5. The time now is 02:58 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search