// Constructing a large C/C++ Example private static IAttack LargeCCxxExample() { var samplesOutput = new SamplesOutput(); var attackName = "LargeCCxx"; var attack = new Attack(new IOutput[] { samplesOutput, }, name: attackName); // spawn notepad var createProcessSource1 = new CreateProcess("notepad"); // spawn calc var createProcessSource2 = new CreateProcess("calc"); // returns the we specified path var targetPathSource = new StaticTargetPathCCxxSource(@"C:\Users\Public\baby.txt"); // returns the data we specified var fileResourceSource = new StaticFileResourceCCxxSource(new byte[] { 0x65, 0x65, 0x65, 0x65 }); // Drop a file to disk (drop the file "C:\Users\Public\baby.txt" to disk with contents "AAAA") var writeFileSource = new WriteFileResourceCCxxSource <StaticTargetPathCCxxSource, StaticFileResourceCCxxSource>(targetPathSource, fileResourceSource); // Call a series C functions in order var functionCallsSource = new SequentialFunctionCallCCxxSource(new IParameterlessCFunction[] { createProcessSource1, writeFileSource }); // Limit to at most 1 running instance of this code at a time by creating a Global mutex. Only 1 process can have an open handle to a global mutex at a time var mutexSource = new MutexSingletonCCxxSource(functionCallsSource, mutexName: @"Global\SomeMutexName"); // Check a conditional statement, (check if a debugger is attached) var antidebuggerSource1 = new NotIsDebuggerPresentCCxxSource(); // Returns true if it's safe to execute (No debugger is attached) var antidebuggerSource2 = new RemoteDebuggerCCxxSource(); // Retruns true if it's safe to execute (No debugger is attached) var ifElseSource = new IfElseFunctionCallCCxxSource( "{0} && {1}", // If this boolean expression is true new IParameterlessCFunction[] { antidebuggerSource1, antidebuggerSource2 }, trueCaseFunction: mutexSource, // Then execute this falseCaseFunction: createProcessSource2); // Otherwise execute this var createThreadSource = new CreateThreadCCxxSource(ifElseSource); // Create a new thread and execute this var exeWinMainSource = new FunctionCallExeWinMainCCxxSource(createThreadSource); var exeSource = exeWinMainSource; // Summary, // In the main function (WinMain), // Create a thread // In the new thread, Check if a debugger is present using the IsDebuggerPresent technique and the CheckRemoteDebuggerPresent technique // If a debugger is attached, // spawn calc // Else // debuger is not attached // create a mutex. If the mutex is free, // Spawn notepad // Drop C:\Users\Public\baby.txt to disk var createProcessExeStaticLibrary = ((ICCxxCompiler <Win64ObjectFile>) new MyWarez.Plugins.Msvc.Compiler()).Compile(exeSource); var createProcessExe = ((ILinker <Win64ObjectFile, Executable>) new MyWarez.Plugins.Msvc.Linker()).Link(createProcessExeStaticLibrary); samplesOutput.Add("LargeCCxx.exe", createProcessExe); // Double click the to confirm that notepad spawns. // Open the sample in WinDbg to confirm that calc spawns when a debugger is attached attack.Generate(); return(attack); }
// Steps for writing C code that can be turned into shellcode: // Code must be in C (and have a file extension of ".c") // Declare (and don't initilize) all variables that the start of functions // Initialze variables, if any. // For strings, don't use string constants (qoute notation) to initialize, use arrays instead. // Write Win32 API calls as you normally would, ShellcodeCCxxSource will automagically swap out the calls for dynamically loaded versions // Make sure there is no space between the API name and "(" // Don't use the C runtime library // Use compiler intrinsics where possible // Otherwise copy and paste the implementation of needed C runtime functions from GCC's or ucrt's source code. Or roll your own. // Declare helper functions as static and change the name so that they don't conflict with functions in the CRT // Have at most 1 (nonstatic) function per file. // Place "//HEADERS" near the top of the source file(s) // At the top of every function body, place "//DECLARATIONS" // After the declarations in a function body, place "//INITIALIZATIONS" // For an example, see Resources/Payloads/Windows/Execution/NativeAPI/CreateProcess/CreateProcess.c // Also, prototypes for the Win32 API functions used need to be added to Resources\Base\CCxxSource\ShellodeCCxxSource\DynamicallyLoadedFunctionSignatures.h // Constructing a large C -> Shellcode with MSVC Example private static IAttack LargeCShellcodeMsvcExample() { var samplesOutput = new SamplesOutput(); var attackName = "LargeCShellcodeMsvc"; var attack = new Attack(new IOutput[] { samplesOutput, }, name: attackName); // Same code from LargeCCxx (Some classes changed to their ShellcodeCCxxSource versions) // The CCxxSource and ShellcodeCCxxSource of class should be identical except some implented interfaces, some types, and the different parent class var createProcessSource1 = new CreateProcess("notepad"); var createProcessSource2 = new CreateProcess("calc"); var targetPathSource = new StaticTargetPathCCxxSource(@"C:\Users\Public\baby.txt"); var fileResourceSource = new StaticFileResourceCCxxSource(new byte[] { 0x65, 0x65, 0x65, 0x65 }); var writeFileSource = new WriteFileResourceCCxxSource <StaticTargetPathCCxxSource, StaticFileResourceCCxxSource>(targetPathSource, fileResourceSource); var functionCallsSource = new SequentialFunctionCallShellcodeCCxxSource(new IShellcodeParameterlessCFunction[] { createProcessSource1, writeFileSource }); var mutexSource = new MutexSingletonShellcodeCCxxSource(functionCallsSource, mutexName: @"Global\SomeMutexName"); var antidebuggerSource1 = new NotIsDebuggerPresentCCxxSource(); var antidebuggerSource2 = new RemoteDebuggerCCxxSource(); var ifElseSource = new IfElseFunctionCallShellcodeCCxxSource( "{0} && {1}", new IShellcodeParameterlessCFunction[] { antidebuggerSource1, antidebuggerSource2 }, trueCaseFunction: mutexSource, falseCaseFunction: createProcessSource2); var createThreadSource = new CreateThreadShellcodeCCxxSource(ifElseSource); var shellcodeSource = createThreadSource; // Summary, Same summary as the one from LargeCCxx (minus WinMain) var shellcode = MyWarez.Plugins.Msvc.Utils.CompileToShellcode(shellcodeSource, (StaticLibrary <Win64ObjectFile>)null, optimize: true); // shellcode -> exe wrapper from AssemblyShellcodeYasmGoLink var rawShellcodeAsm = new RawShellcodeYasmAssemblySource(shellcode, symbolName: "SheSellsShellCodesByTheSilkRoad"); var staticLibrary = ((IAssembler <YASM, Win64ObjectFile>) new MyWarez.Plugins.Yasm.Yasm()).Assemble(rawShellcodeAsm); var entryPoint = ((ICFunction)rawShellcodeAsm).Name; var linkerConfig = new MyWarez.Plugins.GoDevTool.Linker.Config(ENTRY: entryPoint); var createProcessExe = ((ILinker <Win64ObjectFile, Executable>) new MyWarez.Plugins.GoDevTool.Linker(linkerConfig)).Link(staticLibrary); // Note: MSVC could also be used for the linker if desired samplesOutput.Add("LargeCShellcodeMsvcNotepad.exe", createProcessExe); // Double click the to confirm that notepad spawns. // Open the sample in WinDbg to confirm that calc spawns when a debugger is attached attack.Generate(); return(attack); }