[PATCH v4 0/2] MR7579: ntdll: Return STATUS_ACCESS_VIOLATION if ret_len is not writable
Required for implementation correctness check in certain protection software. Thanks to mkrsym1 <mkrsym1(a)gmail.com> for the patch! -- v4: ntdll/tests: Add tests for ret_len on NtQueryInformationThread HideFromDebugger. ntdll: Return STATUS_ACCESS_VIOLATION from NtQueryInformationThread ThreadHideFromDebugger if *ret_len is not writable. https://gitlab.winehq.org/wine/wine/-/merge_requests/7579
From: Dylan Donnell <dylan.donnell(a)student.griffith.ie> --- dlls/ntdll/unix/thread.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index b64a7dd40af..d3ddcf13963 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -2275,6 +2275,12 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class, return get_thread_wow64_context( handle, data, length ); case ThreadHideFromDebugger: + /* TP Shell Service depends on ThreadHideFromDebugger returning + * STATUS_ACCESS_VIOLATION if *ret_len is not writable, before + * any other checks. Despite the status, the variable does not + * actually seem to be written at that time. */ + if (ret_len) *(volatile ULONG *)ret_len |= 0; + if (length != sizeof(BOOLEAN)) return STATUS_INFO_LENGTH_MISMATCH; if (!data) return STATUS_ACCESS_VIOLATION; SERVER_START_REQ( get_thread_info ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7579
From: Dylan Donnell <dylan.donnell(a)student.griffith.ie> --- dlls/ntdll/tests/info.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 5003a5b50c2..e78edae48d4 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -3274,7 +3274,7 @@ static void test_HideFromDebugger(void) { NTSTATUS status; HANDLE thread, stop_event; - ULONG dummy; + ULONG dummy, ret_len; dummy = 0; status = pNtSetInformationThread( GetCurrentThread(), ThreadHideFromDebugger, &dummy, sizeof(ULONG) ); @@ -3321,6 +3321,27 @@ static void test_HideFromDebugger(void) ok( status == STATUS_SUCCESS, "got %#lx\n", status ); ok( dummy == 1, "Expected dummy == 1, got %08lx\n", dummy ); + status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, (ULONG *)1 ); + ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status ); + + status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 0, (ULONG *)1 ); + ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", status ); + + ret_len = 0xdeadbeef; + status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 0, &ret_len ); + ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#lx\n", status ); + ok( ret_len == 1, "Expected ret_len == 1, got %08lx\n", ret_len ); + + ret_len = 0xdeadbeef; + status = NtQueryInformationThread( (HANDLE)0xdeadbeef, ThreadHideFromDebugger, &dummy, 1, &ret_len ); + ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %#lx\n", status ); + ok( ret_len == 0xdeadbeef, "Expected ret_len == deadbeef, got %08lx\n", ret_len ); + + ret_len = 0xdeadbeef; + status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, &ret_len ); + ok( status == STATUS_SUCCESS, "got %#lx\n", status ); + ok( ret_len == 0xdeadbeef, "Expected ret_len == deadbeef, got %08lx\n", ret_len ); + SetEvent( stop_event ); WaitForSingleObject( thread, INFINITE ); CloseHandle( thread ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7579
participants (2)
-
Dylan Donnell -
Dylan Donnell (@dy-tea)