d0g3战队给学弟学妹引荐了一下,我这就捎带看了看eth题目,顺手a了下misc,写下eth的wp吧,misc太多了懒得写((
Where the flag?
先看合约代码
contract find{
uint96 private a=7855;
address private owner=msg.sender;
bool private f=false;
bool private t=true;
string[] private flag=[flag1,flag2];
}
直接把flag两端写在变量定义处了,也就是说直接去合约的地址是可以看见flag明文的。
eazy_predict
先看合约代码
contract storageplace{
mapping(uint=>string)private _flag;
address owner;
constructor()public{
owner=msg.sender;
}
function flag() public view returns(string memory)
{
require(msg.sender==owner);
}
function buy(uint number) public returns(bytes1){
require(msg.sender==owner);
}
}
contract question{
mapping(address=>bool)public regeister;
mapping(address=>uint)private seed;
uint constant Price_Per_Char=10 ether;
address owner;
storageplace immutable Flag;
constructor() public {
owner=msg.sender;
storageplace _Flag = new storageplace();
Flag = _Flag;
}
modifier isowner(){
require(msg.sender==owner,"I think you are not the rignt person");
_;
}
function addRight(address tar)public isowner{
regeister[tar]=true;
}
function removeRight(address tar)public isowner{
regeister[tar]=false;
}
function regeist() public {
require(regeister[msg.sender]==false);
regeister[msg.sender]=true;
seed[msg.sender]=block.number+1;
}
function buyflag(uint want) public payable returns(bytes1){
require(msg.value==Price_Per_Char,"is not free");
return Flag.buy(want);
}
function query(bytes32 answer) public view returns(string memory)
{
require(regeister[msg.sender]);
require(block.number >seed[msg.sender],"too early");
bytes32 result = blockhash(seed[msg.sender]);
require(answer==result,"wrong answer");
return Flag.flag();
}
function withdraw() public payable{
require(msg.sender==owner);
msg.sender.transfer(address(this).balance);
}
}
简单过一遍,首先regist注册用户,然后进行buyflag,不过一次就要10eth,非常贵了,最后在query处进行获得最终flag,注意到这里的flag被定义了一个immutable,里面是存在一些方法的,所以在题目合约地址的hex处看见flag。
当然,如果正常解的话,我这里技艺不精了,但是我感觉还是在伪随机数这个地方,重点应该还是在query处吧,等官方wp在学习学习。
Common found
多少有点偏密码了属于是,先看合约。
pragma solidity ^0.8.9;
contract turn {
string private flag;
address private owner;
constructor(string memory _flag) {
flag = _flag;
owner = msg.sender;
}
function random() private view returns (uint) {
return uint(
keccak256(
abi.encodePacked(
block.difficulty,
block.timestamp,
msg.sender,
block.coinbase))
);
}
function calculate() public payable returns (bytes1) {
require(msg.value >= 5 ether);
bytes memory _flag = bytes(flag);
bytes1 entropy = bytes1(uint8(random() % _flag.length));
return _flag[uint8(entropy)] ^ bytes1(keccak256(abi.encode(entropy)));
}
function withdraw(address payable receipt) public payable {
require (msg.sender == owner);
receipt.transfer(address(this).balance);
}
receive() payable external{}
}
https://ropsten.etherscan.io/tx/0xda1f22f9146a50c51973b89ef927eb74540f873e117bfbbb58e65c281b38982f
重点是他每次异或是随机地址异或,也就是说位置随机,但是注意到他的flag明文是可以直接在合约地址中取出的,也就是说只要先把后面keccak256的全部值计算出来,与他给的flag异或即可。
写一下脚本,不太能直接用solidity直接写脚本异或,就先把需要异或的内容算出来,最后用python写个脚本就行了。
pragma solidity ^0.8.9;
contract turn {
string private flag = "6dd433b6ba64c5ddb75e9972efba88d26f598a08890aacf6eeff36097e322790bb5e548a3f741aecbead8e641a2e4a";
address private owner;
function random() private view returns (uint) {
return uint(
keccak256(
abi.encodePacked(
block.difficulty,
block.timestamp,
msg.sender,
block.coinbase))
);
}
function calculate() public view returns ( bytes1[94] memory) {
bytes1[94] memory val;
uint256 entropy1;
for(uint8 i = 0; i < 94; i++){
entropy1 = uint256(i);
val[i] = bytes1(keccak256(abi.encode(entropy1)));
}
return val;
}
receive() payable external{}
}
剩余内容:
b = [0x29,0xb1,0x40,0xc2,0x8a,0x03,0xf6,0xa6,0xf3,0x6e,0xc6,0x01,0xdf,0xd7,0xbb,0x8d,0x1b,0x31,0xbb,0x66,0xce,0x55,0xd8,0xc6,0xb1,0x94,0x05,0x3a,0x0e,0x6d,0x50,0xa0,0xc9,0x3a,0x61,0xd5,0x7c,0x40,0x74,0x98,0xe1,0xcb,0xbe,0x11,0x74,0x4a,0x37,0xa8,0x6f,0xc5,0x11,0x82,0x46,0xcf,0x4a,0x42,0x38,0xdc,0xa2,0xbb,0xc6,0xec,0x8d,0xc0,0x35,0x7c,0x38,0x96,0x9b,0xa8,0x12,0xc4,0x15,0x37,0xfc,0x17,0x42,0x1b,0x9b,0xa2,0x55,0x99,0xa9,0x4c,0xf0,0x71,0xea,0xe8,0x65,0xd7,0xe8,0xfc,0xec,0x26]
flag = [0x6d,0xd4,0x33,0xb6,0xba,0x64,0xc5,0xdd,0xb7,0x5e,0x99,0x72,0xef,0xba,0x88,0xd2,0x6f,0x59,0x8a,0x08,0x89,0x0a,0xac,0xf6,0xee,0xff,0x36,0x09,0x7e,0x32,0x27,0x90,0xbb,0x5e,0x54,0x8a,0x3f,0x74,0x1a,0xec,0xbe,0xad,0x8e,0x64,0x1a,0x2e,0x4a]
for i in range(len(flag)):
print(chr(flag[i] ^ b[i]), end='')
有个坑点,他输入的flag内容直接是hex值,,不需要二次hex,这里倒是卡了好久。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
- 最新
- 最热
只看作者