Galaxy Fox Exploit Analysis
💰

Galaxy Fox Exploit Analysis

Published
May 24, 2024
Author
daleewong

Intro

Exploit time: May 10, 2024
Loss: 108 ETH
Vuln type: lack of access control

Detail

先确定一下黑客的合约地址,改下别名
notion image
大概确定下功能。1主要是创建合约,2主要是提款。分析攻击过程的话,这两部分可以忽略
notion image
line 4 : 看看0x11a4a5733237082a6c08772927ce0a2b5f8a86b6有多少 token
line5,6调用了两个函数
line11 看黑客合约有多少token
line12-31 把token 换成 eth
notion image
本此攻击没有用闪电贷。几乎可以肯定问题出在line5的两个函数上面。因为掉完了他俩,黑客的账户突然就有钱了。
0x11a4a5733237082a6c08772927ce0a2b5f8a86b6 的合约没有verify,decomplile一下。
问题就出在这个函数,这个函数本应该是控制访问的,但是由于没有verify,开发者抱有侥幸心理
amount = 1780453099185000000000000000;
to=address(this);
_merkleRoot=keccak256(abi.encodePacked(to, amount))
把_merkleRoot传进去
function setMerkleRoot(bytes32 _merkleRoot) public payable { require(msg.data.length - 4 >= 32); _merkleRoot = _merkleRoot; }
claim这个函数关键作用就是最后的 _claimedAmount[to] = v8;
v8 大概等于amount。相当于给to账户增加amount数量的token
黑客传入的参数就是把余额给黑客合约
notion image
require(v1 == _merkleRoot, Error('GfoxClaim: Invalid proof'));// 由于上一步的set,这个require可以通过
function claim(address to, uint256 amount, bytes32[] proof) public payable { require(msg.data.length - 4 >= 96); require(proof <= uint64.max); require(4 + proof + 31 < msg.data.length); require(proof.length <= uint64.max); require(4 + proof + (proof.length << 5) + 32 <= msg.data.length); require(_claimStart > 0, Error('GfoxClaim: Not started')); require(block.timestamp >= _claimStart, Error('GfoxClaim: Not started')); require(amount > _claimedAmount[to], Error('GfoxClaim: Already claimed')); v0 = new uint256[](proof.length); CALLDATACOPY(v0.data, proof.data, proof.length << 5); v0[proof.length] = 0; v1 = v2 = keccak256(bytes20(to << 96), amount); v3 = v4 = 0; while (v3 < v0.length) { require(v3 < v0.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice v1 = v5 = 0x9c0(v0[v3], v1); v3 += 1; } require(v1 == _merkleRoot, Error('GfoxClaim: Invalid proof')); v6 = 0x718(amount); v7 = _SafeSub(v6, _claimedAmount[to]); v8 = _SafeAdd(_claimedAmount[to], v7); _claimedAmount[to] = v8; emit Claimed(to, v7, amount); 0x7d1(v7, to, address(0x8f1cece048cade6b8a05dfa2f90ee4025f4f2662)); }

End

不要因为没给源码,就抱有侥幸心理。无论二进制还是web3,暴露都是早晚的。