BlockChain

记录一点CTF中区块链的题目吧,仅是记录做法

blockchain-ctf.securityinnovation.com

从大佬那里问了个网站,现在似乎进不去,太可惜了

https://blog.csdn.net/2303_79193185/article/details/136534150?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22136534150%22%2C%22source%22%3A%222303_79193185%22%7D&fromshare=blogdetail&shareId=14&sharetype=hot

[NSSRound#4 SWPU]Bridge

1
2
OKC 地址 0x26eD1a5Ce072aB407C9d24b434f9be43b9ADDCe5 发生了大额快进快出,经过溯源可以找到他来源于一个 BSC 地址,请找出该 Bridge 在 BSC 上的交易tx
NSSCTF{0x****************************************************************}

这道题学到的是,善用工具区块链浏览器查询 | 欧科云链 OKLink

先打开关于OKC的工具

首页上方输入地址0x26eD1a5Ce072aB407C9d24b434f9be43b9ADDCe5

根据交易数量和交易时间,打开DeFi tracker工具

然后筛选

下一步根据题目要求,打开BNB Chain,再打开DeFi tracker

同样的条件再筛选一次

这个交易哈希就是答案

NSSCTF{0xf787c44151fe21da13c213e3adaa7796176e09b9364eb6f52aa43e387ce4b455}

GHCTF——其疾如风

题目描述:

1
2
My letter has been maliciously tampered with, and now I can't find my wallet address of goerli testnet!
Change flag{} to NSSCTF{}

附件是这样一个残缺的二维码

先把二维码补全,参考:【CTF-MISC】图片隐写中补全二维码定位角的注意事项【详细步骤】_misc二维码缺失-CSDN博客

补成这样即可

扫码得到这样的内容:ethereum: 0x57F1b45c28eDaC71d0A9Ffb54B7d8d2733E8d599

根据题目描述中的goerli testnet

打开区块链浏览器查询 | 欧科云链 OKLink

查询这个地址

在某条交易记录中有flag的16进制形式

GHCTF——侵略如火

题目描述

1
2
3
challenge 111.229.224.125:15000
geth 111.229.224.125:15001
faucet 111.229.224.125:15002

nc 111.229.224.125 15000

输入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
contracts/Example.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;

contract Greeter {
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 = "HelloFAFUer";
return keccak256(abi.encodePacked(expected)) == keccak256(abi.encodePacked(greeting));
}
}

使得isSolved返回True,再输入3即可获得flag

此时,我们再次nc靶机,输入1

获得了一个账户,以及我们的token。

题目要求我们先给这个账户转0.001测试币才能进入下一步

我们需要先有一个钱包账户,用MetaMask即可创建

然后像这样连接到题目给的RPC中

链的ID先随便输,会自动跳出正确的ID

有了钱包之后,我们访问111.229.224.125:15002获取测试币

然后转账到题目给的账户

之后我们再次nc 靶机,并输入2,再输入题目给的token

这时候我们获得了一个合约地址

此时我们打开网站->

把题目给的源码复制近来,然后调整版本,进行编译

完成编译之后,我们来到这个页面

先把环境换成MetaMask,并核对账户

往下拖,找到

输入HelloFAFUer,并点击setGreeting,此时MetaMask会跳出支付页面,支付完成后依次点击greetisSolved

然后nc 靶机,输入3,再输入自己的token即可获得flag

GHCTF——其徐如林

题目描述

1
2
3
你给我邮箱,我给你flag。
合约部署在sepolia测试网上。
contract's address:0x521BF58Dd54663063a779b365CAe9FC974f47047

task.sol

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pragma solidity ^0.8.9;

contract Testcontract {
mapping(address=>uint) _flag;

event sendflag(string email,string tokens);

function test() public {
_flag[msg.sender] = 1;
}
function payforflag(string memory _base64Email,string memory _token) public {
require(_flag[msg.sender] == 1);
emit sendflag(_base64Email , _token);
}
}

mapping函数可以理解为,每个钱包地址都有个变量_flag

有个事件sendflag

test()函数的作用是把调用者的_flag更改为1

payforflag()需要两个参数,分别是base64编码后的邮箱地址,以及token,还要求调用者的_flag值为1

根据代码,本题思路就是先调用test()函数把_flag值变为1,再调用payforflag,然后估计就会把flag发送到我们的邮箱

这里需要先在sepolia测试网中获取一点测试币,需要在网上自行寻找水龙头获取。

然后就是编写脚本(不太明白原理,先存着,当个脚本小子先)。

exp.py

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
from web3 import Web3
import base64
import uuid
import json

w3 = Web3(Web3.HTTPProvider('https://rpc2.sepolia.org')) # Sepolia RPC

wallet = '0x...' # 钱包地址
key = '0x...' # 钱包私钥

target = '0x...' # 合约地址

with open("contract_abi.json", "r") as abi_file:
contract_abi = json.load(abi_file) # 读取合约 ABI(在Remix编译后获取,可以用在线网站)

contract = w3.eth.contract(address=target, abi=contract_abi)

print(f"[CONTRACT] 加载了一个合约,其地址为:{target}")


def send_transaction(transaction, private_key):
signed_transaction = w3.eth.account.sign_transaction(
transaction, private_key)
transaction_hash = w3.eth.send_raw_transaction(
signed_transaction.rawTransaction)

print(f"[TRANSACTION] 发送了一个交易,其哈希为:{transaction_hash.hex()}")
print(f"[TRANSACTION] 正在等待交易确认......")

w3.eth.wait_for_transaction_receipt(transaction_hash)

print(f"[TRANSACTION] 交易已被确认。")

return transaction_hash


def test():
return send_transaction(contract.functions.test().build_transaction({
"chainId": 11155111,
"maxFeePerGas": w3.to_wei(1.000000014, 'gwei'),
"maxPriorityFeePerGas": w3.to_wei(1, 'gwei'),
"gas": 0x200000,
"value": w3.to_wei(0, 'ether'),
"nonce": w3.eth.get_transaction_count(wallet),
}), key)


def payforflag(email: str, token: str):
return send_transaction(contract.functions.payforflag(
base64.b64encode(email.encode()).decode(), token
).build_transaction({
"chainId": 11155111,
"maxFeePerGas": w3.to_wei(1.000000014, 'gwei'),
"maxPriorityFeePerGas": w3.to_wei(1, 'gwei'),
"gas": 0x200000,
"value": w3.to_wei(0, 'ether'),
"nonce": w3.eth.get_transaction_count(wallet),
}), key)


if __name__ == "__main__":

# 要传入的参数
email = "" # 你希望接收flag的邮箱
token = uuid.uuid4().hex #作用不大,随机生成一个即可

test() # 调用 test
payforflag(email, token) # 调用 payforflag

运行完之后,大概30分钟收到了flag:NSSCTF{Step2_contract_st1ll_E4sy_fOr_y0u!}

GHCTF——不动如山

题目描述

1
2
3
challenge 111.229.224.125:16000
geth 111.229.224.125:16001
faucet 111.229.224.125:16002

先nc查源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// contracts/Example.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;

contract GiveMeETH{
constructor() {
//no function to transfer......
}

function isSolved() public view returns(bool) {
return address(this).balance >= 0.66 ether;
}
}

题目还是要求让isSolved()返回True,这里就是要让合约的余额不小于0.66

先输入1获得部署合约的账户

并且转账超过0.001进入下一步

输入2获得合约地址以及交易哈希

一开始试了直接转账,但是失败了。上网查找有没有什么其他转账的方法

https://blog.riskivy.com/%e6%99%ba%e8%83%bd%e5%90%88%e7%ba%a6ctf%ef%bc%9aethernaut-writeup-part-2/#7Force

在remix上写个脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.9;

contract Selfdestruct{
constructor() payable {

}

function attack() public {
address payable addr = payable(address(0x801b7361AbA8FDd63c4Bb741E4E89b4d948b22a6));
selfdestruct(addr);
}
}

再使用remix交互

这些地方记得修改,再点击部署,会跳出支付页面,支付后即可交互

点击attack,再次支付即可

-------------已经到底啦!-------------