Blockchain签到 Checkin 1 2 3 4 5 一般题目中给出了三个端口,分别是 RPC、水龙头、题目交互端。 其中,浏览器可直接访问的是水龙头,浏览器直接访问报 403 的是 RPC,浏览器无法访问的是题目交互端,需使用 nc 连接。 week-1.hgame.lwsec.cn:30111 week-1.hgame.lwsec.cn:32559 week-1.hgame.lwsec.cn:32428
前期准备 通过判断可以知道题目、RPC、水龙头分别对应的端口
1 week-1.hgame.lwsec.cn:32559 水龙头
水龙头访问结果:
1 2 week-1.hgame.lwsec.cn:30111 题目环境 nc week-1.hgame.lwsec.cn 30111
题目环境访问结果
题目环境有四个选项:
1 2 3 4 5 6 7 8 9 10 11 12 13 We design a pretty easy contract challenge. Enjoy it! Your goal is to make isSolved() function returns true! [1] - Create an account which will be used to deploy the challenge contract [2] - Deploy the challenge contract using your generated account [3] - Get your flag once you meet the requirement [4] - Show the contract source code 翻译: 我们设计了一个非常简单的合同挑战。享受它! 您的目标是使isSolved()函数返回true! [1] -创建一个用于部署挑战合同的帐户 [2] -使用生成的帐户部署挑战合同 [3] -一旦满足要求,就拿旗 [4] -显示合同源代码
创建账户 首先选择1创建账户:
1 2 3 4 [-] input your choice: 1 [+] deployer account: 0x6FfB5cCb379A96b3aB7B1527372Ff90b4201f401 [+] token: v4.local.JE3A5C-HZoI2joiVNAHV4NjBaxM7jyToGUKmx9CeCOSHxCLXEACw61gVdVYSAeL4zJeja0NyJkNFvxfwIYh04JYLFNkdLRimDi6mhC-_crrY4gZu1FkS0oyHu0fnIW_2NLdx3njjF4n51HQJXlEnwhizMBZLvtSf7yHRVNyftzOeqw [+] please transfer 0.001 test ether to the deployer account for next step
可以看到拿到了一个账户和和一个token,并且我们需要转0.001 test ether到账户中
此时我们如果选择2会报错:
需要我们提前转账才能做后面的操作。
测试币领取 可以使用水龙头进行测试币领取
合约信息 此时再选2
可以拿到远程合约的地址和交易的hash信息:
1 2 [+] contract address: 0xbdFcE62184338C494e4Ea6593c374c57C02279CB [+] transaction hash: 0xa1b89528e2954356c9cbb0088bceab1f72d151cf96b84e23ba71ecc8848d654c
查看合约源码 我们可以选择4进行源代码查看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 [-] input your choice: 4 contracts/checkin.sol // SPDX-License-Identifier: MIT pragma solidity 0.8.17; contract Checkin { string greeting; constructor(string memory _greeting) { greeting = _greeting; } function greet() public view returns (string memory) { return greeting; } function setGreeting(string memory _greeting) public { greeting = _greeting; } function isSolved() public view returns (bool) { string memory expected = "HelloHGAME!"; return keccak256(abi.encodePacked(expected)) == keccak256(abi.encodePacked(greeting)); } }
通过源码审计之后可以简单的发现攻击思路。
如果需要使isSolved()
放回true,我们需要使keccak256(abi.encodePacked(expected)) == keccak256(abi.encodePacked(greeting));
,其中expected
的值是HelloHGAME!
,所以我们只需要将greeting
的值也设置成HelloHGAME!
即可满足加密。
继续审计可以看到我们可以通过setGreeting
修改greeting
的值即可。
首先尝试使用REMIX解题
Remix解题 RPC地址配置 首先第一步我们需要配置小狐狸的RPC地址
1 HTTP://week-1.hgame.lwsec.cn:32428
配置完了之后查看是否生效,可以使用水龙头往自己的小狐狸地址中转账如果可以收到就表示配置成功。
Remix交互 首先把在题目中拿到的源码复制到Remix中,然后选择Injected Provider - MetaMask,这边注意networks的id是否一样,然后在At Address中输入前面的合约地址:0xbdFcE62184338C494e4Ea6593c374c57C02279CB
输入地址之后可以看到下面加载了合约信息,里面有一些函数跟变量
但是我们点击setGreeting没有反应,所以应该是题目没有做remix的交互,在geth启动的时候需要额外的参数
1 2 Note: To use Geth & https://remix.ethereum.org, configure it to allow requests from Remix geth --http --http.corsdomain https://remix.ethereum.org
所以这边尝试使用web3py合约交互
web3py合约交互 1 官方手册:https://web3py.readthedocs.io/en/stable/web3.eth.html
exp代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 from web3 import Web3, HTTPProviderw3 = Web3(HTTPProvider('http://week-1.hgame.lwsec.cn:32475/' )) assert w3.isConnected() print (w3.isConnected()) pk = '0x16e39235b9e8d246db0c59d09139d3f3b5aeee31858eed44a5f57527c5f42d70' account = w3.eth.account.privateKeyToAccount(pk) print (account.address) abi = '[{"inputs":[{"internalType":"string","name":"_greeting","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"greet","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSolved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_greeting","type":"string"}],"name":"setGreeting","outputs":[],"stateMutability":"nonpayable","type":"function"}]' contract = w3.eth.contract(address='0xF587E2006316F1DF3121Be3ba31dEC1CA558928E' , abi=abi) tx = contract.functions.setGreeting('HelloHGAME!' ).buildTransaction({ 'from' : account.address, 'nonce' : w3.eth.getTransactionCount(account.address), 'gas' : 1000000 , 'gasPrice' : w3.toWei('1' , 'gwei' ), }) signed_tx = account.signTransaction(tx) tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction) tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash) print (tx_receipt)print ('greet : {}' .format (contract.functions.greet().call())) print ('isSo : {}' .format (contract.functions.isSolved().call()))
可以看到效果: