Hello, Ownedcore!
After reading a lot about injection and hooking and facing tons of problems, I come here to share the C++ method I'm currently using (not actually share... more like asking for help, but anyways...). Before anything, let me just point out a couple problems I found "along the road":
1 - CreateRemoteThread
I made this thread (Lua_DoString() in C++ w/ CreateRemoteThread/WriteProcessMemory + Security questions) once and it was the first method I tried. It worked sometimes, but it would crash others. I think the crashes happened due to sometimes having two threads executing the same code and somehow one would affect the other and, therefore, a crash would happen.
In order to solve this problem, as most of you know, I had to learn about Hooking to make Wow's thread run the code that I want.
2 - Hooking - The one I'm currently using
The idea behind it is great and comprehensible. However, I found it a little hard to implement, because, well, it's Assembly. Indeed, there are other great methods and libraries out there to help and ease hooking, but I'm one of those guys that like to learn and suffer a little. My bot was made with that purpose: learning. So I left behind everything (Detours, EasyHook, BlackMagic and other stuff...) and decided to implement my own method, described below:
In order to pass the parameters, I used the code:
Code:
call dummy
dummy: pop edx
sub edx, 0x114
So, EDX+0x4 contains the address of the to-be-called function (offset + Wow base address), EDX+0x8 contains the "flag" (if 0, it runs the code), EDX+0xC contains the parameters, for example, "DoEmote("dance")" for LuaDoString() or the Player Address, etc. In the case of UnitReaction, I move the return value to EDX+0x14 which is later read.
As you guys can see, whenever I need to call a function, I just inject its calling structure in that "NOP Region". The parameters are all written on the "green area" of the picture. The function parameters are located in the BYTE command[255], so, sometimes, I write a sequence os chars for Lua_DoString, others I write the Player Base Pointer for UpdateDisplayInfo and so on. The address of these functions are written in the "function_to_be_called_pointer" and passed into EBX register. Therefore, all the calls must be like "call ebx", as seen on the right side of the picture. The flag is just a parameter to control the execution so that it doesn't call UpdateDisplayInfo infinitely.
Below is the code on what I have to do to call each of these functions. Notice that UnitReaction() is the only function that I really read the EAX after calling the function because that's where the value (1-Hated, 2-Hostile, etc) is returned. And that "loop" to detect if the result was changed meaning that the function was called and returned something... is, at least for me, a little ugly, but it was the first idea that came to my mind...
Code:
void Lua_DoString(string cmd){
char comando[255];
if(loaded == 0){
InjectHooking();
}
convertToASCII(cmd,comando);
mainThread = OpenThread(THREAD_ALL_ACCESS,false,mainThreadID);
SuspendThread(mainThread);
func = reinterpret_cast<unsigned int>(module.modBaseAddr) + Framescript_ExecuteBuffer;
mydata.funcptr = func;
mydata.flag = 0;
WriteProcessMemory( Handle2, reinterpret_cast<void*>(reinterpret_cast<unsigned int>(pLibRemote) + FunctionASMOffset), &ASMLua, 15, NULL);
WriteProcessMemory( Handle2, pLibRemote, &mydata, sizeof(mydata), NULL);
WriteProcessMemory( Handle2, reinterpret_cast<void*>(reinterpret_cast<unsigned int>(pLibRemote) + 0xC), &comando, sizeof(comando), NULL);
ResumeThread(mainThread);
}
void UpdateDisplay(DWORD pTarget){
if(loaded == 0){
InjectHooking();
}
if(pTarget != 0){
mainThread = OpenThread(THREAD_ALL_ACCESS,false,mainThreadID);
SuspendThread(mainThread);
func = reinterpret_cast<unsigned int>(module.modBaseAddr) + UpdateDisplayInfo;
mydata.funcptr = func;
mydata.flag = 0;
WriteProcessMemory( Handle2, reinterpret_cast<void*>(reinterpret_cast<unsigned int>(pLibRemote) + FunctionASMOffset), &ASMUpdate, 20, NULL);
WriteProcessMemory( Handle2, pLibRemote, &mydata, sizeof(mydata), NULL);
WriteProcessMemory( Handle2, reinterpret_cast<void*>(reinterpret_cast<unsigned int>(pLibRemote) + 0xC), &pTarget, 4, NULL);
ResumeThread(mainThread);
}
}
int UnitReaction(DWORD player, DWORD pTarget){
int wait = 0, waitf = 0;
ReadProcessMemory( Handle2, reinterpret_cast<void*>(reinterpret_cast<unsigned int>(pLibRemote) + 0x14), &wait, sizeof(wait), NULL);
wait = waitf;
if(loaded == 0){
InjectHooking();
}
if(pTarget != 0){
mainThread = OpenThread(THREAD_ALL_ACCESS,false,mainThreadID);
SuspendThread(mainThread);
func = reinterpret_cast<unsigned int>(module.modBaseAddr) + GetUnitReaction;
mydata.funcptr = func;
mydata.flag = 0;
WriteProcessMemory( Handle2, reinterpret_cast<void*>(reinterpret_cast<unsigned int>(pLibRemote) + FunctionASMOffset), &ASMUnitReaction, 20, NULL);
WriteProcessMemory( Handle2, pLibRemote, &mydata, sizeof(mydata), NULL);
WriteProcessMemory( Handle2, reinterpret_cast<void*>(reinterpret_cast<unsigned int>(pLibRemote) + 0xC), &player, 4, NULL);
WriteProcessMemory( Handle2, reinterpret_cast<void*>(reinterpret_cast<unsigned int>(pLibRemote) + 0x10), &pTarget, 4, NULL);
ResumeThread(mainThread);
}
while(wait == waitf){
ReadProcessMemory( Handle2, reinterpret_cast<void*>(reinterpret_cast<unsigned int>(pLibRemote) + 0x14), &waitf, sizeof(waitf), NULL);
Sleep(1);
}
return waitf+1;
}
The good thing about this method is that... it works! Even if I call Lua_DoString() and then UpdateDisplayInfo() right after, no crashes happen and everything works just fine since Wow's thread is doing the work.
Although everything is working, dealing with Assembly like this is a headache.
- For every new function that I decide to call, I will have to reverse it and look at how the parameters are passed and WriteProcessMemory() the parameters on the BYTE cmd[255].
- My code is filled with NOPs to reserve space and overwrite a previous injected function, afterall, their sizes are different. So yeah, if you look at my code, it's ugly, at least for me.
So I decided to learn more about DLL Injection, since I could create function pointers that would do all the Assembly work for me.
3 - DLL Injection without Hooking
In this method, I just injected a DLL that would call a certain function. No assembly was needed, but, for example, in order to call UpdateDisplayInfo(), I had to put in the DLL all the ObjectManager functions to iterate through all objects and find the player. Besides that, I couldn't change the UpdateDisplayInfo() parameter, for example, if I decide to pass some Unit's address. When I say "I couldn't" it's not because it isn't something possible, but because I really don't know how to do it, if there's a way.
And although it worked sometimes, others it would crash like the CreateRemoteThread() method, for reasons that I think that are the same.
4 - DLL Injection with Hooking
On the previous method, I just injected a DLL and ran its function which would call UpdateDisplayInfo(). In this one, I actually allocated memory and injected ASM similar to the 2nd method I described, but now, in a more managed way, like below:
Code:
typedef void (__thiscall * UpdateDisplayInfo)(DWORD arg1, DWORD arg2);
typedef int (__cdecl * DoString)(const char *arg1, const char *arg2, int arg3);
__declspec(naked) void codeasm(){
DWORD player_base;
int flag;
__asm{
nop
pushad
pushfd
push ebp
mov ebp, esp
sub esp, __LOCAL_SIZE
mov player_base, 0x0
mov flag, 0x2
}
if(flag == 1){
UpdateDisplayInfo(base + 0x3f7390)(player_base,1);
}else if(flag == 2){
DoString(base + 0x54ee6)(cmd,cmd,0); // yeah, it's a variable located in the DLL
}
flag = 0;
__asm{
mov esp, ebp
pop ebp
ab: popfd
popad
nop
mov eax, edi
pop edi
pop esi
pop ebp
ret
nop
}
}
With this method, I don't need to worry about writing an Assembly structure for each function that I want to call since I'm using fuction pointers and I just need to change the flag to the desired function. I did a bunch of modifications in the above function, for example, setting "flag" and "player_base" as global variables and it would work just fine. The above code isn't totally accurate because I was experimenting some stuff, but I think you guys got the idea of "calling in a managed way" the functions. The issues with this method that I found are:
- Again, what if I want to call UpdateDisplayInfo() on another Unit instead of the Player? How will I change that parameter from my executable (the one that injected the DLL)?
- The DLL will be loaded on Wow's process, which, for me, isn't something safe. Not to mention that all the exported functions are shown, which is something that, as of now, I don't know how to hide.
- Ok, I'm calling the functions in a "managed way", but, it's still quite ugly if I have to add a bunch of "if's" for every function that I decide to call. And how about their parameters? Ok if they are in the DLL, but what if I want to unload the DLL?
What I tried to accomplish with this method is:
1 - Inject my DLL
2 - The DLL injects my codeasm() function which has little ASM and calls Wow functions with function pointers
3 - Unload the DLL but with the code already injected
4 - Pass different parameters easily to the functions in the stub. Therefore, the variables must not refer the DLL at any point.
1, 2 and 3 are ok... but 4, I have no idea on how to do it, not even if that's possible.
Anyways, this post got bigger than I expected so I'm ending it soon. As you guys can notice, I'm quite lost and having a hard time to find the best way to do what I want. If you read until now and have some light to share with me, I'd appreciate it a lot! Feel free to criticize the methods I've tried and even my behaviour in "not wanting to use something that is already done" like Detours, BlackMagic, etc (although I barely know what they do exactly or even how to use them). I think that most of my problems would be solved and I would have learned a lot more if I had opened the source of my code and had someone else to help me out with this stuff. But I haven't done this yet, because my code is ugly and poorly object-oriented. But if you guys need more details to help me out, I will do my best to provide them.
Finally, I didn't touch the "security" subject, because I think I'm quite behind on other basic principles. What I can say is just that I hook where I think Warden doesn't scan, but I don't know exactly how to protect against it. I also don't know what the safest method is among all of these that I tried... so yeah, I don't have much to say about security. Maybe some other time...
Aaaand that's basically it. Thanks a lot for your attention and I apologize for the long post
PS: I probably forgot to add or explain something somewhere... but I guess this is enough to get a general idea of what I want...
PS2: Again, feel free to bash this post if needed. I'm open to any feedback... Even a "Yo, learn C#" will be considered...