52 lines
1.8 KiB
C++
Executable File
52 lines
1.8 KiB
C++
Executable File
#include "stdafx.h"
|
|
#include "ReflectiveFree.h"
|
|
#include <Windows.h>
|
|
|
|
typedef NTSTATUS
|
|
(*NtQueueApcThread)(
|
|
HANDLE ThreadHandle,
|
|
PVOID ApcRoutine,
|
|
ULONG_PTR SystemArgument1,
|
|
ULONG_PTR SystemArgument2,
|
|
ULONG_PTR SystemArgument3
|
|
);
|
|
|
|
|
|
VOID ReflectiveFree(HINSTANCE hAppInstance) {
|
|
NtQueueApcThread pNtQueueApcThread = (NtQueueApcThread)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "NtQueueApcThread");
|
|
HANDLE hThread = NULL;
|
|
HANDLE hThisThread = NULL;
|
|
do {
|
|
if (!pNtQueueApcThread)
|
|
break;
|
|
|
|
// create a suspended thread that will just exit once the APCs have executed
|
|
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ExitThread, 0, CREATE_SUSPENDED, NULL);
|
|
if (!hThread)
|
|
break;
|
|
|
|
// open a real handle to this thread to pass in the APC so it operates on this thread and not itself
|
|
hThisThread = OpenThread(THREAD_QUERY_INFORMATION | SYNCHRONIZE, FALSE, GetCurrentThreadId());
|
|
if (!hThisThread)
|
|
break;
|
|
|
|
// tell that thread to wait on this thread, ensures VirtualFree isn't called until this thread has exited
|
|
NTSTATUS status = pNtQueueApcThread(hThread, WaitForSingleObjectEx, (ULONG_PTR)hThisThread, INFINITE, FALSE);
|
|
|
|
// then close the handle so it's not leaked
|
|
DWORD result = QueueUserAPC((PAPCFUNC)CloseHandle, hThread, (ULONG_PTR)hThisThread);
|
|
// then free the memory
|
|
status = pNtQueueApcThread(hThread, VirtualFree, (ULONG_PTR)hAppInstance, 0, MEM_RELEASE);
|
|
ResumeThread(hThread);
|
|
} while (FALSE);
|
|
|
|
if (hThread)
|
|
CloseHandle(hThread);
|
|
}
|
|
|
|
VOID ReflectiveFreeAndExitThread(HINSTANCE hAppInstance, DWORD dwExitCode) {
|
|
ReflectiveFree(hAppInstance);
|
|
|
|
ExitThread(dwExitCode);
|
|
return;
|
|
} |