Skip to content

Commit 579d2d8

Browse files
committed
prepare 0.1.5
update readme asciinema
1 parent 5aa8818 commit 579d2d8

File tree

2 files changed

+284
-14
lines changed

2 files changed

+284
-14
lines changed

README.md

+282-12
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ ethereum evm bytecode disassembler with static- and dynamic-analysis and functio
77

88
**disassembles evm bytecode**
99

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+
1116

1217
## install
1318

@@ -18,19 +23,18 @@ ethereum evm bytecode disassembler with static- and dynamic-analysis and functio
1823
```
1924

2025
```
21-
#> python3 -m ethereum_dasm -a 0x44919b8026f38d70437a8eb3be47b06ab1c3e4bf # verify installation
26+
#> python3 -m ethereum_dasm -a 0x44919b8026f38d70437a8eb3be47b06ab1c3e4bf # jusst to verify installation
2227
```
2328

2429
## usage
2530

2631
```
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]
3333
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+
3438
3539
Options:
3640
-h, --help show this help message and exit
@@ -49,16 +53,29 @@ Options:
4953
disable dynamic analysis / symolic execution
5054
-S, --no-static-analysis
5155
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
5266
```
5367

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>
5872
#> python3 -m ethereum_dasm -a <contract address> -A
73+
#> python3 -m ethereum_dasm -a <contract address> --simplify [--simplify-show-asm, --simplify-show-unreachable]
5974

6075
## features
6176

77+
* disassemble evm bytecode
78+
* decompile evm bytecode to pseudocode
6279
* provide the path to the ethereum vm bytecode or the bytecode as an argument to evmdasm. Tries to read from stdin by default.
6380
* returns !=0 on errors
6481
* various output modes (`-L` to switch from table to listing mode)
@@ -344,3 +361,256 @@ reconstructed ABI:
344361
[{'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': []}]
345362

346363
```
364+
365+
366+
**decompile to pseudocode**
367+
368+
```
369+
python3 -m ethereum_dasm -a 0x44919b8026f38d70437a8eb3be47b06ab1c3e4bf --simplify #[--simplify-show-asm, --simplify-show-unreachable]
370+
371+
======================[simplified]
372+
373+
:init
374+
memory[0x40] = 0x60
375+
if (Not(ULE(0x4, 1_calldatasize))) goto LOC_0x48
376+
if (And(If(1_calldatasize <= 0x3, 0x0, 1_calldata[0x3]) == 0xa1,
377+
If(1_calldatasize <= 0x2, 0x0, 1_calldata[0x2]) == 0x32,
378+
If(1_calldatasize <= 0x1, 0x0, 1_calldata[0x1]) == 0x4c,
379+
If(1_calldatasize <= 0x0, 0x0, 1_calldata[0x0]) == 0x12)) goto function_enter (LOC_0x4d)
380+
if (And(If(1_calldatasize <= 0x3, 0x0, 1_calldata[0x3]) == 0x52,
381+
If(1_calldatasize <= 0x2, 0x0, 1_calldata[0x2]) == 0x36,
382+
If(1_calldatasize <= 0x1, 0x0, 1_calldata[0x1]) == 0x64,
383+
If(1_calldatasize <= 0x0, 0x0, 1_calldata[0x0]) == 0x60)) goto function_maxEntrants (LOC_0x95)
384+
if (And(If(1_calldatasize <= 0x3, 0x0, 1_calldata[0x3]) == 0xa2,
385+
If(1_calldatasize <= 0x2, 0x0, 1_calldata[0x2]) == 0x63,
386+
If(1_calldatasize <= 0x1, 0x0, 1_calldata[0x1]) == 0x44,
387+
If(1_calldatasize <= 0x0, 0x0, 1_calldata[0x0]) == 0x69)) goto function_totalEntrants (LOC_0xbe)
388+
if (And(If(1_calldatasize <= 0x3, 0x0, 1_calldata[0x3]) == 0x1d,
389+
If(1_calldatasize <= 0x2, 0x0, 1_calldata[0x2]) == 0x63,
390+
If(1_calldatasize <= 0x1, 0x0, 1_calldata[0x1]) == 0xae,
391+
If(1_calldatasize <= 0x0, 0x0, 1_calldata[0x0]) == 0x90)) goto function_assignAll (LOC_0xd1)
392+
393+
:LOC_0x48
394+
REVERT(offset=0x0, size=0x0)
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 == 0x0) goto LOC_0x58
406+
REVERT(offset=0x0, size=0x0)
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 == 0x0) goto LOC_0xa0
423+
REVERT(offset=0x0, size=0x0)
424+
/******* <<terminates execution>> *******/
425+
426+
:LOC_0xa0
427+
goto LOC_0x314
428+
429+
:LOC_0xa8
430+
memory[0x60] = 0xfa
431+
RETURN(offset=0x60, size=0x20)
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 == 0x0) goto LOC_0xc9
443+
REVERT(offset=0x0, size=0x0)
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 == 0x0) goto LOC_0xdc
458+
REVERT(offset=0x0, size=0x0)
459+
/******* <<terminates execution>> *******/
460+
461+
:LOC_0xdc
462+
goto LOC_0x320
463+
464+
:LOC_0xe4
465+
if (Not(Extract(159, 0, origin1) ==
466+
0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef)) goto LOC_0x107
467+
REVERT(offset=0x0, size=0x0)
468+
/******* <<terminates execution>> *******/
469+
470+
:LOC_0x107
471+
if (True) goto LOC_0x114
472+
473+
:LOC_0x114
474+
if (bvurem_i(1_gas, 0x1fff) == 0x0) goto LOC_0x11f
475+
REVERT(offset=0x0, size=0x0)
476+
/******* <<terminates execution>> *******/
477+
478+
:LOC_0x11f
479+
if (And(If(1_calldatasize <= 0x29, 0x0, 1_calldata[0x29]) == 0x0,
480+
If(1_calldatasize <= 0x28, 0x0, 1_calldata[0x28]) == 0x0)) goto LOC_0x154
481+
REVERT(offset=0x0, size=0x0)
482+
/******* <<terminates execution>> *******/
483+
484+
:LOC_0x154
485+
if (Not(And(If(1_calldatasize <= 0x27, 0x0, 1_calldata[0x27]) ==
486+
0x0,
487+
If(1_calldatasize <= 0x26, 0x0, 1_calldata[0x26]) ==
488+
0x0,
489+
If(1_calldatasize <= 0x25, 0x0, 1_calldata[0x25]) ==
490+
0x0,
491+
If(1_calldatasize <= 0x24, 0x0, 1_calldata[0x24]) ==
492+
0x0))) goto LOC_0x18f
493+
REVERT(offset=0x0, size=0x0)
494+
/******* <<terminates execution>> *******/
495+
496+
:LOC_0x18f
497+
if (And(Extract(7, 0, origin1) ==
498+
If(1_calldatasize <= 0x2b, 0x0, 1_calldata[0x2b]),
499+
Extract(15, 8, origin1) ==
500+
If(1_calldatasize <= 0x2a, 0x0, 1_calldata[0x2a]),
501+
If(1_calldatasize <= 0x29, 0x0, 1_calldata[0x29]) == 0x0,
502+
If(1_calldatasize <= 0x28, 0x0, 1_calldata[0x28]) == 0x0)) goto LOC_0x1c0
503+
REVERT(offset=0x0, size=0x0)
504+
/******* <<terminates execution>> *******/
505+
506+
:LOC_0x1c0
507+
if (True) goto LOC_0x1d1
508+
509+
:LOC_0x1d1
510+
memory[0x0] = 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
511+
memory[0x20] = 0x3
512+
if (True) goto LOC_0x1f7
513+
514+
:LOC_0x1f7
515+
memory[0x0] = Concat(0x0, Extract(159, 0, origin1))
516+
memory[0x20] = 0x3
517+
if (True) goto LOC_0x21d
518+
519+
:LOC_0x21d
520+
memory[0x60] = Concat(If(1_calldatasize <= 0x4, 0x0, 1_calldata[0x4]),
521+
If(1_calldatasize <= 0x5, 0x0, 1_calldata[0x5]),
522+
If(1_calldatasize <= 0x6, 0x0, 1_calldata[0x6]),
523+
If(1_calldatasize <= 0x7, 0x0, 1_calldata[0x7]),
524+
If(1_calldatasize <= 0x8, 0x0, 1_calldata[0x8]),
525+
If(1_calldatasize <= 0x9, 0x0, 1_calldata[0x9]),
526+
If(1_calldatasize <= 0xa, 0x0, 1_calldata[0xa]),
527+
If(1_calldatasize <= 0xb, 0x0, 1_calldata[0xb]),
528+
If(1_calldatasize <= 0xc, 0x0, 1_calldata[0xc]),
529+
If(1_calldatasize <= 0xd, 0x0, 1_calldata[0xd]),
530+
If(1_calldatasize <= 0xe, 0x0, 1_calldata[0xe]),
531+
If(1_calldatasize <= 0xf, 0x0, 1_calldata[0xf]),
532+
If(1_calldatasize <= 0x10, 0x0, 1_calldata[0x10]),
533+
If(1_calldatasize <= 0x11, 0x0, 1_calldata[0x11]),
534+
If(1_calldatasize <= 0x12, 0x0, 1_calldata[0x12]),
535+
If(1_calldatasize <= 0x13, 0x0, 1_calldata[0x13]),
536+
If(1_calldatasize <= 0x14, 0x0, 1_calldata[0x14]),
537+
If(1_calldatasize <= 0x15, 0x0, 1_calldata[0x15]),
538+
If(1_calldatasize <= 0x16, 0x0, 1_calldata[0x16]),
539+
If(1_calldatasize <= 0x17, 0x0, 1_calldata[0x17]),
540+
If(1_calldatasize <= 0x18, 0x0, 1_calldata[0x18]),
541+
If(1_calldatasize <= 0x19, 0x0, 1_calldata[0x19]),
542+
If(1_calldatasize <= 0x1a, 0x0, 1_calldata[0x1a]),
543+
If(1_calldatasize <= 0x1b, 0x0, 1_calldata[0x1b]),
544+
If(1_calldatasize <= 0x1c, 0x0, 1_calldata[0x1c]),
545+
If(1_calldatasize <= 0x1d, 0x0, 1_calldata[0x1d]),
546+
If(1_calldatasize <= 0x1e, 0x0, 1_calldata[0x1e]),
547+
If(1_calldatasize <= 0x1f, 0x0, 1_calldata[0x1f]),
548+
If(1_calldatasize <= 0x20, 0x0, 1_calldata[0x20]),
549+
If(1_calldatasize <= 0x21, 0x0, 1_calldata[0x21]),
550+
If(1_calldatasize <= 0x22, 0x0, 1_calldata[0x22]),
551+
If(1_calldatasize <= 0x23, 0x0, 1_calldata[0x23]))
552+
memory[0x0] = KECCAC[If(1_calldatasize_<=_0x4,_0x0,_1_calldata[0x4])]
553+
memory[0x20] = 0x4
554+
if (False) goto LOC_0x257
555+
REVERT(offset=0x0, size=0x0)
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=0x0, size=0x0)
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+
```

setup.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
def read(fname):
88
return open(os.path.join(os.path.dirname(__file__), fname)).read()
99

10-
version="0.1.4"
10+
version="0.1.5"
1111

1212
setup(
1313
name="ethereum-dasm",
@@ -18,7 +18,7 @@ def read(fname):
1818
description=(
1919
"An ethereum bytecode disassembler with static and dynamic analysis features"),
2020
license="GPLv2",
21-
keywords=["ethereum", "blockchain", "evm", "disassembler"],
21+
keywords=["ethereum", "blockchain", "evm", "disassembler", "decompiler", "pseudocode"],
2222
url="https://github.com/tintinweb/ethereum-dasm",
2323
download_url="https://github.com/tintinweb/ethereum-dasm/tarball/v%s"%version,
2424
#python setup.py register -r https://testpypi.python.org/pypi

0 commit comments

Comments
 (0)