一、 题目结构
1.1 Merkle Tree
address key; uint8 value; } |
if (a.value == 0) { return 0; } else { return keccak256(abi.encode(a.key, a.value)); } } |
if (l == 0) { return r; } else if (r == 0) { return l; } else { return keccak256(abi.encode(l, r)); } } |
bytes32[] memory _proofs, Leaf[] memory _leaves, bytes32 _root ) |
function checkGroupSorted(Leaf[] memory _leaves) internal pure returns (bool) { |
bytes32[] memory stackValues = new bytes32[](SMT_STACK_SIZE); uint256 proofIndex = 0; uint256 leaveIndex = 0; uint256 stackTop = 0; |
proofIndex++; require(stackTop < SMT_STACK_SIZE); require(leaveIndex < _leaves.length); stackKeys[stackTop] = uint160(_leaves[leaveIndex].key); stackValues[stackTop] = calcLeaf(_leaves[leaveIndex]); stackTop++; leaveIndex++; } |
function getBit(uint160 key, uint256 height) internal pure returns (uint256) { require(height <= DEPTH); return (key >> height) & 1; } // 低位清零 function parentPath(uint160 key, uint256 height) internal pure returns (uint160) { require(height <= DEPTH); return copyBit(key, height + 1); } function copyBit(uint160 key, uint256 height) internal pure returns (uint160) { require(height <= DEPTH); return ((key >> height) << height); } proofIndex++; require(stackTop != 0); require(proofIndex + 2 <= _proofs.length); uint256 height = uint256(_proofs[proofIndex++]); bytes32 currentProof = _proofs[proofIndex++]; require(currentProof != _root); if (getBit(stackKeys[stackTop - 1], height) == 1) { stackValues[stackTop - 1] = merge(currentProof, stackValues[stackTop - 1]); } else { stackValues[stackTop - 1] = merge(stackValues[stackTop - 1], currentProof); } stackKeys[stackTop - 1] = parentPath(stackKeys[stackTop - 1], height); |
proofIndex++; require(stackTop >= 2); require(proofIndex < _proofs.length); uint256 height = uint256(_proofs[proofIndex++]); uint256 aSet = getBit(stackKeys[stackTop - 2], height); uint256 bSet = getBit(stackKeys[stackTop - 1], height); stackKeys[stackTop - 2] = parentPath(stackKeys[stackTop - 2], height); stackKeys[stackTop - 1] = parentPath(stackKeys[stackTop - 1], height); require(stackKeys[stackTop - 2] == stackKeys[stackTop - 1] && aSet != bSet); if (aSet == 1) { |
require(stackTop == 1); return stackValues[0]; |
bytes32[] memory _proofs, Leaf[] memory _nextLeaves, Leaf[] memory _prevLeaves, bytes32 _prevRoot ) internal pure returns (bytes32) { require(verify(_proofs, _prevLeaves, _prevRoot), "update proof not valid"); return calcRoot(_proofs, _nextLeaves, _prevRoot); } |
bytes32[] memory _proofs, address _target, bytes32 _prevRoot, Method _method ) internal pure returns (bytes32) { Leaf[] memory nextLeaves = new Leaf[](1); Leaf[] memory prevLeaves = new Leaf[](1); nextLeaves[0] = Leaf({key: _target, value: uint8(_method) ^ 1}); prevLeaves[0] = Leaf({key: _target, value: uint8(_method)}); return update(_proofs, nextLeaves, prevLeaves, _prevRoot); } |
1.2 TreasureHunter
require(haveKey[msg.sender] && haveTreasureChest[msg.sender]); solved = true; emit OpenTreasureChest(msg.sender); } |
require(smtMode == SMT.Mode.WhiteList, "not whitelist mode"); require(team.length >= 4); require( SMT.verifyByMode(_proofs, team, root, smtMode), "hunter hasn't found the treasure chest" ); haveTreasureChest[msg.sender] = true; smtMode = SMT.Mode.BlackList; emit PickupTreasureChest(msg.sender); } |
require(smtMode == SMT.Mode.BlackList, "not blacklist mode"); require(team.length >= 4); require(SMT.verifyByMode(_proofs, team, root, smtMode), "hunter has fallen into a trap"); haveKey[msg.sender] = true; smtMode = SMT.Mode.WhiteList; emit FindKey(msg.sender); } |
require(haveKey[msg.sender] == false); require(checkteam()); team.push(msg.sender); root = SMT.updateSingleTarget(_proofs, msg.sender, root, SMT.Method.Insert); } |
二 、 解题思路
2.1 enter
bytes32[] memory _proofs, address _target, bytes32 _prevRoot, Method _method ) internal pure returns (bytes32) { Leaf[] memory nextLeaves = new Leaf[](1); Leaf[] memory prevLeaves = new Leaf[](1); nextLeaves[0] = Leaf({key: _target, value: uint8(_method) ^ 1}); prevLeaves[0] = Leaf({key: _target, value: uint8(_method)}); return update(_proofs, nextLeaves, prevLeaves, _prevRoot); } |
"0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009c", "0xe9f810898db8dc62342eaa122fd26525362f2b70bd462edef6e4e34093d66c17", "0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009f", "0xba13a52ab72064627701ac75ab564f7e786d093c655849458536cc689abdf8e2"] |
"0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009a", "0x423b9e9e1b3a1cfbd4c7d075391785c44def9c2884281cc63e0a78fcc3bb7f66", "0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009f", "0xba13a52ab72064627701ac75ab564f7e786d093c655849458536cc689abdf8e2"] |
"0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009e", "0x4e951b5440112027d135d0f1dc97bff8127bec7439f8a54ff6a6b6a164764c64", "0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009f", "0xba13a52ab72064627701ac75ab564f7e786d093c655849458536cc689abdf8e2"] |
"0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009e", "0x4b3f7ee71efd14747b6620f1919bcdc78724d8a862e987596a1179a6b460be05", "0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009f", "0xba13a52ab72064627701ac75ab564f7e786d093c655849458536cc689abdf8e2"] |
2.2 pickupTreasureChest
0x06F07E646D6724874e72FCE7f3AC534cfbEC754a 0x49Bb1e658D6EE866215D11037A6De1712Ed81B83 0x6a95Ad9945396aF307B6d0D99F5382F8C781B4f4 |
proofIndex++; require(stackTop >= 2); require(proofIndex < _proofs.length); uint256 height = uint256(_proofs[proofIndex++]); uint256 aSet = getBit(stackKeys[stackTop - 2], height); uint256 bSet = getBit(stackKeys[stackTop - 1], height); stackKeys[stackTop - 2] = parentPath(stackKeys[stackTop - 2], height); stackKeys[stackTop - 1] = parentPath(stackKeys[stackTop - 1], height); require(stackKeys[stackTop - 2] == stackKeys[stackTop - 1] && aSet != bSet); if (aSet == 1) { stackValues[stackTop - 2] = merge( stackValues[stackTop - 1], stackValues[stackTop - 2] ); } else { stackValues[stackTop - 2] = merge( stackValues[stackTop - 2], stackValues[stackTop - 1] ); } |
"0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009c", "0xe9f810898db8dc62342eaa122fd26525362f2b70bd462edef6e4e34093d66c17", "0x000000000000000000000000000000000000000000000000000000000000004c", "0x0000000000000000000000000000000000000000000000000000000000000048", "0x000000000000000000000000000000000000000000000000000000000000009a", "0x000000000000000000000000000000000000000000000000000000000000004c", "0x0000000000000000000000000000000000000000000000000000000000000048", "0x000000000000000000000000000000000000000000000000000000000000009e", "0x000000000000000000000000000000000000000000000000000000000000004c", "0x0000000000000000000000000000000000000000000000000000000000000048", "0x000000000000000000000000000000000000000000000000000000000000009e", "0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009f", "0xba13a52ab72064627701ac75ab564f7e786d093c655849458536cc689abdf8e2"] |
2.3 findkey
"0x000000000000000000000000000000000000000000000000000000000000004c", "0x0000000000000000000000000000000000000000000000000000000000000048", "0x000000000000000000000000000000000000000000000000000000000000009a", "0x000000000000000000000000000000000000000000000000000000000000004c", "0x0000000000000000000000000000000000000000000000000000000000000048", "0x000000000000000000000000000000000000000000000000000000000000009e", "0x000000000000000000000000000000000000000000000000000000000000004c", "0x0000000000000000000000000000000000000000000000000000000000000048", "0x000000000000000000000000000000000000000000000000000000000000009e", "0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009c", "0x03f38c848024ba3006373acb4175da682ce9d4e1ade10e0472919f30f664b1e4", "0x0000000000000000000000000000000000000000000000000000000000000050", "0x000000000000000000000000000000000000000000000000000000000000009f", "0xba13a52ab72064627701ac75ab564f7e786d093c655849458536cc689abdf8e2"] |
2.4 完整exp
原文始发于微信公众号(山石网科安全技术研究院):2022starCTF——TreasureHunter
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论