From 802d8a908bbff2b1fd04565e995464dba6e52583 Mon Sep 17 00:00:00 2001 From: diversenok Date: Sun, 23 May 2021 22:41:54 +0200 Subject: [PATCH] Fix some typos --- Readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index 5dfef44..c240ffd 100644 --- a/Readme.md +++ b/Readme.md @@ -6,11 +6,11 @@ I performed most experiments on Windows 10 20H2, but the topics I describe here # Idea -While we can [argue on the exact definition](https://github.com/processhacker/processhacker/issues/856#issuecomment-813092041) of what it means for a thread to be in a suspended state, conceptually, it requires trapping it in the kernel mode and, therefore, preventing it from executing any user-mode code. Since processes do not execute code anyway (they are merely containers for resources), we refer to them as being suspended when all of their threads are. What is interesting for us is to control suspension from an external tool such as Process Hacker. +While we can [argue on the exact definition](https://github.com/processhacker/processhacker/issues/856#issuecomment-813092041) of what it means for a thread to be in a suspended state, conceptually, it requires trapping it in the kernel mode and, therefore, preventing it from executing any user-mode code. Since processes do not execute code anyway (they are merely containers for resources), we refer to them as being suspended when all their threads are. What is interesting for us is to control suspension from an external tool such as Process Hacker. Under the hood, the system maintains a ***suspend count*** for each thread (stored in `KTHREAD`), which we can increment and decrement through [`SuspendThread`](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-suspendthread) and [`ResumeThread`](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-resumethread), respectively. Besides that, suspending queues a kernel APC that always executes before the thread switches modes. Thus, a thread can never execute user-mode code unless its suspend count is zero. Check out [this comment](https://github.com/microsoft/terminal/issues/9704#issuecomment-814398869) for some interesting insights on the pitfalls of interoperation between suspension and non-alertable synchronous I/O. -The second mechanism we are going to cover here is called ***freezing***. Overall, it acts similar to suspension but cannot be undone via `ResumeThread`. Remember that suspension is an entirely per-thread feature? Freezing, on the other hand, is somewhat hybrid. Each thread stores a dedicated bit within its `KTHREAD` structure (as part of `ThreadFlags`), but the actual counter resides in the process object (`KPROCESS`). +The second mechanism we are going to cover here is called ***freezing***. Overall, it acts like suspension but cannot be undone via `ResumeThread`. Remember that suspension is an entirely per-thread feature? Freezing, on the other hand, is somewhat hybrid. Each thread stores a dedicated bit within its `KTHREAD` structure (as part of `ThreadFlags`), but the actual counter resides in the process object (`KPROCESS`). [`NtQueryInformationThread`](https://github.com/processhacker/processhacker/blob/000a748b3c2bf75cff03212cbc59a30cd67c2043/phnt/include/ntpsapi.h#L1360-L1369) exposes the value of the suspend counter via the `ThreadSuspendCount` info class. Note that the function increments the output (originating from `KTHREAD`'s `SuspendCount`) by one for frozen processes. So, if we ever encounter a thread with a `ThreadSuspendCount` of one that we can increment but cannot decrement - it is definitely frozen. @@ -87,7 +87,7 @@ _-_ | Does not suspend f ## Suspend via NtSuspendProcess ### Idea -A pair of functions called [`NtSuspendProcess`](https://github.com/processhacker/processhacker/blob/c28efff632e76f1cb60aeb798a4cceae1289f3dd/phnt/include/ntpsapi.h#L1195-L1200) and [`NtResumeProcess`](https://github.com/processhacker/processhacker/blob/c28efff632e76f1cb60aeb798a4cceae1289f3dd/phnt/include/ntpsapi.h#L1202-L1207) provides an exceptionally straightforward and easy-to-use solution. This is the most widely-used method that powers suspension functionality in **Windows Resource Monitor**, **Process Explorer**, **Process Hacker**, and a handful of other tools. +A pair of functions called [`NtSuspendProcess`](https://github.com/processhacker/processhacker/blob/c28efff632e76f1cb60aeb798a4cceae1289f3dd/phnt/include/ntpsapi.h#L1195-L1200) and [`NtResumeProcess`](https://github.com/processhacker/processhacker/blob/c28efff632e76f1cb60aeb798a4cceae1289f3dd/phnt/include/ntpsapi.h#L1202-L1207) provides an exceptionally straightforward and easy-to-use solution. This is the most widely used method that powers suspension functionality in **Windows Resource Monitor**, **Process Explorer**, **Process Hacker**, and a handful of other tools. ### Bypasses Unfortunately for us, it also suffers from almost the same set of problems. The method itself is surprisingly similar to the previous one with a single significant difference - it executes in the kernel mode and does not require passing additional access checks. Essentially, it uses a loop of `PsGetNextProcessThread` + `PsSuspendThread` as opposed to `NtGetNextThread` + `NtSuspendThread` we had in the previous case. Thus, it fails to provide atomicity and falls victim to the race condition from item **2A**. And again, you can demonstrate this behavior with any of the tools mentioned above by trying to suspend the **SuspendMe** program when it works in the race-condition-bypassing mode. The examples with thread pools and thread hijacking also apply here; feel free to experiment yourself. @@ -267,6 +267,6 @@ Transitions / second: 0 # Conclusion -I was surprised to learn that the most commonly used techniques utilized by both first- and third-party tools have reliability issues that allow a specially crafted program to circumvent them. We saw that Microsoft takes the steps in the right direction: first, they introduced job-based deep-freezing, then significantly improved ordinary freezing and included a great alternative solution. The debugging-based technique turned out to be full of peculiar pitfalls and weaknesses, but with some tweaking, it might a better option than using `NtSuspendProcess` in tools like Process Hacker. +I was surprised to learn that the most commonly used techniques utilized by both first- and third-party tools have reliability issues that allow a specially crafted program to circumvent them. We saw that Microsoft takes the steps in the right direction: first, they introduced job-based deep-freezing, then significantly improved ordinary freezing and included a great alternative solution. The debugging-based technique turned out to be full of peculiar pitfalls and weaknesses, but with some tweaking, it might be a better option than using `NtSuspendProcess` in tools like Process Hacker. Feel free to use the [Discussions page](https://github.com/diversenok/Suspending-Techniques/discussions) for sharing your ideas on improving, bypassing, or utilizing suspension techniques.