(原创作品,转载规则见文末)
由于区块链具备不易封锁、不易篡改、不易溯源、易于访问等特点,一些业界人士提出了使用区块链进行 CC 的方法。就目前的调研情况来看,可根据载体的不同,将这些利用方法分为两类:一类是以比特币的交易为载体进行 CC ,另一类是以区块链的其他应用(如以太坊)为载体进行 CC 。本次报告主要介绍以比特币的交易为载体进行 CC 的方法。
根据利用方式的不同,可以将以比特币交易为载体的 CC 方法分以下几种。
载体 | 原理 | 局限 |
交易脚本 | OP_RETURN 类型的脚本可以输入83字节的自定义内容 | UTXO 需要比特币消耗 |
交易地址 | 信息编码到交易地址中 | 需引入第三方信道 |
交易值 | 使用交易的数字隐藏信息 | 可利用长度受限,存在被外界干扰的风险 |
数字签名 | 命令编码到私钥中,利用 ECDSA 临时密钥重用恢复私钥 | 泄露私钥 |
数字签名 | 命令编码到随机数中,利用 ECDSA 随机密钥重用恢复私钥,进行验证 | Bot 端计算量大 |
数字签名 | 利用不同的随机数,把命令编码到签名值中 | 计算量较大,命令长度受限 |
本文将按照下述思路进行介绍:首先对比特币交易的字段进行介绍,包括交易的组成和字段含义;随后介绍以交易脚本、交易地址和交易值进行 CC 的方法;接下来对椭圆曲线密码算法进行介绍;然后介绍利用 ECDSA 进行 CC 的方法。
概念
交易
交易是比特币系统中的重要组成部分。通过交易,比特币的所属权发生转换。比特币中的节点验证每个交易,并将通过验证的交易写入区块中。交易包含输入输出信息和验证信息,其本质是一个数据结构。交易的结构如下。
UTXO
UTXO(Unspent Transaction Output,未使用的交易输出)是比特币交易的基本单位。UTXO 是交易中未被使用的输出。比特币中的节点会维护一个记录所有 UTXO 的清单。交易的实质是将一部分 UTXO 转换为另一部分 UTXO。经过确认后,交易的输出是新产生的 UTXO,它记录着比特币数额和地址。当要使用这部分比特币时,需要创建新的交易。新交易的输入为 UTXO,它指向了该 UTXO 的“地址”(生成该 UTXO 的交易哈希及输出中的顺序)。当新的交易被确认后,将产生新的 UTXO,旧的 UTXO 不再存在。
下图是一个比特币交易。这笔交易中有两个输入和两个输出。在交易发出时,这两个输入是两个 UTXO,分别对应着不同的比特币地址和比特币数量;输出是将要形成的两个 UTXO,对应着不同的比特币地址和数量。当交易经过确认加入区块链上之后,这两个输入由 Unspent 状态变为 Spent 状态,不再是 UTXO;这两个输出形成两个新的 UTXO。若比特币地址 3PbJsixkjmjzsjCpi4xAYxxaL5NnxrbF9B 的拥有者要使用这笔比特币,需要将这个 UTXO 作为下一个交易的输入,并提供身份验证信息。待该交易得到确认时,这个输入将标记为 Spent 状态,不再是 UTXO。
UTXO 不可再分,UTXO 中的比特币数量在下一次交易时将全部使用。UTXO 中比特币数量的单位为中本聪(Satoshi),1 BTC = 10 000 000 sat,1 sat = 0.00000001 BTC。若一个 UTXO 的比特币数量不足,可以输入多个 UTXO。当输入的比特币总数量大于输出目标需要的数量时,可以在输出中设置“找零”。接收“找零”的比特币地址可以与输入的比特币地址相同,也可以不同。每一笔交易输入的比特币数量都要略大于输出的比特币数量,多出的这部分将作为手续费奖励给矿工。手续费越高,该笔交易被确认的速度越快。若交易中没有设置“找零”,则多出来的比特币数量默认为该笔交易的手续费。例如,下图的交易中共有4个输入,输入的比特币总额为 0.04320707 BTC;输出有两个,输出的比特币总额为 0.04186037 BTC;剩余的 0.00134670 BTC 为这笔交易的手续费。
脚本
一个交易需要满足以下条件才能被比特币节点当作一个合法的交易写入区块链上:
- 输入均为 UTXO。
- 输入的比特币总数大于输出的比特币总数。
- 能完成对输入的身份验证。
完成对输入的身份验证需要使用交易脚本。交易脚本类似于 Forth 语言,基于栈,并由左向右执行。脚本是一系列记录在交易里的指令,描述了下一个要使用比特币的人应以何种方式获取相应的权限。只有当交易中的输入能满足上一个交易中的输出里设定的条件后,交易才能继续。交易输出里的脚本为锁定脚本(scriptPubKey),设置了要使用这笔比特币需要满足的条件。交易输入含有解锁脚本(scriptSig),用于和对应的锁定脚本匹配,证明使用者拥有比特币的使用权。
在验证交易时,需要将解锁脚本和锁定脚本放在一起执行,执行的过程需要将把连起来的脚本按从左到右的顺序依次执行对应的命令。脚本的命令又称为 Opcodes、关键字、功能等,包括常量类、控制流类、堆栈类、位运算类、数字运算类、密码运算类等共 10 个类别,可以通过一系列运算完成对交易的身份验证。交易脚本共有 5 种类型,分别为 P2PKH(Pay-to-Public-Key-Hash)、P2PK(Pay-to-Public-Key)、多重签名(Multiple Signatures,MS)、P2SH(Pay-to-Script-Hash)和数据输出(OP_RETURN),每种类型的锁定脚本和解锁脚本有着不同的格式,如下表。其中在比特币交易中最常见的是 P2PKH 类型。
下表是以 P2PKH 为例的交易脚本执行过程。第一列代表命令执行时堆栈的情况,第二列代表命令的从左到右执行。比特币官方 WiKi 网站(https://en.bitcoin.it/wiki/Script)对脚本中的命令及对应的代码进行了说明。在命令执行中,节点能通过对公钥和签名的校验,完成对使用者的身份验证。只有持有相应地址的私钥,才能生成正确的签名。
由于区块链在其他领域具有很多潜在应用,许多开发者希望充分发挥区块链的优势。然而,如果在区块链上存储与交易无关的数据,会增加各节点的存储负担。经过比特币社区的讨论,最终从比特币 0.9 版本开始,在交易脚本里增加 OP_RETURN 类型,可以存储 40 字节的数据。从比特币 0.12 版本开始,OP_RETURN 后最多可以添加 83 字节的数据。因 OP_RETURN 类型的交易无法指明比特币接收者地址,无法使用解锁脚本进行验证,因此每个 OP_RETURN 类型的交易都是一个 UTXO,而且永远无法被使用。下图是一个使用 OP_RETURN 类型的交易存储数据的案例。交易者在 OP_RETURN 后面写入了一个十六进制字符串,该字符串经 ASCII 解码后为“Yuki will you marry me ? Tetsu.”。另一个 OP_RETURN 类型的交易进行了回复,其数据解码后为“Yes I will. Yuki.”。
增加 OP_RETURN 类型给区块链在其他领域的应用带来了便利之处,但也因此增加了区块链服务滥用的风险。
利用交易进行 CC
利用交易脚本进行 CC
OP_RETURN 字段能够存储一定大小的数据,因此可以创建一个 OP_RETURN 类型的交易,把 CC 命令编码嵌入到 OP_RETRUN 字段中,发布交易,由写入了 Botmaster 比特币地址的 Bot 进行检索、解码和执行。由于未被比特币节点确认的交易也能被检索到,故这里不用等待比特币节点进行交易确认的延时。
2014年,Syed Taha Ali 等人基于此原理提出僵尸网络模型 ZombieCoin。由于 OP_RETURN 字段能嵌入的数据大小有限,在此文中,作者提出了使用哈夫曼树对命令进行编码来节省字节数的方法。在验证性测试中,Bot 运行在比特币 0.9.0 版本上,共包含 5 个命令,如下表。
命令 | 参数 | 含义 |
PING | <1> <website> <number> | Ping 指定网站指定次数 |
REGISTER | <2> <website address> | Bot 到指定网站注册 |
LEASE | <3> <block height> <BTC address> | 将 Bot 租给其他人 |
DOWNLOAD DATA | <4> <transactions> | 从指定的交易处下载数据 |
SCREENSHOT | <5> <server address> <number> | 把指定数量的截屏传到指定地址 |
在运行时,Bot 相当于一个简化付款验证(Simplified Payment Verification,SPV)模式的比特币节点。相比于完整的比特币节点,这种模式的节点占用更少量的内存和存储。作者基于 BitcoinJ 库开发的 Bot 程序大小为 7MB,在本地维护的区块链内容大小为 626KB,其网络流量和其他 SPV 客户端的流量一致。
为了测试不同地区的 Bot 性能,作者在实验室运行两个 Bot,使用微软 Azure 云平台运行多个 Bot,模拟了 Bot 在美国、巴西、欧洲、东亚等地区的运行情况。每个 Bot 单独连接到比特币网络,下载节点列表,寻找 Botmaster 的交易。作者每隔 1 小时按上表的顺序下发一次命令,循环运行 24 小时,共收集 2300 个 Bot 的响应数据。整体来看(如上图),Bot 能在命令发出 5 秒内做出响应的情况约占 50%;在 10 秒内响应的情况约占 90%;响应时间的中位数为 5.54 秒。
作者于 2018 年对 ZombieCoin 进行了完善,提出了 ZombieCoin 2.0。作者实验时,比特币版本已经更新到 0.11.0,OP_RETURN 字段后可以添加80字节的数据。在 ZombieCoin 2.0 中,作者提出通过使用公共服务和 DGA 等解决 Bot 的数据回传问题。作者提出了让 Bot 使用 Botmaster 的公钥加密载荷,把数据传到公共网络中。只有拥有对应私钥的 Botmaster 才能解开数据。当指令过长时,可以通过把指令拆分到多个交易中进行分发。
2020年,J. Yin 等人在 CoinBot 中提出了一些完善方法。Yin 等使用比特币服务的 Web API 进行交易查询,减少了运行 SPV 节点带来的流量异常。由于交易信息会永久记录在区块链上,会为后续分析提供证据,Yin 提出了既能下发命令,又能使对应交易不被区块链记录的方法。该方法在创建含有命令的交易时使用较少的手续费,使该交易长时间得不到比特币节点的确认,而会被 Bot 通过比特币服务的 API 检索到,解码并执行命令。随后,使用相同的 UTXO 创建一个手续费较高的交易,让比特币节点对此交易进行确认。若此交易被确认上链,则原有的含有命令的交易永远不会被区块链记录。
这些方法均未彻底解决 Bot 数据回传的问题。使用区块链下发回连服务器地址、通过公共服务上传数据会在整个过程中引入不安全因素。ZombieCoin 2.0 中提出使用 Botmaster 的公钥对数据进行加密的方法。由于公钥加密数据效率过低,这种方法只在加密数据较少时适用,不适用于需要 Bot 进行大量数据回传的场景。另外,这些方法也没有解决流量异常的问题。在 ZombieCoin 中,作为 SPV 节点,Bot 端会有大量的 P2P 流量,是一个明显的异常。这给 Bot 的隐蔽性带来了挑战。此外,由于 OP_RETURN 中存储着各种自定义的数据,此类型的交易会很容易被监视,例如 CoinSecret(http://coinsecrets.org/)就是一个专门用来记录 OP_REETURN 字段数据的网站。而在区块链上发布过多的 OP_RETURN 交易会引起异常,可能导致 Botmaster 地址被禁用,会为 CC 带来一定的复杂性。
由于上述缺陷,在实际的 CC 中,往往会结合其他方法一起运用。2019 年 9 月,TrendMicro 的研究人员发现一种针对 Windows 用户的 dropper Glupteba。该 dropper 使用 OP_RETURN 字段传递 CC 服务器地址。OP_RETURN 字段后是 AES 加密的数据,前 12 字节为 AES GCM 标签,后 32 字节为 AES 密文,密钥被硬编码在二进制文件中。
利用交易地址进行CC
在交易中,交易地址也是一个容易被定制的字段,故交易地址也可作为载体进行隐蔽通信。有研究人员提出,可以把信息使用 Base58 编码成交易地址的形式,通过交易来传递信息。这种方式能通过一笔交易传递大量的信息,但由于缺少交易地址对应的私钥,所有发送出去的比特币都是无法回收的,成为一个永远无法被解锁的 UTXO,造成比特币的浪费。2020 年,Weizheng Wang 等人提出了一种利用比特币交易地址进行隐蔽通信的方法,能做到既可以隐蔽地传递信息,又可以避免比特币的浪费。
作者的思路分为以下几个步骤。首先准备 DES 密钥 k,对待传递的消息 m 进行加密,使用 Base58 对加密后的结果进行编码,得到 b1 = Base58(DESk (m));生成 ECDSA 密钥对 (s1, p1) 和对应的比特币地址a1 = Base58(RIPEMD160(SHA256(p1)))。然后比对 a1 和 b1 中的每一个字符,若二者相同,则分别记录该字符在 a1 和 b1 中的位置,并把 b1 中匹配上的字符替换为“*”,仍用 b1 表示。若比对结束,b1 中仍有字符未匹配上(即 b1 ≠ “***…***”),则令 b2 = Base58(b1),重复从生成 ECDSA 密钥对到匹配字符的过程,直到 bi 完全匹配成功(即 bi = “***…***”)。随后,发起比特币交易,以生成的比特币地址为接收方,用接收金额的大小来表示比特币地址的生成顺序,记录下交易 ID。最后,将记录下的字符串匹配位置信息和交易 ID 写到文件 F 中,并用 DES 加密,发送给接收方。
接收方收到加密后的文件后,用预定义的密钥解密文件,可以获取到字符串匹配位置信息和比特币交易 ID。然后接收方通过检索交易 ID,可以获取到交易中的比特币地址和金额,并根据接收地址、金额和字符串匹配位置信息恢复出加密后的消息 DESk (m),使用 DES 密钥 k 解密得到消息 m。
作者在 Windows 10 上用比特币客户端 0.18.1 和 Python 3.6 进行了性能测试。作者生成了 10 个长度从 5 到 50 比特的消息,每个长度进行 100 次测试,记录生成加密文件的时间(下左图)和从加密文件恢复原文的时间(下右图)。从图中可以看出,随着消息长度的增加,加解密时间均有所增加。作者的另一个实验表明,随着消息长度的增加,比特币地址的重复使用率越来越高,故当消息变长时,加解密的比特效率也随之增长。由于解密过程不需要进行比特币地址的生成和字符串按字符匹配,解密过程花费的时间要少于加密过程。
这种方法的传输具备较高的信息嵌入率,可以使用一次交易传递更长的信息。作者提出的比特币地址匹配的方法,能够生成 ECDSA 密钥对,保证交易中的比特币可收回,花费更少。本方法不用在接收方硬编码比特币地址,有一定的抗溯源功能。但作者从隐蔽通信角度提出的方法不能完全适用于 CC。本方法中有两处需要 DES 加密的地方,需要预先定义两个 DES 密钥,来解密两个 DES 文件,这种行为可能会引起异常。此外,记录信息的加密文件需要引入其他信道传递给接收方,这也会给本系统带来安全风险。而且,既然有其他信道传递文件,为何不通过此信道传递消息呢?此方法也没有考虑数据回传机制。另外,作者认为,尽管 DES 已经不再安全,但 DES 输出的密文较短,进行比特币地址生成和匹配的效率更高。然而,即使从效率角度考虑,也不应该继续使用 DES,应换为其他的加密算法。由于上述问题,此方法还需要进行改进才能用于 CC。
利用交易值进行 CC
在交易中,另一个容易被定制的字段是交易输出的数额,即以聪为单位的比特币数量。此字段可以用来编码存储信息。
2019 年 9 月,Check Point 的研究人员发现 Redaman 开始利用区块链来隐藏 CC地址。Redaman 是针对俄语用户的通过钓鱼方式传播的银行恶意软件,最初于2015 年被发现。CheckPoint 的研究人员在其新版本中,发现其使用比特币区块链进行小马 CC 地址的隐藏。它通过对 CC 地址进行编码,转换为一个交易数字,通过给硬编码在 Bot 中的比特币地址转账,进行 CC 地址的传播。它的感染过程如下图。
以IP 185.203.116.47 和比特币地址 1BkeGqpo8M5KNVYXW3obmQt1R58zXAqLBQ 为例,具体对 CC 地址进行编码的过程如下。
首先将 IP 地址由十进制转换为十六进制的形式:185.203.116.47 => B9.CB.74.2F。然后两字节一组,分别调换字节序,组成一个十六进制数字,如 CBB9 和 2F74。把十六进制数字转换为十进制,分别为 52153 和 12148。分别创建交易,给硬编码在 Bot 中的比特币地址转账这两个十进制数字大小的以聪为单位的比特币,即先创建一笔交易,给 1BkeGqpo8M5KNVYXW3obmQt1R58zXAqLBQ 转入 52153 sat(0.00052153 BTC,约 $4),待此交易确认后,再转入 12148 sat(0.00012148 BTC,约$1),如下图。
对于 Bot 来说,可以通过比特币服务平台的 API 查询和被硬编码的比特币地址相关的交易,从交易中获取交易数额,进行上述过程的逆过程,组装成 CC 的 IP。例如,获取到的交易数额分别为 52153 和 12148,转换为十六进制为 CBB9 和 2F74,再分别转换字节序进行拆分,得到 B9、CB、2F 和 74,将其转换为十进制连接起来即可,即 185.203.116.47。
由于涉及到数据的回传,在这个案例里面,还是引入了与区块链无关的通信信道,区块链的优势未完全发挥。此外,由于每个人都可以看到区块链上的交易,所有的 CC 地址会被研究人员分析出来,也会被永久记录在区块链上。而所有人都可以给这个地址转账,会增加外界干扰,引起僵尸网络失效或被 take over。
椭圆曲线密码
比特币中使用的是椭圆曲线密码(Elliptic Curve Cryptography,ECC)来进行数字签名和身份认证。有一些 Bot 设计者利用椭圆曲线数字签名的一些问题进行 CC。这里将简单介绍椭圆曲线密码算法、椭圆曲线数字签名算法和存在的问题,然后对 Bot 设计者的利用思路进行介绍。
椭圆曲线密码
密码学上使用的椭圆曲线(Elliptic Curve,EC)通常为在整数域 Zp(p 为素数,p > 3)上形如
y2 ≡ x3 + a∙x + b mod p
其中 a, b ∈ Zp,4a3 + 27b2 ≠ 0 mod p 的曲线,记为 Ep (a, b)。椭圆曲线上的点包含所有满足等式的点 (x, y) 和一个无限远点 O。
下图是实数域上的椭圆曲线 y2 = x3 – 3x + 3。
下图是整数域 Z11 上椭圆曲线 y2 ≡ x3 – 3x + 3 mod 11 的图像。
包含无限远点 O 在内的曲线上的点构成一个循环子群。在一些条件下,椭圆曲线上的所有点可以形成一个循环群。
定义群运算“+”,已知椭圆曲线上的点 P = (x1, y1) 和 Q = (x2, y2),R = (x3, y3) 为第三点,有
P + Q = R
(x1, y1) + (x2, y2) = (x3, y3)
由此定义椭圆曲线离散对数问题(Elliptic Curved Discrete Logarithm Problem,ECDLP):给定一个椭圆曲线 E,记 #E 为 Ep 上的点的数量,考虑生成元 P 和另一个元素 T,则离散对数问题为寻找一个整数 d (1 ≤ d ≤ #E),满足
P + P + ⋯ + P = dP = T
通过将消息编码为曲线上的点,进行“+”运算实现对消息的加密。在密码系统中,d为私钥,(E, #E, P, T) 为公钥。由 d 和 P 计算 T 比较简单,但由 P 和 T 计算 d 则比较困难。若选取非常大的椭圆曲线参数和私钥,则以现有的算力,在有限的时间内不能完成对 d 的破解,由此保证了数据的安全性。在实际使用中,为保证安全性,通常选取 NIST 推荐的标准曲线,选取 160 位以上的密钥。比特币密码算法中使用的 ECC 密钥为 256 位。
椭圆曲线数字签名算法
数字签名的定义为附加在数据单元上的数据,或是对数据单元所作的密码变换,这种数据或变换允许数据单元的接收者用以确认数据单元的来源和完整性,并保护数据防止被人伪造或抵赖。(《GB/T 25069-2010 信息安全技术 术语》)
数字签名算法通常由密钥生成、签名、验证三部分算法组成。密钥生成算法会确定签名方案的基本参数,包括公私钥对、重要参数(如大素数、随机数等)。签名算法将对消息进行数学上的操作与运算,得到消息的签名值。验证算法将针对消息和消息的签名值进行与签名过程对应的数学运算,验证签名是否真实有效。
椭圆曲线数字签名(Elliptic Curve Digital Signature Algorithm,ECDSA)的过程如下。
(1)密钥生成
选定 Ep (a, b),令 q = #E,选择随机数 d(0 < d < q),选定 E 上能生成阶为 q 的循环群的点 A,计算 B = dA。
密钥对如下:
kpub = (p, a, b, q, A, B)
kpr = (d)
(2)签名
选择随机临时密钥 kE(0 < kE < q),计算 R = kE A。令 r = xR,选取消息摘要(Hash)算法 h(x),计算 s ≡ (h(x) + dr) kE-1 mod q。
签名值为 s,签名者需要发送的信息为
(x, (r, s))
(3)验证
计算辅助变量 w ≡ s-1 mod q、u1 ≡ wh(x) mod q、u2 ≡ wr mod q,计算 P = u1 A + u2 B。
验证
xp ≡ r mod q ⇒ valid signature
xp ≢ r mod q ⇒ invalid signature
椭圆曲线数字签名算法的临时密钥重用攻击
椭圆曲线数字签名算法要求每次签名使用的随机数 kE 不能重复,否则会由两个签名消息推算出签名所用的私钥,造成私钥泄露。
具体地,令第一次签名的消息为 x1,得到的签名值为 s1;第二次签名的消息为 x2,得到的签名值为 s2;两次签名使用的随机数为 kE,私钥为 d。则由 ECDSA 签名算法可得
s1 ≡ (h(x1) + dr) kE-1 mod q
s2 ≡ (h(x2) + dr) kE-1 mod q
则有
s1 – s2 ≡ (h(x1) – h(x2)) kE-1 mod q
故
kE ≡ (h(x1) – h(x2))/(s1 – s2) mod q
继续计算可得
R = kE A
r = xR
于是
d ≡ (s1kE – h(x1))/r mod q
私钥 d 被泄露。
利用数字签名进行CC
私钥即命令
由于比特币中使用的 ECC 私钥长度为 32 字节,因此有人提出利用随机密钥重用的方法泄露出私钥,让 Bot 从私钥中获取命令。
具体做法为,对命令进行编码,加入混淆后生成私钥,用此私钥生成公钥和比特币地址;使用这个比特币地址创建两个交易,对这两个交易使用相同的随机密钥进行签名,并先后发布。Bot 需要监听一个比特币地址的交易,在发现两个交易公钥中的 r 相同时,保存交易内容,从中计算出私钥 d,并按预先设置的解码规则解出命令。下表是比特币交易的签名字段组成。交易签名采用 DER 编码,可以很容易地检测出两个相同的 r。
此方法的弊端是,任何人都能通过查看两个交易是否使用相同随机数来进行私钥的计算。比特币网络中会有一些交易发起者因大意等原因使用了相同的随机数进行签名。如果这些私钥被泄露,那么与这个地址相关的比特币存在被窃取的风险。所以比特币网络上有一些程序对交易进行监视,当发现某一地址的两个交易使用相同的随机数时,可以转移该地址的比特币。因此,这种方法会时刻被监视,泄露私钥,进而泄露命令,具备一定的风险。
随后,有研究人员基于秘密共享机制提出了改进方法,如上图。这种方法的基本思想是,如下所示,把比特币地址 AS 的私钥 d 拆分成 X1 和 X2 两部分,X1 预编码到 Bot 中,X2 对应的比特币地址 AL 预编码到 Bot 中;通过临时密钥重用泄露 X2,Bot 可由 X1 和 X2 计算出 d,并由 d 计算出比特币地址 AS;通过监听与 AS 相关的交易,获取命令信息。
0 < d < n, 0 < R < n
X1 ≡ d + R mod n
X2 ≡ d + 2R mod n
d ≡ 2⋅X1 – X2 mod n
研究人员认为,这种方法会减少由泄露私钥带来的命令泄露的风险,也能隐藏实际发送命令的比特币地址 AS。在 Bot 未被逆向时,无法从区块链上的信息恢复出 X2,也无法得到地址 AS。然而,在 Bot 端被拿下后,分析人员仍能通过计算得到私钥d和发送命令的比特币地址 AS,也具有一定的风险。
私钥即密钥
由于重用随机密钥会带来较大的异常,研究人员提出了避免随机密钥重用的方法,如下图。此方法需要把一个 kleak 和比特币地址 AS 预编码到 Bot 中。
对命令发送者来说,把命令信息加密后保存在交易中;使用不同的随机数k生成不同的交易签名 (r, s);对于最后一个交易,使用 kleak 作为随机数进行签名;发送交易到区块链网络,等待上一个交易被确认上链后再发送下一个交易。
对于 Bot 来说,需要监听每一个与 AS 相关的交易,对于每个交易,根据 kleak 计算一个可能的私钥值 d’,并根据 d’ 计算出一个比特币地址 A’。若 A’ ≠ AS,则保存此交易,继续监听区块链信息。若 A’ = AS,则使用此 d’ 作为密钥,解密保存的交易,获取命令。
d’ ≡ r-1⋅(s⋅kleak – h(x)) mod n
这种做法略显复杂,相当于结合了利用交易脚本和利用随机数重用两种方法。但正是因为这种复杂的结合,使这种方法规避了其他方法的一些问题。比如,相对于使用交易脚本进行 CC 来说,即使 Bot 端不可靠,在发出最后一个交易之前,分析人员也不能从已有的交易中获取命令信息;相比 Glupteba 而言,这种方法不需要在 Bot 中硬编码对称密钥,而 32 字节的 d 作为对称密钥也足够安全;相对与直接利用临时密钥重用恢复私钥来说,这种方法不会区块链上留下使用相同随机密钥的记录,也规避了一部分监视。理论上,这种方法可以发送无限长的命令。命令发送者可以在发布的命令中嵌入下一个要监视的比特币地址 AS, new 和新的随机数 kleak, new,这样可以在私钥泄露以后弃用当前的比特币地址,一定程度上规避了该地址被分析人员利用后给 Bot 设施带来的风险。
这种方法也有一定的局限性。携带命令的 OP_RETURN 类型的交易均和一个比特币地址相关,会引起一定的异常。虽然不能被解密,但这种交易也会被区块链永久记录。Bot 需要不断轮询获取与预设的比特币地址相关的交易,需要在宿主机上进行一定量的计算来匹配 d’、A’ 和解密命令,这些网络与文件行为可能会引起异常。另外,此方法也没有提供合适的数据回传机制,在面临 Bot 端需要回传数据的情况时仍需其他方法配合。
签名即命令
与上述两种方法不同的是,这种方法不需要利用椭圆曲线数字签名的临时密钥重用攻击。这种方法的思想是,使用不同的随机数,使产生的签名的前 x 位为命令。这种方法不会引起区块链上的异常,也不必使用 OP_RETURN 字段,但每个交易能嵌入的命令长度大大受限,而且会有一定的计算量。在面对较长的命令时,需将命令拆分成多个交易进行下发。
在 ZombieCoin 中,作者对此方法进行了实验。实验环境为 Intel i7 2.8GHz 8GB RAM 的 64 位 Windows 7 设备,使用 OpenSSL 工具集生成 ECDSA 签名。实验结果如下图。在单线程顺序搜索的情况下,当指定签名的前 14 位时,需要大约 10 分钟完成签名生成。在多线程顺序搜索的情况下,需要大约 3 分钟。在多线程非顺序搜索的情况下,需要大约 2 分钟。
这种方法的优点在于不会引起交易和区块链的异常。其缺点有以下几点。当 Bot 被逆向时,分析人员仍可以对所下发的一切命令进行追踪,这些信息也会被区块链永久记录。由于每个交易能携带的信息有限,这种方法可能需要创建多个交易来发送一条命令,较为繁琐,而且过多的交易会消耗更多的手续费。如果要提高交易携带的信息长度,需要控制端消耗一定的计算量。这种方法也没有考虑 Bot 信息回传的功能。
展望
使用比特币区块链做 CC 的这些方法中,均存在一些尚未解决的问题,如 Bot 网络行为异常、Bot 信息无法回传、交易携带信息少、命令被永久记录在链等。面对这些问题,一些人员提出了使用智能合约、比特币测试链 Testnet 等进行 CC 的方法。比如以太坊智能合约中,命令的长度不受限,可以发布更长的命令;比特币测试链相对比特币主链具有更少的限制,可以更容易地获取币,能解决 Bot 数据回传的问题,也可以发布更长的命令。此外,无论是比特币还是智能合约,这些数字货币中均使用了椭圆曲线密码算法,故本文中提到的利用椭圆曲线数字签名问题进行 CC 的方法也同样适用于其他币种。除此之外,从目前曝光的案例来看,区块链只是 CC 活动中的一部分,使用者往往结合区块链和其他方法一起使用,以此利用区块链的特性并规避区块链的缺陷。关于检测利用比特币区块链做 CC 的活动,目前也有国外研究人员提出了一些方法,但从实验来看,效果并不明朗。
小结
本文总结了目前利用比特币区块链进行 CC 的方法,主要有利用交易脚本、交易地址、交易值和数字签名等几类方法。从目前的分析来看,把命令编码在交易脚本的做法比较灵活,能以较少的开销传递更多的信息,但需要创建很多 OP_RETURN 类型的交易。利用交易地址的方法具有很多优势,如嵌入率高、抗溯源、比特币可回收等,但需要引入第三方信道传递额外的信息,暂时不适用于 CC。利用交易值传递信息的方法只需创建普通的交易即可,但传递的信息量有限。利用 ECDSA 随机密钥重用泄露信息的方法可以以任何交易的形式存在,但这种方法存在泄露私钥的风险;如果对应的比特币地址和私钥在使用一次后就更换,则此方法还是可以考虑的。利用“私钥即密钥”方式进行 CC 的方法,理论上可以在传递无限长的命令,并且不会在比特币区块链上造成太大的异常,但此方法的计算量稍大。利用签名值隐藏命令的方法操作较为容易,但携带的信息实在有限,需要在命令编码与格式上花费功夫才能使用得当。本文还对使用区块链做 CC 进行了展望,汇集了一些学术界与工业界的相关拓展。从目前的观察来看,使用区块链做 CC 的方法比较明确,相关的技术也比较成熟。笔者认为,也许区块链不能承担起完整的 CC 过程,但如果使用巧妙得当,区块链能在 CC 或 APT 活动中发挥出更大价值。我们拭目以待。
致谢
在本文的完成过程中,ArkTeam 和山城安全提出了很多有价值的意见和观点,在此致谢!
参考资料
- KLmoney. “Bitcoin: Dissecting Transactions.” https://klmoney.wordpress.com/bitcoin-dissecting-transactions/.
- Bitcoin Wiki. “Script.” https://en.bitcoin.it/wiki/Script.
- Ali, Syed Taha, et al. “ZombieCoin: Powering Next-Generation Botnets with Bitcoin.” (2015).
- Ali, Syed Taha, et al. “ZombieCoin 2.0: managing next-generation botnets using Bitcoin.” (2018).
- Jie Yin, Xiang Cui, et al. “CoinBot: A Covert Botnet in the Cryptocurrency Network.” (2020)
- Weizheng Wang, Chunhua Su. “CCBRSN: A System with High Embedding Capacity for Covert Communication in Bitcoin.” (2020)
- Kobi Eisenkraft, et al. “Pony’s C&C servers hidden inside the Bitcoin blockchain.” https://research.checkpoint.com/2019/ponys-cc-servers-hidden-inside-the-bitcoin-blockchain/
- Paar, Christof, et al. “Understanding Cryptography.” (2010).
- Jaromir Horejsi, et al. “Glupteba Campaign Hits Network Routers and Updates C&C Servers with Data from Bitcoin Transactions.” https://blog.trendmicro.com/trendlabs-security-intelligence/glupteba-campaign-hits-network-routers-and-updates-cc-servers-with-data-from-bitcoin-transactions/.
- Frkat, Davor, et al. “ChainChannels: Private Botnet Communication Over Public Blockchains.” (2018).
- Jonathan Sweeny. “Tearing up Smart Contract Botnets.” (2018)
- Franzoni, Federico, et al. “Leveraging Bitcoin Testnet for Bidirectional Botnet Command and Control Systems.” (2020).
- Zarpelao, Bruno Bogaz, et al. “Detection of Bitcoin-Based Botnets Using a One-Class Classifier.” (2019)
(本文初版完成于 2020 年 2 月 15 日,于 2020 年 2 月 24 日首发于安全客 https://www.anquanke.com/post/id/199465 。本文二版完成于 2020 年 7 月 11 日,于 2020 年 7 月 12 日发布于 @RealWorls https://www.91tfboys.com/?p=535 。本文三版修订于 2020 年 12 月 12 日。本文系原创作品,转载初版请注明来源于安全客,转载二版、三版请注明来源于 @RealWorlds ,并遵守安全客转载规则)