[PATCH 2/2] ntdll: Correctly implement ThreadHideFromDebugger.

Rémi Bernon rbernon at codeweavers.com
Fri Jun 26 04:27:29 CDT 2020


At least, store the thread information, instead of pretending and
failing to correctly validate handles and access rights.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/ntdll/tests/info.c  |  3 ---
 dlls/ntdll/unix/thread.c | 22 +++++++++++++++++-----
 server/protocol.def      |  3 +++
 server/thread.c          |  8 +++++++-
 server/thread.h          |  1 +
 5 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index b91d54375ce..aae729dccff 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -2498,18 +2498,15 @@ static void test_HideFromDebugger(void)
 
     dummy = 0;
     status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, NULL );
-    todo_wine
     ok( status == STATUS_SUCCESS || status == STATUS_INVALID_INFO_CLASS,
         "Expected STATUS_SUCCESS, got %08x\n", status );
     if (status == STATUS_SUCCESS) ok( dummy == 0, "Expected dummy == 0, got %08x\n", dummy );
 
     status = pNtSetInformationThread( thread, ThreadHideFromDebugger, NULL, 0 );
-    todo_wine
     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
 
     dummy = 0;
     status = NtQueryInformationThread( thread, ThreadHideFromDebugger, &dummy, 1, NULL );
-    todo_wine
     ok( status == STATUS_SUCCESS || status == STATUS_INVALID_INFO_CLASS,
         "Expected STATUS_SUCCESS, got %08x\n", status );
     if (status == STATUS_SUCCESS) ok( dummy == 1, "Expected dummy == 1, got %08x\n", dummy );
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c
index f3dddd2b02a..8463119a5ed 100644
--- a/dlls/ntdll/unix/thread.c
+++ b/dlls/ntdll/unix/thread.c
@@ -1067,8 +1067,15 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
     case ThreadHideFromDebugger:
         if (length != sizeof(BOOLEAN)) return STATUS_INFO_LENGTH_MISMATCH;
         if (!data) return STATUS_ACCESS_VIOLATION;
-        if (handle != GetCurrentThread()) return STATUS_ACCESS_DENIED;
-        *(BOOLEAN*)data = TRUE;
+        SERVER_START_REQ( get_thread_info )
+        {
+            req->handle = wine_server_obj_handle( handle );
+            req->tid_in = 0;
+            req->access = THREAD_QUERY_INFORMATION;
+            if ((status = wine_server_call( req ))) return status;
+            *(BOOLEAN*)data = reply->dbg_hidden;
+        }
+        SERVER_END_REQ;
         if (ret_len) *ret_len = sizeof(BOOLEAN);
         return STATUS_SUCCESS;
 
@@ -1164,9 +1171,14 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
 
     case ThreadHideFromDebugger:
         if (length) return STATUS_INFO_LENGTH_MISMATCH;
-        if (handle != GetCurrentThread()) return STATUS_INVALID_HANDLE;
-        /* pretend the call succeeded to satisfy some code protectors */
-        return STATUS_SUCCESS;
+        SERVER_START_REQ( set_thread_info )
+        {
+            req->handle = wine_server_obj_handle( handle );
+            req->mask   = SET_THREAD_INFO_DBG_HIDDEN;
+            status = wine_server_call( req );
+        }
+        SERVER_END_REQ;
+        return status;
 
     case ThreadQuerySetWin32StartAddress:
     {
diff --git a/server/protocol.def b/server/protocol.def
index c3442c06e9b..ff2f3ed31ab 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -946,6 +946,7 @@ struct rawinput_device
 @REQ(get_thread_info)
     obj_handle_t handle;        /* thread handle */
     thread_id_t  tid_in;        /* thread id (optional) */
+    unsigned int access;        /* required access rights */
 @REPLY
     process_id_t pid;           /* server process id */
     thread_id_t  tid;           /* server thread id */
@@ -956,6 +957,7 @@ struct rawinput_device
     int          priority;      /* thread priority level */
     int          last;          /* last thread in process */
     int          suspend_count; /* thread suspend count */
+    int          dbg_hidden;    /* thread hidden from debugger */
     data_size_t  desc_len;      /* description length in bytes */
     VARARG(desc,unicode_str);   /* description string */
 @END
@@ -985,6 +987,7 @@ struct rawinput_device
 #define SET_THREAD_INFO_TOKEN       0x04
 #define SET_THREAD_INFO_ENTRYPOINT  0x08
 #define SET_THREAD_INFO_DESCRIPTION 0x10
+#define SET_THREAD_INFO_DBG_HIDDEN  0x20
 
 
 /* Retrieve information about a module */
diff --git a/server/thread.c b/server/thread.c
index e2bfa50c7ba..eb287d74184 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -234,6 +234,7 @@ static inline void init_thread_structure( struct thread *thread )
     thread->exit_code       = 0;
     thread->priority        = 0;
     thread->suspend         = 0;
+    thread->dbg_hidden      = 0;
     thread->desktop_users   = 0;
     thread->token           = NULL;
     thread->desc            = NULL;
@@ -624,6 +625,8 @@ static void set_thread_info( struct thread *thread,
         security_set_thread_token( thread, req->token );
     if (req->mask & SET_THREAD_INFO_ENTRYPOINT)
         thread->entry_point = req->entry_point;
+    if (req->mask & SET_THREAD_INFO_DBG_HIDDEN)
+        thread->dbg_hidden = 1;
     if (req->mask & SET_THREAD_INFO_DESCRIPTION)
     {
         WCHAR *desc;
@@ -1516,9 +1519,11 @@ DECL_HANDLER(get_thread_info)
 {
     struct thread *thread;
     obj_handle_t handle = req->handle;
+    unsigned int access = req->access;
 
+    if (!access) access = THREAD_QUERY_LIMITED_INFORMATION;
     if (!handle) thread = get_thread_from_id( req->tid_in );
-    else thread = get_thread_from_handle( req->handle, THREAD_QUERY_LIMITED_INFORMATION );
+    else thread = get_thread_from_handle( req->handle, access );
 
     if (thread)
     {
@@ -1531,6 +1536,7 @@ DECL_HANDLER(get_thread_info)
         reply->affinity       = thread->affinity;
         reply->last           = thread->process->running_threads == 1;
         reply->suspend_count  = thread->suspend;
+        reply->dbg_hidden     = thread->dbg_hidden;
         reply->desc_len       = thread->desc_len;
 
         if (thread->desc && get_reply_max_size())
diff --git a/server/thread.h b/server/thread.h
index 5d12d24dd89..183f6baa0f2 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -82,6 +82,7 @@ struct thread
     affinity_t             affinity;      /* affinity mask */
     int                    priority;      /* priority level */
     int                    suspend;       /* suspend count */
+    int                    dbg_hidden;    /* hidden from debugger */
     obj_handle_t           desktop;       /* desktop handle */
     int                    desktop_users; /* number of objects using the thread desktop */
     timeout_t              creation_time; /* Thread creation time */
-- 
2.27.0




More information about the wine-devel mailing list