Rémi Bernon : ntdll: Raise debug exceptions when invalid heap is destroyed.

Alexandre Julliard julliard at winehq.org
Fri Nov 20 14:54:32 CST 2020


Module: wine
Branch: master
Commit: 255270373e036f06578f71afa7af8765212e0652
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=255270373e036f06578f71afa7af8765212e0652

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Thu Nov 19 10:25:23 2020 +0100

ntdll: Raise debug exceptions when invalid heap is destroyed.

And when PEB->BeingDebugged is set to 1. Lords Of The Fallen anti-tamper
does this and only continues if a DBG_PRINTEXCEPTION_C is received.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/heap.c      |  6 +++++
 dlls/ntdll/tests/rtl.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index 1ac0cb24806..88db935746a 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -1589,6 +1589,12 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap )
     void *addr;
 
     TRACE("%p\n", heap );
+    if (!heapPtr && heap && (((HEAP *)heap)->flags & HEAP_VALIDATE_PARAMS) &&
+        NtCurrentTeb()->Peb->BeingDebugged)
+    {
+        DbgPrint( "Attempt to destroy an invalid heap\n" );
+        DbgBreakPoint();
+    }
     if (!heapPtr) return heap;
 
     if (heap == processHeap) return heap; /* cannot delete the main process heap */
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c
index ae8170f41fe..897be4fcd12 100644
--- a/dlls/ntdll/tests/rtl.c
+++ b/dlls/ntdll/tests/rtl.c
@@ -3599,6 +3599,71 @@ static void test_DbgPrint(void)
     RtlRemoveVectoredExceptionHandler( handler );
 }
 
+static BOOL test_heap_destroy_dbgstr = FALSE;
+static BOOL test_heap_destroy_break = FALSE;
+
+static LONG CALLBACK test_heap_destroy_except_handler( EXCEPTION_POINTERS *eptrs )
+{
+    if (eptrs->ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
+    {
+#if defined( __i386__ )
+        eptrs->ContextRecord->Eip += 1;
+        test_heap_destroy_break = TRUE;
+        return (LONG)EXCEPTION_CONTINUE_EXECUTION;
+#elif defined( __x86_64__ )
+        eptrs->ContextRecord->Rip += 1;
+        test_heap_destroy_break = TRUE;
+        return (LONG)EXCEPTION_CONTINUE_EXECUTION;
+#endif
+    }
+
+    if (eptrs->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C)
+    {
+        test_heap_destroy_dbgstr = TRUE;
+        return (LONG)EXCEPTION_CONTINUE_EXECUTION;
+    }
+
+    return (LONG)EXCEPTION_CONTINUE_SEARCH;
+}
+
+/* partially copied from ntdll/heap.c */
+#define HEAP_VALIDATE_PARAMS 0x40000000
+
+struct heap
+{
+    DWORD_PTR unknown1[2];
+    DWORD     unknown2[2];
+    DWORD_PTR unknown3[4];
+    DWORD     unknown4;
+    DWORD_PTR unknown5[2];
+    DWORD     unknown6[3];
+    DWORD_PTR unknown7[2];
+    DWORD     flags;
+    DWORD     force_flags;
+    DWORD_PTR unknown8[6];
+};
+
+static void test_RtlDestroyHeap(void)
+{
+    const struct heap invalid = {{0, 0}, {0, HEAP_VALIDATE_PARAMS}, {0, 0, 0, 0}, 0, {0, 0}, {0, 0, 0}, {0, 0}, HEAP_VALIDATE_PARAMS, 0, {0}};
+    HANDLE heap = (HANDLE)&invalid, ret;
+    PEB *Peb = NtCurrentTeb()->Peb;
+    BOOL debugged;
+    void *handler = RtlAddVectoredExceptionHandler( TRUE, test_heap_destroy_except_handler );
+
+    test_heap_destroy_dbgstr = FALSE;
+    test_heap_destroy_break = FALSE;
+    debugged = Peb->BeingDebugged;
+    Peb->BeingDebugged = TRUE;
+    ret = RtlDestroyHeap( heap );
+    ok( ret == heap, "RtlDestroyHeap(%p) returned %p\n", heap, ret );
+    ok( test_heap_destroy_dbgstr, "HeapDestroy didn't call OutputDebugStrA\n" );
+    ok( test_heap_destroy_break, "HeapDestroy didn't call DbgBreakPoint\n" );
+    Peb->BeingDebugged = debugged;
+
+    RtlRemoveVectoredExceptionHandler( handler );
+}
+
 START_TEST(rtl)
 {
     InitFunctionPtrs();
@@ -3640,4 +3705,5 @@ START_TEST(rtl)
     test_RtlMakeSelfRelativeSD();
     test_LdrRegisterDllNotification();
     test_DbgPrint();
+    test_RtlDestroyHeap();
 }




More information about the wine-cvs mailing list