一个蜜罐合约的解析

晓道 发布于 2022-02-02 阅读 7342

一个蜜罐合约的解析

合约地址在: etherscan

网上的讨论地址 reddit 源码如下:

contract defi_game {
    function Try(string memory _response) public payable {
        if (
            answerHash == keccak256(abi.encode(_response)) &&
            msg.value > 1 ether
        ) {
            payable(msg.sender).transfer(address(this).balance);
        }
    }

    string public question;

    bytes32 answerHash;

    mapping(bytes32 => bool) admin;

    function Start(string calldata _question, string calldata _response)
        public
        payable
        isAdmin
    {
        if (answerHash == 0x0) {
            answerHash = keccak256(abi.encode(_response));
            question = _question;
        }
    }
    function New(string calldata _question, bytes32 _answerHash) public payable isAdmin {
        question = _question;
        answerHash = _answerHash;
    }
    function Stop() public payable isAdmin {
        payable(msg.sender).transfer(address(this).balance);
    }

    constructor(bytes32[] memory admins) {
        for (uint256 i = 0; i < admins.length; i++) {
            admin[admins[i]] = true;
        }
    }

    modifier isAdmin() {
        require(admin[keccak256(abi.encodePacked(msg.sender))]);
        _;
    }

    fallback() external {}
}

分别是部署合约(constructor),开始游戏(Start),尝试(Try),停止游戏(Stop) 从代码来看,整个代码就是,猜谜游戏,start出题、设置答案,Try解题,对了就转账给对的人。 从交易记录来看,出题人,一下转了2个eth进去,Try需要至少1个eth才能进行。 结果就是合约部署人,在constructor的时候把自己账号的 keccak256(abi.encodePacked(msg.sender)给设置进去

for (uint256 i = 0; i < admins.length; i++) {
            admin[admins[i]] = true;
        }

Start的时候设置问题,

answerHash = keccak256(abi.encode(_response)); question = _question;

这个地方question是一个public变量,所以你能在链上面看到问题,通过Start的参数,你可以看到答案,但是这不是真的答案, try一下你就知道,try一下就至少一个ETH

本地源码部署,测试

我把合约本地部署了一下,调用参数一样,Try可以成功,套路挺深的。 所以那个源码可能不是真的源码。 反汇编代码还是挺累,所以这个坑,后面有时间再填。 如果自己要部署合约,先这样:

function getadmin() public {
    address addr = address(0x9BEF5148fD530244a14830f4984f2B76BCa0dC58);
    bytes32 kca = keccak256(abi.encodePacked(addr));
    emit log_bytes32(kca);//0x8d3dfe9abb5f4b094c84ab5dc2fa239c318e4985fd30286fff6150ea6963222f
}

await defi_game.deploy(["0x0000000000000000000000000000000000000000000000000000000000000020", "0x0000000000000000000000000000000000000000000000000000000000000002",
"0x8d3dfe9abb5f4b094c84ab5dc2fa239c318e4985fd30286fff6150ea6963222f"])

0x9BEF5148fD530244a14830f4984f2B76BCa0dC58 是 Ganache的默认账号。

只是技术探讨,大家可以交流一下。

后面又反汇编了一下代码,发现代码确实是这个。

经过群友Miller的提醒,感谢Miller,ethscan上面合约调用合约显示是有问题的 这个里可以明确看到,New调用

另一个区块链浏览器 16438669931.png 这样就完整了,我一直当ethscan是什么都能看到的,疑惑了几天,看来分析问题得多看几个区块链浏览器。

所以流程如下:

1,部署合约, 2,调用New设置答案hash 3,开始Start,投入2个eth 4,有人Try,投入至少1个eth 5,Stop 收入,转回自己的钱包。

后续,没讲完的 一个蜜罐合约的解析(二)调用隐藏 | 登链社区 | 深入浅出区块链技术 (learnblockchain.cn)

相关文章

19 条评论

所以start里设置的答案是个假的对吧,通过合约调用隐藏了一次new在ethscan的显示?

2022-02-04 10:21

Toggle between Simplified and Advanced view. The 'Advanced' view also shows zero value ETH transfers, while the 'Simple' view only shows ETH transfers with value. Name tags integration is not available in advanced view

打开高级视图就可以看到所有的tx了

2022-02-04 10:27
晓道 回复 hahasdp

是的,就是这么玩的

2022-02-04 11:26

看起来都是走0x1ba21C6cfcD3D082d8Bbe95bC5B78F4eDC3e80D4 这个合约调的new

https://etherscan.io/address/0x92c46747843429054746ace6b2ba11f4e8964c3c 这里也骗了一个

2022-02-07 11:09
晓道 回复 呜呜云

是的,一直在骗,别人连账号都不改的

2022-02-07 14:03
ezio 回复 hahasdp

高级视图开了也没用,我看到他是通过 另一个合约 调用这个蜜罐合约的new 方法,tx被收录在另外一个合约地址上,就得通过楼主给的区块链浏览器才能看到。 这是4楼那个兄弟发的合约的被new记录 可以看一下 高级模式也不会收录,就得多看几个浏览器才行 https://etherscan.io/tx/0x33F5F28A8DFA721D46E15658DB10843B38FDD99D8357FAEEE2DB06541AD9541D

2022-02-10 10:11
hahasdp 回复 ezio

internal tx

2022-02-10 14:47

这个东西的答案在这个Input里应该能找出来

0x2000df4400000000000000000000000070b2461aab1be57cca4a94f0fe809ef760cf11990000000000000000000000000000000000000000000000000000000000000060574b4a7485aa478aba39014eb71f5994b58ae1d4ac1fcbd98cca177eb5e18cbb00000000000000000000000000000000000000000000000000000000000000294e616d65206f6620746865206d6f737420706f70756c61722063727970746f2063757272656e63793f0000000000000000000000000000000000000000000000

2022-02-10 15:03

uint256 _param1, array _param2, uint256 _param3 其中的_param3

2022-02-10 15:05

这个bitch弄了个新的放了3e https://etherscan.io/address/0xd9201abf34b74def7435566681942bcc5cf4089d

new的tx https://etherscan.io/tx/0xf6cdafd15ed96fbe8ec470d8fc1a4c2cc5928f2ad168deda5265740baab0b6cf/advanced

传的参数都没变,有没有大侠去把他这3e掏出来;-)

Panoramix v4 Oct 2019

Decompiled source of 0xA2A2d047d831216f01fAbCe26B10D651Df98CD2B

Let's make the world open source

def _fallback() payable: # default function stop

def unknown2000df44(uint256 _param1, array _param2, uint256 _param3) payable: require calldata.size - 4 >=′ 96 require _param1 == addr(_param1) require _param2 <= 18446744073709551615 require _param2 + 35 <′ calldata.size require _param2.length <= 18446744073709551615 require _param2 + _param2.length + 36 <= calldata.size require ext_code.size(addr(_param1)) call addr(_param1).New(string question, bytes32 responseHash) with: gas gas_remaining wei args Array(len=_param2.length, data=_param2[all]), _param3 if not ext_call.success: revert with ext_call.return_data[0 len return_data.size]

================ 重点

call addr(_param1).New(string question, bytes32 responseHash) with: gas gas_remaining wei args Array(len=_param2.length, data=_param2[all]), _param3

2022-02-10 15:21

刚发现这是keccak256 abi.encode 后的值,散了吧。

2022-02-10 15:47
晓道 回复 hahasdp

你加油,哈哈

2022-02-10 17:43
晓道 回复 hahasdp

我写的时候也是边探索边写,前面的内容对大家有误导,啥时候,我重新编辑一下

2022-02-10 17:59
晓道 回复 hahasdp

大家想知道,new进去了什么,我也发出来,免得大家费神,"[FUNCTION]":"New" "[OPCODE]":"CALL" "from":{ "address":"0x1ba21c6cfcd3d082d8bbe95bc5b78f4edc3e80d4" "balance":"0" } "to":{ "address":"0xd732e40d353aa772a7f82b4b310e75925853a040" "balance":"0" } "value":"0" "input":{ "_question":"Name of the most popular crypto currency?" "_answerHash":"0x574b4a7485aa478aba39014eb71f5994b58ae1d4ac1fcbd98cca177eb5e18cbb" }

2022-02-10 18:03
hahasdp 回复 晓道

怎么取出来的?

2022-02-11 09:55