Injected into WoW! Clarifying things before continuing... menu

User Tag List

Results 1 to 11 of 11
  1. #1
    hubbabubba21's Avatar Member
    Reputation
    1
    Join Date
    Jul 2020
    Posts
    2
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Injected into WoW! Clarifying things before continuing...

    Hi,

    I've recently started playing WoW again on a 3.3.5 private server. The last couple weeks I've been working on getting a simple mining bot working and this forum has been a HUGE help. Although I've recently completed my computer science degree, I love continuing to learn so this whole process has been challenging but rewarding and fun. I've also been using this resource throughout the process: https://drewkestell.us/Article/6/Chapter/1 . For the rest of the post, I'm speaking in the context of WoW 3.3.5 on a private server.

    My first go at making the bot was writing a C# program that reads/writes to WoW's memory but I quickly ran into roadblocks that could be lifted if I could directly call functions in the game. I'm more comfortable writing in C# than C++ so I followed this guide to inject a C++ dll into WoW that would start a .NET runtime within WoW, invoke the entry point into the C# program that will hold my bot's logic, and finally release the dll from WoW's process. : Injecting .NET Assemblies Into Unmanaged Processes - CodeProject

    Now that I'm injected into WoW, I've been reading up how to call WoW functions. Before continuing, I wanted to clarify some things that have been really confusing me:

    1. Do I need to do any sort of hooking/detouring to call WoW functions? I've read countless threads about EndScene hooking/detouring, using WndProc, using "CEventQueue::Register",etc. but from my understanding, you use these methods when you're running a bot EXTERNALLY. Since my bot is running within the WoW process, I'm on it's main thread and I should be able to call functions (including LUA functions) without relying on any hooks or detours. Or am I completely missing something and I do need to hook/detour?
    2. The WoW bot making guide by Drew Kestell I linked above mentions that this method of injection would likely be caught by Warden. Is this because I have a whole ass bot/.NET CLR running within WoW's memory? Should I instead do something like: Setup the WoW functions I want to call as exports within the dll I injected into WoW (and keep the dll in WoW as opposed to removing it as I'm currently doing) and then in an external process, get a handle on that dll module and use CreateRemoteThread to call the exported functions with the necessary arguments? I would still be susceptible to a module scan by Warden but Kestell's guide has an idea on circumventing that which I will try to implement in the case that this is a clear point of failure for my bot.


    Thank you in advance! I'm eager to continue working on this bot!

    Injected into WoW! Clarifying things before continuing...
  2. #2
    andristarr's Avatar Member
    Reputation
    1
    Join Date
    Jul 2018
    Posts
    4
    Thanks G/R
    4/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    1#, you don't NEED to hook anything in order to call in game functions. You can get the address of the game function and invoke it without that you are right on that. I suspect you are not actually running on the main thread of the game , the injection method you are using is probably creating a thread for you in the address space of the game. (didnt check link tbh)
    2# ...
    Last edited by andristarr; 08-28-2020 at 05:13 PM.

  3. #3
    zys924's Avatar Active Member
    Reputation
    20
    Join Date
    Nov 2009
    Posts
    113
    Thanks G/R
    0/7
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by andristarr View Post
    1#, you don't NEED to hook anything in order to call in game functions. You can get the address of the game function and invoke it without that you are right on that. I suspect you are not actually running on the main thread of the game , the injection method you are using is probably creating a thread for you in the address space of the game. (didnt check link tbh)
    2# Am pretty unfamiliar with warden , still reading up on that

    gl
    agree with that. you can't get a "loop" main thread access without some sort of hooking. that's why you need those detours, regardless of external/internal.

    .NET injection sucks as it leaves tons of footprints in process that can't be removed at all (or at least not worth it). You should always stick to native code (C/C++) if you are worried about security.

  4. #4
    xalcon's Avatar Contributor ふたなり
    Authenticator enabled
    Reputation
    198
    Join Date
    Oct 2008
    Posts
    291
    Thanks G/R
    20/58
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by hubbabubba21 View Post
    Do I need to do any sort of hooking/detouring to call WoW functions? I've read countless threads about EndScene hooking/detouring, using WndProc, using "CEventQueue::Register",etc. but from my understanding, you use these methods when you're running a bot EXTERNALLY. Since my bot is running within the WoW process, I'm on it's main thread and I should be able to call functions (including LUA functions) without relying on any hooks or detours. Or am I completely missing something and I do need to hook/detour?
    It highly depends on what you try to achieve and how. If you intend to call lua functions, you MUST synchronize with the main thread that is running the lua code - no matter if you are internal or external. Lua itself is not threadsafe. If you call anything lua related while not in the lua thread, there is an extremely high chance of messing up the lua stack and causing either a crash or other undefined behavior. This is why most people just hook EndScene (or DXGISwapChain::Present on newer versions of wow) or any other method that is called by the mainthread for that matter.

    If you are worried about hooking with c#: It's super easy. You can create unmanaged function pointers for your managed functions, which allow unamanged code to call your managed functions.
    Marshal.GetFunctionPointerForDelegate Method (System.Runtime.InteropServices) | Microsoft Docs
    With C# 9.0 there is an even easier (and faster) way with the use of C# Function Pointers

    Afterwards, you just use any managed or unmanaged hooking library (I'm using Minhook, but there are plenty of other options) to call your function pointer.

    You can also use the Marshaller to call unmanaged functions from C# (see Marshal.GetDelegateForFunctionPointer) - or via C# Function Pointers if available.

    The WoW bot making guide by Drew Kestell I linked above mentions that this method of injection would likely be caught by Warden. Is this because I have a whole ass bot/.NET CLR running within WoW's memory? Should I instead do something like: Setup the WoW functions I want to call as exports within the dll I injected into WoW (and keep the dll in WoW as opposed to removing it as I'm currently doing) and then in an external process, get a handle on that dll module and use CreateRemoteThread to call the exported functions with the necessary arguments? I would still be susceptible to a module scan by Warden but Kestell's guide has an idea on circumventing that which I will try to implement in the case that this is a clear point of failure for my bot.
    Loading a .Net CLR into wow definitely leaves its marks and private server implementations of warden may be a bit more aggressive regarding injected modules. Calling functions via CreateRemoteThread can incur quite the performance hit, depending on how often you need to call them and how much synchronization with the main thread is required. The better option is probably to have a module that just starts a new thread (or works from the mainthread) and have it communicate via some from of IPC (Sockets, Named Pipes, Shared Memory, ...) with an external process.

    Personally, I'm injecting a dotnet core 3.1 runtime into the target process, which works quite well. Thanks to the AssemblyLoadContext I'm also able to reload my assemblies at runtime, which is really helpful during development - but I'm only really using C# for prototyping. I might switch to c++ if this project is actually getting anywhere in the future, but for now I don't care that much about anti-cheats.
    Last edited by xalcon; 07-21-2020 at 03:15 AM.
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

  5. Thanks andristarr, GlittPrizes (2 members gave Thanks to xalcon for this useful post)
  6. #5
    GlittPrizes's Avatar Active Member CoreCoins Purchaser Authenticator enabled
    Reputation
    58
    Join Date
    Nov 2019
    Posts
    104
    Thanks G/R
    53/33
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If your goal is to one and done with a dll injection, it is possible if you don't want to rely on the object manager or click to move. Playing around with what the WoW api offers you will allow you to setup repeatable logic that can run client side after the dll is unloaded with no external process interaction.

    The downside to the above method is you need to remain hooked/injected if you want to do things like click to move and work with the game's objects, so it's really only good for simpler things such as a combat routine.

    As others have mentioned, you aren't necessarily executing from the main thread just because a function call works. If they want to trace the call, they would likely see that the thread id is different from the game's main thread. With some help, I was able to implement a simple state machine that guarantees code only executes from the main thread (via user callback commands). Here is a native example for fishing:

    Code:
    // thread is created when the bobber bobs
    DWORD GoFish(LPVOID param)
    {
    	const auto responseDelay = rand() %    // ... your delay here
    	Sleep(responseDelay);
    	FishBase::State = ShouldCatch;
    
    	const auto recastDelay = rand() %    // ... delay here
    	Sleep(recastDelay);
    	FishBase::State = ShouldCast;
    
    	_hGoFish = nullptr;   // make sure to check exit code before creating a thread like this since the handle closes early
    	return 0;
    }
    The code that fires in the hook will trigger execution when the state changes
    Code:
    // every tick...
    if (LuaBase::State != LuaBusy)
    	LuaBase::Execute(_luaCommand);
    
    if (FishBase::State != FishBusy)
    	FishBase::DecideAction();
    FishBase.cpp
    Code:
    void FishBase::DecideAction()
    {
    	switch (State)
    	{
    	case ShouldCatch:
    		State = FishBusy;
    		Catch();
    		break;
    	case ShouldCast:
    		State = FishBusy;
    		Cast();
    		break;
    	case ShouldAntiAfk:
    		State = FishBusy;
    		AntiAfk();
    		break;
    	default:
    		break;
    	}
    }
    This will probably fly for most private servers depending on what they check. To further improve, it could ditch the lua commands and work with a mouse/keyboard driver to try to mimic human hardware events.

    Also, congrats on the CS degree and getting injected! It's a great feeling to finally breech the game. I also learned a lot from OC and the same bloog bot blog. Hopefully he updates it again soon.
    Last edited by GlittPrizes; 07-22-2020 at 08:41 AM. Reason: OC

  7. #6
    34D's Avatar Member
    Reputation
    4
    Join Date
    May 2020
    Posts
    57
    Thanks G/R
    10/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    SetWindowLongPtr to wow hWnd, and InvokeQueue SendMessage to action Invoke.
    or hook Dx11 DX12 pSwapChain.
    By the way in DX12 You need to get CommandQueue and fence first .
    Last edited by 34D; 07-21-2020 at 10:31 PM.

  8. #7
    34D's Avatar Member
    Reputation
    4
    Join Date
    May 2020
    Posts
    57
    Thanks G/R
    10/3
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by xalcon View Post
    It highly depends on what you try to achieve and how. If you intend to call lua functions, you MUST synchronize with the main thread that is running the lua code - no matter if you are internal or external. Lua itself is not threadsafe. If you call anything lua related while not in the lua thread, there is an extremely high chance of messing up the lua stack and causing either a crash or other undefined behavior. This is why most people just hook EndScene (or DXGISwapChain::Present on newer versions of wow) or any other method that is called by the mainthread for that matter.

    If you are worried about hooking with c#: It's super easy. You can create unmanaged function pointers for your managed functions, which allow unamanged code to call your managed functions.
    Marshal.GetFunctionPointerForDelegate Method (System.Runtime.InteropServices) | Microsoft Docs
    With C# 9.0 there is an even easier (and faster) way with the use of C# Function Pointers

    Afterwards, you just use any managed or unmanaged hooking library (I'm using Minhook, but there are plenty of other options) to call your function pointer.

    You can also use the Marshaller to call unmanaged functions from C# (see Marshal.GetDelegateForFunctionPointer) - or via C# Function Pointers if available.



    Loading a .Net CLR into wow definitely leaves its marks and private server implementations of warden may be a bit more aggressive regarding injected modules. Calling functions via CreateRemoteThread can incur quite the performance hit, depending on how often you need to call them and how much synchronization with the main thread is required. The better option is probably to have a module that just starts a new thread (or works from the mainthread) and have it communicate via some from of IPC (Sockets, Named Pipes, Shared Memory, ...) with an external process.

    Personally, I'm injecting a dotnet core 3.1 runtime into the target process, which works quite well. Thanks to the AssemblyLoadContext I'm also able to reload my assemblies at runtime, which is really helpful during development - but I'm only really using C# for prototyping. I might switch to c++ if this project is actually getting anywhere in the future, but for now I don't care that much about anti-cheats.
    My C Sharp is not very proficient, I want to know how to support hot reloading, can you give some guidance? And what GUI framework do you use to inject .net core?
    now I injected a clr to open a wpf, when I close wpf, wow is also closed, how can I make it only uninstall the dll when wpf is closed without closing the game? I've Hide the Modules and Fake PEH and Hijack another handle. Unable to pass enum module to eject.
    THANKS
    Last edited by 34D; 07-22-2020 at 12:01 AM.

  9. #8
    xalcon's Avatar Contributor ふたなり
    Authenticator enabled
    Reputation
    198
    Join Date
    Oct 2008
    Posts
    291
    Thanks G/R
    20/58
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by 34D View Post
    I want to know how to support hot reloading, can you give some guidance?
    This depends on the framework you are using. In dotnet framework 4.x+ ( up to 4.8 ) you need to use custom app domains. Apoc wrote a pretty good class that can be used as an starting point: https://www.ownedcore.com/forums/wor...ml#post1915992 (.Net Managed Assembly Removal)

    This wont work in dotnet core though since dotnet core (and .net 5 for that matter) only supports one AppDomain. You will need to use the AssemblyLoadContext, which is a bit harder to use since the context wont be able to unload if you have anything that would be kept alive by the GC (i.e. a reference to an object from the loaded assembly). An example with a guide how to troubleshoot unloading issues can be found in the microsoft docs: Understanding AssemblyLoadContext - .NET Core | Microsoft Docs

    Originally Posted by 34D View Post
    And what GUI framework do you use to inject .net core?
    I don't plan to have any gui inside the client. The bot will communicate with an external process, controlling the bot will be done through a web interface using some SPA framework and a web api.

    Originally Posted by 34D View Post
    now I injected a clr to open a wpf, when I close wpf, wow is also closed, how can I make it only uninstall the dll when wpf is closed without closing the game? I've Hide the Modules and Fake PEH and Hijack another handle. Unable to pass enum module to eject.
    I'm not sure about the "legacy" dotnet framework, but atleast dotnet core does not support CLR unloading. You can unload the assemblies that contain your botting logic, but the CLR will probably stay until you close the game. Thats how I handle it - i just close the game, i dont have any special unloading logic other than the logic hotswap. Regarding wpf closing wow as well when closing the WPF window: you will probably need to set the Application.ShutdownMode to OnExplicitShutdown, the default is OnLastWindowClose.
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

  10. #9
    GlittPrizes's Avatar Active Member CoreCoins Purchaser Authenticator enabled
    Reputation
    58
    Join Date
    Nov 2019
    Posts
    104
    Thanks G/R
    53/33
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by 34D View Post
    how can I make it only uninstall the dll when wpf is closed without closing the game?
    The main rule for hot swapping is everything including threads have to return a successful exit code (zero) and all resources loaded have to implicitly or explicitly have the destructor called. If you are willing to have your host app be c++ as well to avoid injecting .NET, it's a lot easier to pull off - just have to make sure nothing is still suspended or running when unloading.

    Code:
    // some say not to spawn a thread from DllMain but that's what this is
    DWORD Init(LPVOID hInstance)
    {
            // class that handles SetWindowLongPtr
    	Window::Init();
    
            // a thread is created for the inter-process communication so the handle needs to be closed after the thread returns 0 before the dll can free its library
            auto* const hPipe = Pipes::Server::Init();
    
            // working but it's probably better to suspend this thread with a condition_variable
    	while (!_safeToExit)
    	{
    		RunPipes();
    		Sleep(10);
    	}
    
            // either wait for a safe signal state or use a check to make sure the GetExitCodeThread(_yourThreadHandle, nullptr) == 0
    	WaitForSingleObject(hPipe, INFINITE);
    
            // anything that has resource cleanup needs to be handled. I couldn't get a destructor to automatically do this so I have a cleanup method
    	Window::Close();
    
            // the safe way to unload the dll and close the remaining thread at the same time
            // this will be last in the chain of closing events
            // hInstance is passed from DllMain
    	FreeLibraryAndExitThread(HMODULE(hInstance), 0);
    }
    Last edited by GlittPrizes; 07-22-2020 at 08:44 AM. Reason: comments

  11. #10
    xalcon's Avatar Contributor ふたなり
    Authenticator enabled
    Reputation
    198
    Join Date
    Oct 2008
    Posts
    291
    Thanks G/R
    20/58
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Code:
    // some say not to spawn a thread from DllMain but that's what this is
    Thats how false information spread - a simple misunderstanding what the original author wanted to say. You CAN create new threads in DllMain, but you MUST NOT (EVER!) wait for them to exit as this will cause a deadlock.

    See this blogpost by Raymond Chen from microsoft: Does creating a thread from DllMain deadlock or doesn't it? | The Old New Thing
    Also DLL Best Practices: Dynamic-Link Library Best Practices - Win32 apps | Microsoft Docs
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

  12. Thanks GlittPrizes (1 members gave Thanks to xalcon for this useful post)
  13. #11
    GlittPrizes's Avatar Active Member CoreCoins Purchaser Authenticator enabled
    Reputation
    58
    Join Date
    Nov 2019
    Posts
    104
    Thanks G/R
    53/33
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @xalcon: so basically don't call WaitForSingleObject or similar on a thread created in DllMain since it needs to return to avoid deadlock. I like Mr. Chen's articles, thanks for clearing that up about ON_ATTACH threads.

    I posted my named pipes library which goes into more detail on the code above if op wants to check it out. It's a decent starting point for communicating with a dll.
    Last edited by GlittPrizes; 07-23-2020 at 07:06 AM. Reason: blah

Similar Threads

  1. [Tutorial] Injecting assembly into WoW using C#
    By Corthezz in forum WoW Memory Editing
    Replies: 7
    Last Post: 12-19-2014, 08:32 AM
  2. [Bot] Injection code into wow. Do you have to call functions from the main thread?
    By Miivers in forum World of Warcraft Bots and Programs
    Replies: 2
    Last Post: 01-13-2014, 02:56 PM
  3. [Guide] Importing Warcraft 3 Models Into WoW *Not for Beginners*
    By Derision in forum WoW ME Tools & Guides
    Replies: 7
    Last Post: 02-07-2008, 11:05 PM
  4. [GUIDE]Stuff your own music into WoW. [Pictures]
    By Macroman in forum WoW ME Tools & Guides
    Replies: 22
    Last Post: 10-23-2007, 06:34 AM
  5. Using proxy/etc. ? to log into wow
    By minim in forum World of Warcraft General
    Replies: 0
    Last Post: 10-15-2007, 01:36 PM
All times are GMT -5. The time now is 06:12 PM. 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