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@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
c5129d6fc0
commit
255270373e
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue