REDAgent进程分析
本文最后更新于50 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

问题的本质


红蜘蛛电子教室的学生端进程 REDAgent.exe 有一个关键特征——它不是一个孤立进程,而是一个受守护机制保护的进程

简单来说:

终止 REDAgent.exe  → 守护进程检测到退出 → 立即拉起新进程 

传统的 taskkill /f /im REDAgent.exe 方式之所以无效,正是因为触发了这个守护机制。要想”让 REDAgent.exe 暂时不干活”,正确的思路不是杀死它,而是让它活着但不干活


进程状态模型分析

Windows 进程有以下几种状态:

状态说明
Running正常执行,分配 CPU 时间片
Ready就绪,等待调度
Waiting等待事件/资源
Suspended挂起——所有线程暂停,不分配任何 CPU 时间片

taskkill 是改变存在状态(存在→不存在)。而 PsSuspend 是改变执行状态(运行→挂起)。

两者的本质区别:

taskkill  → 进程对象销毁 → 句柄失效 → 守护进程收到进程退出通知 → 重新创建
PsSuspend → 进程对象保留 → 句柄有效 → 守护进程认为一切正常 → 不干预

这就是方案可行的底层逻辑——利用守护进程的检测盲区


PsSuspend 的工作原理

Sysinternals PsSuspend 底层调用的是 Windows 未公开的 NT API:

NtSuspendProcess(HANDLE ProcessHandle)

这个 API 会遍历目标进程的所有线程,逐一调用 NtSuspendThread,将每个线程的挂起计数(Suspend Count)加 1。

关键特性:

  • 挂起计数可叠加:调用一次加 1,调用两次加 2,需要调同样次数的 NtResumeProcess 才能恢复
  • 不释放资源:进程的句柄表、内存空间、打开的文件全部保留
  • 不发送退出通知:进程只存在于进程管理器不知晓的特殊挂起状态

PsSuspend -r 恢复时,底层调用 NtResumeProcess,将挂起计数减回 0,进程继续正常运行。


红蜘蛛的守护机制推测

红蜘蛛的进程守护机制通常有两种实现方式:

方案一:服务守护

Services.exe  →  REDAgent.exe(作为子进程启动)
                ↓ 检测到退出
               CreateProcess 重新拉起

这种情况可以通过 sc query 或任务管理器→服务标签页确认是否存在相关服务。

方案二:双进程互监

REDAgent_A.exe  ←→  REDAgent_B.exe
(互相对方进程句柄,WaitForSingleObject 检测退出)
     ↓ 一方退出
     另一方立即 CreateProcess 恢复

这种更难处理,因为即使暂停其中一个,另一个仍然在监控。但这意味着只要两个进程都被暂停,整个系统就冻结了——我们的脚本同时处理了 REDAgentRedSpiderREDServer 三个进程就是为了覆盖这种情况。

方案三:内核回调(罕见)

通过 PsSetCreateProcessNotifyRoutine 注册进程创建回调。这种方式无法通过用户态手段绕过,但红蜘蛛作为普通软件一般没有这么高的权限。

在实际测试中,暂停方式有效,说明红蜘蛛的守护机制属于方案一或方案二,且没有使用内核回调


防复活监控的设计

即使进程被成功暂停,守护进程仍然可能在某些条件下检测到异常(例如心跳超时、通信失败),然后主动创建新进程。针对这种情况,需要在用户态持续监控:

:MONITOR
ping 127.0.0.1 -n 3 >nul    ← 3 秒间隔
pssuspend REDAgent          ← 如果发现新进程,立刻暂停
goto MONITOR

为什么用 ping 做延时?

choice /t 3 /d y /n >nul       ← choice 在某些系统上不可用
timeout /t 3 /nobreak >nul     ← timeout 在某些 Win PE /精简版上缺失
ping 127.0.0.1 -n 3 >nul       ← 所有 Windows 版本都支持,最通用

ping 127.0.0.1 -n 3 大约耗时 2 秒(因为第一个 ping 基本瞬间返回,后面两个各间隔 1 秒),足够平衡 CPU 占用和响应速度。


PsSuspend 的局限性

虽然 PsSuspend 很好地解决了问题,但它也有边界:

1. 无法暂停系统进程

NtSuspendProcess 需要 PROCESS_SUSPEND_RESUME 权限,部分系统关键进程拒绝该操作。

2. 无法绕过内核态守护

如果守护逻辑写在驱动层(内核态),用户态的 PsSuspend 无法阻止驱动重新创建进程。

3. 挂起状态下无法释放资源

进程被挂起时,它占用的内存、句柄、网络连接全部保留,不会释放给系统。

4. 系统休眠/恢复后可能解挂

某些系统在从休眠(S3)恢复时,可能会重置线程的挂起计数,导致进程意外恢复运行。


编码问题的技术根源

在制作这个工具的过程中,最消耗时间的不是逻辑设计,而是 bat 文件的编码问题。从技术角度分析:

GBK vs UTF-8 vs UTF-8 with BOM

Windows cmd 对编码的处理机制:

启动 → 解析 chcp(代码页)→ 用当前代码页解码文件内容 → 执行
  • UTF-8 with BOM:cmd 无法识别 BOM,将 BOM 字节 \xEF\xBB\xBF 当作命令执行,报错
  • UTF-8 without BOM:cmd 默认用 ANSI(GBK)解码,UTF-8 中文会被解码成乱码
  • GBK(ANSI):cmd 原生支持,中文正常显示

这就是为什么 Windows 下写 bat 文件必须用 ANSI/GBK 编码。

iconv 转换的风险

iconv -f UTF-8 -t GBK 在转换时,如果源文件中的字符在 GBK 中不存在映射(如 等 Unicode 符号),iconv 的行为不确定,可能:

  • 替换为 ?
  • 跳过该字符
  • 插入非法字节序列

这会导致 bat 文件语法结构被破坏。

推荐的工具链

对于需要在 Linux 上生成 Windows bat 文件的场景:

# Python 方案(推荐)
content = "@echo off\r\n..."
with open('script.bat', 'wb') as f:
    f.write(content.encode('gbk', errors='replace'))

errors='replace' 可以确保无法编码的字符被 ? 替换,而不是直接导致编码异常。


总结

这个工具的核心价值不在于代码量,而在于对 Windows 进程机制的理解:

  1. 进程 ≠ 线程 — 终止进程和挂起线程是两种完全不同的操作
  2. 守护进程有检测盲区 — 利用进程存活但线程挂起的状态可以绕过
  3. 用户态方案有边界 — 遇到内核态守护时需要更底层的手段
  4. bat 文件的编码问题本质上是代码页(Code Page)的问题

在类似场景下需要控制受守护的进程的核心思路是:与其毁灭它,不如冻结它

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
加载中...
🎵 加载中...