检查虚拟机是否存在内核内存篡改迹象

本页介绍了您可以执行哪些任务来确认 Virtual Machine Threat Detection 中的内核模式根 kit 检测结果的有效性。内核模式 rootkit 发现结果表明,虚拟机的内核内存可能已被恶意软件篡改。

当您收到来自 VM Threat Detection 的内核模式 rootkit 发现结果时,我们建议您在受影响的 Compute Engine 实例上运行以下 Linux 命令,以探查系统中可能表明异常的数据点,例如被盗用的系统调用或隐藏的内核模块。

或者,您也可以在受影响的虚拟机上运行提供的数据收集脚本。该脚本会执行本页介绍的命令。

除非另有说明,否则本页上的每个检查任务都与所有内核模式根 kit 发现结果相关。

本文档假定您满足以下条件:

  • 您在收到 VM Threat Detection 发送的内核模式根 kit 发现结果后,执行本文档中的任务。如需查看相关发现结果类别的列表,请参阅内核模式的根 kit 威胁发现结果

  • 您了解 Linux 命令行工具和 Linux 内核。

VM Threat Detection 简介

Virtual Machine Threat Detection 是 Security Command Center 的一项内置服务,在 Enterprise 和 Premium 层级提供。此服务会扫描 Compute Engine 实例,以检测在遭到破解的云环境中运行的潜在恶意应用,例如加密货币挖矿软件、内核模式 rootkit 和恶意软件。

VM Threat Detection 是 Security Command Center 威胁检测套件的一部分,旨在补充 Event Threat DetectionContainer Threat Detection 的现有功能。

如需了解 VM Threat Detection,请参阅 Virtual Machine Threat Detection 概览。如需了解如何查看 VM Threat Detection 发现结果的详细信息,请参阅在 Google Cloud 控制台中查看发现结果

准备工作

如需获得查看 Security Command Center 中的所有资源和发现以及管理受影响的 Compute Engine 实例所需的权限,请让您的管理员为您授予以下 IAM 角色:

如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

您也可以通过自定义角色或其他预定义角色来获取所需的权限。

确定受影响的虚拟机

  1. 查看发现结果的详细信息
  2. 受影响的资源部分的资源全名字段中,点击链接。受影响 Compute Engine 实例的详细信息视图会在新标签页中打开。
  3. 连接到实例。如需了解详情,请参阅 Compute Engine 文档中的连接到 Linux 虚拟机

查找意外的内核模块

如果虚拟机中存在意外模块,则可能表示虚拟机的内核内存可能已遭到入侵。

如需查找意外的 kernel 模块,请按以下步骤操作:

  1. 列出虚拟机中所有已加载的内核模块:

    lsmod
    cat /proc/modules
    
  2. 列出已加载和已卸载模块的 sysfs 条目:

    ls -l /sys/module/
    
  3. 将这些列表的结果与项目中其他虚拟机的列表进行比较。查找在受影响的虚拟机中显示但在其他虚拟机中未显示的模块。

syslog 中搜索树外模块

虚拟机中已加载非树模块的迹象可能表明已加载非典型内核模块。您可以搜索内核日志缓冲区和 syslog 消息,以确定是否已加载非树模块。在日志条目中,树外模块被标记为已污染的加载。

在内核日志缓冲区和 syslog 消息中,搜索类似于以下内容的日志条目:

MODULE_NAME: loading out-of-tree module taints kernel.
  • 搜索内核日志缓冲区,查找指示存在树外模块的日志条目:

    sudo dmesg | grep out-of-tree
    
  • 搜索所有 syslog 消息,查找指示存在树外模块的日志条目:

    grep "out-of-tree" /var/log/syslog*
    

检查是否有热修补

虚拟机中的实时修补可能会干扰 VM Threat Detection 检测,并可能会触发误报发现结果。

如需检查是否有实时修补,请按以下步骤操作:

  1. 请检查 syslog,了解实时修补模块安装和日志记录。实时修补通常通过安装内核 ftrace 点来修改内核代码。

    sudo grep livepatch /var/log/syslog*
    
  2. 搜索为实时修补而安装的新内核模块(通常带有 livepatch 前缀):

    sudo lsmod | grep livepatch
    
  3. 搜索补丁文件:

    sudo ls -l /sys/kernel/livepatch
    

如需了解实时修补,请参阅 Linux 内核文档中的 Livepatch

检查虚拟机中是否检测到其他可能的恶意活动

  1. 在 Security Command Center 中,查看您要调查的 VM Threat Detection 发现结果的详细信息
  2. 受影响的资源部分的资源全名字段中,点击下拉箭头,然后点击显示使用此资源全名的所有发现结果。发现结果查询会更新为仅显示此虚拟机的发现结果。
  3. 检查是否有任何发现指向潜在的挖矿活动、恶意软件、异常的 IAM 授权和其他安全威胁。

检查杀毒软件是否导致了假正例检测结果

杀毒软件可能会干扰 VM Threat Detection 检测,并可能会触发误报发现结果。

检查系统上所有正在运行的进程

存在意外进程可能表明 VM Threat Detection 发现结果有效,并且虚拟机已遭到入侵。

  1. 列出虚拟机上运行的所有进程:

    ps -eAf
    
  2. 查找您通常不会在此虚拟机上运行的调试程序进程,例如 gdbstracepstack。Debugger 程序进程可以窥探其他进程。

  3. 在虚拟机上查找其他可疑进程。

检查已启动的内核

检查已启动的内核以确定您的 Linux 内核:

cat /proc/version

如果返回的值不是您预期的内核版本,则可能表示存在利用内核中的 kexec 工具进行的盗用攻击。kexec 工具可以软启动系统以使用其他内核。

针对 Unexpected kernel code modification 发现的其他任务

本部分中的任务仅适用于 Defense Evasion: Unexpected kernel code modification 发现类别。请执行以下部分中的任务,以验证此类别中的发现结果的有效性。

这些部分可帮助您确定您的虚拟机是否在使用调试程序 API。Debugger API 可能会触发误报,因为它们可以修改正在运行的核心的代码区域。

通常,如果 VM Threat Detection 检测到使用了调试程序 API,则不会生成发现结果。不过,如果您的虚拟机使用的是 VM Threat Detection 不认识的调试程序 API,您仍然可能会收到误报。

检查是否启用了调试跟踪器

跟踪器(nop 跟踪器除外)可能会导致内核代码修改。这些进程可能会干扰 VM Threat Detection 检测,并触发假正例发现结果。通常,如果 VM Threat Detection 检测到存在跟踪器,则不会发送 Defense Evasion: Unexpected kernel code modification 发现结果。

如需检查已启用的调试跟踪器,请按以下步骤操作:

  1. 查看可用的跟踪工具:

    cat /sys/kernel/debug/tracing/available_tracers
    

    输出类似以下内容:

    hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop
    
  2. 检查当前的跟踪器:

    cat /sys/kernel/debug/tracing/current_tracer
    

    结果是上一个命令中返回的可用跟踪器之一。

  3. 确认系统是否启用了跟踪:

    cat /sys/kernel/debug/tracing/tracing_on
    

    1 表示系统上已启用跟踪。

  4. 列出启用了跟踪功能的 CPU:

    cat /sys/kernel/debug/tracing/tracing_cpumask
    
  5. 查看跟踪记录详情:

    cat /sys/kernel/debug/tracing/trace_stat/function*
    

    输出类似以下内容:

    Function       Hit    Time            Avg             s^2
    

检查调试跟踪器事件

内核中的事件监控可能会导致内核代码修改,并导致虚拟机威胁检测发现结果出现误报。许多调试和性能监控工具都可以自动启用事件监控。

如需检查事件监控是否已启用,请运行以下命令:

cat /sys/kernel/debug/tracing/events/enable
cat /sys/kernel/debug/tracing/events/*/enable

如果输出为 0,则表示事件监控已停用。如果输出为 1,则表示事件监控已启用。

不妨停用事件监控,看看 VM Threat Detection 是否会发出相同的发现结果。如果发现结果减少了,则可能表示一些初始发现结果是误报。

检查 kprobe、eBPF 规则和 netfilter

Netfilter、kprobe 和 eBPF 规则可能会触发代码修改,因为它们会触发对自定义回调的调用转移。VM Threat Detection 会检测这些探测的存在情况,并将其映射到经过修改的代码页,而不考虑哪些探测可能会触发误报。

如需检查 kprobe、eBPF 规则和 netfilter,请运行以下命令:

iptable -L
cat /sys/kernel/debug/kprobes/enabled
cat /sys/kernel/debug/kprobes/list
cat /sys/kernel/debug/kprobes/blacklist
cat /sys/kernel/debug/tracing/enabled_functions
sudo apt-get update && sudo apt-get install bpftrace
bpftrace -l
sudo apt install linux-tools-`uname -r`
bpftool prog

检查是否有早期调试跟踪器

启动时启用的早期调试跟踪器的存在可能会干扰 VM Threat Detection 检测,并可能会触发误报。

如需检查是否有早期调试跟踪器,请运行以下命令:

cat /proc/cmdline

如需查看可能的早期调试跟踪器的列表,请参阅 Linux 内核文档中的启动时跟踪

Unexpected system call handler 的其他任务

如果您收到 Defense Evasion: Unexpected system call handler 发现结果,请执行此任务。

审核系统调用,并查找其使用情况和调用方中的异常。审核日志会提供有关调用进程和系统调用的参数的信息。您还可以执行验证任务,检查常见系统调用的预期行为。如需了解详情,请参阅本页上的使用 Diamorphine 根木马进行的检查示例

Unexpected interrupt handler 的其他任务

如果您收到 Defense Evasion: Unexpected interrupt handler 发现结果,请执行此任务。

列出系统上的实时中断处理程序,并将结果与项目中其他类似虚拟机中的信息进行比较。意外的中断处理程序可能表明虚拟机已遭到入侵。

如需列出实时中断处理程序,请运行以下命令:

cat /proc/interrupts

输出类似以下内容:

           CPU0       CPU1
  0:         44          0   IO-APIC   0-edge      timer
  1:          9          0   IO-APIC   1-edge      i8042
  4:      17493          0   IO-APIC   4-edge      ttyS0
  8:          0          0   IO-APIC   8-edge      rtc0
  9:          0          0   IO-APIC   9-fasteoi   acpi
 12:          0        152   IO-APIC  12-edge      i8042
 24:         16          0   PCI-MSI 81920-edge      virtio2-config
 25:          0      40194   PCI-MSI 81921-edge      virtio2-inflate
 26:      58528          0   PCI-MSI 81922-edge      virtio2-deflate
 27:          0     966356   PCI-MSI 81923-edge      virtio2-stats
 28:          0          0   PCI-MSI 49152-edge      virtio0-config
 29:          0          0   PCI-MSI 49153-edge      virtio0-control
 30:          0          0   PCI-MSI 49154-edge      virtio0-event
 31:          0     555807   PCI-MSI 49155-edge      virtio0-request
 32:          0          0   PCI-MSI 98304-edge      virtio3-config
 33:        184          0   PCI-MSI 98305-edge      virtio3-input
 34:          0          0   PCI-MSI 65536-edge      virtio1-config
 35:     556203          0   PCI-MSI 65537-edge      virtio1-input.0
 36:     552746          1   PCI-MSI 65538-edge      virtio1-output.0
 37:          1     426036   PCI-MSI 65539-edge      virtio1-input.1
 38:          0     408475   PCI-MSI 65540-edge      virtio1-output.1

Unexpected processes in runqueue 的其他任务

如果您收到 Defense Evasion: Unexpected processes in runqueue 发现结果,请执行以下步骤。本部分可帮助您收集更多数据点,以调查您的发现结果。这些数据点可能并不能直接表明存在恶意软件问题。

在此任务中,您将查看每个 CPU 的调度器队列。虽然某些进程可能短暂存在,但您仍然可以根据每个 CPU 的运行进程评估调度器队列行为,以查找异常行为。

  1. 显示每个正在运行的进程在每个 CPU 上花费的时间的详细信息。这有助于您了解特定 CPU 是否非常繁忙。您可以将结果与从 /proc/interrupts 固定到 CPU 的中断相关联。

    cat /proc/schedstat
    

    如需详细了解此命令,请参阅 Linux 内核文档中的调度程序统计信息

  2. 列出当前所有可运行任务,以及每个 CPU 的上下文切换详细信息。

    cat /proc/sched_debug
    

    输出类似以下内容:

    Sched Debug Version: v0.11, 5.4.0-1081-gke #87-Ubuntu
    ktime                                   : 976187427.733850
    sched_clk                               : 976101974.761097
    cpu_clk                                 : 976101973.335113
    jiffies                                 : 4538939132
    sched_clock_stable()                    : 1
    
    sysctl_sched
      .sysctl_sched_latency                    : 12.000000
      .sysctl_sched_min_granularity            : 1.500000
      .sysctl_sched_wakeup_granularity         : 2.000000
      .sysctl_sched_child_runs_first           : 0
      .sysctl_sched_features                   : 2059067
      .sysctl_sched_tunable_scaling            : 1 (logarithmic)
    
    cpu#0, 2199.998 MHz
      .nr_running                    : 0
      .nr_switches                   : 16250401
      .nr_load_updates               : 0
      .nr_uninterruptible            : 12692
      .next_balance                  : 4538.939133
      .curr->pid                     : 0
      .clock                         : 976101971.732857
      .clock_task                    : 976101971.732857
      .avg_idle                      : 880408
      .max_idle_balance_cost         : 500000
    
    runnable tasks:
     S           task   PID         tree-key  switches  prio     wait-time             sum-exec        sum-sleep
    -----------------------------------------------------------------------------------------------------------
     S        systemd     1     51740.602172    326778   120         0.000000    165741.786097         0.000000 0 0 /init.scope
     S       kthreadd     2   1482297.917240      1361   120         0.000000       112.028205         0.000000 0 0 /
     I      rcu_sched    11   1482642.606136   1090339   120         0.000000     17958.156471         0.000000 0 0 /
     S        cpuhp/1    15       537.058588         8   120         0.000000         2.275927         0.000000 0 0 /
     S  idle_inject/1    16        -2.994953         3    49         0.000000         0.012780         0.000000 0 0 /
     S    migration/1    17         0.000000    245774     0         0.000000      5566.508869         0.000000 0 0 /
     S    ksoftirqd/1    18   1482595.656315     47766   120         0.000000      1235.099147         0.000000 0 0 /
     I   kworker/1:0H    20       536.961474         5   100         0.000000         0.043908         0.000000 0 0 /
     S      kdevtmpfs    21     11301.343465       177   120         0.000000         3.195291         0.000000 0 0 /
     I          netns    22         6.983329         2   100         0.000000         0.021870         0.000000 0 0 /
     Srcu_tasks_kthre    23        10.993528         2   120         0.000000         0.010200         0.000000 0 0 /
     S        kauditd    24   1482525.828948       319   120         0.000000        14.489652         0.000000 0 0 /
    
  3. 请查找以下内容:

    • 正在运行的进程名称。
    • 每个 CPU 的上下文切换次数。了解进程在 CPU 上是否发生了过少或过多的切换。
    • 所花费的 CPU 时间(非空闲时间)。

使用 Diamorphine 根木马进行检查的示例

本部分演示了如何检查安装了 Diamorphine 根木马的虚拟机。Diamorphine 是一种常用的可加载内核模块 (LKM)。此根木马会触发以下发现结果类别:

  • Defense Evasion: Unexpected system call handler
  • Defense Evasion: Unexpected kernel modules
  • Defense Evasion: Unexpected kernel read-only data modification

如需详细了解这些发现类别,请参阅内核模式根 kit 威胁发现结果

所采取的检查步骤和在虚拟机上观察到的症状如下:

  1. syslog 中搜索已加载的所有树外内核模块。

    1. 搜索内核日志缓冲区:

      sudo dmesg | grep out-of-tree
      

      输出:

      diamorphine: loading out-of-tree module taints kernel.
      
    2. 搜索 syslog 消息:

      grep "out-of-tree" /var/log/syslog*
      

      输出:

      /var/log/syslog: diamorphine: loading out-of-tree module taints kernel.
      
  2. 搜索 syslog 以查找任何模块验证失败情况(此功能并非适用于所有 Linux 发行版)。

    1. 搜索内核日志缓冲区:

      sudo dmesg | grep "module verification failed"
      

      输出:

      diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
    2. 搜索 syslog 消息:

      sudo grep "module verification failed" /var/log/syslog*
      

      输出:

      /var/log/syslog: diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
  3. 确认该模块已从 /proc/moduleslsmod 命令中隐藏。

    sudo grep diamorphine /proc/modules
    sudo lsmod | grep diamorphine
    

    没有显示任何结果。

  4. 确认该模块在 sysfs 中具有条目。

    sudo cat /sys/module/diamorphine/coresize
    

    输出:

    16384
    
  5. 获取架构的系统调用表:

    sudo ausyscall --dump
    

    输出:

    Using x86_64 syscall table:
    0       read
    1       write
    2       open
    3       close
    

    审核系统调用(例如 killgetdents)中的异常情况,这些调用通常会被 rootkit 篡改。

  6. 如需检查系统调用处理程序是否遭到篡改,请审核系统调用并检查是否存在异常行为。这些行为因系统调用而异。

    通常被黑客入侵的系统调用是 kill 调用。您可以检查 kill 系统调用是否已被绕过。在以下示例中,系统对 kill 系统调用进行了审核。

    1. 安装 auditd,并在没有 Diamorphine 恶意软件库的情况下观察虚拟机的行为:

      $ sudo apt-get update && sudo apt-get install auditd
      $ # Add audit rules for specific system calls
      $ sudo echo "-a exit,always -F arch=b64 -S kill -k audit_kill" >> /etc/audit/rules.d/audit.rules
      $  sudo /etc/init.d/auditd restart
      Restarting auditd (via systemctl): auditd.service.
      
      $ # Behavior observed without rootkit
      $ sleep 600 &
      [1] 1119
      $ sudo kill -9 1119
      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1119"
      type=OBJ_PID msg=audit(1677517839.523:198): opid=1119 oauid=1001 ouid=0 oses=1 obj=unconfined ocomm="sleep"
      type=SYSCALL msg=audit(1677517839.523:198): arch=c000003e syscall=62 success=yes exit=0 a0=45f a1=9 a2=0 a3=7f61c64b2ac0 items=0 ppid=1034 pid=1035 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
      tty=pts0 ses=1 comm="bash" exe="/usr/bin/bash" subj=unconfined key="audit_kill"
      $ sleep 600 &
      [1] 1087
      $ sudo kill -31 1087
      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1087"
      type=OBJ_PID msg=audit(1677517760.844:168): opid=1087 oauid=1001 ouid=0 oses=1 obj=unconfined ocomm="sleep"
      type=SYSCALL msg=audit(1677517760.844:168): arch=c000003e syscall=62 success=yes exit=0 a0=43f a1=1f a2=0 a3=7f61c64b2ac0 items=0 ppid=1034 pid=1035 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0        ses=1 comm="bash" exe="/usr/bin/bash" subj=unconfined key="audit_kill"
      

      在检查过程中,此时安装了 Diamorphine 根 kit。以下步骤展示了安装 rootkit 后的虚拟机行为。

    2. 确认在安装 Diamorphine 根木马后,信号的审核日志条目现在不存在:

      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1158"
      $ sleep 600 &
      [2] 1167
      
    3. 查看信号的审核日志条目中的详细信息。在此示例中,虽然此特定信号并未被 Rootkit 完全盗用,但可以获取有关调用方进程的信息。

      $ sudo kill -9 1167
      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1167"
      type=OBJ_PID msg=audit(1677518008.586:237): opid=1167 oauid=1001 ouid=0 oses=1 obj=unconfined ocomm="sleep"
      type=SYSCALL msg=audit(1677518008.586:237): arch=c000003e syscall=62 success=yes exit=0 a0=48f a1=9 a2=0 a3=7f61c64b2ac0 items=0 ppid=1034 pid=1035 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
      tty=pts0 ses=1 comm="bash" exe="/usr/bin/bash" subj=unconfined key="audit_kill"
      

调试数据收集脚本

以下脚本会执行本页介绍的许多调试任务。您可以在 sudoroot 模式下运行此脚本。该脚本仅从系统读取调试信息。

$ cat kprot.sh
#!/bin/bash

echo "Boot command line"
cat /proc/cmdline
echo "=================================================="
echo "Loaded modules"
cat /proc/modules
echo "=================================================="
echo "Current tracer"
cat /sys/kernel/debug/tracing/current_tracer
echo "=================================================="
echo "Tracing event enable"
cat /sys/kernel/debug/tracing/events/enable
echo "=================================================="
echo "Tracing sub events enable"
for en in `find /sys/kernel/debug/tracing/events/*/enable`; do printf "\b$en\n"; cat $en; done
echo "=================================================="
echo "IP table rules"
iptables -L
echo "=================================================="
echo "Ftrace list"
cat /sys/kernel/debug/tracing/enabled_functions
echo "=================================================="
echo "Kprobes enabled"
cat /sys/kernel/debug/kprobes/enabled
echo "=================================================="
echo "Kprobes list"
cat /sys/kernel/debug/kprobes/list
echo "=================================================="
echo "Kprobes blocklist"
cat /sys/kernel/debug/kprobes/blacklist
echo "=================================================="
echo "BPF trace"
sudo apt update && sudo apt-get update && sudo apt-get install bpftrace
bpftrace -l
echo "=================================================="
echo "BPF prog list"
sudo apt update && sudo apt install linux-tools-`uname -r`
bpftool prog
echo "=================================================="

后续步骤