Expanding on caliber1942's post and analysis, I decided to give this a go. I've played the game for a little bit (note that I don't want to hear or care about multi-player, so don't even bother; I'm playing the Campaign, offline), reminds me of MDK2 for some reason (the grubs, their SFX, dialogues, etc.).
Back on track, not sure how helpful this is gonna be, but hey, at least it might open up room for others to continue on it.
The first thing I usually do with any process (be it a game or not) that has any kinds of protection is to dump it. But to get there, some high level testing first. I recommend you first press Alt+Enter to send the game in windowed mode. Then exit the game so the setting is saved.
***
I've been using [Link] for a long time now as my Task Manager replacement. With that in mind, I've started the game and as soon as it started playing the intro, alt-tabbed, Ctrl+Alt+Del > Task Manager (which, in my case, starts Process Hacker 2) and this:
Notice I've filtered the list for "halo" and found 2 processes derived from that string: "HaloInfinite.exe" and "DumpTool.exe". While writing this, I alt-tabbed back to Process Hacker 2 and saw this now:
Notice the 2nd HaloInfinite.exe showed up. And yes, the game's frozen, just like Caliber mentioned. I also have Cheat Engine open so most likely it was detected.
If you double-click each of them you will see who the parent process is; who created that process:
- DumpTool.exe - PID 11388 - has as parent HaloInfinite.exe
- HaloInfinite[1].exe - PID 1172 - has as parent steam.exe (I ran the Steam shortcut on Desktop, which runs the game through Steam)
- HaloInfinite[2].exe - PID 12896 - has as parent HaloInfinite[1].exe
The above is just informational, I wanted to see WTF is going on with just simple tools, non-invasive.
***
What I did next was to restart the game and as soon as the process starts, open Cheat Engine 7.1 (yes, I still use this version) -- or have it already open -- select HaloInfinite.exe from the Process List and PAUSE it:
Why do you want to do this? Since the detection kicks in quite fast and the process hangs or crashes, you want to be able to catch it BEFORE this happens. What do I mean with "catch"? Put the process in a pause state where you can perform other operations on it. CE is the perfect tool for this, as it doesn't hog on the main thread, allowing you to ATTACH to the process with other tools
***
I debug everything with [Link], so you might as well get it. This tool allows the use of plugins, which you might want to get as well. For anti-debug protections I use mostly ScyllaHide [url=[Link]]plugins[url]. With that in mind and Halo Infinite suspended in CE (paused), just fire x64dbg up and attach it to the HaloInfinite.exe process:
Since I have ScyllaHide active with these settings:
The first thing I saw was this:
Which means that API is hooked by none other than HaloInfinite.exe. Question: which OTHER APIs are hooked? But we'll get to that in a minute.
Several other settings I have active, in case you want to try this:
So, let's dump it:
Now we have a dump of the process, which can be opened statically in x64dbg or the process of your choice (IDA?) and inspected at will
***
So.. which other APIs are hooked by Halo Infinite? You'll have to close x64dbg, which will kill the game process. Back to CE, click the Pause button again so it un-pauses the already killed process (you will want to suspend it again). Start the game again, open process with CE and pause it. When done, let's use another feature almost no one talks about In CE, open Memory View and:
Select the ones I marked and hit OK:
You'll see this:
The ones I highlighted are hooked by our game. Not necessarily by HaloInfinite.exe, but by *something* it spawned.
The ones that aren't highlighted are hooks from gameoverlayrenderer64.dll. How do I know? Let's pick LoadLibraryExW from the list. Double-click it:
Then press SPACE key on that line:
Double-click another in that list and continue checking them out.
Back to the ones I've highlighted. Let's take the first one for a spin:
Double-click and we're here:
The reason I did that is so you see what happens next. We'll do this in the Patch list, right-clicking:
What that action did was to restore the original API code. And we can see that in Memory View:
Do the same with the rest.
So what we did so far was to unhook anything the game hooked, for any reason (I can tell you those hooks aren't for processing purposes, but for anti-debug). How does that help me with bypassing the anti-debug? It doesn't. You've learned how to unhook APIs Simple as that. Why it doesn't help you? Because the game will detect the APIs have been restored.
How does it detect this? Simple. Let's start with just one API, the first one: ntdll.RtlAddVectoredExceptionHandler. Once restored, go to its address in the dump section of Memory View (the bottom part, with bytes), right click the first byte and "Find out what accesses this address":
What you need to be aware of:
- if the game hangs while you do the above, you need to restart the process
- you can use process suspension in CE (pause) at any given point in time
- you can debug while the process is paused ('Find out what accesses this address' works to be activated with process paused!)
Obviously that piece of code you see in the above isn't part of some normal process behavior. It's a scanner Now here's some idea that might break you skull: is this piece of code part of a THREAD you could kill?. And which thread? Well, just set a normal breakpoint on that line and resume the process. Bipity, boppity, bam:
If you take a look at RAX register you can see what it does: it checks our API address for 0xCC values. What is 0xCC? Well, it's an INT3 opcode. What does that mean? Well, when you set a normal, software breakpoint on an address (so not a hardware breakpoint) what the debugger does is to WRITE an 0xCC byte there, at that address. When the address is hit, because we now there have an interrupt code, an exception is triggered. The exception is then intercepted by the debugger through what you visually perceive as "the debugger breaks at that address".
Short version: [in general] process scans APIs for software breakpoints.
Now.. if you remember this API was already hooked and before we restored it, the code there was actually a 0xCC. So what the protection actually checks for here is that you've not restored the code It's not checking for software breakpoints, but to see if what it hooked has been restored or not.
At the same time, my picture above shows a THREAD number: "Currently debugging thread 23E8". Let's see who created this thread and what's going on with it. I'll yet again use x64dbg for that matter, because it has some nice features to it. Even though the process is paused as we've hit a breakpoint, I can still attach x64dbg to the process. What was our thread number? Ah, yes, 23E8.
NOTES:
- the thread number is dynamic, so don't yell "I can't find thread number on my PC" -- it will be different on your PC
- yes, once you attach x64dbg, the process will crash (once resumed in CE, either removing the breakpoint and resuming or unpausing)
You'll see "spaghetti" there, junk bytes. Why? Because, most likely, the protection has cleaned up the code that spawned this thread That doesn't mean we can't kill it. But before you do that, remember to remove the breakpoint in CE and resume the game. Why? We have CE already breaking inside the thread. If you kill the thread before letting the execution finish inside the thread, you'll get an exception - game will crash. That's at least the theory behind it. Game will crash anyway, cuz of the other protections in place I've mentioned
To be continued.
P.S.: Note that Process Hacker 2 is detected and game will freeze. I can only assume it's because it has the word "hack" in the name (or GetWindowTextA/W retrieving the GUI title name contains that).