Finalized Eazfuscator launcher
This commit is contained in:
@@ -2,6 +2,11 @@ kind: pipeline
|
|||||||
name: default
|
name: default
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: mcr.microsoft.com/dotnet/sdk:8.0
|
||||||
|
commands:
|
||||||
|
- dotnet build --configuration Release Eazfuscator-Launcher/Eazfuscator-Launcher.csproj
|
||||||
|
|
||||||
- name: docker
|
- name: docker
|
||||||
image: plugins/docker
|
image: plugins/docker
|
||||||
settings:
|
settings:
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ ENV DISPLAY ":95"
|
|||||||
ENV WINEARCH win32
|
ENV WINEARCH win32
|
||||||
|
|
||||||
COPY tools/* /root/.wine/drive_c/windows/system32/
|
COPY tools/* /root/.wine/drive_c/windows/system32/
|
||||||
|
COPY Eazfuscator-Launcher/bin/Release/net472/Eazfuscator-Launcher.exe /root/.wine/drive_c/users/root/Eazfuscator/Launcher/Eazfuscator.NET.exe
|
||||||
|
|
||||||
RUN set -x -e; \
|
RUN set -x -e; \
|
||||||
# Install dotnet
|
# Install dotnet
|
||||||
@@ -40,7 +41,7 @@ RUN set -x -e; \
|
|||||||
PATH_TRIMMED_LEFT=${PATH_DIRTY#${PATH_DIRTY%%[![:space:]]*}}; \
|
PATH_TRIMMED_LEFT=${PATH_DIRTY#${PATH_DIRTY%%[![:space:]]*}}; \
|
||||||
# trim end
|
# trim end
|
||||||
PATH_VALUE=${PATH_TRIMMED_LEFT%${PATH_TRIMMED_LEFT##*[![:space:]]}}; \
|
PATH_VALUE=${PATH_TRIMMED_LEFT%${PATH_TRIMMED_LEFT##*[![:space:]]}}; \
|
||||||
wine reg add "HKLM\\SYSTEM\\CurrentControlSet\\Control\Session Manager\\Environment" /v PATH /t REG_EXPAND_SZ /d "C:\\Users\\root\\Eazfuscator;$PATH_VALUE" /f; \
|
wine reg add "HKLM\\SYSTEM\\CurrentControlSet\\Control\Session Manager\\Environment" /v PATH /t REG_EXPAND_SZ /d "C:\\Users\\root\\Eazfuscator\\Launcher;$PATH_VALUE" /f; \
|
||||||
wine reg add "HKLM\\SYSTEM\\CurrentControlSet\\Control\Session Manager\\Environment" /v EAZFUSCATOR_NET_LICENSE /t REG_SZ /d "4SY9QB68-3WD55J3Y-XWCD7DFF-UPZVRNXJ-PWFEH4P5-YHJFCGQP-AGTBM5GF-JSK8JN35"; \
|
wine reg add "HKLM\\SYSTEM\\CurrentControlSet\\Control\Session Manager\\Environment" /v EAZFUSCATOR_NET_LICENSE /t REG_SZ /d "4SY9QB68-3WD55J3Y-XWCD7DFF-UPZVRNXJ-PWFEH4P5-YHJFCGQP-AGTBM5GF-JSK8JN35"; \
|
||||||
# HACK: Wait for the registry writes to complete in Wine
|
# HACK: Wait for the registry writes to complete in Wine
|
||||||
# (see more at https://serverfault.com/questions/1082578/wine-in-docker-reg-add-only-keeps-effects-temporarily)
|
# (see more at https://serverfault.com/questions/1082578/wine-in-docker-reg-add-only-keeps-effects-temporarily)
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.IO;
|
|
||||||
using System.IO.Pipes;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
class A
|
class A
|
||||||
{
|
{
|
||||||
private const int STD_OUTPUT_HANDLE = -11;
|
private const int STD_OUTPUT_HANDLE = -11;
|
||||||
private const int STD_ERROR_HANDLE = -12;
|
private const int STD_ERROR_HANDLE = -12;
|
||||||
|
|
||||||
private const uint CREATE_SUSPENDED = 0x00000004;
|
private const uint CREATE_SUSPENDED = 0x00000004;
|
||||||
private const uint DETACHED_PROCESS = 0x00000008;
|
private const uint DETACHED_PROCESS = 0x00000008;
|
||||||
|
|
||||||
private const int STARTF_USESTDHANDLES = 0x00000100;
|
private const int STARTF_USESTDHANDLES = 0x00000100;
|
||||||
private static readonly IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);
|
private static readonly IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);
|
||||||
|
|
||||||
|
private const uint WINSTA_ALL_ACCESS = 0x37F;
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
[DllImport("kernel32.dll")]
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
private static extern bool CreateProcess(
|
private static extern bool CreateProcess(
|
||||||
@@ -63,35 +63,23 @@ class A
|
|||||||
public int dwThreadId;
|
public int dwThreadId;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
|
||||||
[return: MarshalAs(UnmanagedType.U4)]
|
|
||||||
private static extern uint ResumeThread(IntPtr hThread);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||||
private static extern IntPtr CreateWindowStation(string lpwinsta, uint dwReserved, uint dwDesiredAccess, IntPtr lpsa);
|
private static extern IntPtr CreateWindowStation(string lpwinsta, uint dwReserved, uint dwDesiredAccess, IntPtr lpsa);
|
||||||
|
|
||||||
private const uint WINSTA_ALL_ACCESS = 0x37F;
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
private static extern bool SetProcessWindowStation(IntPtr hWinSta);
|
private static extern bool SetProcessWindowStation(IntPtr hWinSta);
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
public static int Main(string[] args)
|
||||||
private static extern IntPtr CreateDesktop(string lpszDesktop, IntPtr lpszDevice, IntPtr pDevmode, uint dwFlags, uint dwDesiredAccess, IntPtr lpsa);
|
|
||||||
|
|
||||||
private const uint GENERIC_ALL = 0x10000000;
|
|
||||||
|
|
||||||
public static async Task<int> Main(string[] args)
|
|
||||||
{
|
{
|
||||||
Console.WriteLine(string.Format("Is user-interactive: {0}", Environment.UserInteractive));
|
// The main executable is in the parent directory and named the same
|
||||||
|
string execPath = Assembly.GetExecutingAssembly().Location;
|
||||||
if (args.Length == 0)
|
string fileName = Path.GetFileName(execPath);
|
||||||
{
|
string mainExecutablePath = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(execPath)), fileName);
|
||||||
Console.Error.WriteLine("Specify executable to run detached.");
|
Console.WriteLine(mainExecutablePath);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Propagate the command line
|
// Propagate the command line
|
||||||
StringBuilder argsSub = new StringBuilder();
|
StringBuilder argsSub = new StringBuilder();
|
||||||
|
argsSub.Append('"').Append(mainExecutablePath).Append('"').Append(' ');
|
||||||
for (int i = 0; i < args.Length; i++)
|
for (int i = 0; i < args.Length; i++)
|
||||||
argsSub.Append('"').Append(args[i]).Append('"').Append(' ');
|
argsSub.Append('"').Append(args[i]).Append('"').Append(' ');
|
||||||
|
|
||||||
@@ -100,197 +88,42 @@ class A
|
|||||||
foreach (DictionaryEntry i in Environment.GetEnvironmentVariables())
|
foreach (DictionaryEntry i in Environment.GetEnvironmentVariables())
|
||||||
env.Append((string)i.Key).Append('=').Append((string)i.Value).Append('\0');
|
env.Append((string)i.Key).Append('=').Append((string)i.Value).Append('\0');
|
||||||
|
|
||||||
|
// Use a new window-station so that Environment.UserInteractive becomes false
|
||||||
|
// search for WSF_VISIBLE
|
||||||
|
// or see https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/SystemInformation.cs,416f4f3dac9f38f1,references
|
||||||
IntPtr hSta = CreateWindowStation("detach", 0, WINSTA_ALL_ACCESS, IntPtr.Zero);
|
IntPtr hSta = CreateWindowStation("detach", 0, WINSTA_ALL_ACCESS, IntPtr.Zero);
|
||||||
if (!SetProcessWindowStation(hSta)) {
|
if (!SetProcessWindowStation(hSta)) {
|
||||||
Console.Error.WriteLine("Failed to switch to a new windows station.");
|
Console.Error.WriteLine("Failed to switch to a new windows station.");
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
Console.WriteLine(string.Format("Is user-interactive2: {0}", Environment.UserInteractive));
|
|
||||||
IntPtr hDesktop = CreateDesktop("desktop", IntPtr.Zero, IntPtr.Zero, 0, GENERIC_ALL, IntPtr.Zero);
|
|
||||||
if (hDesktop == IntPtr.Zero) {
|
|
||||||
Console.Error.WriteLine("Failed to create a non-interactive desktop.");
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
//env.Append("EAZFUSCATOR_NET_LICENSE=").Append("4SY9QB68-3WD55J3Y-XWCD7DFF-UPZVRNXJ-PWFEH4P5-YHJFCGQP-AGTBM5GF-JSK8JN3").Append('\0');
|
STARTUPINFO si = new STARTUPINFO();
|
||||||
|
si.cb = Marshal.SizeOf(si);
|
||||||
|
si.hStdInput = INVALID_HANDLE_VALUE;
|
||||||
|
si.hStdOutput = INVALID_HANDLE_VALUE;
|
||||||
|
si.hStdError = INVALID_HANDLE_VALUE;
|
||||||
|
si.dwFlags = 0;
|
||||||
|
|
||||||
using (AnonymousPipeServerStream fOutW = new AnonymousPipeServerStream(PipeDirection.Out))
|
// Start the process detached from the current console and thus losing
|
||||||
using (AnonymousPipeClientStream fOutR = new AnonymousPipeClientStream(PipeDirection.In, fOutW.GetClientHandleAsString()))
|
// the "interactiveness"
|
||||||
using (AnonymousPipeServerStream fErrW = new AnonymousPipeServerStream(PipeDirection.Out))
|
PROCESS_INFORMATION pi;
|
||||||
using (AnonymousPipeClientStream fErrR = new AnonymousPipeClientStream(PipeDirection.In, fErrW.GetClientHandleAsString()))
|
if (!CreateProcess(mainExecutablePath, argsSub.ToString(), IntPtr.Zero, IntPtr.Zero, false, 0, env.ToString(), null, ref si, out pi))
|
||||||
{
|
{
|
||||||
STARTUPINFO si = new STARTUPINFO();
|
Console.Error.WriteLine(string.Format("Failed to start process '{0}'.", mainExecutablePath));
|
||||||
si.cb = Marshal.SizeOf(si);
|
return 2;
|
||||||
si.hStdInput = INVALID_HANDLE_VALUE;
|
|
||||||
si.hStdOutput = fOutW.SafePipeHandle.DangerousGetHandle();
|
|
||||||
si.hStdError = fErrW.SafePipeHandle.DangerousGetHandle();
|
|
||||||
si.dwFlags = STARTF_USESTDHANDLES;
|
|
||||||
//si.lpDesktop = "";// "detach\\desktop"; // does not work
|
|
||||||
|
|
||||||
// Start the process detached from the current console and thus losing
|
|
||||||
// the "interactiveness"
|
|
||||||
PROCESS_INFORMATION pi;
|
|
||||||
string executablePath = args[0];
|
|
||||||
if (!CreateProcess(executablePath, argsSub.ToString(), IntPtr.Zero, IntPtr.Zero, false, DETACHED_PROCESS, env.ToString(), null, ref si, out pi))
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine(string.Format("Failed to start process '{0}'.", executablePath));
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (Process p = Process.GetProcessById(pi.dwProcessId))
|
|
||||||
{
|
|
||||||
// Continually copy the standard streams
|
|
||||||
CancellationTokenSource cancel = new CancellationTokenSource();
|
|
||||||
Task tCopyOut = CopyStreamAsync(fOutR, Console.OpenStandardOutput(), cancel.Token);
|
|
||||||
Task tCopyErr = CopyStreamAsync(fErrR, Console.OpenStandardError(), cancel.Token);
|
|
||||||
|
|
||||||
p.WaitForExit();
|
|
||||||
|
|
||||||
// Complete
|
|
||||||
cancel.Cancel();
|
|
||||||
//await Task.WhenAll(tCopyOut, tCopyErr);
|
|
||||||
|
|
||||||
int exitCode;
|
|
||||||
if (!GetExitCodeProcess(pi.hProcess, out exitCode))
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine("Failed to get the exit code.");
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
return exitCode;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task CopyStreamAsync(Stream src, Stream dst, CancellationToken cancel)
|
using (Process p = Process.GetProcessById(pi.dwProcessId))
|
||||||
{
|
|
||||||
byte[] buffer = new byte[4096];
|
|
||||||
while (!cancel.IsCancellationRequested)
|
|
||||||
{
|
{
|
||||||
int read = await src.ReadAsync(buffer, 0, buffer.Length, cancel);
|
p.WaitForExit();
|
||||||
await dst.WriteAsync(buffer, 0, read, cancel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int exitCode;
|
||||||
|
if (!GetExitCodeProcess(pi.hProcess, out exitCode))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static void EnumSessions()
|
|
||||||
{
|
|
||||||
UInt64 count;
|
|
||||||
IntPtr luidPtr = IntPtr.Zero;
|
|
||||||
LsaEnumerateLogonSessions(out count, out luidPtr); //gets an array of
|
|
||||||
//pointers to LUIDs
|
|
||||||
|
|
||||||
IntPtr iter = luidPtr; //set the pointer to the
|
|
||||||
//start of the array
|
|
||||||
|
|
||||||
for (ulong i = 0; i < count; i++) //for each pointer in the
|
|
||||||
//array
|
|
||||||
{
|
|
||||||
IntPtr sessionData;
|
|
||||||
|
|
||||||
LsaGetLogonSessionData(iter, out sessionData);
|
|
||||||
SECURITY_LOGON_SESSION_DATA data = (
|
|
||||||
SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure
|
|
||||||
(sessionData, typeof(SECURITY_LOGON_SESSION_DATA));
|
|
||||||
|
|
||||||
//if we have a valid logon
|
|
||||||
if (data.PSiD != IntPtr.Zero)
|
|
||||||
{
|
{
|
||||||
//get the security identifier for further use
|
Console.Error.WriteLine("Failed to get the exit code.");
|
||||||
System.Security.Principal.SecurityIdentifier sid =
|
return 3;
|
||||||
new System.Security.Principal.SecurityIdentifier(data.PSiD);
|
|
||||||
|
|
||||||
SECURITY_LOGON_TYPE secType = (SECURITY_LOGON_TYPE)data.LogonType;
|
|
||||||
|
|
||||||
//Look at sectype to see if interactive or remote interactive
|
|
||||||
Console.WriteLine(secType.ToString());
|
|
||||||
if (secType == SECURITY_LOGON_TYPE.Interactive || secType == SECURITY_LOGON_TYPE.RemoteInteractive)
|
|
||||||
{
|
|
||||||
//do something
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return exitCode;
|
||||||
iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LUID)));
|
|
||||||
//move the pointer forward
|
|
||||||
LsaFreeReturnBuffer(sessionData);
|
|
||||||
//free the SECURITY_LOGON_SESSION_DATA memory in the struct
|
|
||||||
}
|
}
|
||||||
LsaFreeReturnBuffer(luidPtr); //free the array of LUIDs
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[DllImport("secur32.dll", SetLastError = false)]
|
|
||||||
private static extern uint LsaFreeReturnBuffer(IntPtr buffer);
|
|
||||||
|
|
||||||
[DllImport("Secur32.dll", SetLastError = false)]
|
|
||||||
private static extern uint LsaEnumerateLogonSessions
|
|
||||||
(out UInt64 LogonSessionCount, out IntPtr LogonSessionList);
|
|
||||||
|
|
||||||
[DllImport("Secur32.dll", SetLastError = false)]
|
|
||||||
private static extern uint LsaGetLogonSessionData(IntPtr luid,
|
|
||||||
out IntPtr ppLogonSessionData);
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
private struct LSA_UNICODE_STRING
|
|
||||||
{
|
|
||||||
public UInt16 Length;
|
|
||||||
public UInt16 MaximumLength;
|
|
||||||
public IntPtr buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
private struct LUID
|
|
||||||
{
|
|
||||||
public UInt32 LowPart;
|
|
||||||
public UInt32 HighPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
private struct SECURITY_LOGON_SESSION_DATA
|
|
||||||
{
|
|
||||||
public UInt32 Size;
|
|
||||||
public LUID LoginID;
|
|
||||||
public LSA_UNICODE_STRING Username;
|
|
||||||
public LSA_UNICODE_STRING LoginDomain;
|
|
||||||
public LSA_UNICODE_STRING AuthenticationPackage;
|
|
||||||
public UInt32 LogonType;
|
|
||||||
public UInt32 Session;
|
|
||||||
public IntPtr PSiD;
|
|
||||||
public UInt64 LoginTime;
|
|
||||||
public LSA_UNICODE_STRING LogonServer;
|
|
||||||
public LSA_UNICODE_STRING DnsDomainName;
|
|
||||||
public LSA_UNICODE_STRING Upn;
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum SECURITY_LOGON_TYPE : uint
|
|
||||||
{
|
|
||||||
Interactive = 2, //The security principal is logging on
|
|
||||||
//interactively.
|
|
||||||
Network, //The security principal is logging using a
|
|
||||||
//network.
|
|
||||||
Batch, //The logon is for a batch process.
|
|
||||||
Service, //The logon is for a service account.
|
|
||||||
Proxy, //Not supported.
|
|
||||||
Unlock, //The logon is an attempt to unlock a workstation.
|
|
||||||
NetworkCleartext, //The logon is a network logon with cleartext
|
|
||||||
//credentials.
|
|
||||||
NewCredentials, //Allows the caller to clone its current token and
|
|
||||||
//specify new credentials for outbound connections.
|
|
||||||
RemoteInteractive, //A terminal server session that is both remote
|
|
||||||
//and interactive.
|
|
||||||
CachedInteractive, //Attempt to use the cached credentials without
|
|
||||||
//going out across the network.
|
|
||||||
CachedRemoteInteractive,// Same as RemoteInteractive, except used
|
|
||||||
// internally for auditing purposes.
|
|
||||||
CachedUnlock // The logon is an attempt to unlock a workstation.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user