-
Member
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:
- 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?
- 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!
-
Member
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.
-
Active Member
Originally Posted by
andristarr
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.
-
Originally Posted by
hubbabubba21
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
-
Post Thanks / Like - 2 Thanks
-
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
-
Member
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.
-
Member
Originally Posted by
xalcon
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.
-
Originally Posted by
34D
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
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
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
-
Originally Posted by
34D
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
-
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
-
Post Thanks / Like - 1 Thanks
GlittPrizes (1 members gave Thanks to xalcon for this useful post)
-
@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