Page 1 of 1

Help me suspend winlogon on Win10 without external tools (run as SYSTEM?)

Posted: 12 Sep 2017, 16:56
by WAZAAAAA
I'm trying to suspend the running process winlogon.exe on a Windows 10 machine without the aid of third party programs, just AHK.
My final goal is to build a script that allows me to easily toggle the desktop composition ON/OFF by triggering the old Basic theme, since the last OS capable of doing this in a "normal" way was Windows 7.

Using AHK I can suspend most of the processes, but winlogon.exe in particular seems to ignore everything coming from my scripts. These are the various suspension methods that have failed me thus far:
NtSuspendProcess/ZwSuspendProcess, SuspendThread/Wow64SuspendThread, DebugActiveProcess
(and the resume ones:)
NtResumeProcess/ZwResumeProcess, ResumeThread/Wow64ResumeThread, DebugActiveProcessStop

Suspending winlogon.exe succeeded with all the other programs I used: Resource Monitor, Process Hacker, Process Explorer and PsSuspend.

I've also tried to launch my script with a combination of admin vs standard privileges, uncompiled vs compiled with ANSI32 vs UNICODE32 vs UNICODE64 and have had no success.

A glimmer of hope was given to me when I found out that running my script as username "NT AUTHORITY\SYSTEM" under Desktop "WinSta0\Default" with the help of Process Hacker's "Run as..." function FINALLY let me to suspend the goddamn process through my script, but I don't know how to code this within AHK, and the only script I've found on the forums that does something similar on Win10 is a 2000 lines long project with like 5 include files that I frankly don't know how to touch https://autohotkey.com/boards/viewtopic.php?t=27709

Therefore, my request would be... is there a way to "self-elevate" a script to run as SYSTEM without external tools? Or is there some alternative way to properly suspend winlogon.exe on Win10 that I'm missing?

Re: Help me suspend winlogon on Win10 without external tools (run as SYSTEM?)  Topic is solved

Posted: 12 Sep 2017, 17:09
by qwerty12
WAZAAAAA wrote:Using AHK I can suspend most of the processes, but winlogon.exe in particular seems to ignore everything coming from my scripts. These are the various suspension methods that have failed me thus far[...]

Suspending winlogon.exe succeeded with all the other programs I used: Resource Monitor, Process Hacker, Process Explorer and PsSuspend.
You're just forgetting to enable SeDebugPrivilege (which by default can only be done in an elevated process, so make sure that's the case first). Look at example 4 here.
A glimmer of hope was given to me when I found out that running my script as username "NT AUTHORITY\SYSTEM" under Desktop "WinSta0\Default" with the help of Process Hacker's "Run as..." function FINALLY let me to suspend the goddamn process through my script, but I don't know how to code this within AHK, and the only script I've found on the forums that does something similar on Win10 is a 2000 lines long project with like 5 include files that I frankly don't know how to touch https://autohotkey.com/boards/viewtopic.php?t=27709
:( But, granted, it is messy and it's overkill for this anyway - the main point of that is to run programs on different desktops. If you really want to run your script as SYSTEM, just take the Task Scheduler function I have in LogonDesktop.ahk or find the example I have there that tries to find a suitable SYSTEM token to impersonate with in the same process (I'm pretty sure that script just relies on LogonDesktop.ahk, nothing else). But you shouldn't need it anyway - enabling the priv above in an elevated process should do it...

Re: Help me suspend winlogon on Win10 without external tools (run as SYSTEM?)

Posted: 12 Sep 2017, 19:43
by WAZAAAAA
YEEES

That was it, it works. I have copy&pasted example 4 verbatim in my script starting from "Process, Exist" up to "close this process handle to save memory", thank you.

On to my next quest of finding a working way to check if a process has been suspended or not...

Re: Help me suspend winlogon on Win10 without external tools (run as SYSTEM?)

Posted: 13 Sep 2017, 09:52
by qwerty12
WAZAAAAA wrote:On to my next quest of finding a working way to check if a process has been suspended or not...
I had the C equivalent of this, taken from the Process Hacker source code, lying around when fixing a bug in clink. There's something off with my conversion, because this works only with 64-bit AutoHotkey (the original C program works fine under 32-bit). Fixed thanks to jeeswg

Code: Select all

#NoEnv

ProcessIsSuspended(pid, ByRef isPartiallySuspended := 0) {
	static initialBufferSize := 0x4000, cbSYSTEM_THREAD_INFORMATION := A_PtrSize == 8 ? 80 : 64
	static SystemProcessInformation := 5, STATUS_BUFFER_TOO_SMALL := 0xC0000023, STATUS_INFO_LENGTH_MISMATCH := 0xC0000004
	static Waiting := 5, Suspended := 5
	static UniqueProcessIdOffset := A_PtrSize == 8 ? 80 : 68, NumberOfThreadsOffset := 4, ThreadsArrayOffset := A_PtrSize == 8 ? 256 : 184
	static ThreadStateOffset := A_PtrSize == 8 ? 68 : 52, WaitReasonOffset := A_PtrSize == 8 ? 72 : 56
	bufferSize := initialBufferSize

	VarSetCapacity(ProcessBuffer, bufferSize)
	
	Loop {
		status := DllCall("ntdll\NtQuerySystemInformation", "UInt", SystemProcessInformation, "Ptr", &ProcessBuffer, "UInt", bufferSize, "UInt*", bufferSize, "UInt")
		if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MISMATCH) {
			VarSetCapacity(ProcessBuffer, bufferSize)
		}
		else {
			break
		}
	}

	if (status < 0)	{
		return False
	}

	if (bufferSize <= 0x100000) initialBufferSize := bufferSize

	isSuspended := pid > 0
	isPartiallySuspended := False
	ThisEntryOffset := 0

	Loop {
		if (NumGet(ProcessBuffer, ThisEntryOffset + UniqueProcessIdOffset, "Ptr") == pid) {
			Loop % NumGet(ProcessBuffer, ThisEntryOffset + NumberOfThreadsOffset, "UInt") {
				ThisThreadsOffset := ThisEntryOffset + ThreadsArrayOffset + (cbSYSTEM_THREAD_INFORMATION * (A_Index - 1))
				ThreadState := NumGet(ProcessBuffer, ThisThreadsOffset + ThreadStateOffset, "UInt")
				WaitReason := NumGet(ProcessBuffer, ThisThreadsOffset + WaitReasonOffset, "UInt")
				if (ThreadState != Waiting || WaitReason != Suspended) {
					isSuspended := False
				} else {
					isPartiallySuspended := True
				}
			}
			return isSuspended
		}
	} until (!(NextEntryOffset := NumGet(ProcessBuffer, ThisEntryOffset, "UInt")), ThisEntryOffset += NextEntryOffset)
	
	return -1
}

MsgBox % ProcessIsSuspended(560)
I believe another way of checking if a process is suspended is with enumerating the process's threads with WMI, but I neither like it nor know how to use it...

EDIT:
jeeswg wrote:According to this, the size is 80 or 64.
Oops. Thanks, adding the missing four bytes sorted it.

Re: Help me suspend winlogon on Win10 without external tools (run as SYSTEM?)

Posted: 13 Sep 2017, 10:50
by jeeswg
Re. x64 v. x32.
SYSTEM_THREAD_INFORMATION
http://www.geoffchappell.com/studies/wi ... thread.htm
According to this, the size is 80 or 64.

Re: Help me suspend winlogon on Win10 without external tools (run as SYSTEM?)

Posted: 13 Sep 2017, 19:38
by WAZAAAAA
I wanna kiss you