Solved Hooking GetAsyncKeyState or Finding References to vTable Functions

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

bozo

Dank Tier Donator
Aug 26, 2020
4
223
1
Game Name
Nexus
Anticheat
Not sure... used to be run by Nexon, so maybe one of theirs?
How long you been coding/hacking?
Coding? ~7 years. Hacking? ~4 months.
Coding Language
C++
I've been using an old MMO to learn reversing for the past few months:
Nexus, The kingdom of winds

Things are going pretty well. I've gotten the hang of stuff like building/injecting DLLs, reading/writing memory, basic RTTI, and even trampoline/gateway hooks. I've been using Cheat Engine, Reclass.NET, and Ghidra, mostly. The current state of my work is here: unkmc/WhisperBracelet but be warned, this repo is kind of a scratch-pad for all of the random stuff I've been working through so it's really messy.

One thing I've been struggling with is input. In game, if you click and hold left mouse-button down on an NPC, your character will run over and start attacking it. I'd like to simulate that behavior with my injected DLL. I've hooked the WndProc function using FindWindowExA and SetWindowLongPtr and monitored what happens when input comes into the window. Mouse stuff is a little weird, as I seem to get 3 messages each time a mouse action happens, one with the expected uMsg of WM_LBUTTONDOWN, and two others, 0x84 and 0x20. Anyway, when I reproduce those (I'm not actually sure the extra 2 need to be reproduced, but I send them anyway) I do get some input behavior. For example, I can pick up and rearrange inventory items, click to walk, etc. But clicking on an NPC doesn't quite work. The mouse cursor changes to the "attack" icon, so I can tell the game detects that the mouse is within the NPC's hit box, but that's it: unkmc/WhisperBracelet

I've set debug breakpoints in CheatEngine and looked around in Ghidra a lot and followed various paths through the decompiled code, and my primary suspect for why this isn't working is in case #7 of this function:
FUN_00509030.png

It's checking the mouse button with GetAsyncKeyState there, and I read here: GetAsyncKeyState function (winuser.h) - Win32 apps "the call GetAsyncKeyState(VK_LBUTTON) always returns the state of the left physical mouse button". The physical button isn't being pressed, so I tried hooking GetAsyncKeyState. I figured, after I send WM_LBUTTONDOWN, I could hook GetAsyncKeyState to respond that the mouse button is really down until I'm ready to send WM_LBUTTONUP: unkmc/WhisperBracelet

The hook itself actually works pretty well... until it doesn't. I see my hooked GetAsyncKeyState spamming about 160 and 17, but the game inevitably crashes and the Visual Studio debugger shows an error like "Exception thrown at 0x004A8AF0 in NexusTK.exe: 0xC0000005: Access violation reading location 0x92F16096." with other, similarly wild locations. So, question #1, did I do something wrong with my hook? Forum search results about how to hook GetAsyncKeyState are poisoned with references to GetAsyncKeyState driven hotkeys, so I was trying to adapt these two posts to work for me:
Guide - How to Hook Functions - Code Detouring Guide (vTable hooking section)
Source Code - Simple internal VFTManager - ( vTable Hook )

Instead of emulating input should I try to figure out what's calling this function, what calls that, etc in order to call some higher level function? If so, I think I need some help with that. I'm familiar with how to find references to functions in Ghidra, but this is a vTable function and the only reference I see is the vTable. So, main question #2 is, how do I find references to a vTable function?
 

bozo

Dank Tier Donator
Aug 26, 2020
4
223
1
Alright, I got my GetAsyncKeyState hook working. I reviewed it, Ghidra, and user32.dll a couple of times and figured out that the calling convention I used wasn't right.
For future reference, if anyone comes across this thread, here's how I hooked GetAsyncKeyState:

Hooks.h:
//SHORT __stdcall GetAsyncKeyState(int vKey)
typedef SHORT(__stdcall *GetAsyncKeyState_t)(int);
extern GetAsyncKeyState_t originalGetAsyncKeyState;
SHORT __stdcall hookedGetAsyncKeyState(int vKey);
tuple<char*, char*, int> hookGetAsyncKeyState();
Hooks.cpp:
GetAsyncKeyState_t originalGetAsyncKeyState;
SHORT __stdcall hookedGetAsyncKeyState(int vKey) {
  if (vKey != VK_END
    && vKey != VK_HOME
    && vKey != VK_CONTROL
    && vKey != 0xA0
    && vKey != 0x17) {
    cout << "GetAsyncKeyState: " << hex << vKey << dec << "\n";
  }
  if (vKey == VK_LBUTTON) {
    return 1;
  }
  return originalGetAsyncKeyState(vKey);
}

tuple<char*, char*, int> hookGetAsyncKeyState() {
  int numBytesToReplace = 5;
  char* originalGetAsyncKeyStatePointer = (char*)GetAsyncKeyState;
  char* GetAsyncKeyStateGatewayPointer = TrampHook32(originalGetAsyncKeyStatePointer, (char*)hookedGetAsyncKeyState, numBytesToReplace);
  originalGetAsyncKeyState = (GetAsyncKeyState_t)GetAsyncKeyStateGatewayPointer;
  return { originalGetAsyncKeyStatePointer, GetAsyncKeyStateGatewayPointer, numBytesToReplace };
}

void UnHook(tuple<char*, char*, int> hookResult) {
  UnHook32(get<0>(hookResult), get<1>(hookResult), get<2>(hookResult));
}
 
  • Like
Reactions: Rake and Petko123

Rake

I'm not your friend
Administrator
Jan 21, 2014
12,497
78,998
2,417
how do I find references to a vTable function?
statically? in my experience, you can't, you have to breakpoint it and check the call stack to find what functions calls it, or make a little logger that does it

if the game uses GAKs it's retarded
 

bozo

Dank Tier Donator
Aug 26, 2020
4
223
1
statically? in my experience, you can't, you have to breakpoint it and check the call stack to find what functions calls it, or make a little logger that does it

if the game uses GAKs it's retarded
Well, I was trying to use IDA to debug the game, but it instant-crashes. I'm not so great with assembly, so I haven't jumped in to debug with Cheat Engine.
Adding logging sounds more like my style, so maybe I can do that. Can you link me to a thread about finding callers of functions at runtime?

Also, yeah... the game was written in the early 90s, so it's 25+ years old. I'm not surprised they used some shortcuts here and there. Is hooking GetAsyncKeyState an option? After I posted this I did some testing while holding the left mouse button down (to simulate what I would return if I had it hooked) and it seemed like it might work.
 

Oskars

Jr.Coder
Dank Tier Donator
Nobleman
Sep 13, 2017
167
2,698
18
Why not simulate input with SendInput or mouse_event ?
To check if you hook correctly, just hook and call the function yourself. If it doesn't crash it means the hooks works.
Also it is worth checking if your game uses direct input...
 

bozo

Dank Tier Donator
Aug 26, 2020
4
223
1
Why not simulate input with SendInput or mouse_event ?
To check if you hook correctly, just hook and call the function yourself. If it doesn't crash it means the hooks works.
Also it is worth checking if your game uses direct input...
SendInput doesn't work when the window is not in focus, right?
Does mouse_event?

Edit: Oh.... I am calling GetAsyncKeyState within my hookedGetAsyncKeyState: unkmc/WhisperBracelet
That might be my problem🤦‍♂️ I probably need to save the value of the game's GetAsyncKeyState pointer and call that.
 

h4nsbr1x

Dank Tier Donator
Full Member
Nobleman
Jul 24, 2020
63
3,343
1
As Rake said, get a debugger working with it. This is useful not just for reversing the code flow, but also for fixing bugs in your own hooks
 

Rake

I'm not your friend
Administrator
Jan 21, 2014
12,497
78,998
2,417
sendinput and mouse_event are the same, mouse_event is deprecated in favor of sendinput
 
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Similar threads

Community Mods