据 PeckShield 监测发现,4月10日23点02分,黑客向波场竞猜类游戏 TronWow 发起攻击 1,203 次,共计获利 2,167,377 个 TRX(约 $57,148 )。PeckShield 安全人员当即展开分析发现,黑客每投注 20TRX,即可获得 1,940 个 TRX 作为回报,回报率高达 97 倍。而此次攻击中,黑客共计投注 23,004 个 TRX, 收获 2,167,377 个 TRX。4月12日下午,PeckShield 安全人员对此次攻击进一步分析,发现 TronWow 合约在检查下注范围时存在缺陷,允许用户在非页面下注时构造恶意输入,从而实现稳赢的游戏结果。
TronWow 是一个典型的 dice 类游戏。玩家通过选定下注数字和押大押小来进行一轮游戏。
如下图所示,当用户在 TronWow 游戏页面中参与游戏,无论选择 Under 模式或 Over 模式,都被限制了下注数字的范围和胜率。
其中
Under 和 Over 两种模式的胜率均为 [2%, 95%]
,奖励倍数为【97 / 胜率百分数】。
PeckShield 安全人员在深入逆向分析 TronWow 合约时发现,TronWow 合约在检查下注范围时存在缺陷,允许用户在非页面下注时构造恶意输入。换而言之,一旦用户避开游戏页面,直接调用游戏合约的下注函数,即可设法绕过合约中的下注范围检查条件,实现 100% 胜率以及最高回报倍数(97倍)。
下面以正常下注交易和恶意下注交易对该合约漏洞进行说明。
在 TronWow 合约代码中,函数 placeBet(uint24 _betMask,uint256 _commit,bytes32 _r,bytes32 _s)
为下注函数,参数 uint24 _betMask
为玩家的下注信息。
其中正常下注交易调用 placeBet
函数时输入如下:
这是一个选择了 Under 模式且下注数字为 95 的正常交易,换而言之,当游戏生成的随机数小于等于 95 时玩家获胜。
在此交易中,参数 _betMask
的值 24321
转换成十六进制为 0x005F01
,我们将其分拆为三个字节,分别如下:
其中:
其中第一部分 0x00
表示若当该轮游戏产生的随机数计算结果处于 [0x01, 0x5f]
之间,则玩家获胜;相反,前两位不为 0x00
时表示若该轮游戏产生的随机数计算结果处于 [0x01, 0x5f]
之外,则玩家获胜。
在逆向过程中,我们将下注函数的部分汇编指令还原成伪代码,如下图所示:
阅读上述下注函数伪代码可以发现,合约只对玩家下注信息中的胜率百分数进行了检查,要求其小于等于 95,却未对下注数字做数值限制。故玩家可通过构造下注数字来绕过该检查。
下图为攻击者发起的诸多攻击交易之一:
其中 _betMask
参数被构造为 130971
,十六进制为 0x01FF9B
。其中前两位 0x01 表示若该轮游戏产生的随机数计算结果处于 [0x9B, 0xFF]
之外,则玩家获胜。而 0x9B
、0xFF
对应的十进制分别为 155、255,则根据合约撰写的胜率百分比计算规则,winRate = 100 - (0xFF - 0x9B) + 1
,即等于 1,从而成功绕过下注范围检查函数,并将本次交易的奖励倍数设置为 97。需要特别强调的是,在页面下注中,奖励倍数最高仅为 48.5 倍。
接着,我们将开奖函数 settleBet(uint256 _reveal, bytes32 _txHash)
的判断游戏输赢部分汇编指令还原成伪代码:
其中 rollResult
为本轮游戏的随机数计算结果,取值范围为 [1,100]
。而在攻击者设置的恶意参数中,rollResult
必然处于 [155,255]
区间之外,满足赢得本轮游戏的条件,从而确保了攻击者游戏结果稳赢。
对于 TronWow 合约被攻击事件,PeckShield 安全人员分析发现:TronWow 合约在检查下注范围时存在缺陷,允许用户在非页面下注时构造恶意输入,实现 100% 胜率。需要注意的是,该漏洞已在 TronWow 上线的新版本合约中被修复,游戏方增添了对下注范围的约束检查。
在此,PeckShield 安全人员提醒广大项目方及交易所应当重视区块链世界中的任何安全问题,确保项目方及用户的资产安全可靠。安全无小事,采取不公布源代码来抵御黑客攻击的行为,在黑客面前形同虚设。DApp 开发者应杜绝侥幸心理,在合约上线前做好必要的安全措施和已知攻击特征检查,必要时可联系第三方安全公司进行漏洞排查,避免造成不必要的数字资产损失。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)