New Question!

c++ / delphi package - dll injection and api hooking
Post Reply
Astaelan
Posts: 22
Joined: Wed Sep 22, 2004 7:08 pm

New Question!

Post by Astaelan »

Okay, so I've decided I'm going to try and hook GetKeyState, you can imagine the pain this is causing me to even test it.

What I need to know, is how I can limit the injection of my DLL into 2 specific places. First, there is the game.exe, second there is HanDes.dll. I don't know if you can inject a DLL into another DLL. So I assume the way it works is game.exe calls HanDes.dll, and makes all it's calls through the hooks HanDes provides. These calls I believe are made through some sort of encrypted function calls.

So I guess what I'm asking is if I hook into GetKeyState, is HanDes.dll going to override this? Is there a specific order hooking has to occur (HanDes.dll first?). I really don't know how they are doing this. Seems like their protection is lightyears beyond what other games today are using...

Any help on this would be much appreciated.
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

You can't inject a dll into another dll. You can inject a dll into one process or into multiple processes. And when using madCodeHook for API hooking you'll get all API calls that are done in the hooked process, not just those of some specific dlls. In your hook callback function you can ask "GetCallingModule", though, to ask which dll called the hooked API.
Astaelan
Posts: 22
Joined: Wed Sep 22, 2004 7:08 pm

Post by Astaelan »

Hello again.

I tried the GetCallingModule, but I think I am using it wrong.

First, a question. Let's assume I make the EXE, it runs, injects the DLL system-wide. This much I know how to do from my DirectInput success.
Now the problem with GetKeyState is that when I hooked it, I get about 10 thousand msgbox's before explorer crashes. No problem, we know it's hooking properly. Next step, how do I make sure it's only a GetKeyState for the game?
Here is where I'm confused because of specifically how the game is written, and how the DLL calls are done...
In game.exe, it imports only 1 function from HanDes.dll, which is the DecryptFunc. So, my question is, if I'm hooking GetKeyState and trying to match using GetCallingModule, how and what should I compare against? Would it be the game.exe, or HanDes.dll? I think I need to hook the call HanDes.dll is actually doing, since the game itself uses an DecryptFunc call to prevent hooking between HanDes.dll and game.exe.

Okay, I'm getting a bit confusing here, so let me try to break it down a bit simpler. If I hook GetKeyState, how do I compare GetCallingModule so only game.exe and handes.dll are given any special treatment? Here is sorta what I tried, but didn't work right, probably because I'm not using it correctly.

Code: Select all

SHORT WINAPI GetKeyStateCallback(IN int nVirtKey)
{
	SHORT result = GetKeyStateNext(nVirtKey);
	HMODULE hHanDes = GetModuleHandle("c:\\Program Files\\TriglowPictures\\PristonTale\\HanDes.dll");
	HMODULE hGame = GetModuleHandle("c:\\Program Files\\TriglowPictures\\PristonTale\\game.exe");

	if(GetCallingModule() == (DWORD)hGame)
		MessageBox(NULL, "Game!", "", MB_OK);
	else if(GetCallingModule() == (DWORD)hHanDes)
		MessageBox(NULL, "HanDes!", "", MB_OK);

	return result;
}
All I get is a bunch of Game! messagebox's that never end. This should only occur once I open the game though, otherwise just return the result without spamming me.

I kinda had this same idea after hours of digging through the forums and demos, but it just didn't work right.

I guess the main question is, if I call HookAPI for GetKeyState in game.exe, is that even going to get triggered when it calls DecryptFunc in HanDes.dll? It is in HanDes.dll which I suspect makes the GetKeyState call. Game.exe never makes a call to GetKeyState, it probably calls something like DecryptFunc(char *, char *) and returns an int, so I'm guessing it takes a couple strings, decrypts them in the DLL, and returns an integer which gets converted to a pointer or something. I'm not exactly sure, I'm just wondering if GetKeyState will even get triggered if a DLL is injected systemwide to hook GetKeyState, but it's a DLL that makes the call?

If that is what you have explained is possible, then I need to figure out how to specify only to process keys from the correct module, which currently doesn't work. I get spammed soon as the program is opened without ever opening the game.

Thanks again.
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Astaelan wrote:Your code looks alright to me. Does your GetKeyStateCallback function have a stack frame? As is written in the documentation:
"GetCallingModule" returns this information, but it works only if your function has a stack frame.
If your function does have a stack frame, it seems that HanDes.dll didn't t really call GetKeyState.
I guess the main question is, if I call HookAPI for GetKeyState in game.exe, is that even going to get triggered when it calls DecryptFunc in HanDes.dll?
Generally yes. There are some rare special situations where this might fail, but generally madCodeHook API hooks don't care which module (dll/exe) calls the hooked API.
Game.exe never makes a call to GetKeyState
How can you know? Did you disassemble Game.exe? I don't think so. Maybe Game.exe uses GetProcAddress to link to GetKeyState? Sounds a bit strange, but it's possible.
I'm just wondering if GetKeyState will even get triggered if a DLL is injected systemwide to hook GetKeyState, but it's a DLL that makes the call?
Sure it will be triggered. Otherwise madCodeHook wouldn't make that much sense.
Astaelan
Posts: 22
Joined: Wed Sep 22, 2004 7:08 pm

Post by Astaelan »

Okay, sorry this seems a bit newbish, but I'm not familiar with how to force a function to have a stack frame. What do I have to do to ensure it has a stack frame?

My calls to GetCallingModule don't seem to be working the way I expect. They always return the same value. I guess this might have something to do with that stack frame thing you're talking about.

Instead, I did this, and it seems to sort of work?

Code: Select all

	HMODULE hHanDes = GetModuleHandle("handes.dll");
	if(hHanDes != 0)
	{
		bRet = HookAPI("user32.dll", "GetKeyState", GetKeyStateCallback, (PVOID *)&GetKeyStateNext);
		char sBuf[MAX_PATH];
		ProcessIdToFileName(ProcessHandleToId(GetCurrentProcess()), sBuf);
		MessageBox(NULL, sBuf, "", MB_OK);
I get a messagebox that says "game.exe". I'm assuming that if the game itself is doing something like madCodeHook and hooking GetKeyState, then my hook is hopefully being created after theirs here.

I have tried hooking GetKeyState during game.exe, oddly though when I log the value of nVirtKey passed into GetKeyState, it's always 1 of 2 values, either 16 or 17, no matter what keys are pressed. And always 17 then 16, repeating for each key pressed, including mouse clicks it seems.

But I expected GetKeyState to be called repeatedly for different key values, but doesn't seem to be working that way. GetKeyState callback seems to get called only if a key is pressed. This would seem to indicate maybe that my hook is lower in the order, and they are not passing the event on to the next hook unless the key is pressed.

Anyways, back to guess and testing.
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Astaelan wrote:Okay, sorry this seems a bit newbish, but I'm not familiar with how to force a function to have a stack frame. What do I have to do to ensure it has a stack frame?
In Delphi there's a checkbox for forced stack frames in the compiler options. I don't know how you can force stack frames in MSVC. It's probably possible somehow, but I don't know how, I'm not a MSVC expert.
Astaelan wrote:My calls to GetCallingModule don't seem to be working the way I expect. They always return the same value. I guess this might have something to do with that stack frame thing you're talking about.
Either that. Or maybe it's correct? Which module handle does it return? Can't it be true that always only one module is calling GetKeyState?
Astaelan wrote:Instead, I did this, and it seems to sort of work?
I'm sorry, but I don't know what your code is meant for. Btw, "ProcessHandleToId(GetCurrentProcess())" is only a more complicated way to do "GetCurrentProcessId()". And "ProcessIdToFileName(GetCurrentProcessId())" is only a more complicated way to do "GetModuleFileName(NULL)".
Astaelan wrote:I have tried hooking GetKeyState during game.exe, oddly though when I log the value of nVirtKey passed into GetKeyState, it's always 1 of 2 values, either 16 or 17, no matter what keys are pressed. And always 17 then 16, repeating for each key pressed, including mouse clicks it seems.

Code: Select all

const
  VK_SHIFT = 16;
  VK_CONTROL = 17;
Evidently the program uses GetKeyState only for shift and control state asking. That means the program very probably gets the other key information in a different way.
Astaelan
Posts: 22
Joined: Wed Sep 22, 2004 7:08 pm

Post by Astaelan »

Some random searches using google have rendered some hits that say SetWindowsHookExA could be used to obtain unbuffered low level input.

I have tried to hook this call with madCodeHook, but it never seems to get called.

I have tried something else with the developer of AutoHotKey. He graciously wrote a modified copy of AutoHotKey that strips the INJECTED bits during WH_LL events. The script would pop a tooltip up and show you the overall time since last virtual event, and the physical time since last physical move of the mouse. The modified version stripped the bit, and convinced AutoHotKey at least that virtual movements were physical. However, upon starting the game, neither overall nor physical would update without physically moving the mouse, and then both were updated.
Little tidbits of information figured out here and there, but nothing has been successful yet. However, using AutoHotKey, running the mouse move script, then the tooltip script, then the game, and finally a third script that readded a hook at the top of the stack, caused tooltips to at least remain in the foreground, whereas without the third script they would quickly disappear behind the window. I know this isn't much to go on, just another tidbit of information.

It seems you're right, that control and shift are the only key's polled using GetKeyState. So they must be using some other method of obtaining input. Round and round I go in circles, but the latest google searchs bring me back to them using SetWindowsHookExA and hooking low level input. Yet, using madCodeHook, it doesn't seem to get called by the time keyboard and mouse are available. I am out of ideas as to where they could be getting input. It seems if I can figure out where, then madCodeHook can hook it and problem solved. Just no idea where to look anymore... Any other cool tools or ideas that might give me another trail of breadcrumbs to follow?

Thank you so much for your patience. And thanks for the breakdown on the complications of what I was doing with getting process names.

One more minor detail. Having used this code, I found out that after Game.exe runs, 2 more programs are run. GameGuard.des and GameMon.des, both of which contain some exports, but nothing as large as HanDes.dll. I believe GameGuard.des is the autoupdater for GameMon.des, and GameMon.des is a program that somehow interacts with game.exe to ensure people cannot hack the memory of the game while it's running as I understand it.
I don't think this applies to where we're just trying to inject input, so I'm ignoring that for now. I need to figure out how they are obtaining input other than control/shift codes.

Any game designers out there? All I've done is some basic Managed DirectX 9...
madshi
Site Admin
Posts: 10764
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Have you tried hooking SetWindowsHookExW? Apart from that I don't know what to say or how to help. As you said yourself, the problem is not that madCodeHook wouldn't work for you, it's just that you don't know what to hook. And that's the part I can't really help with.
Post Reply