private IEnumerable <T> Assmeble <T>(AssemblySource <MASM> assemblySource, TargetArch targetArch, Func <byte[], T> TConstructor) where T : ObjectFile, new() { List <T> objectFiles = new List <T>(); using (new TemporaryContext()) { foreach (var sourceFile in assemblySource.SourceFiles) { System.IO.File.WriteAllBytes(sourceFile.Filename, sourceFile.Bytes); } foreach (var sourceFile in assemblySource.SourceFiles.Where(sf => sf.Type == AssemblySourceFileType.Asm)) { var program = targetArch == TargetArch.x64 ? "ml64.exe" : "ml.exe"; var arguments = String.Format("/nologo /Fo object.obj /c /Cx {0}", sourceFile.Filename); var assembleCommand = program + " " + arguments; var msvcVersion = version.ToString().Replace("v", "").Replace("_", "."); var assembleBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n" + assembleCommand; assembleBatFile = String.Format(assembleBatFile, targetArch.ToString()); File.WriteAllText("assemble.bat", assembleBatFile); var proc = Process.Start("cmd.exe", "/c " + "assemble.bat"); proc.WaitForExit(); if (!System.IO.File.Exists("object.obj")) { throw new Exception("Masm error. Object file not found."); } var objectFileBytes = System.IO.File.ReadAllBytes("object.obj"); objectFiles.Add(TConstructor(objectFileBytes)); } } return(objectFiles); }
public static IntPtr GetDisasm(Machine machine) { TargetArch target = TargetArch.Target_Host; switch (machine) { case Machine.Amd64: target = TargetArch.Target_X64; break; case Machine.I386: target = TargetArch.Target_X86; break; case Machine.Arm64: target = TargetArch.Target_Arm64; break; case Machine.ArmThumb2: target = TargetArch.Target_Thumb; break; default: R2RDump.WriteWarning($"{machine} not supported on CoreDisTools"); return(IntPtr.Zero); } return(InitBufferedDisasm(target)); }
static Executable ShellcodeToExe(IShellcode shellcode, TargetArch targetArch) { switch (targetArch) { case TargetArch.x64: { 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); return(((ILinker <Win64ObjectFile, Executable>) new MyWarez.Plugins.GoDevTool.Linker(linkerConfig)).Link(staticLibrary)); } case TargetArch.x86: { var rawShellcodeAsm = new RawShellcodeYasmAssemblySource(shellcode, symbolName: "SheSellsShellCodesByTheSilkRoad"); var staticLibrary = ((IAssembler <YASM, Win32ObjectFile>) new MyWarez.Plugins.Yasm.Yasm()).Assemble(rawShellcodeAsm); var entryPoint = ((ICFunction)rawShellcodeAsm).Name; var linkerConfig = new MyWarez.Plugins.GoDevTool.Linker.Config(ENTRY: entryPoint); var exe = ((ILinker <Win32ObjectFile, Executable>) new MyWarez.Plugins.GoDevTool.Linker(linkerConfig)).Link(staticLibrary); return(exe); } default: throw new Exception(); } }
// TODO: Support compiling source files recursively private StaticLibrary <T> Compile <T>(ICCxxSource source, TargetArch targetArch, Func <byte[], T> TConstructor) where T : ObjectFile, new() { switch (targetArch) { case TargetArch.x86: CConfig.MACHINE = Config.Machine.X86; break; case TargetArch.x64: CConfig.MACHINE = Config.Machine.X64; break; case TargetArch.arm: case TargetArch.arm64: CConfig.MACHINE = Config.Machine.ARM; break; } using (new TemporaryContext()) { var exts = new HashSet <string>(); foreach (var sourceFile in source.SourceFiles) { File.WriteAllText(sourceFile.Filename, sourceFile.Source); if (sourceFile.Type == CCxxSourceFileType.C || sourceFile.Type == CCxxSourceFileType.Cxx) { exts.Add(Path.GetExtension(sourceFile.Filename)); } } var sourceFilenames = exts.Select(ext => "*" + ext); var compilerOptions = CConfig.ToString(); var compileCommand = $"cl.exe /c /nologo /diagnostics:column {compilerOptions} {string.Join(" ", sourceFilenames)}"; var msvcVersion = version.ToString().Replace("v", "").Replace("_", "."); var compileBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n" + compileCommand; compileBatFile = String.Format(compileBatFile, targetArch.ToString()); File.WriteAllText("compile.bat", compileBatFile); var proc = Process.Start("cmd.exe", "/c " + "compile.bat"); proc.WaitForExit(); string[] objectFilePaths = Directory.GetFiles(".", "*.obj", SearchOption.AllDirectories); var objectFiles = objectFilePaths.ToList().Select((file) => TConstructor(File.ReadAllBytes(file))).ToList(); return(new StaticLibrary <T>(objectFiles)); } }
public static IntPtr GetDisasm(Machine machine) { TargetArch target = TargetArch.Target_Host; switch (machine) { case Machine.Amd64: target = TargetArch.Target_X64; break; case Machine.I386: target = TargetArch.Target_X86; break; case Machine.Arm64: target = TargetArch.Target_Arm64; break; case Machine.ArmThumb2: target = TargetArch.Target_Thumb; break; } return(InitBufferedDisasm(target)); }
public static extern IntPtr InitBufferedDisasm(TargetArch Target);
private static extern IntPtr InitBufferedDisasm(TargetArch Target);
public Script(string Name, string Content, TargetPlatform platform = TargetPlatform.UNKNOWN, TargetOS os = TargetOS.UNKNOWN, TargetArch arch = TargetArch.UNKNOWN) { scriptName = Name; scriptBody = Content; this.platform = platform; this.os = os; this.arch = arch; }
private U Link <T, U>(IEnumerable <StaticLibrary <T> > staticLibraries, TargetArch targetArch, Func <byte[], U> UConstructor, Config.OutputType outputType) where T : ObjectFile, new() where U : IPortableExecutable, new() { switch (targetArch) { case TargetArch.x86: CConfig.MACHINE = Config.Machine.X86; break; case TargetArch.x64: CConfig.MACHINE = Config.Machine.X64; break; case TargetArch.arm: case TargetArch.arm64: CConfig.MACHINE = Config.Machine.ARM; break; } var outputExtension = ".exe"; switch (outputType) { case Config.OutputType.EXE: CConfig.outputType = Config.OutputType.EXE; outputExtension = ".exe"; break; case Config.OutputType.DLL: CConfig.outputType = Config.OutputType.DLL; outputExtension = ".dll"; break; case Config.OutputType.DRIVER: CConfig.outputType = Config.OutputType.DRIVER; outputExtension = ".sys"; break; } using (new TemporaryContext()) { foreach (var staticLibrary in staticLibraries) { foreach (var objectFile in staticLibrary.ObjectFiles) { File.WriteAllBytes(Core.Utils.RandomString(10) + ".obj", objectFile.Bytes); } } var outputfilename = "OUTPUT" + outputExtension; var linkerOptions = CConfig.ToString(); if (linkerOptions.Length > 0) { linkerOptions = " " + linkerOptions; } var linkCommand = "link.exe"; linkCommand += " /out:" + outputfilename; linkCommand += " /NOLOGO"; linkCommand += linkerOptions; linkCommand += " *.obj"; var msvcVersion = version.ToString().Replace("v", "").Replace("_", "."); var linkBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n" + linkCommand; linkBatFile = String.Format(linkBatFile, targetArch.ToString()); File.WriteAllText("link.bat", linkBatFile); var proc = Process.Start("cmd.exe", "/c " + "link.bat"); proc.WaitForExit(); var pe = UConstructor(File.ReadAllBytes(outputfilename)); if (CConfig.MAP) { pe.Map = File.ReadAllText("OUTPUT.map"); } return(pe); } }
internal static StaticLibrary <T> LibFileToStaticLibrary <T>(string libFile, Func <byte[], T> TConstructor, TargetArch targetArch, Version version = Version.v14_16, IEnumerable <string> includeFilter = null) where T : ObjectFile, new() { var objectPaths = new List <string>(); using (new TemporaryContext()) { var command = $"lib.exe /nologo /list {libFile}"; var msvcVersion = version.ToString().Replace("v", "").Replace("_", "."); var listBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n" + command; listBatFile = String.Format(listBatFile, targetArch.ToString()); File.WriteAllText("list.bat", listBatFile); Process process = new Process(); process.StartInfo.FileName = "cmd.exe"; process.StartInfo.Arguments = "/c list.bat"; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.Start(); while (!process.StandardOutput.EndOfStream) { string line = process.StandardOutput.ReadLine(); if (line.Contains("**")) { continue; } if (line.ToLower().Contains("vcvars")) { continue; } if (line != "") { objectPaths.Add(line); } } process.WaitForExit(); } objectPaths = objectPaths.Where(x => includeFilter == null || includeFilter.Any(y => x.Contains(y))).ToList(); using (new TemporaryContext()) { var msvcVersion = version.ToString().Replace("v", "").Replace("_", "."); var extractBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n"; extractBatFile = String.Format(extractBatFile, targetArch.ToString()); File.WriteAllText("extract.bat", extractBatFile); foreach (var objectPath in objectPaths) { var command = $"lib.exe /nologo {libFile} /EXTRACT:{objectPath}"; File.AppendAllText("extract.bat", $"\r\n{command}"); } Process.Start("cmd.exe", "/c extract.bat").WaitForExit(); // Parse the object files for their Symbol names string[] objectFilePaths = Directory.GetFiles(".", "*.obj", SearchOption.AllDirectories); var symbolsBatFile = @"call ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\VCVARSALL.bat"" {0} -vcvars_ver=" + msvcVersion + "\r\n"; symbolsBatFile = String.Format(symbolsBatFile, targetArch.ToString()); File.WriteAllText("symbols.bat", symbolsBatFile); foreach (var objectFilePath in objectFilePaths) { var command = $"dumpbin /symbols {objectFilePath} | findstr External | findstr -v UNDEF > {objectFilePath}.txt"; File.AppendAllText("symbols.bat", $"\r\n{command}"); } Process.Start("cmd.exe", "/c symbols.bat").WaitForExit(); var objectFiles = new List <T>(); foreach (var objectFilePath in objectFilePaths) { var symbols = new List <string>(); var objectFile = TConstructor(File.ReadAllBytes(objectFilePath)); var lines = File.ReadLines($"{objectFilePath}.txt"); foreach (var line in lines) { var line2 = line.Trim(); if (line2 == "") { continue; } var symbol = line.Split("| ")[1]; symbols.Add(symbol); } objectFile.ExternalSymbols = symbols; objectFiles.Add(objectFile); } return(new StaticLibrary <T>(objectFiles)); } }
// http://www.exploit-monday.com/2013/08/writing-optimized-windows-shellcode-in-c.html private static byte[] CompileToShellcode(TargetArch targetArch, IShellcodeCCxxSourceIParameterlessCFunction ccxxSource, IEnumerable <ObjectFile> additionalShellcodeObjectFiles, bool optimize) { // __chkstk will be linked if large portion of the stack used. Still POC if we statically link crt additionalShellcodeObjectFiles = additionalShellcodeObjectFiles ?? new List <ObjectFile>(); var source = new CCxxSource(((IShellcodeCCxxSource)ccxxSource).SourceFiles); var shellcodeEntryFunction = ccxxSource.Name; // Compile Compiler.Config compilerConfig; if (optimize) { compilerConfig = new Compiler.Config( GL: true, O1: true, Os: true, // Optimizations that differ O2: false, Og: false, Ot: false, Od: false, Oy: true, Oi: true, // Optimizations that are the same GF: true, Gy: true, GS: false, sdl: null, Zl: false, FA: true, runtime: Compiler.Config.RunTimeLibrary.MT, // Necessary for PIE callingConvention: null, EHa: null, EHs: null, EHc: null, EHr: null // unsure of the effect of these, so leaving as unspecified ); } else { compilerConfig = new Compiler.Config( GL: false, O1: false, Os: false, // Optimizations that differ O2: false, Og: false, Ot: false, Od: false, Oy: true, Oi: true, // Optimizations that are the same GF: true, Gy: true, GS: false, sdl: null, Zl: false, FA: true, runtime: Compiler.Config.RunTimeLibrary.MT, // Necessary for PIE callingConvention: null, EHa: null, EHs: null, EHc: null, EHr: null // unsure of the effect of these, so leaving as unspecified ); } Linker.Config linkerConfig; if (optimize) { linkerConfig = new Linker.Config( LTCG: Linker.Config.Ltcg.ON, // Optimizations that differ OPTREF: true, OPTICF: 1, // Optimizations that are the same ENTRY: "Begin", SUBSYSTEM: Linker.Config.Subsystem.CONSOLE, MAP: true, SAFESEH: false, NODEFAULTLIB: true, ORDER: new List <string>() { "Begin", shellcodeEntryFunction }, // Necessary for PIE additionalDependencies: new List <string> { "libucrt.lib", "libvcruntime.lib", "libcmt.lib" } ); } else { linkerConfig = new Linker.Config( LTCG: Linker.Config.Ltcg.OFF, // Optimizations that differ OPTREF: true, OPTICF: 1, // Optimizations that are the same ENTRY: "Begin", SUBSYSTEM: Linker.Config.Subsystem.CONSOLE, MAP: true, SAFESEH: false, NODEFAULTLIB: true, ORDER: new List <string>() { "Begin", shellcodeEntryFunction }, // Necessary for PIE additionalDependencies: new List <string> { "libucrt.lib", "libvcruntime.lib", "libcmt.lib" } ); } Executable exe; switch (targetArch) { case TargetArch.x64: { var additionalShellcodeObjectFiles64 = new StaticLibrary <Win64ObjectFile>(additionalShellcodeObjectFiles.Cast <Win64ObjectFile>()); var staticLibrary = ((ICCxxCompiler <Win64ObjectFile>) new Compiler(compilerConfig)).Compile(source); // Since this is x64, we need to ensure that the stack is aligned before we execute our C/C++'s entry function var alignStackAsm = new AlignRSPMasmAssemblySource(shellcodeEntryFunction); var alignStackSL = ((IAssembler <MASM, Win64ObjectFile>) new Masm()).Assemble(alignStackAsm); var linkerInput = new List <StaticLibrary <Win64ObjectFile> >() { staticLibrary, additionalShellcodeObjectFiles64, alignStackSL }; exe = ((ILinker <Win64ObjectFile, Executable>) new Linker(linkerConfig)).Link(linkerInput); break; } case TargetArch.x86: { var additionalShellcodeObjectFiles32 = new StaticLibrary <Win32ObjectFile>(additionalShellcodeObjectFiles.Cast <Win32ObjectFile>()); source.FindAndReplace("BeginExecutePayload", shellcodeEntryFunction); var staticLibrary = ((ICCxxCompiler <Win32ObjectFile>) new Compiler(compilerConfig)).Compile(source); var linkerInput = new List <StaticLibrary <Win32ObjectFile> >() { staticLibrary, additionalShellcodeObjectFiles32 }; exe = ((ILinker <Win32ObjectFile, Executable>) new Linker(linkerConfig)).Link(linkerInput); break; } default: throw new ArgumentException("Invalid TargetArch valid"); } // Check if Position Independent Code was generate // Sometimes when building for 32-bit, char[] initialzied with an arrary of a certain length gets placed in the data section ... // Seems to be when the strlen >= 15 (>= 16 with null byte) // Possible solution, split up array into multiple smalle rarrarys? if (exe.Map.Split("Publics by Value")[1].Split("entry point")[0].Contains("0002:") || exe.Map.Split("Publics by Value")[1].Split("entry point")[0].Contains("0003:")) { Console.Error.Write(exe.Map); throw new Exception("Failed to generate shellcode: code dependent on data section. See Map file for more info"); } // 'Begin' is the entry point to our shellcode if (!exe.Map.Split("Publics by Value")[1].Split("0001:")[1].Split("\n")[0].Contains("Begin")) { Console.Error.Write(exe.Map); throw new Exception("Failed to generate shellcode: function 'Begin' is not the first function in the CODE section. See Map file for more info"); } // Extract shellcoode var shellcodeBytes = PeCode.Extract(exe); var codeLengthHexString = exe.Map.Split("CODE")[0].Split("H ")[0].Split(" ")[^ 1];
public static extern long InitDisasm(TargetArch Target);
public Config(TargetPlatform targetPlatform = TargetPlatform.UNKNOWN, TargetOS targetOS = TargetOS.UNKNOWN, TargetArch targetArch = TargetArch.UNKNOWN) { }