浅析Blockchain类题入门

分享一下blockchain方向ctf入门题的解决办法

前期准备

1、MetaMask小狐狸插件(链接题目私链)

2、remix工具(可以本地搭建也可以使用在线的https://remix.ethereum.org/)

3、nc工具

题目解析:

题目会给出三个链接

1、水龙头

2、私链地址

3、题目部署地址

1、水龙头是干嘛的呢,为你私链链接之后给你的私链账户发送测试币的,这也是题目必须的

2、私链地址,我们需要在MetaMask中配置私链的网络环境,需要将题目的私链地址加上http://输入进去,他的链ID在随便输入之后会提示你正确ID

3、nc链接之后一般会给三个选项:

​ 1)创建合约地址(一般创建完成之后向该地址转入0.001测试币即可生效)

​ 2)部署挑战合约(在1生效之后可以部署挑战合约地址用来后续攻击)

​ 3)测试是否攻击成功,如果成功即可拿到flag

​ 4)查看solidity源码

下面用一个最近比赛WMCTF2023的Blockchain的例子来简单过一下入门:

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
contracts/Example.sol
pragma solidity ^0.5.0;

contract Challenge {
bool public solved = false;
uint256 private secretNumber;

constructor() public {
secretNumber = block.timestamp % 10 + 1;
}

function guessNumber(uint256 _num) public {
uint256 num = _num;

assembly {
let m := mload(0x40)
let a := and(sload(secretNumber_slot), 1)
let b := and(num, 1)
let result := eq(a, b)
mstore(m, result)
sstore(solved_slot, result)
}
}

function isSolved() public view returns (bool) {
return solved;
}
}

分析一下代码

1
2
3
4
5
    constructor() public {
secretNumber = block.timestamp % 10 + 1;
}
这个构造函数在合约部署时会被调用.
它会计算当前区块的时间戳对 10 取模,然后加 1,得到一个 1 到 10 之间的随机数,并将其存储在 secretNumber 变量中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function guessNumber(uint256 _num) public {
uint256 num = _num;

assembly {
let m := mload(0x40)
let a := and(sload(secretNumber_slot), 1)
let b := and(num, 1)
let result := eq(a, b)
mstore(m, result)
sstore(solved_slot, result)
}
}

接受一个_num参数使用汇编来比较secretNumber 的最低位和 _num 的最低位是否相等。
如果相等,将 result 设置为 true,否则为 false。最后,将 result 存储在 solved 变量中。

合约的核心逻辑是,在猜测数字时,它并不是直接比较输入数字与 secretNumber 是否相等,而是比较它们的最低有效位(LSB)是否相等。如果相等,solved 将被设置为 true

只需要最低位是否相等所以我们只需要比较一个0还有一个1就可以得出是否解决问题。

所以我们需要构造一个函数来调用

1
2
3
4
5
6
7
8
9
10
function guess() public {
// 尝试一个奇数
challengeInstance.guessNumber(1);
if(challengeInstance.isSolved()) {
return;
}

// 如果奇数不工作,尝试一个偶数
challengeInstance.guessNumber(2);
}

全部都构造完成之后调用check检查是否成功

1
2
3
function checkSolved() public view returns (bool) {
return challengeInstance.isSolved();
}

​ 最后回到题目nc链接输入地址就可以拿到flag

blockchain_1