SpecialK is seemingly creating a new process when DACLs are set

I have an interesting situation here with a game launcher that seems to result in SpecialK terminating a game’s original process and creating a new one. I’m talking about the FFXIVQuickLauncher for Final Fantasy 14: GitHub - goatcorp/FFXIVQuickLauncher: Custom launcher for Final Fantasy XIV

The symptom is that the launcher starts the game process, does some stuff to it, then immediately checks whether it’s still running… and if I have SpecialK loading, it isn’t; the original game process is gone, replaced with a new one. I can prevent this from happening by inserting a sleep at a specific point, but I’d like to understand why that is.

You can see what it’s doing here, starting at line 378. FFXIVQuickLauncher/NativeAclFix.cs at f89c277739ff7a4f19124f2b3774b4818ef9e5ff · goatcorp/FFXIVQuickLauncher · GitHub

  1. CreateProcess, with CREATE_SUSPENDED
  2. LookupPrivilegeValue, PrivilegeCheck, and, if necessary, AdjustTokenPrivileges
  3. ResumeThread
  4. WaitForInputIdle
  5. SetSecurityInfo
  6. Back in Launcher.cs, it calls .Refresh() on the Process object and then checks .HasExited.

This unexpected behavior of the game process exiting and being replaced with a new one occurs between steps 5 and 6. It does not happen if I insert a 1-second sleep after the WaitForInputIdle call and before the SetSecurityInfo one, steps 4 and 5.

I don’t know anything about DACLs or SpecialK’s code, so I can’t even take a guess as to what’s happening, here. Does anyone have any insight on this?

What version of Special K does this occur with? And are you using global or local injection?

It’s probably triggering SK’s anti-debug protection code. Why is that launcher removing privileges while the process is suspended?

SK’s designed to prevent tampering with debug privileges while threads are suspended. It will resume the thread and revert any attempts made to hide a thread from debuggers, detach debuggers, etc. There’s no legitimate reason to do that sort of thing.

So if the launcher’s waiting on the thread that it’s tampering with, it’s going to have run to completion already. I’d try nixing the anti-debug stuff :slight_smile:

Several versions, including 0.9.24, 0.10.3, and 21.4.4.

That’s interesting, thank you. I’ll ask that of the author.

Summary: This is not due to anything specific to Special K, and I desire no changes to it. Thanks for your answers.

The author told me that the game re-launches itself to correct its ACLs if it detects that they’re wrong, and that the launcher changes the ACLs in order to allow non-Admin process (like the launcher itself) to interact with the game. I infer from the code that it tries to wait until after the main thread checks the ACLs before changing them. With Special K in the pipeline, I must assume that either the ACL check is delayed or WaitForIdle returns earlier, such that the ACL-changing code is executed before the game checks them, thus the game restarts itself.

I haven’t gotten an explanation for why the SeDebugPrivilege is removed despite asking twice. The game appeared to run fine when I commented that line out, though I didn’t run it for long.

Anyway, this is solved by putting a short Thread.sleep in before the ACLs are changed, giving the game time to do its check. I am seeing if I can convince the author to consider a PR. If not, at least I can use my own fork.