diff --git a/MemoryModule/MemoryModule.cpp b/MemoryModule/MemoryModule.cpp index 85a7e86..6d1be7e 100644 --- a/MemoryModule/MemoryModule.cpp +++ b/MemoryModule/MemoryModule.cpp @@ -4,6 +4,7 @@ #include #include "rtltype.h" #include "ntstatus.h" +#include "Native.h" #include #if _MSC_VER @@ -134,7 +135,7 @@ static BOOL CheckSize(size_t size, size_t expected) { return TRUE; } -static BOOL CopySections(const unsigned char* data, size_t size, PMEMORYMODULE module) { +static BOOL CopySections(const unsigned char* data, PMEMORYMODULE module) { LPBYTE codeBase = module->codeBase; LPVOID dest; PIMAGE_NT_HEADERS headers = GetImageNtHeaders(module); @@ -145,7 +146,12 @@ static BOOL CopySections(const unsigned char* data, size_t size, PMEMORYMODULE m alloc_size = headers->OptionalHeader.SectionAlignment; cp = false; if (section->SizeOfRawData) { - if (!CheckSize(size, static_cast(section->PointerToRawData) + section->SizeOfRawData)) return FALSE; + __try { + ProbeForRead(data, static_cast(section->PointerToRawData) + section->SizeOfRawData); + } + __except (EXCEPTION_EXECUTE_HANDLER) { + return FALSE; + } alloc_size = section->SizeOfRawData; cp = true; } @@ -354,15 +360,23 @@ static BOOL BuildImportTable(PMEMORYMODULE module) { return result; } -HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) { +//static BOOL PerformForwardExport(PMEMORYMODULE module) { +// PIMAGE_EXPORT_DIRECTORY exports; +// PIMAGE_NT_HEADERS headers = GetImageNtHeaders(module); +// PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(headers, IMAGE_DIRECTORY_ENTRY_EXPORT); +// if (!directory->Size)return TRUE; +// return FALSE; +// +//} + +HMEMORYMODULE MemoryLoadLibrary(const void* data) { PMEMORYMODULE hMemoryModule = nullptr; PIMAGE_DOS_HEADER dos_header, new_dos_header; PIMAGE_NT_HEADERS old_header, new_header; - unsigned char* code; + unsigned char* base; ptrdiff_t locationDelta; - SYSTEM_INFO sysInfo; + static SYSTEM_INFO sysInfo{}; PIMAGE_SECTION_HEADER section; - DWORD i; size_t optionalSectionSize; size_t lastSectionEnd = 0; size_t alignedImageSize; @@ -371,40 +385,36 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) { POINTER_LIST* blockedMemory = nullptr; #endif - if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) return nullptr; - dos_header = (PIMAGE_DOS_HEADER)data; - if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { - SetLastError(ERROR_BAD_EXE_FORMAT); + __try { + ProbeForRead(data, sizeof(IMAGE_DOS_HEADER)); + dos_header = (PIMAGE_DOS_HEADER)data; + if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { + SetLastError(ERROR_BAD_EXE_FORMAT); + return nullptr; + } + ProbeForRead(data, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS)); + old_header = (PIMAGE_NT_HEADERS)((size_t)data + dos_header->e_lfanew); + if (old_header->Signature != IMAGE_NT_SIGNATURE || + !ProbeForRead(data, old_header->OptionalHeader.SizeOfHeaders) || + old_header->FileHeader.Machine != HOST_MACHINE || + old_header->OptionalHeader.SectionAlignment & 1) { + SetLastError(ERROR_BAD_EXE_FORMAT); + return nullptr; + } + //only dll image support + if (!(old_header->FileHeader.Characteristics & IMAGE_FILE_DLL)) { + SetLastError(ERROR_NOT_SUPPORTED); + return nullptr; + } + } + __except (EXCEPTION_EXECUTE_HANDLER) { + SetLastError(ERROR_INVALID_DATA); return nullptr; } - - if (!CheckSize(size, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS))) return nullptr; - old_header = (PIMAGE_NT_HEADERS) & ((const unsigned char*)(data))[dos_header->e_lfanew]; - if (old_header->Signature != IMAGE_NT_SIGNATURE) { - SetLastError(ERROR_BAD_EXE_FORMAT); - return nullptr; - } - - if (old_header->FileHeader.Machine != HOST_MACHINE) { - SetLastError(ERROR_BAD_EXE_FORMAT); - return nullptr; - } - - if (old_header->OptionalHeader.SectionAlignment & 1) { - // Only support section alignments that are a multiple of 2 - SetLastError(ERROR_BAD_EXE_FORMAT); - return nullptr; - } - - //only dll image support - if (!(old_header->FileHeader.Characteristics & IMAGE_FILE_DLL)) { - SetLastError(ERROR_NOT_SUPPORTED); - return nullptr; - } - + section = IMAGE_FIRST_SECTION(old_header); optionalSectionSize = old_header->OptionalHeader.SectionAlignment; - for (i = 0; i < old_header->FileHeader.NumberOfSections; i++, section++) { + for (DWORD i = 0; i < old_header->FileHeader.NumberOfSections; i++, section++) { size_t endOfSection; if (section->SizeOfRawData == 0) { // Section without data in the DLL @@ -419,7 +429,7 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) { } } - GetNativeSystemInfo(&sysInfo); + if (!sysInfo.dwPageSize)GetNativeSystemInfo(&sysInfo); alignedImageSize = AlignValueUp(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize); if (alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize)) { SetLastError(ERROR_BAD_EXE_FORMAT); @@ -430,12 +440,12 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) { // reserve memory for image of library // XXX: is it correct to commit the complete memory region at once? // calling DllEntry raises an exception if we don't... - if (!(code = (LPBYTE)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase), alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) { + if (!(base = (LPBYTE)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase), alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) { if (!(old_header->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)) { SetLastError(ERROR_BAD_EXE_FORMAT); return nullptr; } - if (!(code = (LPBYTE)VirtualAlloc(nullptr, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) { + if (!(base = (LPBYTE)VirtualAlloc(nullptr, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) { SetLastError(ERROR_OUTOFMEMORY); return nullptr; } @@ -443,20 +453,20 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) { #ifdef _WIN64 // Memory block may not span 4 GB boundaries. - while ((((uintptr_t)code) >> 32) < (((uintptr_t)(code + alignedImageSize)) >> 32)) { + while ((((uintptr_t)base) >> 32) < (((uintptr_t)(base + alignedImageSize)) >> 32)) { POINTER_LIST* node = new POINTER_LIST; if (!node) { - VirtualFree(code, 0, MEM_RELEASE); + VirtualFree(base, 0, MEM_RELEASE); FreePointerList(blockedMemory); SetLastError(ERROR_OUTOFMEMORY); return nullptr; } node->next = blockedMemory; - node->address = code; + node->address = base; blockedMemory = node; - if (!(code = (LPBYTE)VirtualAlloc(nullptr, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) { + if (!(base = (LPBYTE)VirtualAlloc(nullptr, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))) { FreePointerList(blockedMemory); SetLastError(ERROR_OUTOFMEMORY); return nullptr; @@ -464,11 +474,11 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) { } #endif - new_dos_header = (PIMAGE_DOS_HEADER)code; - new_header = (PIMAGE_NT_HEADERS)(code + dos_header->e_lfanew); - hMemoryModule = (PMEMORYMODULE)(code + old_header->OptionalHeader.SizeOfHeaders); + new_dos_header = (PIMAGE_DOS_HEADER)base; + new_header = (PIMAGE_NT_HEADERS)(base + dos_header->e_lfanew); + hMemoryModule = (PMEMORYMODULE)(base + old_header->OptionalHeader.SizeOfHeaders); RtlZeroMemory(hMemoryModule, sizeof(MEMORYMODULE)); - hMemoryModule->codeBase = code; + hMemoryModule->codeBase = base; hMemoryModule->pageSize = sysInfo.dwPageSize; hMemoryModule->Signature = MEMORY_MODULE_SIGNATURE; hMemoryModule->SizeofHeaders = old_header->OptionalHeader.SizeOfHeaders; @@ -477,18 +487,14 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) { hMemoryModule->blockedMemory = blockedMemory; #endif - if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) { - goto error; - } - // copy PE header to code memcpy(new_dos_header, dos_header, old_header->OptionalHeader.SizeOfHeaders); new_header->OptionalHeader.SizeOfImage = (DWORD)(alignedImageSize); - new_header->OptionalHeader.ImageBase = (size_t)code; + new_header->OptionalHeader.ImageBase = (size_t)base; new_header->OptionalHeader.BaseOfCode = headers_align; // copy sections from DLL file block to new memory location - if (!CopySections((LPBYTE)data, size, hMemoryModule)) goto error; + if (!CopySections((LPBYTE)data, hMemoryModule)) goto error; // adjust base address of imported data locationDelta = (ptrdiff_t)(hMemoryModule->codeBase - old_header->OptionalHeader.ImageBase); @@ -509,7 +515,7 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) { if (new_header->OptionalHeader.AddressOfEntryPoint) { __try { // notify library about attaching to process - if (!((DllEntryProc)(code + new_header->OptionalHeader.AddressOfEntryPoint))((HINSTANCE)code, DLL_PROCESS_ATTACH, 0)) { + if (!((DllEntryProc)(base + new_header->OptionalHeader.AddressOfEntryPoint))((HINSTANCE)base, DLL_PROCESS_ATTACH, 0)) { SetLastError(ERROR_DLL_INIT_FAILED); goto error; } @@ -521,7 +527,7 @@ HMEMORYMODULE MemoryLoadLibrary(const void* data, size_t size) { hMemoryModule->initialized = TRUE; } - return code; + return base; error: // cleanup MemoryFreeLibrary(hMemoryModule); diff --git a/MemoryModule/MemoryModule.h b/MemoryModule/MemoryModule.h index 17f1b71..a32d5a8 100644 --- a/MemoryModule/MemoryModule.h +++ b/MemoryModule/MemoryModule.h @@ -101,7 +101,7 @@ extern "C" { * All dependencies are resolved using default LoadLibrary/GetProcAddress * calls through the Windows API. */ - HMEMORYMODULE MemoryLoadLibrary(const void*, size_t); + HMEMORYMODULE MemoryLoadLibrary(const void*); /** * Get address of exported method. Supports loading both by name and by diff --git a/MemoryModule/Native.cpp b/MemoryModule/Native.cpp index 6cfaba7..51feaec 100644 --- a/MemoryModule/Native.cpp +++ b/MemoryModule/Native.cpp @@ -364,3 +364,24 @@ PVOID NTAPI RtlEncodeSystemPointer(PVOID Pointer) { PVOID NTAPI RtlDecodeSystemPointer(PVOID Pointer) { return decltype(&RtlDecodeSystemPointer)(RtlGetNtProcAddress("RtlDecodeSystemPointer"))(Pointer); } + +BOOLEAN NTAPI VirtualAccessCheck(LPCVOID pBuffer, size_t size, ACCESS_MASK protect) { + MEMORY_BASIC_INFORMATION mbi{}; + SIZE_T len = 0; + if (!NT_SUCCESS(NtQueryVirtualMemory(NtCurrentProcess(), const_cast(pBuffer), MemoryBasicInformation, &mbi, sizeof(mbi), &len)) || + !(mbi.Protect & protect)) { + RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, nullptr); + return FALSE; + } + return TRUE; +} + +NTSTATUS NTAPI LdrLockLoaderLock(size_t Flags, size_t* State, size_t* Cookie) { + return (decltype(&LdrLockLoaderLock)(RtlGetNtProcAddress("LdrLockLoaderLock")))(Flags, State, Cookie); +} +NTSTATUS NTAPI LdrUnlockLoaderLock(size_t Flags, size_t Cookie) { + return (decltype(&LdrUnlockLoaderLock)(RtlGetNtProcAddress("LdrUnlockLoaderLock")))(Flags, Cookie); +} +NTSTATUS NTAPI LdrUnloadDll(IN HANDLE ModuleHandle) { + return (decltype(&LdrUnloadDll)(RtlGetNtProcAddress("LdrUnloadDll")))(ModuleHandle); +} diff --git a/MemoryModule/Native.h b/MemoryModule/Native.h index beb0121..b758285 100644 --- a/MemoryModule/Native.h +++ b/MemoryModule/Native.h @@ -372,6 +372,60 @@ typedef enum _PROCESSINFOCLASS { ProcessLeapSecondInformation, // PROCESS_LEAP_SECOND_INFORMATION MaxProcessInfoClass } PROCESSINFOCLASS; +typedef enum _THREADINFOCLASS { + ThreadBasicInformation, // q: THREAD_BASIC_INFORMATION + ThreadTimes, // q: KERNEL_USER_TIMES + ThreadPriority, // s: KPRIORITY + ThreadBasePriority, // s: LONG + ThreadAffinityMask, // s: KAFFINITY + ThreadImpersonationToken, // s: HANDLE + ThreadDescriptorTableEntry, // q: DESCRIPTOR_TABLE_ENTRY (or WOW64_DESCRIPTOR_TABLE_ENTRY) + ThreadEnableAlignmentFaultFixup, // s: BOOLEAN + ThreadEventPair, + ThreadQuerySetWin32StartAddress, // q: PVOID + ThreadZeroTlsCell, // 10 + ThreadPerformanceCount, // q: LARGE_INTEGER + ThreadAmILastThread, // q: ULONG + ThreadIdealProcessor, // s: ULONG + ThreadPriorityBoost, // qs: ULONG + ThreadSetTlsArrayAddress, + ThreadIsIoPending, // q: ULONG + ThreadHideFromDebugger, // s: void + ThreadBreakOnTermination, // qs: ULONG + ThreadSwitchLegacyState, + ThreadIsTerminated, // q: ULONG // 20 + ThreadLastSystemCall, // q: THREAD_LAST_SYSCALL_INFORMATION + ThreadIoPriority, // qs: IO_PRIORITY_HINT + ThreadCycleTime, // q: THREAD_CYCLE_TIME_INFORMATION + ThreadPagePriority, // q: ULONG + ThreadActualBasePriority, + ThreadTebInformation, // q: THREAD_TEB_INFORMATION (requires THREAD_GET_CONTEXT + THREAD_SET_CONTEXT) + ThreadCSwitchMon, + ThreadCSwitchPmu, + ThreadWow64Context, // q: WOW64_CONTEXT + ThreadGroupInformation, // q: GROUP_AFFINITY // 30 + ThreadUmsInformation, // q: THREAD_UMS_INFORMATION + ThreadCounterProfiling, + ThreadIdealProcessorEx, // q: PROCESSOR_NUMBER + ThreadCpuAccountingInformation, // since WIN8 + ThreadSuspendCount, // since WINBLUE + ThreadHeterogeneousCpuPolicy, // q: KHETERO_CPU_POLICY // since THRESHOLD + ThreadContainerId, // q: GUID + ThreadNameInformation, // qs: THREAD_NAME_INFORMATION + ThreadSelectedCpuSets, + ThreadSystemThreadInformation, // q: SYSTEM_THREAD_INFORMATION // 40 + ThreadActualGroupAffinity, // since THRESHOLD2 + ThreadDynamicCodePolicyInfo, + ThreadExplicitCaseSensitivity, // qs: ULONG; s: 0 disables, otherwise enables + ThreadWorkOnBehalfTicket, + ThreadSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 + ThreadDbgkWerReportActive, + ThreadAttachContainer, + ThreadManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 + ThreadPowerThrottlingState, // THREAD_POWER_THROTTLING_STATE + ThreadWorkloadClass, // THREAD_WORKLOAD_CLASS // since REDSTONE5 // 50 + MaxThreadInfoClass +} THREADINFOCLASS; typedef struct _SYSTEM_PROCESS { ULONG NextEntryOffset;//relative offset ULONG ThreadCount; @@ -998,6 +1052,13 @@ typedef struct _SECURITY__LOGON_SESSION_DATA { LARGE_INTEGER PasswordMustChange; }SECURITY_LOGON_SESSION_DATA, *PSECURITY_LOGON_SESSION_DATA, LOGON_SESSION_DATA, *PLOGON_SESSION_DATA; +typedef struct _INITIAL_TEB { + PVOID StackBase; + PVOID StackLimit; + PVOID StackCommit; + PVOID StackCommitMax; + PVOID StackReserved; +} INITIAL_TEB, * PINITIAL_TEB; NTSTATUS NTAPI NtQueryObject( IN HANDLE ObjectHandle, @@ -1340,3 +1401,23 @@ typedef struct _UNWIND_INFO { NTSTATUS NTAPI NtQuerySystemTime(PLARGE_INTEGER SystemTime); PVOID NTAPI RtlEncodeSystemPointer(PVOID Pointer); PVOID NTAPI RtlDecodeSystemPointer(PVOID Pointer); + +#define NtCurrentProcess() (HANDLE)-1 +#define NtCurrentThread() (HANDLE)-2 + +BOOLEAN NTAPI VirtualAccessCheck(LPCVOID pBuffer, size_t size, ACCESS_MASK protect); +#define ProbeForRead(pBuffer, size) VirtualAccessCheck(pBuffer, size, PAGE_READONLY | PAGE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE) +#define ProbeForWrite(pBuffer, size) VirtualAccessCheck(pBuffer, size, PAGE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE) +#define ProbeForReadWrite(pBuffer, size) VirtualAccessCheck(pBuffer, size, PAGE_EXECUTE_READWRITE | PAGE_READWRITE) +#define ProbeForExecute(pBuffer, size) VirtualAccessCheck(pBuffer, size, PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) + +//Flags +#define LOCK_RAISE_EXCEPTION 1 +#define LOCK_NO_WAIT_IF_BUSY 2 +//State +#define LOCK_STATE_NO_ENTER 0 +#define LOCK_STATE_ENTERED 1 +#define LOCK_STATE_LOCK_BUSY 2 +NTSTATUS NTAPI LdrLockLoaderLock(size_t Flags, size_t* State, size_t* Cookie); +NTSTATUS NTAPI LdrUnlockLoaderLock(size_t Flags, size_t Cookie); +NTSTATUS NTAPI LdrUnloadDll(IN HANDLE ModuleHandle); diff --git a/MemoryModule/NativeFunctionsInternal.cpp b/MemoryModule/NativeFunctionsInternal.cpp index ba5b568..3e5acc6 100644 --- a/MemoryModule/NativeFunctionsInternal.cpp +++ b/MemoryModule/NativeFunctionsInternal.cpp @@ -51,26 +51,16 @@ static ULONG NTAPI LdrHashEntry(IN const UNICODE_STRING& str, IN bool _xor = tru static HANDLE NTAPI RtlFindtLdrpHeap() { PLIST_ENTRY ListHead, ListEntry; PLDR_DATA_TABLE_ENTRY CurEntry; + MEMORY_BASIC_INFORMATION mbi{}; static HANDLE result = nullptr; - DWORD dwHeaps = 0; - HANDLE* hHeaps = nullptr; - if (result)return result; - dwHeaps = GetProcessHeaps(dwHeaps, hHeaps); - hHeaps = new HANDLE[dwHeaps]; + ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; ListEntry = ListHead->Flink; - if (ListHead == ListEntry)return nullptr; + if (ListHead == ListEntry)return result; CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - GetProcessHeaps(dwHeaps, hHeaps); - for (DWORD i = 0; i < dwHeaps; ++i) { - if (HeapValidate(hHeaps[i], 0, CurEntry)) { - result = hHeaps[i]; - break; - } - } - delete[]hHeaps; - return result; + NtQueryVirtualMemory(NtCurrentProcess(), CurEntry, MemoryBasicInformation, &mbi, sizeof(mbi), (PSIZE_T)&ListHead); + return result = mbi.AllocationBase; } static PLDR_DATA_TABLE_ENTRY NTAPI RtlFindNtdllLdrEntry() { PLIST_ENTRY ListHead, ListEntry; @@ -242,7 +232,7 @@ static PRTL_BALANCED_NODE NTAPI RtlFindLdrpModuleBaseAddressIndex() { return LdrpModuleBaseAddressIndex; } static NTSTATUS NTAPI NtInsertModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENTRY DataTableEntry, IN PVOID BaseAddress) { - auto LdrpModuleBaseAddressIndex = RtlFindLdrpModuleBaseAddressIndex(); + static auto LdrpModuleBaseAddressIndex = RtlFindLdrpModuleBaseAddressIndex(); if (!LdrpModuleBaseAddressIndex)return STATUS_UNSUCCESSFUL; PLDR_DATA_TABLE_ENTRY_WIN8 LdrNode = decltype(LdrNode)((size_t)LdrpModuleBaseAddressIndex - offsetof(LDR_DATA_TABLE_ENTRY_WIN8, BaseAddressIndexNode)); @@ -274,20 +264,82 @@ static NTSTATUS NTAPI NtInsertModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENTR return STATUS_SUCCESS; } static NTSTATUS NTAPI NtRemoveModuleBaseAddressIndexNode(IN PLDR_DATA_TABLE_ENTRY DataTableEntry) { - RTL_RB_TREE tree{ RtlFindLdrpModuleBaseAddressIndex() }; + static RTL_RB_TREE tree{ RtlFindLdrpModuleBaseAddressIndex() }; if (!tree.Root)return STATUS_UNSUCCESSFUL; RtlRbRemoveNode(&tree, &PLDR_DATA_TABLE_ENTRY_WIN8(DataTableEntry)->BaseAddressIndexNode); return STATUS_SUCCESS; } +static NTSTATUS NTAPI NtFreeDependencies(IN PLDR_DATA_TABLE_ENTRY_WIN8 LdrEntry) { + _LDR_DDAG_NODE* DependentDdgeNode = nullptr; + PLDR_DATA_TABLE_ENTRY_WIN8 ModuleEntry = nullptr; + _LDRP_CSLIST* head = (decltype(head))LdrEntry->DdagNode->Dependencies, *entry = head; + if (!LdrEntry->DdagNode->Dependencies)return STATUS_SUCCESS; + + //find all dependencies and free + do { + DependentDdgeNode = entry->Dependent.DependentDdagNode; + if (DependentDdgeNode->Modules.Flink->Flink != &DependentDdgeNode->Modules) RaiseException(-1, EXCEPTION_NONCONTINUABLE, 0, nullptr); + ModuleEntry = decltype(ModuleEntry)((size_t)DependentDdgeNode->Modules.Flink - offsetof(_LDR_DATA_TABLE_ENTRY_WIN8, NodeModuleLink)); + if (ModuleEntry->DdagNode != DependentDdgeNode) RaiseException(-1, EXCEPTION_NONCONTINUABLE, 0, nullptr); + if (!DependentDdgeNode->IncomingDependencies) RaiseException(-1, EXCEPTION_NONCONTINUABLE, 0, nullptr); + _LDRP_CSLIST::_LDRP_CSLIST_INCOMMING* _last = DependentDdgeNode->IncomingDependencies, *_entry = _last; + _LDR_DDAG_NODE* CurrentDdagNode; + size_t State = 0, Cookies; + + //Acquire LoaderLock + do { + if (!NT_SUCCESS(LdrLockLoaderLock(LOCK_NO_WAIT_IF_BUSY, &State, &Cookies))) + RaiseException(-1, EXCEPTION_NONCONTINUABLE, 0, nullptr); + } while (State != LOCK_STATE_ENTERED); + do { + CurrentDdagNode = (decltype(CurrentDdagNode))((size_t)_entry->IncommingDdagNode & ~1); + if (CurrentDdagNode == LdrEntry->DdagNode) { + //node is head + if (_entry == DependentDdgeNode->IncomingDependencies) { + //only one node in list + if (_entry->NextIncommingEntry == (PSINGLE_LIST_ENTRY)DependentDdgeNode->IncomingDependencies) { + DependentDdgeNode->IncomingDependencies = nullptr; + } + else { + //find the last node in the list + PSINGLE_LIST_ENTRY i = _entry->NextIncommingEntry; + while (i->Next != (PSINGLE_LIST_ENTRY)_entry)i = i->Next; + i->Next = _entry->NextIncommingEntry; + DependentDdgeNode->IncomingDependencies = (_LDRP_CSLIST::_LDRP_CSLIST_INCOMMING*)_entry->NextIncommingEntry; + } + } + //node is not head + else { + _last->NextIncommingEntry = _entry->NextIncommingEntry; + } + break; + } + //save the last entry + if (_last != _entry)_last = (decltype(_last))_last->NextIncommingEntry; + _entry = (decltype(_entry))_entry->NextIncommingEntry; + } while (_entry != _last); + //free LoaderLock + LdrUnlockLoaderLock(0, Cookies); + + //free it + LdrUnloadDll(ModuleEntry->DllBase); + NtFreeLdrpHeap(LdrEntry->DdagNode->Dependencies); + + //lookup next dependent. + entry = (decltype(entry))entry->Dependent.NextDependentEntry; + LdrEntry->DdagNode->Dependencies = (_LDRP_CSLIST::_LDRP_CSLIST_DEPENDENT*)(entry == head ? nullptr : entry); + } while (entry != head); + + return STATUS_SUCCESS; +} static bool NTAPI NtInitializeLdrDataTableEntry( OUT PLDR_DATA_TABLE_ENTRY LdrEntry, IN DWORD dwFlags, IN PVOID BaseAddress, IN UNICODE_STRING &DllBaseName, IN UNICODE_STRING &DllFullName) { - UNREFERENCED_PARAMETER(dwFlags); RtlZeroMemory(LdrEntry, NtLdrDataTableEntrySize()); PIMAGE_NT_HEADERS headers = RtlImageNtHeader(BaseAddress); if (!headers)return false; @@ -303,7 +355,7 @@ static bool NTAPI NtInitializeLdrDataTableEntry( case win8: case win8_1: { auto entry = (PLDR_DATA_TABLE_ENTRY_WIN8)LdrEntry; - + NtQuerySystemTime(&entry->LoadTime); entry->OriginalBase = headers->OptionalHeader.ImageBase; entry->BaseNameHashValue = LdrHashEntry(DllBaseName, false); entry->LoadReason = LoadReasonDynamicLoad; @@ -311,14 +363,17 @@ static bool NTAPI NtInitializeLdrDataTableEntry( if (!(entry->DdagNode = (decltype(entry->DdagNode))NtAllocateLdrpHeap(sizeof(_LDR_DDAG_NODE))))return false; //NtInitializeListEntry(&entry->NodeModuleLink); //NtInitializeListEntry(&entry->DdagNode->Modules); + //NtInitializeSingleEntry(&entry->DdagNode->CondenseLink); entry->NodeModuleLink.Flink = &entry->DdagNode->Modules; entry->NodeModuleLink.Blink = &entry->DdagNode->Modules; entry->DdagNode->Modules.Flink = &entry->NodeModuleLink; entry->DdagNode->Modules.Blink = &entry->NodeModuleLink; entry->DdagNode->State = LdrModulesReadyToRun; - entry->DdagNode->LoadCount = 0; - - NtInitializeSingleEntry(&entry->DdagNode->CondenseLink); + entry->DdagNode->LoadCount = 1; + entry->ImageDll = entry->LoadNotificationsSent = entry->EntryProcessed = + entry->InLegacyLists = entry->InIndexes = entry->ProcessAttachCalled = true; + entry->InExceptionTable = !(dwFlags & LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION); + FlagsProcessed = true; } case win7: { @@ -344,6 +399,7 @@ static bool NTAPI NtInitializeLdrDataTableEntry( LdrEntry->BaseDllName = DllBaseName; LdrEntry->FullDllName = DllFullName; LdrEntry->EntryPoint = (PVOID)((size_t)BaseAddress + headers->OptionalHeader.AddressOfEntryPoint); + LdrEntry->LoadCount = 1; if (!FlagsProcessed) LdrEntry->Flags = LDRP_IMAGE_DLL | LDRP_ENTRY_INSERTED | LDRP_ENTRY_PROCESSED | LDRP_PROCESS_ATTACH_CALLED; NtInitializeListEntry(&LdrEntry->HashLinks); return true; @@ -355,12 +411,12 @@ static bool NTAPI NtFreeLdrDataTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry) { switch (NtWindowsVersion()) { case win10: case win10_1: - case win10_2: { - auto entry = (PLDR_DATA_TABLE_ENTRY_WIN10)LdrEntry; - NtFreeLdrpHeap(entry->DdagNode); - } + case win10_2: case win8: case win8_1: { + auto entry = (PLDR_DATA_TABLE_ENTRY_WIN8)LdrEntry; + NtFreeDependencies(entry); + NtFreeLdrpHeap(entry->DdagNode); NtRemoveModuleBaseAddressIndexNode(LdrEntry); } case win7: @@ -556,7 +612,7 @@ static NTSTATUS NTAPI NtMapDllMemory(IN HMEMORYMODULE ViewBase, IN DWORD dwFlags } NTSTATUS NTAPI NtLoadDllMemory(OUT HMEMORYMODULE* BaseAddress, IN LPVOID BufferAddress, IN size_t BufferSize) { - return NtLoadDllMemoryExW(BaseAddress, nullptr, 0, BufferAddress, BufferSize, nullptr, nullptr); + return NtLoadDllMemoryExW(BaseAddress, nullptr, LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS, BufferAddress, BufferSize, nullptr, nullptr); } NTSTATUS NTAPI NtLoadDllMemoryExW( @@ -570,6 +626,8 @@ NTSTATUS NTAPI NtLoadDllMemoryExW( PMEMORYMODULE module = nullptr; NTSTATUS status = STATUS_SUCCESS; PLDR_DATA_TABLE_ENTRY ModuleEntry = nullptr; + PIMAGE_NT_HEADERS headers = nullptr; + UNREFERENCED_PARAMETER(BufferSize); __try { if (IsBadReadPtr(BufferAddress, BufferSize))status = STATUS_ACCESS_VIOLATION; @@ -616,7 +674,7 @@ NTSTATUS NTAPI NtLoadDllMemoryExW( } } - if (!(*BaseAddress = MemoryLoadLibrary(BufferAddress, BufferSize))) { + if (!(*BaseAddress = MemoryLoadLibrary(BufferAddress))) { switch (GetLastError()) { case ERROR_BAD_EXE_FORMAT: return STATUS_INVALID_IMAGE_FORMAT; @@ -633,7 +691,9 @@ NTSTATUS NTAPI NtLoadDllMemoryExW( return STATUS_INVALID_ADDRESS; } module->loadFromNtLoadDllMemory = true; - if (dwFlags & LOAD_FLAGS_NOT_MAP_DLL) return STATUS_SUCCESS; + 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; status = NtMapDllMemory(*BaseAddress, dwFlags, DllName, DllFullName, &ModuleEntry); if (!NT_SUCCESS(status)) { @@ -647,26 +707,34 @@ NTSTATUS NTAPI NtLoadDllMemoryExW( if (!(dwFlags & LOAD_FLAGS_NOT_USE_REFERENCE_COUNT))module->UseReferenceCount = true; - if (dwFlags & LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION)return STATUS_SUCCESS; - status = RtlInsertInvertedFunctionTable((PVOID)module->codeBase, RtlImageNtHeader(*BaseAddress)->OptionalHeader.SizeOfImage); - if (!NT_SUCCESS(status)) { - NtUnloadDllMemory(*BaseAddress); - *BaseAddress = nullptr; - if (LdrEntry)*LdrEntry = nullptr; - return status; - } - module->InsertInvertedFunctionTableEntry = true; - - if (dwFlags & LOAD_FLAGS_NOT_HANDLE_TLS)return STATUS_SUCCESS; - status = LdrpHandleTlsData(ModuleEntry); - if (!NT_SUCCESS(status)) { - NtUnloadDllMemory(*BaseAddress); - *BaseAddress = nullptr; - if (LdrEntry)*LdrEntry = nullptr; - return status; + if (!(dwFlags & LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION)) { + status = RtlInsertInvertedFunctionTable((PVOID)module->codeBase, headers->OptionalHeader.SizeOfImage); + if (!NT_SUCCESS(status)) { + NtUnloadDllMemory(*BaseAddress); + *BaseAddress = nullptr; + if (LdrEntry)*LdrEntry = nullptr; + return status; + } + module->InsertInvertedFunctionTableEntry = true; } - return STATUS_SUCCESS; + if (!(dwFlags & LOAD_FLAGS_NOT_HANDLE_TLS)) { + status = LdrpHandleTlsData(ModuleEntry); + if (!NT_SUCCESS(status)) { + do { + if (dwFlags & LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS) { + status = 0x7fffffff; + break; + } + NtUnloadDllMemory(*BaseAddress); + *BaseAddress = nullptr; + if (LdrEntry)*LdrEntry = nullptr; + return status; + } while (false); + } + } + + return status; } NTSTATUS NTAPI NtLoadDllMemoryExA( @@ -705,22 +773,28 @@ NTSTATUS NTAPI NtUnloadDllMemory(IN HMEMORYMODULE BaseAddress) { NTSTATUS status = STATUS_SUCCESS; PMEMORYMODULE module = MapMemoryModuleHandle(BaseAddress); + //Not a memory module loaded via NtLoadDllMemory if (!module || !module->loadFromNtLoadDllMemory)return STATUS_INVALID_HANDLE; + + //Mapping dll failed + if (module->loadFromNtLoadDllMemory && !module->MappedDll) { + module->underUnload = true; + MemoryFreeLibrary(BaseAddress); + return STATUS_SUCCESS; + } + ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; ListEntry = ListHead->Flink; while (ListEntry != ListHead) { CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); ListEntry = ListEntry->Flink; - /* Check if it's being unloaded */ - if (!CurEntry->InMemoryOrderLinks.Flink) continue; - /* Check if name matches */ if (CurEntry->DllBase == BaseAddress) { if (RtlImageNtHeader(BaseAddress)->OptionalHeader.SizeOfImage == CurEntry->SizeOfImage) { if (module->UseReferenceCount) { status = NtGetReferenceCount(CurEntry, &count); if (!NT_SUCCESS(status))return status; } - if (!count) { + if (!(count & ~1)) { module->underUnload = true; if (module->MappedDll) { if (module->InsertInvertedFunctionTableEntry) { @@ -774,7 +848,10 @@ static VOID NTAPI RtlpInsertInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABL if (CurrentSize != InvertedTable->MaxCount) { //if (need)_InterlockedIncrement(&InvertedTable->Epoch); if (CurrentSize != 0) { - while (Index < CurrentSize)if (ImageBase < InvertedTable->Entries[Index].ImageBase)break; + while (Index < CurrentSize) { + if (ImageBase < InvertedTable->Entries[Index].ImageBase)break; + ++Index; + } if (Index != CurrentSize) { RtlMoveMemory(&InvertedTable->Entries[Index + 1], @@ -873,13 +950,13 @@ static VOID NTAPI RtlpRemoveInvertedFunctionTable(IN PRTL_INVERTED_FUNCTION_TABL #else if (IsWin10) { RtlMoveMemory(&InvertedTable->Entries[Index], &InvertedTable->Entries[Index + 1], - (CurrentSize - Index) * sizeof(PRTL_INVERTED_FUNCTION_TABLE_ENTRY)); + (CurrentSize - Index) * sizeof(RTL_INVERTED_FUNCTION_TABLE_ENTRY)); } else { RtlMoveMemory( Index ? &InvertedTable->Entries[Index - 1].NextEntrySEHandlerTableEncoded : (PVOID)&InvertedTable->NextEntrySEHandlerTableEncoded, &InvertedTable->Entries[Index].NextEntrySEHandlerTableEncoded, - (CurrentSize - Index) * sizeof(PRTL_INVERTED_FUNCTION_TABLE_ENTRY)); + (CurrentSize - Index) * sizeof(RTL_INVERTED_FUNCTION_TABLE_ENTRY)); } #endif } diff --git a/MemoryModule/NativeFunctionsInternal.h b/MemoryModule/NativeFunctionsInternal.h index 13f7ae0..e6a26a6 100644 --- a/MemoryModule/NativeFunctionsInternal.h +++ b/MemoryModule/NativeFunctionsInternal.h @@ -81,7 +81,14 @@ struct _LDR_SERVICE_TAG_RECORD { }; //0x8 bytes (sizeof) struct _LDRP_CSLIST { - _SINGLE_LIST_ENTRY* Tail; //0x0 + struct _LDRP_CSLIST_DEPENDENT { + _SINGLE_LIST_ENTRY* NextDependentEntry; //0x0 + struct _LDR_DDAG_NODE* DependentDdagNode; + }Dependent; + struct _LDRP_CSLIST_INCOMMING { + _SINGLE_LIST_ENTRY* NextIncommingEntry; + struct _LDR_DDAG_NODE* IncommingDdagNode; + }Incomming; }; //0x4 bytes (sizeof) enum _LDR_DDAG_STATE { @@ -108,8 +115,8 @@ struct _LDR_DDAG_NODE { ULONG LoadCount; //0x18 ULONG LoadWhileUnloadingCount; //0x1c ULONG LowestLink; //0x20 - _LDRP_CSLIST Dependencies; //0x28 - _LDRP_CSLIST IncomingDependencies; //0x30 + _LDRP_CSLIST::_LDRP_CSLIST_DEPENDENT* Dependencies; //0x28 + _LDRP_CSLIST::_LDRP_CSLIST_INCOMMING* IncomingDependencies; //0x30 _LDR_DDAG_STATE State; //0x38 _SINGLE_LIST_ENTRY CondenseLink; //0x40 ULONG PreorderNumber; //0x48 @@ -398,6 +405,9 @@ NTSTATUS NTAPI NtLoadDllMemory( //Also, will be incompatible with Win32 API. #define LOAD_FLAGS_NOT_MAP_DLL 0x10000000 +//If this flag is specified, this routine will not fail even if the call to LdrpTlsData fails. +#define LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS 0x20000000 + //If this flag is specified, exception handling will not be supported. #define LOAD_FLAGS_NOT_ADD_INVERTED_FUNCTION 0x00000001 diff --git a/MemoryModulePP.sln b/MemoryModulePP.sln index 3755ce1..0b985a5 100644 --- a/MemoryModulePP.sln +++ b/MemoryModulePP.sln @@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MemoryModule", "MemoryModul EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{5B3131BA-178A-4A28-BD54-315A45C97ED1}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "a", "a\a.vcxproj", "{DA79C619-BDAC-4CF1-A38C-B1F5E05F4485}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -33,6 +35,14 @@ Global {5B3131BA-178A-4A28-BD54-315A45C97ED1}.Release|x64.Build.0 = Release|x64 {5B3131BA-178A-4A28-BD54-315A45C97ED1}.Release|x86.ActiveCfg = Release|Win32 {5B3131BA-178A-4A28-BD54-315A45C97ED1}.Release|x86.Build.0 = Release|Win32 + {DA79C619-BDAC-4CF1-A38C-B1F5E05F4485}.Debug|x64.ActiveCfg = Debug|x64 + {DA79C619-BDAC-4CF1-A38C-B1F5E05F4485}.Debug|x64.Build.0 = Debug|x64 + {DA79C619-BDAC-4CF1-A38C-B1F5E05F4485}.Debug|x86.ActiveCfg = Debug|Win32 + {DA79C619-BDAC-4CF1-A38C-B1F5E05F4485}.Debug|x86.Build.0 = Debug|Win32 + {DA79C619-BDAC-4CF1-A38C-B1F5E05F4485}.Release|x64.ActiveCfg = Release|x64 + {DA79C619-BDAC-4CF1-A38C-B1F5E05F4485}.Release|x64.Build.0 = Release|x64 + {DA79C619-BDAC-4CF1-A38C-B1F5E05F4485}.Release|x86.ActiveCfg = Release|Win32 + {DA79C619-BDAC-4CF1-A38C-B1F5E05F4485}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index 804facb..3a04f8e 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,12 @@ MemoryModulePP, used to load a DLL from memory. MemoryModulePP is compatible wit **This repository is under development.** ## New Features - - Compatible with Win7(x86) + - Support Win10 forward export ## Features - Compatible with Win32 API (GetModuleHandleA/W/Ex GetModuleFileNameA/W/Ex GetProcAddress and any Resource API) - - Support for C ++ exceptions and SEH - - Compatible with Win7(x64) and Win10(x64) + - Support for C++ exceptions and SEH + - Compatible with Win7 and Win10 - Optimized MEMORYMODULE structure - Use reference counting, repeated loading of the same module will update the reference counting, please refer to NtLoadDllMemoryExW - The above features can be turned off through the dwFlags parameter of NtLoadDllMemoryExW diff --git a/a/a.rc b/a/a.rc new file mode 100644 index 0000000..7080dca --- /dev/null +++ b/a/a.rc @@ -0,0 +1,72 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Chinese (Simplified, PRC) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED +#pragma code_page(936) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_STRING101 "aabbccdd" +END + +#endif // Chinese (Simplified, PRC) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/a/a.vcxproj b/a/a.vcxproj new file mode 100644 index 0000000..b6603b7 --- /dev/null +++ b/a/a.vcxproj @@ -0,0 +1,186 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {DA79C619-BDAC-4CF1-A38C-B1F5E05F4485} + Win32Proj + a + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + NotUsing + Level3 + true + WIN32;_DEBUG;A_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + MultiThreaded + + + + Windows + true + false + m.def + + + + + NotUsing + Level3 + true + _DEBUG;A_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + MultiThreadedDebug + + + + Windows + true + false + m.def + + + + + NotUsing + Level3 + true + true + true + WIN32;NDEBUG;A_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + MultiThreaded + + + + Windows + true + true + true + false + m.def + + + + + NotUsing + Level3 + true + true + true + NDEBUG;A_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + + + MultiThreaded + Sync + + + + Windows + true + true + true + false + m.def + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/a/a.vcxproj.filters b/a/a.vcxproj.filters new file mode 100644 index 0000000..4bd388e --- /dev/null +++ b/a/a.vcxproj.filters @@ -0,0 +1,40 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/a/dllmain.cpp b/a/dllmain.cpp new file mode 100644 index 0000000..3a21854 --- /dev/null +++ b/a/dllmain.cpp @@ -0,0 +1,101 @@ +// dllmain.cpp : Defines the entry point for the DLL application. +#include +#include +#include "../MemoryModule/Native.h" +#pragma comment(lib,"ws2_32.lib") +#pragma comment(lib,"wintrust.lib") +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + printf("DLL_PROCESS_ATTACH\n"); break; + case DLL_THREAD_ATTACH: + printf("DLL_THREAD_ATTACH\n"); break; + case DLL_THREAD_DETACH: + printf("DLL_THREAD_DETACH\n"); break; + case DLL_PROCESS_DETACH: + printf("DLL_PROCESS_DETACH\n"); break; + } + 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"); + 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 (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; +DWORD WINAPI Thread(PVOID) { + printf("[1] ThreadLocalStoragePointer = %p\n", NtCurrentTeb()->ThreadLocalStoragePointer); + return x == 0xffccffdd ? 0 : 1; const auto i = offsetof(CONTEXT, Dr0); +} + +int thread() { + x = 2; + printf("[0] ThreadLocalStoragePointer = %p\n", NtCurrentTeb()->ThreadLocalStoragePointer); + HANDLE hThread = CreateThread(nullptr, 0, Thread, nullptr, 0, nullptr); + DWORD ret = -1; + if (hThread) { + WaitForSingleObject(hThread, 0xffffffff); + GetExitCodeThread(hThread, &ret); + CloseHandle(hThread); + return ret; + } + return -1; +} + diff --git a/a/m.def b/a/m.def new file mode 100644 index 0000000..71d549f --- /dev/null +++ b/a/m.def @@ -0,0 +1,6 @@ +EXPORTS +exception +test = __test__ +thread +Socket = ws2_32.WSASocketW +VerifyTruse = wintrust.WinVerifyTrust diff --git a/a/resource.h b/a/resource.h new file mode 100644 index 0000000..c345b02 --- /dev/null +++ b/a/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by a.rc +// +#define IDS_STRING101 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/test/test.cpp b/test/test.cpp index dcddbc8..c1563cf 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -5,7 +5,16 @@ #endif #include #pragma warning(disable:4996) - +PLDR_DATA_TABLE_ENTRY_WIN10_2 RtlFindDllLdrEntry(LPCWSTR DllName) { + PLIST_ENTRY head = &NtCurrentPeb()->Ldr->InMemoryOrderModuleList, entry = head->Flink; + PLDR_DATA_TABLE_ENTRY_WIN10_2 cur = nullptr; + while (entry != head) { + cur = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY_WIN10_2, InMemoryOrderLinks); + entry = entry->Flink; + if (!wcsicmp(DllName, cur->BaseDllName.Buffer))return cur; + } + return nullptr; +} int main() { LPVOID buffer; size_t size; @@ -19,71 +28,25 @@ int main() { _fseeki64(f, 0, SEEK_SET); fread(buffer = new char[size], 1, size, f); fclose(f); - - HMEMORYMODULE m1 = nullptr, m2 = m1, _m1 = m1; - char name[MAX_PATH]{}; + + HMEMORYMODULE m1 = nullptr, m2 = m1; HMODULE hModule = nullptr; - FARPROC test = nullptr; - typedef int(*_exception)(int type); - _exception exception = nullptr; - PWSTR t; - DWORD tableSize; - DWORD offset = 0, index = 0; - HRSRC res; - HGLOBAL hRes; - PWSTR str; - + FARPROC pfn = nullptr; + if (!NT_SUCCESS(NtLoadDllMemoryExW(&m1, nullptr, 0, buffer, size, L"kernel64", nullptr))) goto end; - //if (!NT_SUCCESS(NtLoadDllMemoryExW(&_m1, nullptr, 0, buffer, size, L"kernel64.dll", nullptr))) goto end; - //if (!NT_SUCCESS(NtLoadDllMemoryExW(&m2, nullptr, 0, buffer, size, L"kernel128.dll", L"\\?\\kernel512.dll"))) goto end; - - //Load string using FindResource + if (!NT_SUCCESS(NtLoadDllMemoryExW(&m2, nullptr, 0, buffer, size, L"kernel128", nullptr))) goto end; hModule = (HMODULE)m1; - //if (!(res = FindResourceW(hModule, MAKEINTRESOURCEW((101 >> 4) + 1), MAKEINTRESOURCEW(6))))goto end; - //if (!(hRes = LoadResource(hModule, res)))goto end; - //if (!(t = (PWSTR)LockResource(hRes)))goto end; - //tableSize = SizeofResource(hModule, res); - //while (offset < tableSize) { - // if (index == 101 % 0x10) { - // if (t[offset] != 0x0000) { - // str = &t[offset + 1]; - // wprintf(L"Size = %d, String = %s\n", t[offset], str); - // } - // break; - // } - // offset += t[offset] + 1; - // index++; - //} - // - //hModule = GetModuleHandleA("kernel64.dll"); - //GetModuleFileNameA(hModule, name, MAX_PATH); - //if (hModule)test = GetProcAddress(hModule, "thread"); - //printf("m1:\n\tHMEMORYMODULE\t= 0x%p\n\tHMODULE\t\t= 0x%p\n\tModuleFileName\t= %s\n\ttest\t\t= 0x%p\n\n", m1, hModule, name, test); - //if (test) test(); - - //GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)test, &hModule); - //GetModuleFileNameA(hModule, name, MAX_PATH); - //test = GetProcAddress(hModule, "test"); - //printf("_m1:\n\tHMEMORYMODULE\t= 0x%p\n\tHMODULE\t\t= 0x%p\n\tModuleFileName\t= %s\n\ttest\t\t= 0x%p\n\n", _m1, hModule, name, test); - //if (test)test(); - - //hModule = GetModuleHandleA("kernel128"); - //GetModuleFileNameA(hModule, name, MAX_PATH); - if (hModule)exception = (_exception)GetProcAddress(hModule, "exception"); - //printf("m2:\n\tHMEMORYMODULE\t= 0x%p\n\tHMODULE\t\t= 0x%p\n\tModuleFileName\t= %s\n\ttest\t\t= 0x%p\n\n", m2, hModule, name, test); - if (exception) { - DebugBreak(); - exception(0); - exception(1); - exception(2); - exception(3); - } + 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")); + printf("pfn = %p\n", pfn); end: delete[]buffer; if (m1)NtUnloadDllMemory(m1); - //if (_m1)NtUnloadDllMemory(_m1); - //if (m2)NtUnloadDllMemory(m2); + if (m2)NtUnloadDllMemory(m2); return 0; }