From 9e9fd2ab94c54c2c5d23d19b3a1c4dd2e35852d6 Mon Sep 17 00:00:00 2001 From: Boring <1079299053@qq.com> Date: Sat, 18 Mar 2023 21:50:04 +0800 Subject: [PATCH] fixed a bug when processing tls --- MemoryModule/MmpTls.cpp | 22 +++++- a/a.vcxproj | 4 + a/a.vcxproj.filters | 12 +++ a/dllmain.cpp | 160 -------------------------------------- a/exception.cpp | 63 +++++++++++++++ a/gdiplus.cpp | 83 ++++++++++++++++++++ a/m.def | 3 +- a/thread.cpp | 55 +++++++++++++ a/unhandled_exception.cpp | 49 ++++++++++++ test/test.cpp | 104 +++---------------------- 10 files changed, 295 insertions(+), 260 deletions(-) create mode 100644 a/exception.cpp create mode 100644 a/gdiplus.cpp create mode 100644 a/thread.cpp create mode 100644 a/unhandled_exception.cpp diff --git a/MemoryModule/MmpTls.cpp b/MemoryModule/MmpTls.cpp index 8d07b81..cfb529d 100644 --- a/MemoryModule/MmpTls.cpp +++ b/MemoryModule/MmpTls.cpp @@ -454,7 +454,7 @@ BOOL NTAPI PreHookNtSetInformationProcess() { } NTSTATUS NTAPI HookNtSetInformationProcess( - _In_ HANDLE ProcessHandle, + _In_opt_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _In_reads_bytes_(ProcessInformationLength) PVOID ProcessInformation, _In_ ULONG ProcessInformationLength) { @@ -468,7 +468,6 @@ NTSTATUS NTAPI HookNtSetInformationProcess( ); } - auto ProcessTlsInformation = PPROCESS_TLS_INFORMATION(ProcessInformation); auto hProcess = ProcessHandle ? ProcessHandle : NtCurrentProcess(); auto TlsLength = ProcessInformationLength; @@ -556,9 +555,12 @@ NTSTATUS NTAPI HookNtSetInformationProcess( PMMP_TLSP_RECORD j = CONTAINING_RECORD(entry, MMP_TLSP_RECORD, InMmpThreadLocalStoragePointer); if (ProcessTlsInformation->OperationType == ProcessTlsReplaceVector) { - if (j->TlspMmpBlock[ProcessTlsInformation->TlsVectorLength] == ProcessTlsInformation->ThreadData->TlsVector[ProcessTlsInformation->TlsVectorLength]) { + if (j->TlspMmpBlock[ProcessTlsInformation->TlsVectorLength] == ProcessTlsInformation->ThreadData[i].TlsVector[ProcessTlsInformation->TlsVectorLength]) { found = true; + //auto tlsp = CONTAINING_RECORD(ProcessTlsInformation->ThreadData[i].TlsVector, TLS_VECTOR, TLS_VECTOR::ModuleTlsData); + //assert(tlsp->Length >= ProcessTlsInformation->TlsVectorLength); + // Copy old data to new pointer RtlCopyMemory( ProcessTlsInformation->ThreadData[i].TlsVector, @@ -767,17 +769,29 @@ NTSTATUS NTAPI MmpHandleTlsData(_In_ PLDR_DATA_TABLE_ENTRY lpModuleEntry) { return STATUS_NO_MEMORY; } - status = NtSetInformationProcess( + status = HookNtSetInformationProcess( nullptr, // hack PROCESSINFOCLASS::ProcessTlsInformation, ProcessTlsInformation, (ULONG)Length ); + ThreadCount = 0; for (DWORD i = 0; i < ProcessTlsInformation->ThreadDataCount; ++i) { + if (!ProcessTlsInformation->ThreadData[i].Flags) { + ++ThreadCount; + } + RtlFreeHeap(RtlProcessHeap(), 0, ProcessTlsInformation->ThreadData[i].TlsModulePointer); } + if (ThreadCount) { + EnterCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); + MmpGlobalDataPtr->MmpTls->MmpActiveThreadCount -= ThreadCount; + assert(MmpGlobalDataPtr->MmpTls->MmpActiveThreadCount > 0); + LeaveCriticalSection(&MmpGlobalDataPtr->MmpTls->MmpTlspLock); + } + RtlFreeHeap(RtlProcessHeap(), 0, ProcessTlsInformation); return status; } diff --git a/a/a.vcxproj b/a/a.vcxproj index 64c97ec..2bdc7fc 100644 --- a/a/a.vcxproj +++ b/a/a.vcxproj @@ -172,7 +172,11 @@ + + + + diff --git a/a/a.vcxproj.filters b/a/a.vcxproj.filters index c622f7a..3cd8839 100644 --- a/a/a.vcxproj.filters +++ b/a/a.vcxproj.filters @@ -21,6 +21,18 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + diff --git a/a/dllmain.cpp b/a/dllmain.cpp index d40eb91..5f782f0 100644 --- a/a/dllmain.cpp +++ b/a/dllmain.cpp @@ -1,46 +1,10 @@ -// dllmain.cpp : Defines the entry point for the DLL application. #include -#include #include -#include -#include #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"wintrust.lib") #pragma comment(lib,"ntdll.lib") -typedef NTSTATUS(NTAPI* PUSER_THREAD_START_ROUTINE)(_In_ PVOID ThreadParameter); - -#define NtCurrentProcess() (HANDLE)-1 - -#ifdef _WIN64 -#define NtCurrentThreadLocalStoragePointer() *(LPVOID*)(LPBYTE(NtCurrentTeb()) + 0x58) -#else -#define NtCurrentThreadLocalStoragePointer() *(LPVOID*)(LPBYTE(NtCurrentTeb()) + 0x2C) -#endif - -typedef struct _CLIENT_ID { - VOID* UniqueProcess; - VOID* UniqueThread; -}CLIENT_ID, * PCLIENT_ID; - -extern "C" -NTSYSAPI -NTSTATUS -NTAPI -RtlCreateUserThread( - _In_ HANDLE Process, - _In_opt_ PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, - _In_ BOOLEAN CreateSuspended, - _In_opt_ ULONG ZeroBits, - _In_opt_ SIZE_T MaximumStackSize, - _In_opt_ SIZE_T CommittedStackSize, - _In_ PUSER_THREAD_START_ROUTINE StartAddress, - _In_opt_ PVOID Parameter, - _Out_opt_ PHANDLE Thread, - _Out_opt_ PCLIENT_ID ClientId -); - BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved @@ -60,131 +24,7 @@ BOOL APIENTRY DllMain( HMODULE hModule, return TRUE; } -/* - exception type - 0 int - 1 char - 2 std::exception - ... DWORD64 -*/ - -int exception(int exception_type) { - //int a = 0; - //__try { - // *(PDWORD)(nullptr) = -1; - // a = 2; - //} - //__except (EXCEPTION_EXECUTE_HANDLER) { - // printf("-----------\n"); - // getchar(); - // a = 1; - //} - try { - switch (exception_type) { - case 0: - throw 0; - case 1: - throw '1'; - case 2: - throw std::exception("2"); - case 3: - { - std::string s = "foo"; - s.at(10); - } - default: - throw (DWORD64)-1; - } - return 0; - } - catch (int val) { - printf("exception code = %d\n", val); - return val; - } - catch (char val) { - printf("exception code = %c\n", val); - return val - '0'; - } - catch (const std::out_of_range& e) { - printf("%s\n", e.what()); - return 3; - } - catch (std::exception val) { - printf("exception code = %s\n", val.what()); - return 2; - } - catch (...) { - printf("exception catched!!\n"); - return 0; - } - //return a; -} - int __test__() { printf("HelloWorld!\n"); return 0; } - -static thread_local int x = 0xffccffdd; -NTSTATUS WINAPI Thread(PVOID) { - printf("[1] ThreadLocalStoragePointer = %p\n", NtCurrentThreadLocalStoragePointer()); - return x == 0xffccffdd ? 0 : 1; -} - -int thread() { - x = 2; - printf("[0] ThreadLocalStoragePointer = %p\n", NtCurrentThreadLocalStoragePointer()); - HANDLE hThread;// = CreateThread(nullptr, 0, Thread, nullptr, 0, nullptr); - RtlCreateUserThread(NtCurrentProcess(), nullptr, FALSE, 0, 0, 0, Thread, nullptr, &hThread, nullptr); - DWORD ret = -1; - if (hThread) { - WaitForSingleObject(hThread, 0xffffffff); - GetExitCodeThread(hThread, &ret); - CloseHandle(hThread); - return ret; - } - return -1; -} - -DWORD Value; -volatile LPDWORD lpAddr; - -LONG WINAPI Filter(_In_ struct _EXCEPTION_POINTERS* ExceptionInfo) { - - if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) { - - lpAddr = &Value; - - // +++++++ - // begin compiler specific - // +++++++ - - //ExceptionInfo->ContextRecord->Rip -= 7; - ExceptionInfo->ContextRecord->Rax = (ULONG_PTR)lpAddr; - - // +++++++ - // end compiler specific - // +++++++ - - return EXCEPTION_CONTINUE_EXECUTION; - } - - return EXCEPTION_CONTINUE_SEARCH; -} - -int unhandled_exception() { - auto filter = SetUnhandledExceptionFilter(Filter); - auto ff = SetUnhandledExceptionFilter(filter); - - if (ff != Filter) { - printf("%p\t%p\t%p\nfailed\n", filter, ff, Filter); - return 0; - } - - filter = SetUnhandledExceptionFilter(Filter); - lpAddr = nullptr; - *lpAddr = 1; - SetUnhandledExceptionFilter(filter); - - return 1234; -} diff --git a/a/exception.cpp b/a/exception.cpp new file mode 100644 index 0000000..515db56 --- /dev/null +++ b/a/exception.cpp @@ -0,0 +1,63 @@ +#include +#include +#include + +/* + exception type + 0 int + 1 char + 2 std::exception + ... DWORD64 +*/ + +int exception(int exception_type) { + //int a = 0; + //__try { + // *(PDWORD)(nullptr) = -1; + // a = 2; + //} + //__except (EXCEPTION_EXECUTE_HANDLER) { + // printf("-----------\n"); + // getchar(); + // a = 1; + //} + try { + switch (exception_type) { + case 0: + throw 0; + case 1: + throw '1'; + case 2: + throw std::exception("2"); + case 3: + { + std::string s = "foo"; + s.at(10); + } + default: + throw (DWORD64)-1; + } + return 0; + } + catch (int val) { + printf("exception code = %d\n", val); + return val; + } + catch (char val) { + printf("exception code = %c\n", val); + return val - '0'; + } + catch (const std::out_of_range& e) { + printf("%s\n", e.what()); + return 3; + } + catch (std::exception val) { + printf("exception code = %s\n", val.what()); + return 2; + } + catch (...) { + printf("exception catched!!\n"); + return 0; + } + //return a; +} \ No newline at end of file diff --git a/a/gdiplus.cpp b/a/gdiplus.cpp new file mode 100644 index 0000000..ed65830 --- /dev/null +++ b/a/gdiplus.cpp @@ -0,0 +1,83 @@ +#include +#include +#include +using namespace Gdiplus; +#pragma comment (lib,"Gdiplus.lib") + +VOID OnPaint(HDC hdc) +{ + Graphics graphics(hdc); + Pen pen(Color(255, 0, 0, 255)); + graphics.DrawLine(&pen, 0, 0, 200, 100); +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + HDC hdc; + PAINTSTRUCT ps; + + switch (message) + { + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + OnPaint(hdc); + EndPaint(hWnd, &ps); + return 0; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } +} + +int WINAPI GdiplusTest() +{ + HWND hWnd; + MSG msg; + WNDCLASS wndClass; + GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + // Initialize GDI+. + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + wndClass.style = CS_HREDRAW | CS_VREDRAW; + wndClass.lpfnWndProc = WndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = GetModuleHandle(nullptr); + wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = TEXT("GettingStarted"); + + RegisterClass(&wndClass); + + hWnd = CreateWindow( + TEXT("GettingStarted"), // window class name + TEXT("Getting Started"), // window caption + WS_OVERLAPPEDWINDOW, // window style + CW_USEDEFAULT, // initial x position + CW_USEDEFAULT, // initial y position + CW_USEDEFAULT, // initial x size + CW_USEDEFAULT, // initial y size + NULL, // parent window handle + NULL, // window menu handle + wndClass.hInstance, // program instance handle + NULL); // creation parameters + + ShowWindow(hWnd, SW_SHOW); + UpdateWindow(hWnd); + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + GdiplusShutdown(gdiplusToken); + return msg.wParam; +} diff --git a/a/m.def b/a/m.def index 8959306..545acdc 100644 --- a/a/m.def +++ b/a/m.def @@ -5,4 +5,5 @@ thread Socket = ws2_32.WSASocketW VerifyTruse = wintrust.WinVerifyTrust test_user32 -unhandled_exception \ No newline at end of file +unhandled_exception +GdiplusTest \ No newline at end of file diff --git a/a/thread.cpp b/a/thread.cpp new file mode 100644 index 0000000..8b4fb74 --- /dev/null +++ b/a/thread.cpp @@ -0,0 +1,55 @@ +#include +#include + +typedef NTSTATUS(NTAPI* PUSER_THREAD_START_ROUTINE)(_In_ PVOID ThreadParameter); + +#define NtCurrentProcess() (HANDLE)-1 + +#ifdef _WIN64 +#define NtCurrentThreadLocalStoragePointer() *(LPVOID*)(LPBYTE(NtCurrentTeb()) + 0x58) +#else +#define NtCurrentThreadLocalStoragePointer() *(LPVOID*)(LPBYTE(NtCurrentTeb()) + 0x2C) +#endif + +typedef struct _CLIENT_ID { + VOID* UniqueProcess; + VOID* UniqueThread; +}CLIENT_ID, * PCLIENT_ID; + +extern "C" +NTSYSAPI +NTSTATUS +NTAPI +RtlCreateUserThread( + _In_ HANDLE Process, + _In_opt_ PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, + _In_ BOOLEAN CreateSuspended, + _In_opt_ ULONG ZeroBits, + _In_opt_ SIZE_T MaximumStackSize, + _In_opt_ SIZE_T CommittedStackSize, + _In_ PUSER_THREAD_START_ROUTINE StartAddress, + _In_opt_ PVOID Parameter, + _Out_opt_ PHANDLE Thread, + _Out_opt_ PCLIENT_ID ClientId +); + +static thread_local int x = 0xffccffdd; +NTSTATUS WINAPI Thread(PVOID) { + printf("[1] ThreadLocalStoragePointer = %p\n", NtCurrentThreadLocalStoragePointer()); + return x == 0xffccffdd ? 0 : 1; +} + +int thread() { + x = 2; + printf("[0] ThreadLocalStoragePointer = %p\n", NtCurrentThreadLocalStoragePointer()); + HANDLE hThread;// = CreateThread(nullptr, 0, Thread, nullptr, 0, nullptr); + RtlCreateUserThread(NtCurrentProcess(), nullptr, FALSE, 0, 0, 0, Thread, nullptr, &hThread, nullptr); + DWORD ret = -1; + if (hThread) { + WaitForSingleObject(hThread, 0xffffffff); + GetExitCodeThread(hThread, &ret); + CloseHandle(hThread); + return ret; + } + return -1; +} \ No newline at end of file diff --git a/a/unhandled_exception.cpp b/a/unhandled_exception.cpp new file mode 100644 index 0000000..f442ed2 --- /dev/null +++ b/a/unhandled_exception.cpp @@ -0,0 +1,49 @@ +#include +#include + +#ifdef _WIN64 +DWORD Value; +volatile LPDWORD lpAddr; + +LONG WINAPI Filter(_In_ struct _EXCEPTION_POINTERS* ExceptionInfo) { + + if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) { + + lpAddr = &Value; + + // +++++++ + // begin compiler specific + // +++++++ + + //ExceptionInfo->ContextRecord->Rip -= 7; + ExceptionInfo->ContextRecord->Rax = (ULONG_PTR)lpAddr; + + // +++++++ + // end compiler specific + // +++++++ + + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} +#endif + +int unhandled_exception() { +#ifdef _WIN64 + auto filter = SetUnhandledExceptionFilter(Filter); + auto ff = SetUnhandledExceptionFilter(filter); + + if (ff != Filter) { + printf("%p\t%p\t%p\nfailed\n", filter, ff, Filter); + return 0; + } + + filter = SetUnhandledExceptionFilter(Filter); + lpAddr = nullptr; + *lpAddr = 1; + SetUnhandledExceptionFilter(filter); +#endif + + return 1234; +} diff --git a/test/test.cpp b/test/test.cpp index d4c6ca5..606369e 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -39,107 +39,21 @@ static void DisplayStatus() { int test() { LPVOID buffer = ReadDllFile("a.dll"); - HMEMORYMODULE m1 = nullptr, m2 = m1; - HMODULE hModule = nullptr; - FARPROC pfn = nullptr; - DWORD MemoryModuleFeatures = 0; - - typedef int(*_exception)(int code); - _exception exception = nullptr; - HRSRC hRsrc; - DWORD SizeofRes; - HGLOBAL gRes; - char str[10]; - - LdrQuerySystemMemoryModuleFeatures(&MemoryModuleFeatures); - if (MemoryModuleFeatures != MEMORY_FEATURE_ALL) { - printf("not support all features on this version of windows.\n"); + HMODULE hm = LoadLibraryMemory(buffer); + FARPROC fp = GetProcAddress(hm, "GdiplusTest"); + bool c = true; + while (c) { + fp(); } - - if (!NT_SUCCESS(LdrLoadDllMemoryExW(&m1, nullptr, 0, buffer, 0, L"kernel64", nullptr))) goto end; - LoadLibraryW(L"wininet.dll"); - if (!NT_SUCCESS(LdrLoadDllMemoryExW(&m2, nullptr, 0, buffer, 0, L"kernel128", nullptr))) goto end; - - //forward export - hModule = (HMODULE)m1; - pfn = (decltype(pfn))(GetProcAddress(hModule, "Socket")); //ws2_32.WSASocketW - pfn = (decltype(pfn))(GetProcAddress(hModule, "VerifyTruse")); //wintrust.WinVerifyTrust - hModule = (HMODULE)m2; - pfn = (decltype(pfn))(GetProcAddress(hModule, "Socket")); - pfn = (decltype(pfn))(GetProcAddress(hModule, "VerifyTruse")); - - //exception - hModule = (HMODULE)m1; - exception = (_exception)GetProcAddress(hModule, "exception"); - if (exception) { - for (int i = 0; i < 5; ++i)exception(i); - } - - //tls - pfn = GetProcAddress(hModule, "thread"); - if (pfn && pfn()) { - printf("thread test failed.\n"); - } - - //resource - if (!LoadStringA(hModule, 101, str, 10)) { - printf("load string failed.\n"); - } - else { - printf("%s\n", str); - } - if (!(hRsrc = FindResourceA(hModule, MAKEINTRESOURCEA(102), "BINARY"))) { - printf("find binary resource failed.\n"); - } - else { - if ((SizeofRes = SizeofResource(hModule, hRsrc)) != 0x10) { - printf("invalid res size.\n"); - } - else { - if (!(gRes = LoadResource(hModule, hRsrc))) { - printf("load res failed.\n"); - } - else { - if (!LockResource(gRes))printf("lock res failed.\n"); - else { - printf("resource test success.\n"); - } - } - } - } - -end: - delete[]buffer; - if (m1)LdrUnloadDllMemory(m1); - FreeLibrary(LoadLibraryW(L"wininet.dll")); - FreeLibrary(GetModuleHandleW(L"wininet.dll")); - if (m2)LdrUnloadDllMemory(m2); - + return 0; } -void test_cf() { - auto buffer = ReadDllFile("CoreFoundation.dll"); - - if (buffer) { - HMODULE hm = LoadLibraryMemory(buffer); - delete[]buffer; - - if (hm) { - printf("Load success: %p\n", hm); - FreeLibraryMemory(hm); - } - else { - printf("Load fail: %d\n", GetLastError()); - } - } - - return; -} - int main() { DisplayStatus(); - test_cf(); + test(); + + WaitForSingleObject(NtCurrentProcess(), INFINITE); return 0; }