IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> 34C3-CTF.crypto.chaingang解题记录 -> 正文阅读

[区块链]34C3-CTF.crypto.chaingang解题记录

题目的地址为 :
https://archive.aachen.ccc.de/34c3ctf.ccc.ac/challenges/
题目描述:

chaingang

send 1505 szabo 457282 babbage 649604 wei 0x949a6ac29b9347b3eb9a420272a9dd7890b787a3

有一些与以太坊相关的关键字如 send 、 wei ,还有个地址,尝试访问在 以太坊浏览器搜索(https://etherscan.io/address/0x949a6ac29b9347b3eb9a420272a9dd7890b787a3) 发现是一个智能合约。
在这里插入图片描述
但只有字节码,因此需要逆向。
百度发现以太坊虚拟机官方已经提供了实验性的在线逆向工具.
https://ethervm.io/decompile
直接输入合约地址就自动解析完成了…
在这里插入图片描述
显示代码如下:

contract Contract {
    function main() {
        memory[0x40:0x60] = 0x60;
    
        if (msg.data.length < 0x04) { revert(memory[0x00:0x00]); }
    
        var var0 = msg.data[0x00:0x20] / 0x0100000000000000000000000000000000000000000000000000000000 & 0xffffffff;
    
        if (var0 == 0x2a0f7696) {
            // Dispatch table entry for 0x2a0f7696 (unknown)
            if (msg.value) { revert(memory[0x00:0x00]); }
        
            var var1 = 0x0081;
            var var2 = msg.data[0x04:0x24] & 0xffff;
            var1 = func_00CC(var2);
            var temp0 = memory[0x40:0x60];
            memory[temp0:temp0 + 0x20] = var1;
            var temp1 = memory[0x40:0x60];
            return memory[temp1:temp1 + (temp0 + 0x20) - temp1];
        } else if (var0 == 0x5b6b431d) {
            // Dispatch table entry for Withdraw(uint256)
            if (msg.value) { revert(memory[0x00:0x00]); }
        
            var1 = 0x00c0;
            var2 = msg.data[0x04:0x24];
            Withdraw(var2);
            stop();
        } else if (var0 == 0x9f1b3bad) {
            // Dispatch table entry for Receive()
            var1 = 0x00ca;
            Receive();
            stop();
        } else { revert(memory[0x00:0x00]); }
    }
    
    function func_00CC(var arg0) returns (var r0) {
        var var0 = 0x00;
    
        if (arg0 & 0xffff != storage[0x01] & 0xffff) { return 0x00; }
    
        memory[0x00:0x20] = msg.sender;
        memory[0x20:0x40] = 0x02;
        return storage[keccak256(memory[0x00:0x40])];
    }
    
    function Withdraw(var arg0) {
        if (msg.sender != storage[0x00] & 0xffffffffffffffffffffffffffffffffffffffff) { revert(memory[0x00:0x00]); }
    
        var temp0 = arg0;
        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) { return; }
        else { revert(memory[0x00:0x00]); }
    }
    
    function Receive() {
        var var0 = 0x00;
        var var1 = var0;
        var var2 = 0x02;
        memory[memory[0x40:0x60] + 0x20:memory[0x40:0x60] + 0x20 + 0x20] = 0x00;
        var temp0 = memory[0x40:0x60];
        memory[temp0:temp0 + 0x20] = msg.value;
        var var3 = temp0 + 0x20;
        var temp1 = memory[0x40:0x60];
        var temp2;
        temp2, memory[temp1:temp1 + 0x20] = address(var2).call.gas(msg.gas - 0x646e)(memory[temp1:temp1 + var3 - temp1]);
    
        if (!temp2) { revert(memory[0x00:0x00]); }
    
        var temp3 = memory[memory[0x40:0x60]:memory[0x40:0x60] + 0x20] ~ storage[0x01];
        memory[0x00:0x20] = msg.sender;
        memory[0x20:0x40] = 0x02;
        storage[keccak256(memory[0x00:0x40])] = temp3;
    }
}

可以看到,总共有 3 个函数接口。第一个没有查到历史函数名称,说明是合约开发者自己写的,反编译器直接把给它命名为 main 。而后面两个,是比较常见的函数 WithdrawReceive

查看主要函数及调用情况

整理出这5条交易信息如下:

1: 0x2a0f7696

2: 0x2a0f7696c1cb

3 :0x2a0f7696000000000000000000000000000000000000000000000000000000000000c1cb

4: 0x9f1b3bad

5: 0x2a0f7696000000000000000000000000000000000000000000000000000000000000c1cb

通过查看调用情况,可以看到 main 被调用了四次,Receive 被调用了一次。

查看函数的功能
因只有 mainReceive 被调用,这里我们主要查看一下这两个函数的功能。

main 函数

这里的 main() 函数为入口调试器,用于选择函数。所以调用 main 函数时,先经历下面的代码,一个是函数头,一个是函数执行部分:

1、函数头部分

if (var0 == 0x2a0f7696) {

    // Dispatch table entry for 0x2a0f7696 (unknown)

    if (msg.value) { revert(memory[0x00:0x00]); }

    var var1 = 0x0081;

    var var2 = msg.data[0x04:0x24] & 0xffff;

    var1 = main(var2);

    var temp0 = memory[0x40:0x60];

    memory[temp0:temp0 + 0x20] = var1;

    var temp1 = memory[0x40:0x60];

    return memory[temp1:temp1 + (temp0 + 0x20) - temp1];

首先,这里 `if (msg.value) { revert(memory[0x00:0x00]); }` 表示不接受 `msg.value`,即 `solidity` 中的 `not payable`。

其次,由 `var var2 = msg.data[0x04:0x24] & 0xffff;` 可看出,这一个是输入参数部分,从 `0x04` 读取 32 个字节的数据,并 `& 0xffff` ,而没有 `/0x0100000000000000000000000000000000000000000000000000000000` ,说明这是一个占用存储位置为 32 个字节的槽,但参数内容长度为 2 个字节的参数。所以应该是一个 `byte2` 类型的变量。

(3)观察调度器中的几个 if 可以发现其它有些 if 最后是 `return`,有些是 `stop();`。这里的 `return` 说明这个函数是有返回值。

2、接下来看函数执行部分
function main(var arg0) returns (var r0) {

    var var0 = 0x00;

    if (arg0 & 0xffff != storage[0x01] & 0xffff) { return 0x00; }

    memory[0x00:0x20] = msg.sender;

    memory[0x20:0x40] = 0x02;

    return storage[keccak256(memory[0x00:0x40])];

}

(1)从 `if (arg0 & 0xffff != storage[0x01] & 0xffff) { return 0x00; }` 可以看出这里是条件判断,判断成功则返回 `0x00`,这里的条件为输入的变量与存储在 `storage[0x01]` 的值进行比较,如果不相等,则返回 `0x00`

(2)通过查看交易信息 `tx -> Tools -> Parity Trace -> Raw traces`  查看发现交易 1、2、3 都是返回 `0x00`。说明都在这个判断 `return 0x00` 了,而交易 5 的返回结果是 `0x333443335f6772616e646d615f626f756768745f736f6d655f626974636f696e` , 说明通过交易4 的 `Receive` 操作,再调用这个 `main` 函数能够通过这个判断,并执行下面语句

因此,可以尝试解一下这个返回值,应该就是答案。

用crypto工具包

 from Crypto.Util.number import *

 a = 0x333443335f6772616e646d615f626f756768745f736f6d655f626974636f696e

 print(long_to_bytes(a))

结局Flagb'34C3_grandma_bought_some_bitcoin'

  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2021-07-10 14:35:35  更:2021-07-10 14:36:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 11:18:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计