好久没打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就可以了