给木马带双眼睛
字数 1205 2025-08-26 22:11:23
基于Poller内存马的全流量监控技术研究
前言
内存马技术已从传统的命令执行/文件下载发展到更高级的网络流量监控阶段。本文详细介绍如何利用Tomcat的Poller组件实现全流量监控内存马,使攻击者能够实时监控经过系统的每一个请求。
技术背景
传统内存马技术面临内网渗透中的局限性,促使研究者寻找新的载体。Poller作为Tomcat中TCP连接最前置的处理类,能够直接处理socket上的完整原始数据,成为理想的新型内存马载体。
Poller与Executor的对比分析
选择Poller的原因
- 处理位置优势:Poller位于TCP连接处理的最前端,能决定是否提交给web业务处理
- 性能优势:Executor需要经过Poller的多道判断与注册流程
- 灵活性:Poller能灵活控制web业务流程
Poller的风险
- 全局唯一线程(Tomcat 8/9/Spring Boot)
- 线程异常终止会导致整个Tomcat服务崩溃
- 代码必须高度稳定,任何bug都可能导致服务不可用
Poller内存马实现原理
核心是通过继承Poller类并重写processKey方法:
@Override
protected void processKey(SelectionKey sk, NioEndpoint.NioSocketWrapper attachment) {
// 自定义:业务处理之前
beforeHandler();
super.processKey(sk, attachment);
// 自定义:业务处理之后
afterHandler();
}
关键点:
super.processKey()会创建SocketProcessor并执行web业务逻辑- 在super前添加代码可拦截请求
- 直接return可阻止web业务执行
- super调用后程序不会等待响应,而是直接结束processKey函数
技术难点与解决方案
难点1:获取完整请求/响应数据
解决方案:利用buffer缓存机制
ByteBuffer allocate = ByteBuffer.allocate(8192);
try {
read = attachment.read(false, allocate);
} catch (IOException e) {}
ByteBuffer allocate1 = ByteBuffer.allocate(read);
allocate1.put(allocate.array(), 0, read);
allocate1.position(0);
attachment.unRead(allocate1);
allocate.clear();
注意事项:
- unRead的数据大小必须精确
- 获取的永远是上一次请求的记录
难点2:数据传输通道
解决方案:WebSocket协议
优势:
- 在HTTP代理日志中只显示一条记录
- 协议升级后不再使用HTTP传输
- 常见于web应用,降低环境需求
NGINX WebSocket配置示例:
server {
listen 80;
server_name localhost;
location /sell {
proxy_pass http://127.0.0.1:8080/;
proxy_http_version 1.1;
proxy_read_timeout 3600s;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
完整实现流程
- 初始化WebSocket连接:建立持久化通信通道
- 重写Poller.processKey:拦截所有网络流量
- 缓存处理:通过unRead机制获取请求/响应数据
- 数据传输:将缓存数据通过WebSocket发送给控制端
- 异常处理:确保Poller线程不会因异常终止
防御建议
- 监控Poller类修改:检测是否有异常继承或重写
- WebSocket连接审计:监控异常的WebSocket连接
- NGINX配置审查:检查是否有异常的keepalive或upgrade配置
- 线程监控:关注Tomcat关键线程的异常行为
- 流量分析:检测是否有异常的流量转发模式
总结
Poller内存马技术代表了内存马发展的新方向,从简单的命令执行转向更隐蔽的流量监控。这种技术结合了底层socket处理和WebSocket通信,具有高度隐蔽性和持久性。防御方需要从多个层面建立防护体系,才能有效应对这类高级威胁。