首页 体育 教育 财经 社会 娱乐 军事 国内 科技 互联网 房产 国际 女人 汽车 游戏

逆向解密 LSDMiner 新样本利用 DNS TXT 通道传输的数据

2020-05-07

其他歹意行为依照惯例的逆向剖析办法墨守成规剖析即可,而关于加密的 DNS TXT 数据的逆向与解密进程,Anomali 的 Blog 中描绘一带而过,并没胪陈,依照他们 Blog 中简略的描绘,并不足以解密这些数据。本文就以上述样本为例,解析一下怎么经过逆向样本一步一步解密这些数据。

歹意样本全体的履行流程分为 3 步:

在最终第 3 步,也会经过 DNS TXT 通道获取最新歹意 Shell 脚本以及二进制样本的下载 URL。本文要点剖析 DNS TXT 通道数据的获取以及解密。

先看一下歹意样本经过 DNS TXT 通道获取最新的用来篡改沦陷主机 Cron 使命的歹意 URL 的全体流程:

能够看到样本首要从 cron.iap5u1rbety6vifaxsi9vovnc9jjay2l.com 获取数据,然后用 AES-128bit 算法将其解密。再看一下从 cron.iap5u1rbety6vifaxsi9vovnc9jjay2l.com 获取的加密数据:

DNS TXT 呼应是一串字符,而且是经过 Base64 编码的字符串 A7PZtADnYAEMEArGhmA9xQihPq9TRz4QigssjeOmUnQ 。函数 github_com_hippies_LSD_LSDC__AesCipher128_Decrypt 中的处理流程能够证明这一点:

到这儿能够看出,要用 Go 言语编程解密这些数据,需求 3 步走:

先用 Linux 自带的指令行东西 base64 测验解码:

有点奇怪,不能用 base64 指令直接解码,看来用的并不是规范的 Base64 编码。这儿先弥补一下关于 Base64 编码的两点布景常识:

上述两个常识点,在 Go 的 Base64 规范库文档 最初就有阐明:

两个常识点各自分为两种状况,这样组合起来就有 4 种细分的 Base64 Encoding:

那 LSDMiner 样本中详细是用什么样的 Base64 解码呢?需求先看一下样本中 Base64 解码的 Encoding 句柄是怎么生成的。在函数 github_com_hippies_LSD_LSDC__AesCipher128_Decrypt 中,是先拿到 Base64 解码的 Encoding 句柄再进行解码:

经过上面的 xrefs 信息,可知这个 b64EncodingObj 是在函数 encoding_base64_init 中生成的。进入这个 init 函数, b64EncodingObj 生成进程如下:

能够看到这样两点:

至此就能够解码 DNS TXT 呼应的字符串了。测验代码与成果如下:

经过前面大略的逆向剖析,咱们仅知道样本中用了 AES-128bit 算法来解密数据,但这些常识远不足以解密上面用 Base64 解码得到的二进制数据。AES 加密算法此处不胪陈,能够自行查找相关材料,本文只重视怎么用算法来解密数据。要想正确解密数据,还需求承认以下 AES 解密算法相关的几个要素:

上面的逆向剖析进程中,咱们注意到样本中调用了函数 crypto_cipher_NewCBCDecrypter ,能够承认样本中用到的分组暗码方法是 CBC 。

在剖析承认其他几个要素之前,咱们先捋一下两个要害函数的逻辑:初始化 AES 解密句柄的 NewAesCipher128 和 履行 AES 解密操作的 AesCipher128_Decrypt 。

首要,样本调用该函数的时分传入一个参数,即待查询 DNS TXT 记载的域名字符串 cron.iap5u1rbety6vifaxsi9vovnc9jjay2l.com :

在函数内部先初始化一个 crypto/md5 句柄(代码片段对照左面规范库函数 crypto_md5_New 即可了解):

然后将传入的域名字符串由 string 类型转成字符切片并写入 MD5 digest 目标,再经过 md5.digest.Sum 函数做一次 MD5 Hash 核算:

再把这轮 MD5 核算的值经过 hex.EncodeToString 转成 32-bytes 的字符串,即惯例的字符串方法的 MD5 值。然后取出再取出这个 MD5 值的 前 16 字节 ,保存到变量中备用:

接下来,样本又做了一次 MD5 核算,而且取出这一次 MD5 值的 后 16 字节 ,保存到变量中备用 来写入新字节,而且调用 md5.digest.Sum 函数时仍然传入参数 nil ):

后边能够看到,第一次 MD5 核算后取出的 前 16 字节 数据,被作为 AES 密钥 传入 aes.NewCipher 函数来初始化 AES 解密句柄:

而第2次 MD5 核算后取出的 后 16 字节 数据被保存起来,作为本函数回来值的一部分回来,接下来作为 AES 的 IV 向量 传给后边函数 AesCipher128_Decrypt 中调用的 crypto_cipher_NewCBCDecrypter 函数。

前面内容剖析承认了 AES 的 Key、IV 以及分组暗码方法,还需最终承认 AES 算法所用的 Padding 方法,即可正确解密数据。这一个点需求逆向剖析函数 AesCipher128_Decrypt 才干承认。

AES 加密算法用到的常见的 Padding 方法有以下几种:

LSDMiner 中用到的 Padding 方法便是简略的 ZeroPadding,经过函数 AesCipher128_Decrypt 中解密操作后的 byte.Trim 函数即可承认:

上述剖析进程中描绘过,歹意样本为生成 AES 解密用到的 Key 和 IV 向量,对相应域名字符串接连做了 2 轮 MD5 Hash 核算,这一点 Anomali 的 Blog 中也说到了,仅仅他们没说到 Key 和 IV 详细的生成进程。

但是样本中接连两轮的 MD5 核算的值其实是相同的——这是 Go 言语特有的 MD5 核算方法,参阅 hash – Golang md5 Sum函数 ,演示代码如下:

这一点不知道是歹意软件作者的失误,仍是有意为之。却是简单给逆向剖析形成困扰,由于乍一看“两轮 MD5 核算”,很可能直观以为应该得出两个不同的 MD5 值,并别离截取一段做 AES 解密的 Key 和 IV 向量,没想到两次 MD5 核算得出相同的值。

根据以上剖析,就能够编写程序完结咱们想要的解密工作了。完好的 Go 言语代码已上传到 Github:

https://github.com/0xjiayu/LSDMiner_DNS_TXT_Decrypt

运转成果如下:

当时解密出来的 Cron URL 是 lsd.systemten.org ,在样本中假如整个 DNS TXT 数据通道操作进程有任何反常而无法解密出最新的 Cron URL,备用的默认值也是这个 lsd.systemten.org :

文章最初的截图中现已显现过,假如样本用 net.LookupTXT 函数检索 DNS TXT 记载失利,还会跳转到别的一个代码分支,去用 DoH 向 CloudFlare 的 DoH 服务器恳求相应的 DNS TXT 记载:

咱们用指令行东西测验一下,能够看到这种方法也有用:

使用 DNS TXT 记载和 DoH 下发歹意数据来辅佐歹意样本的运转,能够进一步提高整个 Botnet 基础设施的健壮性和运营的灵活性,鉴于这个 Botnet 存活已久并不断更新,应该引起业界的继续重视。

前文说过,歹意样本中使用 DNS TXT 通道传输的数据还有其他几种,方法都是相同:检索 DNS TXT 数据,用 base64.RawURLEncoding 解码得到二进制数据;然后对域名进行 MD5 核算得出 AES 解密用到的 Key 和 IV,然后用 CBC 方法、ZeroPadding 的 AES-128bit 算法对 Base64 解码后的二进制数据进行解密。对应的域名还有以下几个,均能够用以上 Go 程序来解密:

 update.iap5u1rbety6vifaxsi9vovnc9jjay2l.com 
 shell.iap5u1rbety6vifaxsi9vovnc9jjay2l.com 
 1x32.iap5u1rbety6vifaxsi9vovnc9jjay2l.com 
 2x32.iap5u1rbety6vifaxsi9vovnc9jjay2l.com 
 3x32.iap5u1rbety6vifaxsi9vovnc9jjay2l.com 
 1x64.iap5u1rbety6vifaxsi9vovnc9jjay2l.com 
 2x64.iap5u1rbety6vifaxsi9vovnc9jjay2l.com 
 3x64.iap5u1rbety6vifaxsi9vovnc9jjay2l.com 

别的,LSDMiner 触及的二进制歹意样本,都用变形 UPX 加了壳,而且壳的特征很不显着,难以用固定的特征直接检测加壳的样本。而且,相关加壳二进制样本的 UPX 壳幻数还常常改变,比方本文剖析的 MD5 为 114d76b774185b826830cb6b015cb56f 的 UPX 壳幻数为 0x2124922A ;最新的 x86_64 架构的样本 的 UPX 壳幻数则变成了 0x215E77F2 。

热门文章

随机推荐

推荐文章