Created
July 3, 2023 12:43
-
-
Save rxwx/1717e95e5ec11bea12d33e93a3832508 to your computer and use it in GitHub Desktop.
Determine redirection path for SxS DotLocal DLL Hijacking
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Text; | |
using System.Diagnostics; | |
using System.Runtime.InteropServices; | |
using static GetSxsPath.NativeMethods; | |
namespace GetSxsPath | |
{ | |
internal class NativeMethods | |
{ | |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] | |
public struct ACTCTX | |
{ | |
public int cbSize; | |
public uint dwFlags; | |
public string lpSource; | |
public UInt16 wProcessorArchitecture; | |
public UInt16 wLangId; | |
public string lpAssemblyDirectory; | |
public UInt16 lpResourceName; | |
public string lpApplicationName; | |
public IntPtr hModule; | |
} | |
public const uint ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID = 0x001; | |
public const uint ACTCTX_FLAG_LANGID_VALID = 0x002; | |
public const uint ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x004; | |
public const uint ACTCTX_FLAG_RESOURCE_NAME_VALID = 0x008; | |
public const uint ACTCTX_FLAG_SET_PROCESS_DEFAULT = 0x010; | |
public const uint ACTCTX_FLAG_APPLICATION_NAME_VALID = 0x020; | |
public const uint ACTCTX_FLAG_HMODULE_VALID = 0x080; | |
public const uint RT_MANIFEST = 24; | |
public const uint CREATEPROCESS_MANIFEST_RESOURCE_ID = 1; | |
public const uint ISOLATIONAWARE_MANIFEST_RESOURCE_ID = 2; | |
public const uint ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID = 3; | |
[Flags] | |
public enum LoadLibraryFlags : uint | |
{ | |
None = 0, | |
DONT_RESOLVE_DLL_REFERENCES = 0x00000001, | |
LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010, | |
LOAD_LIBRARY_AS_DATAFILE = 0x00000002, | |
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040, | |
LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020, | |
LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200, | |
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000, | |
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100, | |
LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800, | |
LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400, | |
LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008, | |
LOAD_LIBRARY_REQUIRE_SIGNED_TARGET = 0x00000080, | |
LOAD_LIBRARY_SAFE_CURRENT_DIRS = 0x00002000, | |
} | |
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | |
public static extern IntPtr CreateActCtx(ref ACTCTX pActCtx); | |
[DllImport("Kernel32.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool ActivateActCtx(IntPtr hActCtx, out IntPtr lpCookie); | |
[DllImport("Kernel32.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool DeactivateActCtx(int dwFlags, IntPtr lpCookie); | |
[DllImport("Kernel32.dll", SetLastError = true)] | |
public static extern void ReleaseActCtx(IntPtr hActCtx); | |
[DllImport("psapi.dll", SetLastError = true)] | |
public static extern uint GetMappedFileName(IntPtr hProcess, IntPtr lpv, StringBuilder lpFilename, uint nSize); | |
[DllImport("kernel32.dll", SetLastError = true)] | |
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags); | |
[DllImport("kernel32.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool FreeLibrary(IntPtr hModule); | |
} | |
internal class Program | |
{ | |
/// <summary> | |
/// Creates an Activation Context using the specified executable's manifest | |
/// The function then returns the redirected SxS path for the requested DLL | |
/// </summary> | |
private static string GetSxsPathFromActivationContext(string executablePath, | |
string queryDll = "comctl32.dll") | |
{ | |
string sxsPath = null; | |
var actCtx = new ACTCTX | |
{ | |
cbSize = Marshal.SizeOf(typeof(ACTCTX)), | |
lpSource = Path.GetFullPath(executablePath), | |
lpResourceName = 1, | |
dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID, | |
}; | |
IntPtr hActCtx = CreateActCtx(ref actCtx); | |
if (hActCtx == new IntPtr(-1)) | |
{ | |
Console.WriteLine("[!] Failed to create Activation Context: {0}", Marshal.GetLastWin32Error()); | |
return sxsPath; | |
} | |
Console.WriteLine("[+] Created Activation Context"); | |
if (!ActivateActCtx(hActCtx, out IntPtr cookie)) | |
{ | |
Console.WriteLine("[!] Unable to activate ActCtx: {0}", Marshal.GetLastWin32Error()); | |
goto CLEANUP_RELEASE; | |
} | |
Console.WriteLine("[*] Cookie: 0x{0:X}", cookie); | |
// Load the library we're interested in | |
IntPtr hModule = LoadLibraryEx(queryDll, IntPtr.Zero, LoadLibraryFlags.LOAD_LIBRARY_AS_DATAFILE); | |
if (hModule == IntPtr.Zero) | |
{ | |
Console.WriteLine("[!] Unable to load redirected DLL"); | |
goto CLEANUP_DEACTIVATE; | |
} | |
else | |
{ | |
Console.WriteLine("[*] LoadLibraryEx success"); | |
StringBuilder fullPath = new StringBuilder(260); | |
GetMappedFileName(Process.GetCurrentProcess().Handle, hModule, fullPath, (uint)fullPath.Capacity); | |
if (fullPath.ToString().ToLower().Contains(queryDll) && | |
fullPath.ToString().ToLower().Contains("winsxs")) | |
{ | |
sxsPath = new DirectoryInfo(Path.GetDirectoryName(fullPath.ToString())).Name; | |
Console.WriteLine($"[+] Found SxS path: {sxsPath}"); | |
} | |
FreeLibrary(hModule); | |
} | |
CLEANUP_DEACTIVATE: | |
if (!DeactivateActCtx(0, cookie)) | |
{ | |
Console.WriteLine("[!] Unable to deactivate ActCtx: {0}", Marshal.GetLastWin32Error()); | |
} | |
CLEANUP_RELEASE: | |
ReleaseActCtx(hActCtx); | |
return sxsPath; | |
} | |
static void Main(string[] args) | |
{ | |
string defaultFile = "uninstaller.exe"; | |
if (!File.Exists(defaultFile) && (args.Length == 0 || !File.Exists(args[0]))) | |
{ | |
Console.WriteLine($"[!] {defaultFile} is not found in current directory, please provide the path as the first argument"); | |
return; | |
} | |
// Determine SxS path to spoof, e.g. | |
// amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.22621.608_none_a9444ca7c10bb01d | |
// x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.19041.1110_none_c0da534e38c01f4d | |
string sxsPath = GetSxsPathFromActivationContext(File.Exists(defaultFile) ? defaultFile : args[0]); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment