usermode:process_handle
GameProcess handle detection & bypass
Cheat
Type: External usermode
Goal: Obtaining process handle too perform memory reads/writes.
AntiCheat
Type: Usermode
Goal: Monitor active handles and block suspicious handles.
Notes:
Many legit / non malicious processes open handles to game processes, banning based on handles is not directly possible, but we can easily block non whitelisted or suspicious handles and further investigate origin processes. For many games like Counter Strike not enforcing very strict limitations opening or hijacking a handle doesnt really matter, they have not been banning based on handles too the process. Because/due too user experience, theres many legit processes which require a handle too the game.
Cheater
Using OpenProcess to open / create and obtain a handle to the target game process, in order to interact with the process.
DWORD gamePid = std::stoul(argv[1]);
HANDLE hGame = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
gamePid
);AntiCheat
AntiCheat can enumerate all handles, keep track (count) and whitelist certain process handles via signature, licenses or just PID. (pid in our simple POC) We will just block any new opened handle and only allow a certain whitelist. (Which opens a backdoor for cheaters -> handle hijacking)
Windows handles are valid only within the process that owns them, so you cannot directly inspect or close another process’s handle. Following pseudo code visualizes the code flow.
// Pseudo‐code for user‐mode handle detection
DWORD myPid = GetCurrentProcessId();
std::vector<SystemHandle> handles = NtQuerySystemHandleInformation(); // returns all system handles
for (auto& h : handles) {
if (h.targetPid == myPid && !isWhitelisted(h.ownerPid)) {
HANDLE srcProc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, h.ownerPid);
DuplicateHandle(srcProc, (HANDLE)(ULONG_PTR)h.handleValue, NULL, NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
std::cout << "Closed handle from PID " << h.ownerPid << "\n";
CloseHandle(srcProc);
}
}Cheater Bypass
Cheaters can now bypass this detection/prevention with hijacking an existing or in our case whitelisted handle.
// Pseudo‐code for hijacking a handle from a whitelisted process
DWORD sourcePid = WHITELISTED_PID; // PID that already has a valid handle to the game
HANDLE srcProc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, sourcePid);
HANDLE hijackedGameHandle = NULL;
DuplicateHandle(
srcProc,
(HANDLE)(ULONG_PTR)knownHandleValue, // the handle in sourcePid that points to the game
GetCurrentProcess(),
&hijackedGameHandle,
PROCESS_ALL_ACCESS,
FALSE,
DUPLICATE_SAME_ACCESS
);
if (GetProcessId(hijackedGameHandle) == targetGamePid) {
// Successfully hijacked a valid handle to the game
}
CloseHandle(srcProc);You can find full source of the PoC here: https://github.com/0x90sh/fairplaylab_detections/tree/main/usermode-process_handle
Last updated
Was this helpful?


