好久没打ctf了,周末一个人随便打了打,题是真多,记录下区块链题目

Onchain Checkin

不是很懂solana,最近在啃rust圣经,以后就可以学学solana,但是还好这题不需要懂

打开附件先看到了Anchor.toml,里面的内容提示了这是部署在solana的一个测试链devnet上的

然后是里面几段rust

首先是lib.rs,里面给了公钥和flag2的信息

还有checkin.rs,大概看看就知道去找区块链浏览器就行了

地址如下

https://explorer.solana.com/tx/21hrX9ekAihzk5M1fE7EdagACu1LGJj8j4bBbU12oNc26nxdGpXknyXTXhUzG9ukuEgnPV2h5M5Yb57geD4vgjnk?cluster=devnet

然后就可以找到flag的几个部分,拼起来就好

其中flag1和flag3是base58编码的

Onchain Magician

对于同一个私钥和消息,可以生成不同的签名,具体可以看这篇文章

https://learnblockchain.cn/article/8046#6.%20%E5%AE%9E%E7%8E%B0%E5%90%8C%E4%B8%80%E7%A7%81%E9%92%A5%EF%BC%8C%E5%90%8C%E4%B8%80%E6%B6%88%E6%81%AF%EF%BC%8C%E4%B8%8D%E5%90%8C%E7%AD%BE%E5%90%8D

于是自己本地生产两组sig,然后交互就可以了

不过这题由于使用的是普通的ecrecover不是openzepplin的安全版本,似乎还有别的密码学相关的漏洞,这里没去详细了解

签名:

const ethereumjsUtil = require('ethereumjs-util');

// 要签名的消息
const message = Buffer.from('xxx', 'hex');

// 私钥(注意:这只是一个示例私钥,不应该在实际项目中使用)
const privateKey = Buffer.from('xxx', 'hex');

const messageHash = ethereumjsUtil.keccak256(message);

// 使用私钥对消息哈希进行签名
const signature = ethereumjsUtil.ecsign(messageHash, privateKey);

// 将签名结果进行格式化
const formattedSignature = {
    v: signature.v,
    r: signature.r.toString('hex'),
    s: signature.s.toString('hex')
};

console.log('Message:', message);
console.log('Message Hash:', messageHash.toString('hex'));
console.log('Signature:', formattedSignature);

由于限制了msg.sender,所以直接at address和题目合约手动交互就比较方便

直接在remix里传v r s,大概这样

[27, "0x3ed65490190a0203c07c4ded2857be47c9db091d089cf1211febadb54c910fee", "0x5d8db8c4d35f5286ebf3a05a1a4f60e8d26251269a330c2c724214578b2a6835"]

signin方法调用一次然后再生成新的v r s去调用openbox就可以了