mirror of https://github.com/ConsenSys/mythril
commit
9b5ae7acb7
@ -0,0 +1,78 @@ |
|||||||
|
# -*- coding: utf8 -*- |
||||||
|
import copy |
||||||
|
import hashlib |
||||||
|
import coincurve |
||||||
|
|
||||||
|
from py_ecc.secp256k1 import N as secp256k1n |
||||||
|
|
||||||
|
from mythril.laser.ethereum.helper import ALL_BYTES, bytearray_to_int, concrete_int_to_bytes, sha3, zpad |
||||||
|
|
||||||
|
|
||||||
|
def int_to_32bytes(i): #used because int can't fit as bytes function's input |
||||||
|
o = [0] * 32 |
||||||
|
for x in range(32): |
||||||
|
o[31 - x] = i & 0xff |
||||||
|
i >>= 8 |
||||||
|
return bytes(o) |
||||||
|
|
||||||
|
|
||||||
|
def ecrecover_to_pub(rawhash, v, r, s): |
||||||
|
try: |
||||||
|
pk = coincurve.PublicKey.from_signature_and_message( |
||||||
|
zpad(concrete_int_to_bytes(r), 32) + zpad(concrete_int_to_bytes(s), 32) + |
||||||
|
ALL_BYTES[v - 27], |
||||||
|
rawhash, |
||||||
|
hasher=None, |
||||||
|
) |
||||||
|
pub = pk.format(compressed=False)[1:] |
||||||
|
except BaseException: |
||||||
|
pub = b"\x00" * 64 |
||||||
|
|
||||||
|
return pub |
||||||
|
|
||||||
|
|
||||||
|
def extract32(data, i): |
||||||
|
if i >= len(data): |
||||||
|
return 0 |
||||||
|
o = data[i: min(i + 32, len(data))] |
||||||
|
o.extend(bytearray(32 - len(o))) |
||||||
|
return bytearray_to_int(o) |
||||||
|
|
||||||
|
|
||||||
|
def ecrecover(data): |
||||||
|
data = bytearray(data) |
||||||
|
message = b''.join(map(lambda x: ALL_BYTES[x], data[0:32])) |
||||||
|
v = extract32(data, 32) |
||||||
|
r = extract32(data, 64) |
||||||
|
s = extract32(data, 96) |
||||||
|
if r >= secp256k1n or s >= secp256k1n or v < 27 or v > 28: |
||||||
|
return [] |
||||||
|
try: |
||||||
|
pub = ecrecover_to_pub(message, v, r, s) |
||||||
|
except Exception as e: |
||||||
|
return [] |
||||||
|
o = [0] * 12 + [x for x in sha3(pub)[-20:]] |
||||||
|
return o |
||||||
|
|
||||||
|
|
||||||
|
def sha256(data): |
||||||
|
data = bytes(data) |
||||||
|
return hashlib.sha256(data).digest() |
||||||
|
|
||||||
|
|
||||||
|
def ripemd160(data): |
||||||
|
data = bytes(data) |
||||||
|
return 12*[0]+[i for i in hashlib.new('ripemd160', data).digest()] |
||||||
|
|
||||||
|
|
||||||
|
def identity(data): |
||||||
|
return copy.copy(data) |
||||||
|
|
||||||
|
|
||||||
|
def native_contracts(address, data): |
||||||
|
''' |
||||||
|
takes integer address 1, 2, 3, 4 |
||||||
|
''' |
||||||
|
|
||||||
|
functions = (ecrecover, sha256, ripemd160, identity) |
||||||
|
return functions[address-1](data) |
@ -0,0 +1,117 @@ |
|||||||
|
import json |
||||||
|
from mythril.ether.soliditycontract import SolidityContract |
||||||
|
|
||||||
|
from mythril.laser.ethereum.svm import GlobalState, MachineState |
||||||
|
from mythril.laser.ethereum import svm |
||||||
|
from tests import * |
||||||
|
|
||||||
|
|
||||||
|
SHA256_TEST = [ (0,False) for i in range(6)] |
||||||
|
|
||||||
|
RIPEMD160_TEST = [ (0,False) for i in range(6)] |
||||||
|
|
||||||
|
ECRECOVER_TEST = [ (0,False) for i in range(9)] |
||||||
|
|
||||||
|
IDENTITY_TEST = [ (0, False) for i in range(4)] |
||||||
|
|
||||||
|
SHA256_TEST[0] = (5555555555555555, True) #These are Random numbers to check whether the 'if condition' is entered or not(True means entered) |
||||||
|
SHA256_TEST[1] = (323232325445454546, True) |
||||||
|
SHA256_TEST[2] = (34756834765834658, False) |
||||||
|
SHA256_TEST[3] = (8756476956956795876987, True) |
||||||
|
SHA256_TEST[4] = (5763467587689578369, True) |
||||||
|
SHA256_TEST[5] = (948365957658767467857, False) |
||||||
|
|
||||||
|
RIPEMD160_TEST[0] = (1242435356364, True) |
||||||
|
RIPEMD160_TEST[1] = (6732648654386435, True) |
||||||
|
RIPEMD160_TEST[2] = (97457657536546465, False) |
||||||
|
RIPEMD160_TEST[3] = (56436346436456546, True) |
||||||
|
RIPEMD160_TEST[4] = (999999999999999999993, True) |
||||||
|
RIPEMD160_TEST[5] = (1111111111112, False) |
||||||
|
|
||||||
|
|
||||||
|
ECRECOVER_TEST[0] = (786428768768632537676, True) |
||||||
|
ECRECOVER_TEST[1] = (4897983476979346779638, False) |
||||||
|
ECRECOVER_TEST[2] = (674837568743979857398564869, True) |
||||||
|
ECRECOVER_TEST[3] = (3487683476979311, False) |
||||||
|
ECRECOVER_TEST[4] = (853729594875984769847369, True) |
||||||
|
ECRECOVER_TEST[5] = (83579382475972439587, False) |
||||||
|
ECRECOVER_TEST[6] = (8437589437695876985769, True) |
||||||
|
ECRECOVER_TEST[7] = (9486794873598347697596, False) |
||||||
|
ECRECOVER_TEST[8] = (346934876983476, True) |
||||||
|
|
||||||
|
IDENTITY_TEST[0] = (87426857369875698, True) |
||||||
|
IDENTITY_TEST[1] = (476934798798347, False) |
||||||
|
|
||||||
|
IDENTITY_TEST[2] = (7346948379483769, True) |
||||||
|
IDENTITY_TEST[3] = (83269476937987, False) |
||||||
|
|
||||||
|
def _all_info(laser): |
||||||
|
accounts = {} |
||||||
|
for address, _account in laser.accounts.items(): |
||||||
|
account = _account.as_dict() |
||||||
|
account["code"] = account["code"].instruction_list |
||||||
|
account['balance'] = str(account['balance']) |
||||||
|
accounts[address] = account |
||||||
|
|
||||||
|
nodes = {} |
||||||
|
for uid, node in laser.nodes.items(): |
||||||
|
states = [] |
||||||
|
for state in node.states: |
||||||
|
if isinstance(state, MachineState): |
||||||
|
states.append(state.as_dict()) |
||||||
|
elif isinstance(state, GlobalState): |
||||||
|
environment = state.environment.as_dict() |
||||||
|
environment["active_account"] = environment["active_account"].address |
||||||
|
states.append({ |
||||||
|
'accounts': state.accounts.keys(), |
||||||
|
'environment': environment, |
||||||
|
'mstate': state.mstate.as_dict() |
||||||
|
}) |
||||||
|
|
||||||
|
nodes[uid] = { |
||||||
|
'uid': node.uid, |
||||||
|
'contract_name': node.contract_name, |
||||||
|
'start_addr': node.start_addr, |
||||||
|
'states': states, |
||||||
|
'constraints': node.constraints, |
||||||
|
'function_name': node.function_name, |
||||||
|
'flags': str(node.flags) |
||||||
|
} |
||||||
|
|
||||||
|
edges = [edge.as_dict() for edge in laser.edges] |
||||||
|
|
||||||
|
return { |
||||||
|
'accounts': accounts, |
||||||
|
'nodes': nodes, |
||||||
|
'edges': edges, |
||||||
|
'total_states': laser.total_states, |
||||||
|
'max_depth': laser.max_depth |
||||||
|
} |
||||||
|
|
||||||
|
def _test_natives(laser_info, test_list, test_name): |
||||||
|
success = 0 |
||||||
|
for i,j in test_list: |
||||||
|
if (str(i) in laser_info) == j: |
||||||
|
success+=1 |
||||||
|
else: |
||||||
|
print ("Failed: "+str(i)+" "+str(j)) |
||||||
|
assert(success == len(test_list)) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class NativeTests(BaseTestCase): |
||||||
|
def runTest(self): |
||||||
|
disassembly = SolidityContract('./tests/native_tests.sol').disassembly |
||||||
|
account = svm.Account("0x0000000000000000000000000000000000000000", disassembly) |
||||||
|
accounts = {account.address: account} |
||||||
|
|
||||||
|
laser = svm.LaserEVM(accounts, max_depth = 100) |
||||||
|
laser.sym_exec(account.address) |
||||||
|
laser_info = str(_all_info(laser)) |
||||||
|
print('\n') |
||||||
|
|
||||||
|
_test_natives(laser_info, SHA256_TEST, 'SHA256') |
||||||
|
_test_natives(laser_info, RIPEMD160_TEST, 'RIPEMD160') |
||||||
|
_test_natives(laser_info, ECRECOVER_TEST, 'ECRECOVER') |
||||||
|
_test_natives(laser_info, IDENTITY_TEST, 'IDENTITY') |
||||||
|
|
@ -0,0 +1,166 @@ |
|||||||
|
pragma solidity ^0.4.17; |
||||||
|
|
||||||
|
|
||||||
|
contract Caller { |
||||||
|
|
||||||
|
address public fixed_address; //Just some useless variables |
||||||
|
address public stored_address; |
||||||
|
|
||||||
|
uint256 statevar; //useless( but good for testing as they contribute as decoys) |
||||||
|
bytes32 far; |
||||||
|
|
||||||
|
function Caller(address addr) { |
||||||
|
fixed_address = addr; |
||||||
|
} |
||||||
|
|
||||||
|
function thisisfine() public { //some typical function as a decoy |
||||||
|
fixed_address.call(); |
||||||
|
} |
||||||
|
function sha256_test1() public { |
||||||
|
uint256 i; |
||||||
|
if(sha256('ab','c') == 0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad){ //True |
||||||
|
i = 5555555555555555; |
||||||
|
} |
||||||
|
|
||||||
|
if(sha256('abc') == 0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad){ //True |
||||||
|
i = 323232325445454546; |
||||||
|
} |
||||||
|
} |
||||||
|
function sha256_test2() public { |
||||||
|
uint256 i; |
||||||
|
if(sha256('abd') == 0xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad) { //False |
||||||
|
i = 34756834765834658; |
||||||
|
} |
||||||
|
if(sha256('ab','d') == 0xa52d159f262b2c6ddb724a61840befc36eb30c88877a4030b65cbe86298449c9) { //True |
||||||
|
i = 8756476956956795876987; |
||||||
|
} |
||||||
|
} |
||||||
|
function sha256_test3() public { |
||||||
|
uint256 i; |
||||||
|
if(sha256('') == 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855) { //True |
||||||
|
i = 5763467587689578369; |
||||||
|
} |
||||||
|
if(sha256('hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhfdhhfdhhhhhh') == 0xe4ebd771f821e3277b77dcc39e94fe7172a5c9c8c12f8885c2d5513385a0a8b8) { //False |
||||||
|
i = 948365957658767467857; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function ripemd_test1() public { |
||||||
|
uint256 i; |
||||||
|
if(ripemd160('ab','c') == 0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc){ //True |
||||||
|
i = 1242435356364; |
||||||
|
} |
||||||
|
if(ripemd160('abc') == 0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc){ //True |
||||||
|
i = 6732648654386435; |
||||||
|
} |
||||||
|
} |
||||||
|
function ripemd_test2() public { |
||||||
|
uint256 i; |
||||||
|
if(ripemd160('abd') == 0x8eb208f7e05d987a9b044a8e98c6b087f15a0bfc) { //False |
||||||
|
i = 97457657536546465; |
||||||
|
} |
||||||
|
if(ripemd160('ab','d') == 0xb0a79cc77e333ea11974e105cd051d33836928b0) { //True |
||||||
|
i = 56436346436456546; |
||||||
|
} |
||||||
|
} |
||||||
|
function ripemd_test3() public { |
||||||
|
uint256 i; |
||||||
|
if(ripemd160('') == 0x9c1185a5c5e9fc54612808977ee8f548b2258d31) { //True |
||||||
|
i = 999999999999999999993; |
||||||
|
} |
||||||
|
if(ripemd160('hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh') == 0x2d1b88a5daa5d138eb7bb14ee320010937f0ebe7) { //False |
||||||
|
i = 1111111111112; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function ecrecover_test1() public { |
||||||
|
bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8; |
||||||
|
bytes memory prefix = "\x19Ethereum Signed Message:\n32"; |
||||||
|
bytes32 prefixedHash = keccak256(prefix, foobar); |
||||||
|
uint8 v = 28; |
||||||
|
bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608; |
||||||
|
bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada; |
||||||
|
if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8a) { //True |
||||||
|
uint256 bignum = 786428768768632537676; |
||||||
|
} |
||||||
|
if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8b) { //False |
||||||
|
uint256 small = 4897983476979346779638; |
||||||
|
} |
||||||
|
foobar = 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e; |
||||||
|
if( ecrecover( keccak256(foobar), v, r, s) == 0x0faf91ea0aaaa5377dfdf188b21409007f0b4019) { //True |
||||||
|
uint256 dk = 674837568743979857398564869; |
||||||
|
} |
||||||
|
foobar = 0x38d18acb67d25c7bb9942764b62f18e17054f66a817bd4295423adf9ed98873e; //not same as above, minor change(7bb instead of 8bb) |
||||||
|
if( ecrecover( keccak256(foobar), v, r, s) == 0x0faf91ea0aaaa5377dfdf188b21409007f0b4019) { //False |
||||||
|
uint256 pk = 3487683476979311; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
function ecrecover_test2() public { |
||||||
|
bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8; |
||||||
|
bytes memory prefix = "\x19Ethereum Signed Message:\n32"; |
||||||
|
bytes32 prefixedHash = keccak256(prefix, foobar); |
||||||
|
uint8 v = 26; |
||||||
|
bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608; |
||||||
|
bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada; |
||||||
|
if( ecrecover(prefixedHash, v, r, s) == 0x0000000000000000000000000000000000000000) { //True |
||||||
|
uint256 bignum = 853729594875984769847369; |
||||||
|
} |
||||||
|
if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8b) { //False |
||||||
|
uint256 small = 83579382475972439587; |
||||||
|
} |
||||||
|
} |
||||||
|
function ecrecover_test3() public { |
||||||
|
bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8; |
||||||
|
bytes memory prefix = "\x19Ethereum Signed Message:\n32"; |
||||||
|
bytes32 prefixedHash = keccak256(prefix, foobar); |
||||||
|
uint8 v = 29; |
||||||
|
bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608; |
||||||
|
bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada; |
||||||
|
if( ecrecover(prefixedHash, v, r, s) == 0x0000000000000000000000000000000000000000) { //True |
||||||
|
uint256 bignum = 8437589437695876985769; |
||||||
|
} |
||||||
|
if( ecrecover(prefixedHash, v, r, s) == 0x7156526fbd7a3c72969b54f64e42c10fbb768c8b) { //False |
||||||
|
uint256 small = 9486794873598347697596; |
||||||
|
} |
||||||
|
} |
||||||
|
function ecrecover_test4() public { |
||||||
|
bytes32 foobar = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8; |
||||||
|
bytes memory prefix = "\x19Ethereum Signed Message:\n32"; |
||||||
|
bytes32 prefixedHash = keccak256(prefix, foobar); |
||||||
|
uint8 v = 27; |
||||||
|
bytes32 r = 0xfffffffffffffffffffffffffffffffffaaedce6af48a03bbfd25e8cd0364141; //greater than the max limit |
||||||
|
bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada; |
||||||
|
|
||||||
|
if( ecrecover(prefixedHash, v, r, s) == 0x0000000000000000000000000000000000000000) { //True |
||||||
|
uint256 bignum = 346934876983476; |
||||||
|
} |
||||||
|
} |
||||||
|
function need_identity_invoke(uint sea) returns (uint) { |
||||||
|
return sea; //identity is invoked here in compiler and not below |
||||||
|
} |
||||||
|
function identity_function(int input) public returns(int out) { |
||||||
|
assembly{ |
||||||
|
let x := mload(0x40) |
||||||
|
mstore(x, input) |
||||||
|
|
||||||
|
let success := call(500000000, 0x4, 100000, x, 0x20, x, 0x20) |
||||||
|
out := mload(x) |
||||||
|
mstore(0x40, x) |
||||||
|
} |
||||||
|
} |
||||||
|
function identity_test1() public{ |
||||||
|
if(identity_function(100)==100) //True |
||||||
|
uint256 smallnum = 87426857369875698; |
||||||
|
if(identity_function(200)==100) //False |
||||||
|
uint256 bignum = 476934798798347; |
||||||
|
} |
||||||
|
function identity_test2() public{ |
||||||
|
if(identity_function(12345678)==12345678) //True |
||||||
|
uint256 smallnum = 7346948379483769; |
||||||
|
if(identity_function(74648796976)==4685987) //False |
||||||
|
uint256 bignum = 83269476937987; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue