Skip to content

Instantly share code, notes, and snippets.

@tyranid
Created April 27, 2021 20:41
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save tyranid/c4a77598169e1a75b70c5a2c023bc5df to your computer and use it in GitHub Desktop.
Save tyranid/c4a77598169e1a75b70c5a2c023bc5df to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace StandardActivator
{
enum RUNLEVEL : uint
{
RUNLEVEL_LUA = 0x0,
RUNLEVEL_HIGHEST = 0x1,
RUNLEVEL_ADMIN = 0x2,
RUNLEVEL_MAX_NON_UIA = 0x3,
RUNLEVEL_LUA_UIA = 0x10,
RUNLEVEL_HIGHEST_UIA = 0x11,
RUNLEVEL_ADMIN_UIA = 0x12,
RUNLEVEL_MAX = 0x13,
INVALID_LUA_RUNLEVEL = 0xFFFFFFFF,
};
enum PRT
{
PRT_IGNORE = 0x0,
PRT_CREATE_NEW = 0x1,
PRT_USE_THIS = 0x2,
PRT_USE_THIS_ONLY = 0x3,
};
[Guid("000001B9-0000-0000-c000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ISpecialSystemPropertiesActivator
{
void SetSessionId(int dwSessionId, int bUseConsole, int fRemoteThisSessionId);
void GetSessionId(out int pdwSessionId, out int pbUseConsole);
void GetSessionId2(out int pdwSessionId, out int pbUseConsole, out int pfRemoteThisSessionId);
void SetClientImpersonating(int fClientImpersonating);
void GetClientImpersonating(out int pfClientImpersonating);
void SetPartitionId(ref Guid guidPartition);
void GetPartitionId(out Guid pguidPartition);
void SetProcessRequestType(PRT dwPRT);
void GetProcessRequestType(out PRT pdwPRT);
void SetOrigClsctx(int dwOrigClsctx);
void GetOrigClsctx(out int pdwOrigClsctx);
void GetDefaultAuthenticationLevel(out int pdwDefaultAuthnLvl);
void SetDefaultAuthenticationLevel(int dwDefaultAuthnLvl);
void GetLUARunLevel(out RUNLEVEL pdwLUARunLevel, out IntPtr phwnd);
void SetLUARunLevel(RUNLEVEL dwLUARunLevel, IntPtr hwnd);
}
[Flags]
public enum CLSCTX : uint
{
INPROC_SERVER = 0x1,
INPROC_HANDLER = 0x2,
LOCAL_SERVER = 0x4,
INPROC_SERVER16 = 0x8,
REMOTE_SERVER = 0x10,
INPROC_HANDLER16 = 0x20,
RESERVED1 = 0x40,
RESERVED2 = 0x80,
RESERVED3 = 0x100,
RESERVED4 = 0x200,
NO_CODE_DOWNLOAD = 0x400,
RESERVED5 = 0x800,
NO_CUSTOM_MARSHAL = 0x1000,
ENABLE_CODE_DOWNLOAD = 0x2000,
NO_FAILURE_LOG = 0x4000,
DISABLE_AAA = 0x8000,
ENABLE_AAA = 0x10000,
FROM_DEFAULT_CONTEXT = 0x20000,
ACTIVATE_32_BIT_SERVER = 0x40000,
ACTIVATE_64_BIT_SERVER = 0x80000,
ENABLE_CLOAKING = 0x100000,
APPCONTAINER = 0x400000,
ACTIVATE_AAA_AS_IU = 0x800000,
ACTIVATE_NATIVE_SERVER = 0x1000000,
ACTIVATE_ARM32_SERVER = 0x2000000,
PS_DLL = 0x80000000,
SERVER = INPROC_SERVER | LOCAL_SERVER | REMOTE_SERVER,
ALL = INPROC_SERVER | INPROC_HANDLER | LOCAL_SERVER | REMOTE_SERVER
}
[StructLayout(LayoutKind.Sequential)]
public struct OptionalGuid : IDisposable
{
IntPtr pGuid;
void IDisposable.Dispose()
{
if (pGuid != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(pGuid);
pGuid = IntPtr.Zero;
}
}
public OptionalGuid(Guid guid)
{
pGuid = Marshal.AllocCoTaskMem(16);
Marshal.Copy(guid.ToByteArray(), 0, pGuid, 16);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MULTI_QI : IDisposable
{
OptionalGuid pIID;
IntPtr pItf;
int hr;
public object GetObject()
{
if (pItf == IntPtr.Zero)
{
return null;
}
else
{
return Marshal.GetObjectForIUnknown(pItf);
}
}
public IntPtr GetObjectPointer()
{
if (pItf != IntPtr.Zero)
{
Marshal.AddRef(pItf);
}
return pItf;
}
public int HResult()
{
return hr;
}
void IDisposable.Dispose()
{
((IDisposable)pIID).Dispose();
if (pItf != IntPtr.Zero)
{
Marshal.Release(pItf);
pItf = IntPtr.Zero;
}
}
public MULTI_QI(Guid iid)
{
pIID = new OptionalGuid(iid);
pItf = IntPtr.Zero;
hr = 0;
}
}
[StructLayout(LayoutKind.Sequential)]
public sealed class COSERVERINFO : IDisposable
{
int dwReserved1;
[MarshalAs(UnmanagedType.LPWStr)]
string pwszName;
IntPtr pAuthInfo;
int dwReserved2;
void IDisposable.Dispose()
{
if (pAuthInfo != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(pAuthInfo);
}
}
public COSERVERINFO(string name)
{
pwszName = name;
}
}
[Guid("000001B8-0000-0000-c000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IStandardActivator
{
void StandardGetClassObject(in Guid rclsid, CLSCTX dwContext, [In] COSERVERINFO pServerInfo, in Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppvClassObj);
void StandardCreateInstance(in Guid Clsid, IntPtr punkOuter, CLSCTX dwClsCtx, [In] COSERVERINFO pServerInfo, int dwCount, [In, Out][MarshalAs(UnmanagedType.LPArray)] MULTI_QI[] pResults);
void StandardGetInstanceFromFile([In] COSERVERINFO pServerInfo, in Guid pclsidOverride,
IntPtr punkOuter, CLSCTX dwClsCtx, int grfMode, [MarshalAs(UnmanagedType.LPWStr)] string pwszName, int dwCount, [In, Out] [MarshalAs(UnmanagedType.LPArray)] MULTI_QI[] pResults);
void StandardGetInstanceFromIStorage([In] COSERVERINFO pServerInfo, in Guid pclsidOverride,
IntPtr punkOuter, CLSCTX dwClsCtx, IntPtr /*IStorage* */ pstg, int dwCount, [In, Out][MarshalAs(UnmanagedType.LPArray)] MULTI_QI[] pResults);
void Reset();
}
[Flags]
enum STGM
{
READ = 0x00000000,
WRITE = 0x00000001,
READWRITE = 0x00000002,
SHARE_DENY_NONE = 0x00000040,
SHARE_DENY_READ = 0x00000030,
SHARE_DENY_WRITE = 0x00000020,
SHARE_EXCLUSIVE = 0x00000010,
PRIORITY = 0x00040000,
CREATE = 0x00001000,
CONVERT = 0x00020000,
FAILIFTHERE = READ,
DIRECT = READ,
TRANSACTED = 0x00010000,
NOSCRATCH = 0x00100000,
NOSNAPSHOT = 0x00200000,
SIMPLE = 0x08000000,
DIRECT_SWMR = 0x00400000,
DELETEONRELEASE = 0x04000000
}
enum STGFMT
{
Storage = 0,
File = 3,
Any = 4,
Docfile = 5
}
[StructLayout(LayoutKind.Sequential)]
class STGOPTIONS
{
public short usVersion;
public short reserved;
public int ulSectorSize;
[MarshalAs(UnmanagedType.LPWStr)]
public string pwcsTemplateFile;
}
class Program
{
[DllImport("ole32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
public static extern IntPtr StgCreateStorageEx(
string pwcsName,
STGM grfMode,
STGFMT stgfmt,
int grfAttrs,
[In] STGOPTIONS pStgOptions,
IntPtr pSecurityDescriptor,
ref Guid riid
);
[Guid("0000033C-0000-0000-c000-000000000046")]
[ComImport]
class StandardActivator
{
}
enum EOLE_AUTHENTICATION_CAPABILITIES
{
EOAC_NONE = 0,
EOAC_MUTUAL_AUTH = 0x1,
EOAC_STATIC_CLOAKING = 0x20,
EOAC_DYNAMIC_CLOAKING = 0x40,
EOAC_ANY_AUTHORITY = 0x80,
EOAC_MAKE_FULLSIC = 0x100,
EOAC_DEFAULT = 0x800,
EOAC_SECURE_REFS = 0x2,
EOAC_ACCESS_CONTROL = 0x4,
EOAC_APPID = 0x8,
EOAC_DYNAMIC = 0x10,
EOAC_REQUIRE_FULLSIC = 0x200,
EOAC_AUTO_IMPERSONATE = 0x400,
EOAC_NO_CUSTOM_MARSHAL = 0x2000,
EOAC_DISABLE_AAA = 0x1000
}
enum AuthnLevel
{
RPC_C_AUTHN_LEVEL_DEFAULT = 0,
RPC_C_AUTHN_LEVEL_NONE = 1,
RPC_C_AUTHN_LEVEL_CONNECT = 2,
RPC_C_AUTHN_LEVEL_CALL = 3,
RPC_C_AUTHN_LEVEL_PKT = 4,
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY = 5,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6
}
enum ImpLevel
{
RPC_C_IMP_LEVEL_DEFAULT = 0,
RPC_C_IMP_LEVEL_ANONYMOUS = 1,
RPC_C_IMP_LEVEL_IDENTIFY = 2,
RPC_C_IMP_LEVEL_IMPERSONATE = 3,
RPC_C_IMP_LEVEL_DELEGATE = 4,
}
[DllImport("ole32.dll")]
static extern int CoInitializeSecurity(
IntPtr pSecDesc,
int cAuthSvc,
IntPtr asAuthSvc,
IntPtr pReserved1,
AuthnLevel dwAuthnLevel,
ImpLevel dwImpLevel,
IntPtr pAuthList,
EOLE_AUTHENTICATION_CAPABILITIES dwCapabilities,
IntPtr pReserved3
);
// Run here to ensure it's called before the main thread.
static readonly int _security_init = CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero,
AuthnLevel.RPC_C_AUTHN_LEVEL_DEFAULT, ImpLevel.RPC_C_IMP_LEVEL_IMPERSONATE, IntPtr.Zero,
EOLE_AUTHENTICATION_CAPABILITIES.EOAC_DYNAMIC_CLOAKING, IntPtr.Zero);
static IntPtr CreateStorage(string name, STGM mode, STGFMT format)
{
Guid iid = new Guid("0000000B-0000-0000-C000-000000000046");
return StgCreateStorageEx(name, mode, format, 0, null, IntPtr.Zero, ref iid);
}
[STAThread]
static void Main(string[] args)
{
try
{
string path = Path.GetDirectoryName(typeof(Program).Assembly.Location);
IntPtr stg = CreateStorage(Path.Combine(path, "test.stg"), STGM.CREATE | STGM.READWRITE | STGM.SHARE_EXCLUSIVE, STGFMT.Docfile);
Console.WriteLine(stg);
var act = (IStandardActivator)new StandardActivator();
ISpecialSystemPropertiesActivator props = (ISpecialSystemPropertiesActivator)act;
if (args.Length > 0)
{
int session_id = int.Parse(args[0]);
Console.WriteLine("Spawning in session {0}", session_id);
props.SetSessionId(session_id, 0, 1);
}
Guid test_clsid = new Guid("8cec58ae-07a1-11d9-b15e-000d56bfe6ee");
Guid iid = new Guid("00000000-0000-0000-c000-000000000046");
MULTI_QI[] qis = new MULTI_QI[1];
qis[0] = new MULTI_QI(iid);
act.StandardGetInstanceFromIStorage(null, test_clsid, IntPtr.Zero, CLSCTX.LOCAL_SERVER, stg, 1, qis);
Console.WriteLine(qis[0].GetObject());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment