@@ -7,7 +7,12 @@ ethereum evm bytecode disassembler with static- and dynamic-analysis and functio
7
7
8
8
** disassembles evm bytecode**
9
9
10
- [ ![ asciicast] ( https://asciinema.org/a/fbWad5tV9YmpCGB97wbI1al9w.png )] ( https://asciinema.org/a/fbWad5tV9YmpCGB97wbI1al9w )
10
+ [ ![ asciicast] ( https://asciinema.org/a/256036.png )] ( https://asciinema.org/a/256036 )
11
+
12
+ ** decompile a contract to pseudocode**
13
+
14
+ [ ![ asciicast] ( https://asciinema.org/a/0xJvR55Zr7svqibS0oLHA2vY5.png )] ( https://asciinema.org/a/0xJvR55Zr7svqibS0oLHA2vY5 )
15
+
11
16
12
17
## install
13
18
@@ -18,19 +23,18 @@ ethereum evm bytecode disassembler with static- and dynamic-analysis and functio
18
23
```
19
24
20
25
```
21
- #> python3 -m ethereum_dasm -a 0x44919b8026f38d70437a8eb3be47b06ab1c3e4bf # verify installation
26
+ #> python3 -m ethereum_dasm -a 0x44919b8026f38d70437a8eb3be47b06ab1c3e4bf # jusst to verify installation
22
27
```
23
28
24
29
## usage
25
30
26
31
```
27
- #> evmdasm.py --help
28
- Usage: evmdasm.py [options]
29
-
30
- example: evmdasm.py [-L -F -v] <file_or_bytecode>
31
- evmdasm.py [-L -F -v] # read from stdin
32
- evmdasm.py [-L -F -a <address>] # fetch contract code from infura.io
32
+ Usage: ethereum_dasm.py [options]
33
33
34
+ example: ethereum_dasm.py [-L -F -v] <file_or_bytecode>
35
+ ethereum_dasm.py [-L -F -v] # read from stdin
36
+ ethereum_dasm.py [-L -F -a <address>] # fetch contract code from infura.io
37
+
34
38
35
39
Options:
36
40
-h, --help show this help message and exit
@@ -49,16 +53,29 @@ Options:
49
53
disable dynamic analysis / symolic execution
50
54
-S, --no-static-analysis
51
55
disable static analysis
56
+ -s, --simplify simplify disassembly to human readable code
57
+ -x, --simplify-show-asm
58
+ simplify: show or hide asm annotations in simplified
59
+ code
60
+ -y, --simplify-show-unreachable
61
+ simplify: show or hide annotations for unreachable
62
+ instructions in simplified code
63
+ -n NETWORK, --network=NETWORK
64
+ network for address lookup (default: mainnet, ropsten,
65
+ rinkeby, kovan
52
66
```
53
67
54
- #> echo "0x12345678" | python3 evmdasm.py
55
- #> python3 evmdasm.py 0x12345678
56
- #> python3 evmdasm.py ether_contract.evm
57
- #> python3 evmdasm.py -a <contract address>
68
+ #> echo "0x12345678" | python3 -m ethereum_dasm
69
+ #> python3 -m ethereum_dasm 0x12345678
70
+ #> python3 -m ethereum_dasm ether_contract.evm
71
+ #> python3 -m ethereum_dasm -a <contract address>
58
72
#> python3 -m ethereum_dasm -a <contract address> -A
73
+ #> python3 -m ethereum_dasm -a <contract address> --simplify [--simplify-show-asm, --simplify-show-unreachable]
59
74
60
75
## features
61
76
77
+ * disassemble evm bytecode
78
+ * decompile evm bytecode to pseudocode
62
79
* provide the path to the ethereum vm bytecode or the bytecode as an argument to evmdasm. Tries to read from stdin by default.
63
80
* returns !=0 on errors
64
81
* various output modes (` -L ` to switch from table to listing mode)
@@ -344,3 +361,256 @@ reconstructed ABI:
344
361
[{' name' : ' enter' , ' stateMutability' : ' nonpayable' , ' signature' : ' 0x124c32a1' , ' payable' : False , ' inputs' : [{' name' : ' _passcode' , ' type' : ' bytes32' }, {' name' : ' _gateKey' , ' type' : ' bytes8' }], ' constant' : False , ' type' : ' function' , ' outputs' : [{' name' : ' ' , ' type' : ' bool' }]}, {' name' : ' maxEntrants' , ' stateMutability' : ' pure' , ' signature' : ' 0x60643652' , ' payable' : False , ' inputs' : [], ' constant' : True , ' type' : ' function' , ' outputs' : [{' name' : ' ' , ' type' : ' uint8' }]}, {' name' : ' totalEntrants' , ' stateMutability' : ' view' , ' signature' : ' 0x694463a2' , ' payable' : False , ' inputs' : [], ' constant' : True , ' type' : ' function' , ' outputs' : [{' name' : ' ' , ' type' : ' uint8' }]}, {' name' : ' assignAll' , ' stateMutability' : ' nonpayable' , ' signature' : ' 0x90ae631d' , ' payable' : False , ' inputs' : [], ' constant' : False , ' type' : ' function' , ' outputs' : [{' name' : ' ' , ' type' : ' bool' }]}, {' stateMutability' : ' nonpayable' , ' type' : ' constructor' , ' payable' : False , ' inputs' : []}]
345
362
346
363
```
364
+
365
+
366
+ ** decompile to pseudocode**
367
+
368
+ ```
369
+ python3 - m ethereum_dasm - a 0x 44919b8026f38d70437a8eb3be47b06ab1c3e4bf -- simplify # [--simplify-show-asm, --simplify-show-unreachable]
370
+
371
+ ====================== [simplified]
372
+
373
+ :init
374
+ memory[0x 40 ] = 0x 60
375
+ if (Not(ULE(0x 4 , 1_calldatasize ))) goto LOC_0x48
376
+ if (And(If(1_calldatasize <= 0x 3 , 0x 0 , 1_calldata [0x 3 ]) == 0x a1 ,
377
+ If(1_calldatasize <= 0x 2 , 0x 0 , 1_calldata [0x 2 ]) == 0x 32 ,
378
+ If(1_calldatasize <= 0x 1 , 0x 0 , 1_calldata [0x 1 ]) == 0x 4c ,
379
+ If(1_calldatasize <= 0x 0 , 0x 0 , 1_calldata [0x 0 ]) == 0x 12 )) goto function_enter (LOC_0x4d )
380
+ if (And(If(1_calldatasize <= 0x 3 , 0x 0 , 1_calldata [0x 3 ]) == 0x 52 ,
381
+ If(1_calldatasize <= 0x 2 , 0x 0 , 1_calldata [0x 2 ]) == 0x 36 ,
382
+ If(1_calldatasize <= 0x 1 , 0x 0 , 1_calldata [0x 1 ]) == 0x 64 ,
383
+ If(1_calldatasize <= 0x 0 , 0x 0 , 1_calldata [0x 0 ]) == 0x 60 )) goto function_maxEntrants (LOC_0x95 )
384
+ if (And(If(1_calldatasize <= 0x 3 , 0x 0 , 1_calldata [0x 3 ]) == 0x a2 ,
385
+ If(1_calldatasize <= 0x 2 , 0x 0 , 1_calldata [0x 2 ]) == 0x 63 ,
386
+ If(1_calldatasize <= 0x 1 , 0x 0 , 1_calldata [0x 1 ]) == 0x 44 ,
387
+ If(1_calldatasize <= 0x 0 , 0x 0 , 1_calldata [0x 0 ]) == 0x 69 )) goto function_totalEntrants (LOC_0xbe )
388
+ if (And(If(1_calldatasize <= 0x 3 , 0x 0 , 1_calldata [0x 3 ]) == 0x 1d ,
389
+ If(1_calldatasize <= 0x 2 , 0x 0 , 1_calldata [0x 2 ]) == 0x 63 ,
390
+ If(1_calldatasize <= 0x 1 , 0x 0 , 1_calldata [0x 1 ]) == 0x ae ,
391
+ If(1_calldatasize <= 0x 0 , 0x 0 , 1_calldata [0x 0 ]) == 0x 90 )) goto function_assignAll (LOC_0xd1 )
392
+
393
+ :LOC_0x48
394
+ REVERT(offset = 0x 0 , size = 0x 0 )
395
+ /******* << terminates execution>> *******/
396
+
397
+ :function_enter (LOC_0x4d )
398
+ /*******************************************************************
399
+ function enter(bytes32,bytes8)
400
+ payable: False
401
+ inputs: (2 ) [' bytes32' , ' <bytes??>' ]
402
+ potential signatures: [' enter(bytes32,bytes8)' ]
403
+ *******************************************************************/
404
+
405
+ if (call_value1 == 0x 0 ) goto LOC_0x58
406
+ REVERT(offset = 0x 0 , size = 0x 0 )
407
+ /******* << terminates execution>> *******/
408
+
409
+ :LOC_0x58
410
+ goto LOC_0xe4
411
+
412
+ :LOC_0x81
413
+
414
+ :function_maxEntrants (LOC_0x95 )
415
+ /*******************************************************************
416
+ function maxEntrants()
417
+ payable: False
418
+ inputs: (0 ) []
419
+ potential signatures: [' maxEntrants()' ]
420
+ *******************************************************************/
421
+
422
+ if (call_value1 == 0x 0 ) goto LOC_0xa0
423
+ REVERT(offset = 0x 0 , size = 0x 0 )
424
+ /******* << terminates execution>> *******/
425
+
426
+ :LOC_0xa0
427
+ goto LOC_0x314
428
+
429
+ :LOC_0xa8
430
+ memory[0x 60 ] = 0x fa
431
+ RETURN(offset = 0x 60 , size = 0x 20 )
432
+ /******* << terminates execution>> *******/
433
+
434
+ :function_totalEntrants (LOC_0xbe )
435
+ /*******************************************************************
436
+ function totalEntrants()
437
+ payable: False
438
+ inputs: (0 ) []
439
+ potential signatures: [' totalEntrants()' ]
440
+ *******************************************************************/
441
+
442
+ if (call_value1 == 0x 0 ) goto LOC_0xc9
443
+ REVERT(offset = 0x 0 , size = 0x 0 )
444
+ /******* << terminates execution>> *******/
445
+
446
+ :LOC_0xc9
447
+ goto LOC_0x31a
448
+
449
+ :function_assignAll (LOC_0xd1 )
450
+ /*******************************************************************
451
+ function assignAll()
452
+ payable: False
453
+ inputs: (0 ) []
454
+ potential signatures: [' assignAll()' ]
455
+ *******************************************************************/
456
+
457
+ if (call_value1 == 0x 0 ) goto LOC_0xdc
458
+ REVERT(offset = 0x 0 , size = 0x 0 )
459
+ /******* << terminates execution>> *******/
460
+
461
+ :LOC_0xdc
462
+ goto LOC_0x320
463
+
464
+ :LOC_0xe4
465
+ if (Not(Extract(159 , 0 , origin1) ==
466
+ 0x deadbeefdeadbeefdeadbeefdeadbeefdeadbeef )) goto LOC_0x107
467
+ REVERT(offset = 0x 0 , size = 0x 0 )
468
+ /******* << terminates execution>> *******/
469
+
470
+ :LOC_0x107
471
+ if (True ) goto LOC_0x114
472
+
473
+ :LOC_0x114
474
+ if (bvurem_i(1_gas , 0x 1fff ) == 0x 0 ) goto LOC_0x11f
475
+ REVERT(offset = 0x 0 , size = 0x 0 )
476
+ /******* << terminates execution>> *******/
477
+
478
+ :LOC_0x11f
479
+ if (And(If(1_calldatasize <= 0x 29 , 0x 0 , 1_calldata [0x 29 ]) == 0x 0 ,
480
+ If(1_calldatasize <= 0x 28 , 0x 0 , 1_calldata [0x 28 ]) == 0x 0 )) goto LOC_0x154
481
+ REVERT(offset = 0x 0 , size = 0x 0 )
482
+ /******* << terminates execution>> *******/
483
+
484
+ :LOC_0x154
485
+ if (Not(And(If(1_calldatasize <= 0x 27 , 0x 0 , 1_calldata [0x 27 ]) ==
486
+ 0x 0 ,
487
+ If(1_calldatasize <= 0x 26 , 0x 0 , 1_calldata [0x 26 ]) ==
488
+ 0x 0 ,
489
+ If(1_calldatasize <= 0x 25 , 0x 0 , 1_calldata [0x 25 ]) ==
490
+ 0x 0 ,
491
+ If(1_calldatasize <= 0x 24 , 0x 0 , 1_calldata [0x 24 ]) ==
492
+ 0x 0 ))) goto LOC_0x18f
493
+ REVERT(offset = 0x 0 , size = 0x 0 )
494
+ /******* << terminates execution>> *******/
495
+
496
+ :LOC_0x18f
497
+ if (And(Extract(7 , 0 , origin1) ==
498
+ If(1_calldatasize <= 0x 2b , 0x 0 , 1_calldata [0x 2b ]),
499
+ Extract(15 , 8 , origin1) ==
500
+ If(1_calldatasize <= 0x 2a , 0x 0 , 1_calldata [0x 2a ]),
501
+ If(1_calldatasize <= 0x 29 , 0x 0 , 1_calldata [0x 29 ]) == 0x 0 ,
502
+ If(1_calldatasize <= 0x 28 , 0x 0 , 1_calldata [0x 28 ]) == 0x 0 )) goto LOC_0x1c0
503
+ REVERT(offset = 0x 0 , size = 0x 0 )
504
+ /******* << terminates execution>> *******/
505
+
506
+ :LOC_0x1c0
507
+ if (True ) goto LOC_0x1d1
508
+
509
+ :LOC_0x1d1
510
+ memory[0x 0 ] = 0x deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
511
+ memory[0x 20 ] = 0x 3
512
+ if (True ) goto LOC_0x1f7
513
+
514
+ :LOC_0x1f7
515
+ memory[0x 0 ] = Concat(0x 0 , Extract(159 , 0 , origin1))
516
+ memory[0x 20 ] = 0x 3
517
+ if (True ) goto LOC_0x21d
518
+
519
+ :LOC_0x21d
520
+ memory[0x 60 ] = Concat(If(1_calldatasize <= 0x 4 , 0x 0 , 1_calldata [0x 4 ]),
521
+ If(1_calldatasize <= 0x 5 , 0x 0 , 1_calldata [0x 5 ]),
522
+ If(1_calldatasize <= 0x 6 , 0x 0 , 1_calldata [0x 6 ]),
523
+ If(1_calldatasize <= 0x 7 , 0x 0 , 1_calldata [0x 7 ]),
524
+ If(1_calldatasize <= 0x 8 , 0x 0 , 1_calldata [0x 8 ]),
525
+ If(1_calldatasize <= 0x 9 , 0x 0 , 1_calldata [0x 9 ]),
526
+ If(1_calldatasize <= 0x a , 0x 0 , 1_calldata [0x a ]),
527
+ If(1_calldatasize <= 0x b , 0x 0 , 1_calldata [0x b ]),
528
+ If(1_calldatasize <= 0x c , 0x 0 , 1_calldata [0x c ]),
529
+ If(1_calldatasize <= 0x d , 0x 0 , 1_calldata [0x d ]),
530
+ If(1_calldatasize <= 0x e , 0x 0 , 1_calldata [0x e ]),
531
+ If(1_calldatasize <= 0x f , 0x 0 , 1_calldata [0x f ]),
532
+ If(1_calldatasize <= 0x 10 , 0x 0 , 1_calldata [0x 10 ]),
533
+ If(1_calldatasize <= 0x 11 , 0x 0 , 1_calldata [0x 11 ]),
534
+ If(1_calldatasize <= 0x 12 , 0x 0 , 1_calldata [0x 12 ]),
535
+ If(1_calldatasize <= 0x 13 , 0x 0 , 1_calldata [0x 13 ]),
536
+ If(1_calldatasize <= 0x 14 , 0x 0 , 1_calldata [0x 14 ]),
537
+ If(1_calldatasize <= 0x 15 , 0x 0 , 1_calldata [0x 15 ]),
538
+ If(1_calldatasize <= 0x 16 , 0x 0 , 1_calldata [0x 16 ]),
539
+ If(1_calldatasize <= 0x 17 , 0x 0 , 1_calldata [0x 17 ]),
540
+ If(1_calldatasize <= 0x 18 , 0x 0 , 1_calldata [0x 18 ]),
541
+ If(1_calldatasize <= 0x 19 , 0x 0 , 1_calldata [0x 19 ]),
542
+ If(1_calldatasize <= 0x 1a , 0x 0 , 1_calldata [0x 1a ]),
543
+ If(1_calldatasize <= 0x 1b , 0x 0 , 1_calldata [0x 1b ]),
544
+ If(1_calldatasize <= 0x 1c , 0x 0 , 1_calldata [0x 1c ]),
545
+ If(1_calldatasize <= 0x 1d , 0x 0 , 1_calldata [0x 1d ]),
546
+ If(1_calldatasize <= 0x 1e , 0x 0 , 1_calldata [0x 1e ]),
547
+ If(1_calldatasize <= 0x 1f , 0x 0 , 1_calldata [0x 1f ]),
548
+ If(1_calldatasize <= 0x 20 , 0x 0 , 1_calldata [0x 20 ]),
549
+ If(1_calldatasize <= 0x 21 , 0x 0 , 1_calldata [0x 21 ]),
550
+ If(1_calldatasize <= 0x 22 , 0x 0 , 1_calldata [0x 22 ]),
551
+ If(1_calldatasize <= 0x 23 , 0x 0 , 1_calldata [0x 23 ]))
552
+ memory[0x 0 ] = KECCAC [If(1_calldatasize_ <= _0x4,_0x0,_1_calldata[0x 4 ])]
553
+ memory[0x 20 ] = 0x 4
554
+ if (False ) goto LOC_0x257
555
+ REVERT(offset = 0x 0 , size = 0x 0 )
556
+ /******* << terminates execution>> *******/
557
+
558
+ :LOC_0x257
559
+
560
+ :LOC_0x275
561
+
562
+ :LOC_0x2d6
563
+
564
+ :LOC_0x314
565
+
566
+ :LOC_0x317
567
+ goto LOC_0xa8
568
+
569
+ :LOC_0x31a
570
+ goto LOC_0xa8
571
+
572
+ :LOC_0x320
573
+ if (False ) goto LOC_0x338
574
+ REVERT(offset = 0x 0 , size = 0x 0 )
575
+ /******* << terminates execution>> *******/
576
+
577
+ :LOC_0x338
578
+
579
+ :LOC_0x347
580
+
581
+ :LOC_0x3a8
582
+
583
+ :LOC_0x3b9
584
+
585
+ :LOC_0x3d8
586
+
587
+ :LOC_0x3e0
588
+
589
+ :LOC_0x3f5
590
+
591
+ :LOC_0x459
592
+
593
+ :LOC_0x46a
594
+
595
+ :LOC_0x4de
596
+
597
+ :LOC_0x541
598
+
599
+ :LOC_0x552
600
+
601
+ :LOC_0x556
602
+
603
+ :LOC_0x55e
604
+
605
+ :LOC_0x588
606
+
607
+ :LOC_0x592
608
+
609
+ :LOC_0x5b6
610
+
611
+ :LOC_0x5bb
612
+
613
+ :LOC_0x5c1
614
+
615
+ :LOC_0x5d5
616
+ ```
0 commit comments