. . .
How to bypass EAAC (EA anti-cheat)?
EA started using its own anti-cheat EAAC on 10th Oct 2023 in BF2042. Similarly to EAC's hidden system threads. EAAC creates one and spoof the start address. The only way to find a hidden system thread is to use the kernel thread notify callbacks or by stackwalking each system thread. When you stalkwalk system threads, you just check is there a frame that points to their kernel driver memory range.
[!] EAAC system thread: pId: 4 tId: 32596 PETHREAD: 0xFFFFDE8E47CB90C0 start address: 0xFFFFF8046639F430 0xFFFFF8046639F430
Code integrity checks in the anti-cheat that attempts to detect any tampering in the kernel are in EAAC are somewhat equal to EAC. If it detects any tampering. The anti-cheat will terminate the game process and the following popup will appear:
Their anti-cheat also pools a DPC whose deferred routine points to their kernel driver text section. Pointers to deferred routines in the DPC pool are obfuscated in the kernel. It is worth noting that the DPC is in the text section of the driver. Any tampering can be easily detected unless you disable their checks. The less you disable anti-cheats code integrity checks (self-defense), the better.
Once EAAC driver has been initialized. The anti-cheat also blocks any new driver from loading that use ("Nt"ZwLoadDriver) kernel API using a clever method. Code injection will neither work because of a mitigation flags that prevents dynamic code injection (manually mapped DLL's) from loading. The result is 0xC0000604 (STATUS_DYNAMIC_CODE_BLOCKED) if you try to allocate executable memory or alter memory protection from RW to RWX. This is a built-in security feature in the kernel.
More about flags: https://www.unknowncheats.me/forum/3540472-post31.html
To overcome the issue without triggering their integrity checks. You'll need to allocate a RW section and copy the payload. Enable execution via a PTE and it will execute even though the section was allocated RW. If it's a large page (more than 4096 bytes), then you must use the PDE instead.
EAC bypass RtlCreateUserThread
How to bypass EAC's thread creation checks? Both anti-cheats "blocks" any newly created thread outside the protected process. One anti-cheat bypassing technique is to hijack an existing thread. If you hijack the wrong thread, or if there is an error in the shellcode, the game process will crash.
It's also worth mentioning that after you've hijacked a thread, that thread executes code outside of modules (non backed) and this is going to get you either flagged or banned after the anti-cheat stackwalk threads. An additional anti-cheat evasion techniques are required.
To keep the author's private bypass undetectable in EAC and EAAC. I leave that as an exercise for the reader. The article is to be updated...
The trick is to allocate executable memory (RWX
) in the context of a process thread. That eliminates the need to disable mitigation flags
that may trigger anti-cheat's integrity checks. The very same method enables you to create a new dedicated thread but that thread is still executing non backed dynamic code. You'll need to DKOM your newly created thread. The DKOM method the author uses is private and bypasses EAC as well. It's worth to mention that most of DKOM's are subject to PatchGuard bug check but there is a working solution to bypass PatchGuard at runtime for the latest versions of windows https://overlayhack.com/patchguard-bypass
EAC / EAAC
There is a hook on kernel32.dll!BaseThreadInitThunk, ntdll.dll!RtlUserThreadStart, ntdll.dll!KiUserApcDispatch and ntdll.dll!RtlCreateUserThread
The author did not found any inline hooks in the text section but I did not checked the IAT pointers yet.
The lab was performed on Windows 10 Pro 22H2 Build: 19045.3324
CREDITS: IChooseYou vmcall