diff --git a/MemoryModule/MemoryModule.cpp b/MemoryModule/MemoryModule.cpp index 897c847..4ac8326 100644 --- a/MemoryModule/MemoryModule.cpp +++ b/MemoryModule/MemoryModule.cpp @@ -230,25 +230,6 @@ static BOOL FinalizeSections(PMEMORYMODULE module) { return FinalizeSection(module, §ionData); } -static BOOL ExecuteTLS(PMEMORYMODULE module) { - unsigned char* codeBase = module->codeBase; - PIMAGE_TLS_DIRECTORY tls; - PIMAGE_TLS_CALLBACK* callback; - PIMAGE_NT_HEADERS headers = RtlImageNtHeader(codeBase); - PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(headers, IMAGE_DIRECTORY_ENTRY_TLS); - if (directory->VirtualAddress == 0) return TRUE; - - tls = (PIMAGE_TLS_DIRECTORY)(codeBase + directory->VirtualAddress); - callback = (PIMAGE_TLS_CALLBACK*)tls->AddressOfCallBacks; - if (callback) { - while (*callback) { - (*callback)((LPVOID)codeBase, DLL_PROCESS_ATTACH, nullptr); - callback++; - } - } - return TRUE; -} - typedef struct _REBASE_INFO { USHORT Offset : 12; USHORT Type : 4; @@ -499,25 +480,6 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data) { // mark memory pages depending on section headers and release // sections that are marked as "discardable" if (!FinalizeSections(hMemoryModule)) goto error; - - // TLS callbacks are executed BEFORE the main loading - if (!ExecuteTLS(hMemoryModule)) goto error; - - // get entry point of loaded library - if (new_header->OptionalHeader.AddressOfEntryPoint) { - __try { - // notify library about attaching to process - if (!((DllEntryProc)(base + new_header->OptionalHeader.AddressOfEntryPoint))((HINSTANCE)base, DLL_PROCESS_ATTACH, 0)) { - SetLastError(ERROR_DLL_INIT_FAILED); - goto error; - } - } - __except (EXCEPTION_EXECUTE_HANDLER) { - SetLastError(RtlNtStatusToDosError(GetExceptionCode())); - goto error; - } - hMemoryModule->initialized = TRUE; - } return (HMEMORYMODULE)base; error: @@ -532,10 +494,6 @@ bool MemoryFreeLibrary(HMEMORYMODULE mod) { if (!module) return false; if (module->loadFromNtLoadDllMemory && !module->underUnload)return false; - if (module->initialized) { - DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(module->codeBase + headers->OptionalHeader.AddressOfEntryPoint); - (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0); - } if (module->nameExportsTable)delete[] module->nameExportsTable; if (module->hModulesList) { for (DWORD i = 0; i < module->dwModulesCount; ++i) { diff --git a/MemoryModule/NativeFunctionsInternal.cpp b/MemoryModule/NativeFunctionsInternal.cpp index b0e7dd1..ceeae6d 100644 --- a/MemoryModule/NativeFunctionsInternal.cpp +++ b/MemoryModule/NativeFunctionsInternal.cpp @@ -521,6 +521,47 @@ BOOLEAN NTAPI RtlIsValidImageBuffer(PVOID Buffer) { return result; } +BOOL NTAPI LdrpExecuteTLS(PMEMORYMODULE module) { + unsigned char* codeBase = module->codeBase; + PIMAGE_TLS_DIRECTORY tls; + PIMAGE_TLS_CALLBACK* callback; + PIMAGE_NT_HEADERS headers = RtlImageNtHeader(codeBase); + PIMAGE_DATA_DIRECTORY directory = &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]; + if (directory->VirtualAddress == 0) return TRUE; + + tls = (PIMAGE_TLS_DIRECTORY)(codeBase + directory->VirtualAddress); + callback = (PIMAGE_TLS_CALLBACK*)tls->AddressOfCallBacks; + if (callback) { + while (*callback) { + (*callback)((LPVOID)codeBase, DLL_PROCESS_ATTACH, nullptr); + callback++; + } + } + return TRUE; +} + +BOOL NTAPI LdrpCallInitializers(PMEMORYMODULE module, DWORD dwReason) { + PIMAGE_NT_HEADERS headers = RtlImageNtHeader(module->codeBase); + + if (headers->OptionalHeader.AddressOfEntryPoint) { + __try { + // notify library about attaching to process + if (((DllEntryProc)(module->codeBase + headers->OptionalHeader.AddressOfEntryPoint))((HINSTANCE)module->codeBase, dwReason, 0)) { + module->initialized = TRUE; + return TRUE; + } + SetLastError(ERROR_DLL_INIT_FAILED); + } + __except (EXCEPTION_EXECUTE_HANDLER) { + SetLastError(RtlNtStatusToDosError(GetExceptionCode())); + } + + return FALSE; + } + + return TRUE; +} + NTSTATUS NTAPI LdrLoadDllMemory(OUT HMEMORYMODULE* BaseAddress, IN LPVOID BufferAddress, IN size_t BufferSize) { return LdrLoadDllMemoryExW(BaseAddress, nullptr, LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS, BufferAddress, BufferSize, nullptr, nullptr); } @@ -606,7 +647,15 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW( module->loadFromNtLoadDllMemory = true; headers = RtlImageNtHeader(*BaseAddress); if (headers->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_SEH)dwFlags |= LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION; - if (dwFlags & LOAD_FLAGS_NOT_MAP_DLL) return status; + if (dwFlags & LOAD_FLAGS_NOT_MAP_DLL) { + + if (!LdrpExecuteTLS(module) || !LdrpCallInitializers(module, DLL_PROCESS_ATTACH)) { + status = STATUS_DLL_INIT_FAILED; + MemoryFreeLibrary(*BaseAddress); + } + + return status; + } status = LdrMapDllMemory(*BaseAddress, dwFlags, DllName, DllFullName, &ModuleEntry); if (!NT_SUCCESS(status)) { @@ -650,6 +699,11 @@ NTSTATUS NTAPI LdrLoadDllMemoryExW( } } + if (!LdrpExecuteTLS(module) || !LdrpCallInitializers(module, DLL_PROCESS_ATTACH)) { + status = STATUS_DLL_INIT_FAILED; + LdrUnloadDllMemory(*BaseAddress); + } + return status; } @@ -703,13 +757,18 @@ NTSTATUS NTAPI LdrUnloadDllMemory(IN HMEMORYMODULE BaseAddress) { } if (CurEntry = RtlFindLdrTableEntryByHandle(BaseAddress)) { - if (RtlImageNtHeader(BaseAddress)->OptionalHeader.SizeOfImage == CurEntry->SizeOfImage) { + PIMAGE_NT_HEADERS headers = RtlImageNtHeader(BaseAddress); + if (headers->OptionalHeader.SizeOfImage == CurEntry->SizeOfImage) { if (module->UseReferenceCount) { status = RtlGetReferenceCount(CurEntry, &count); if (!NT_SUCCESS(status))return status; } if (!(count & ~1)) { module->underUnload = true; + if (module->initialized) { + DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(module->codeBase + headers->OptionalHeader.AddressOfEntryPoint); + (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0); + } if (module->MappedDll) { if (module->InsertInvertedFunctionTableEntry) { status = RtlRemoveInvertedFunctionTable(BaseAddress); diff --git a/MemoryModule/rtltls.cpp b/MemoryModule/rtltls.cpp index 768547e..0b8d3da 100644 --- a/MemoryModule/rtltls.cpp +++ b/MemoryModule/rtltls.cpp @@ -175,7 +175,7 @@ NTSTATUS NTAPI RtlFindLdrpReleaseTlsEntry(PVOID* _LdrpReleaseTlsEntry, bool* std status = STATUS_NOT_SUPPORTED; break; } - if (Versions[2] >= 19041) { + if (Versions[2] >= 18362) { Size = 0x10; OffsetOfFunctionBegin = 0x2F; Feature = "\x74\x26\x48\x8B\x00\x48\x39\x58\x08\x75\x5D\x48\x8B\x4B\x08"; diff --git a/test/test.cpp b/test/test.cpp index 841c60b..517e1f7 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -100,70 +100,6 @@ end: return 0; } -#define WSADESCRIPTION_LEN 256 -#define WSASYS_STATUS_LEN 128 -typedef USHORT ADDRESS_FAMILY; -typedef int (PASCAL* WSAStartup_t)(WORD wVersionRequired, LPWSADATA lpWSAData); -typedef int (PASCAL* WSACleanup_t)(void); -typedef SOCKET (PASCAL* socket_t)(int af, int type, int protocol); -typedef int (PASCAL* closesocket_t)(SOCKET s); -typedef int (PASCAL* connect_t)(SOCKET s, const struct sockaddr FAR* name, int namelen); -typedef unsigned long (PASCAL* inet_addr_t)(const char FAR* cp); -typedef u_short (PASCAL* htons_t)(u_short hostshort); - -int test_ws2_32() { - PVOID buffer = ReadDllFile("C:\\Windows\\system32\\ws2_32.dll"); - - HMEMORYMODULE hMemoryModule = nullptr; - HMODULE hModule = nullptr; - NTSTATUS status; - - WSAData data{}; - SOCKET sock = INVALID_SOCKET; - sockaddr_in addr{}; - WSAStartup_t _WSAStartup = nullptr; - WSACleanup_t _WSACleanup = nullptr; - socket_t _socket = nullptr; - closesocket_t _closesocket = nullptr; - connect_t _connect = nullptr; - inet_addr_t _inet_addr = nullptr; - htons_t _htons = nullptr; - - hMemoryModule = LoadLibraryMemoryExW(buffer, 0, L"ws2.dll", nullptr, LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS); - hModule = MemoryModuleToModule(hMemoryModule); - if (buffer)delete[]buffer; - if (!hModule)return 0; - - _WSAStartup = (decltype(_WSAStartup)(GetProcAddress(hModule, "WSAStartup"))); - _WSACleanup = (decltype(_WSACleanup)(GetProcAddress(hModule, "WSACleanup"))); - _socket = (decltype(_socket)(GetProcAddress(hModule, "socket"))); - _closesocket = (decltype(_closesocket)(GetProcAddress(hModule, "closesocket"))); - _connect = (decltype(_connect)(GetProcAddress(hModule, "connect"))); - _inet_addr = (decltype(_inet_addr)(GetProcAddress(hModule, "inet_addr"))); - _htons = (decltype(_htons)(GetProcAddress(hModule, "htons"))); - if (!_WSAStartup || !_WSACleanup || !_socket || !_closesocket || !_connect || !_inet_addr || !_htons)goto end; - - if (_WSAStartup(MAKEWORD(2, 2), &data) != 0)goto end; - if ((sock = _socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)goto end; - addr.sin_family = AF_INET; - addr.sin_port = _htons(80); - addr.sin_addr.S_un.S_addr = _inet_addr("1.1.1.1"); - if (_connect(sock, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)goto end; - - //success - printf("ws2_32 completed successfully.\n"); - -end: - if (sock != INVALID_SOCKET && _closesocket)_closesocket(sock); - if (_WSACleanup)_WSACleanup(); - FreeLibraryMemory(hMemoryModule); - return 0; -} - -DWORD WINAPI thread(PVOID) { - return 0; -} - int main() { //test_default(); //test_ws2_32(); @@ -173,21 +109,24 @@ int main() { printf("\n"); DebugBreak(); } + + auto pOle32 = ReadDllFile("C:\\Windows\\System32\\ole32.dll"); + HMEMORYMODULE hModule; + NTSTATUS status = LdrLoadDllMemoryExW( + &hModule, + nullptr, + 0, + pOle32, + 0, + nullptr, + nullptr + ); - auto a = ReadDllFile("a.dll"); + delete[]pOle32; - //LOAD_FLAGS_NOT_HANDLE_TLS - HMEMORYMODULE p1 = LoadLibraryMemoryExA(a, 0, "a.dll", nullptr, 0), - p2 = LoadLibraryMemoryExA(a, 0, "b.dll", nullptr, 0); - delete[]a; - - FreeLibraryMemory(p2); - - HANDLE hThread = CreateThread(nullptr, 0, thread, nullptr, 0, nullptr); - WaitForSingleObject(hThread, INFINITE); - CloseHandle(hThread); - - FreeLibraryMemory(p1); + if (NT_SUCCESS(status)) { + LdrUnloadDllMemory(hModule); + } return 0; }