(第二弹)从字节码分析钓鱼的过程

上次的事情一直挂在心头。某个晚上,在写密码学作业的时候,突然想起,既然钓鱼者会设置PassHash,那么原生的pass, 也就是PassHash的原像会在某个交易中或者代碼中出现吧!能不能逆向分析代码或者交易hash,得到pass,然后自己计算keccak256的Hash,不就得到PassHash然後可以得到eth了吗?
说干就干![下面是字节码分析,太长不看的拉倒最后]

先附上钓鱼代码

contract GIFT_1_ETH
{
    bytes32 public hashPass;
    bool closed = false;
    address sender;
    uint unlockTime;
    
    function SetPass(bytes32 hash)
    public
    payable
    {
        if( (!closed&&(msg.value > 1 ether)) || hashPass==0x0 )
        {
            hashPass = hash;
            sender = msg.sender;
            unlockTime = now;
        }
    }
    function GetGift(bytes pass)
    external
    payable
    canOpen
    {
        if(hashPass == keccak256(pass))
        {
            msg.sender.transfer(this.balance);
        }
    }
    
    
    function PassHasBeenSet(bytes32 hash)
    public
    {
        if(hash==hashPass&&msg.sender==sender)
        {
           closed=true;
        }
    }
    
    modifier canOpen
    {
        require(now>unlockTime);
        _;
    }
    
    function() public payable{}
    
}

提要

上一篇说了,实施整个攻击一共有4个账户,分别是N_A(普通账户), N_B(普通账户),C_A(合约账户, 也是钓鱼代码的账户),C_B(合约账户).

重点
N_BC_B创建者.
N_B先于N_A通过C_B设置了C_A的PassHash,并设置Closed为true。

字节码分析

N_B(普通账户)在创建C_B后向C_B发送了一笔交易,TX_HASH是0x45e45a3de69a0e301eb8f9aeb0dd95311e66e5859b1675ecf0e1e2aa7754f6fe

让我们调试这次交易看看他到底做了什么

  • 首先我们来看看开头的字节码

0000 PUSH1 60
// stack: [0x60]
0002 PUSH1 40
// stack: [0x40 0x60]
0004 MSTORE
// 内存中从0x40開始的32个字节用于存储0x60
// stack: []

0005 PUSH1 04
// stack: [0x04]
0007 CALLDATASIZE
// stack: [0x44 0x04]
0008 LT
// lt(x, y) 1 如果x < y, 否则0
// 显然这个结果是0
// stack: [0x0]

0009 PUSH2 0078
// stack: [0x0078, 0x0]
0012 JUMPI
//  jumpi(x, y) 如果y为真,则跳到x,否则继续
// stack:[]

0013 PUSH1 00
// stack:[0x00]
0015 CALLDATALOAD
// 从msg.data的index 0开始,读取32个字节
// stack: [0x1562621f0000000000000000000000005dac036595568ff792f5064451b6b37e]

0016 PUSH29 0100000000000000000000000000000000000000000000000000000000
0046 SWAP1
0047 DIV
0048 PUSH4 ffffffff
0053 AND
// 上面4个指令后的stack状态
// stack: [0x1562621f]

0054 DUP1
//  复制第ith个item到栈顶,从栈顶开始计数
// stack: [0x1562621f, 0x1562621f]
0055 PUSH4 1562621f
// stack: [0x1562621f, 0x1562621f, 0x1562621f]
0060 EQ
// stack: [0x1, 0x1562621f]
0061 PUSH2 007a
// stack: [007a, 0x1, 0x1562621f]
0064 JUMPI
// 跳转到0x007a指令去

// summary:
// 大家其实也已经猜到了这里就是在**匹配**函数标志符
// 如果失败,则会失败revert
  • 让我们看看进入到函数之后发生了什么?
0122 JUMPDEST
0123 PUSH2 00b3
0126 PUSH1 04
0128 DUP1
0129 DUP1
// stack: [0x4,0x4, 0x4,0xb3,0x1562621f]
0130 CALLDATALOAD
// 从msgdata中index4的位置起,读取32个字节
//stack: [0x5dac036595568ff792f5064451b6b37e801ecab9,0x4, 0x4,0xb3,0x1562621f]
0131 PUSH20 ffffffffffffffffffffffffffffffffffffffff
0152 AND
// stack: [0x5dac036595568ff792f5064451b6b37e801ecab9,0x4, 0x4,0xb3,0x1562621f]


0153 SWAP1
0154 PUSH1 20
0156 ADD
0157 SWAP1
0158 SWAP2
0159 SWAP1
0160 DUP1
// stack: [0x24,0x24,0x4,0x5dac036595568ff792f5064451b6b37e801ecab9,0xb3,0x1562621f]
0161 CALLDATALOAD
// 从msgdata中index34的位置起,读取32个字节
// stack: [0x30a602cddf72988a065febf9b3257b03c23a17b75220a422685e0bc152db5241,0x24,0x4,0x5dac036595568ff792f5064451b6b37e801ecab9,0xb3,0x1562621f]

0162 PUSH1 00
0164 NOT
0165 AND
0166 SWAP1
0167 PUSH1 20
0169 ADD
0170 SWAP1
0171 SWAP2
0172 SWAP1
0173 POP
0174 POP
0175 PUSH2 01d6
0178 JUMP
// stack:[ 0x1d6, 0x30a602cddf72988a065febf9b3257b03c23a17b75220a422685e0bc152db5241,0x5dac036595568ff792f5064451b6b37e801ecab9,0xb3,0x1562621f]


// summary:
// EVM在为函数执行做了很多工作,比如基本的逻辑判断,msgdata的载入

  • C_B中肯定会调用c_A的函数,让我们直接找到有call的地方
******省略了无关紧要的字节码******
//此时stack: [0x5dac036595568ff792f5064451b6b37e801ecab9,0x0, 0x60, 0x24,0x60,0x0,0x84,0xa6fbb05,0x5dac036595568ff792f5064451b6b37e801ecab9,0x5dac036595568ff792f5064451b6b37e801ecab9,0x30a602cddf72988a065febf9b3257b03c23a17b75220a422685e0bc152db5241,0x5dac036595568ff792f5064451b6b37e801ecab9,0xb3, 0x1562621f]

0684 JUMPDEST
0685 PUSH2 02c6
0688 GAS
//得到当前可用的gas, 结果是0x2e0b8,与交易显示的GAS LIMIT相差无几

0689 SUB
0690 CALL

//此时跳入被调用者的运行环境中....

0691 ISZERO
0692 ISZERO
0693 PUSH2 02bd
0696 JUMPI
  • 经过上述处理,代码调用C_B的代码,已经进入了C_B的运行环境,让我们看看他做了什么
.....省略了一些字节码
.....
0015 CALLDATALOAD
0016 PUSH29 0100000000000000000000000000000000000000000000000000000000
0046 SWAP1
0047 DIV
0048 PUSH4 ffffffff
0053 AND
0054 DUP1
0055 PUSH4 0a6fbb05
0060 EQ
//stack: [0xa6fbb05, 0xa6fbb05,0xa6fbb05]
// 这段代码是匹配函数,大家都知道
// 显示也是成功匹配的
// 那么我们再看看,这个是那个函数的标识符??
// SetPass(bytes32 hash)!!!!
// 所以n_b确实是通过c_b设置pass!!
// 那么会出现pass吗?
  • 我们继续看..
0133 JUMPDEST
0134 PUSH2 009f
0137 PUSH1 04
0139 DUP1
0140 DUP1
0141 CALLDATALOAD
// 加载msg.data
// 此时stack:[0x30a602cddf72988a065febf9b3257b03c23a17b75220a422685e0bc152db5241,0x4,0x4,0x9f,0xa6fbb05]
// 

.......省略......
......
.................
0450 JUMPDEST
0451 PUSH1 01
0453 PUSH1 00
0455 SWAP1
0456 SLOAD
0457 SWAP1
0458 PUSH2 0100
0461 EXP
0462 SWAP1
0463 DIV
0464 PUSH1 ff
0466 AND
0467 ISZERO
0468 DUP1
0469 ISZERO
0470 PUSH2 01e6
0473 JUMPI
///summary:
/// 执行!closed表达式



0475 PUSH8 0de0b6b3a7640000
0484 CALLVALUE
0485 GT
0486 JUMPDEST
// summary:
//
// 执行msg.value > 1 ether表达式


.........省略
..............
0516 PUSH1 00
0518 NOT
0519 AND
0520 SWAP1
0521 SSTORE
// 上述几个指令即其前面的指令
// 将storage第0个位置存入callvalue
//即0x30a602cddf72988a065febf9b3257b03c23a17b75220a422685e0bc152db5241
// 而第0个位置的值就是PassHash
// 所以钓鱼者没有将Hash原像出现在交易中,而是**直接**设置了hash


0523 CALLER
.........省略.....
0585 SSTORE
0586 POP
// 设置sender

0587 TIMESTAMP
0588 PUSH1 02
0590 DUP2
0591 SWAP1
0592 SSTORE
0593 POP
//// 设置unlockTime
  • 如果到现在为止,都只是在设置passHash,那么设置closed是在哪儿呢??? 字节码还没有执行完呢,继续看.....
// 调回原来的运行环境
// 检查返回值
0691 ISZERO
0692 ISZERO
0693 PUSH2 02bd
0696 JUMPI

.........省略
...............................

/// 又发现一个call调用
0822 JUMPDEST
0823 PUSH2 02c6
0826 GAS
0827 SUB
0828 CALL
//stack: [0x1e959, 0x5dac036595568ff792f5064451b6b37e801ecab9, .........]
// 第一个是gas的可用量,第二个是被调用者的地址,即C_A
/// 跳入被调者的运行环境。。。。。
.........
0829 ISZERO
0830 ISZERO
0831 PUSH2 0347
0834 JUMPI

  • 现在这是调用哪个函数呢?
.....省略
..........
// stack: [0x31fd725a]
0076 DUP1
0077 PUSH4 31fd725a
0082 EQ
0083 PUSH2 00c4
0086 JUMPI
//  匹配函数0x31fd725a, 是谁???
//   Keccak-256("PassHasBeenSet(bytes32)")[0:4] == 0x31fd725a!!!!
// 

........接下来的时候就是一些判断
.......然后设置closed为true

结论

  • N_B从没有让passHash的原像出现在区块链上,除非你跟钓鱼黑客心心相印,知道Hash的原像是什么,否则是很难拿走所谓的gift.
  • 调试0x6290f0dfb9673f56a3da48884414e3c99a59021d99fc5c4a866b89180b4a64e1这个Tx,也就是N_B是怎么转走C_A的eth的交易,我们可以知道,N_B是通过C_B,调用C_A的Revoce()来转走eth的,而不是GetGift,没有出现bytes参数。

最后要打赏的客官这边: 0x003be5df5fef651ef0c59cd175c73ca1415f53ea

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容

  • 以太坊(Ethereum ):下一代智能合约和去中心化应用平台 翻译:巨蟹 、少平 译者注:中文读者可以到以太坊爱...
    车圣阅读 3,684评论 1 7
  • 【中文版】以太坊白皮书 翻译:少平、 Seven当中本聪在 2009 年 1 月启动比特币区块链时,他同时向世界引...
    __Seven__阅读 4,049评论 0 10
  • 不过才早上四点,这个院子里就已经香火缭绕。 他揉揉眼,发现自己盘坐在一个蒲团上,周围是嗡嗡诵经的声音。在这一瞬间,...
    smarthmily阅读 186评论 3 1
  • 今天星期六,十一点钟昏昏沉沉从床上爬起来。昨天同事周末聚会,开始说好8头,结果只来了4只,不过也在预料中,小江,大...
    烂梗王阅读 377评论 0 0
  • 子曰:“中人以上,可以语上也;中人以下,不可以语上也。” 孔子讲:“资质中等以上的,可以和他说高深的道理;资质中等...
    哈皮波阅读 649评论 0 0