Skip to content

Commit 806bbfa

Browse files
committed
Merge branch 'master' into native-arb-cf-redirect-detector
* master: Improve performance of bulk read/writes to memory (#1509) Fixes ConstraintSet.new_bitvec size check (#1511) Fix operators.ORD for BitVecs of size > 8 (#1512) Removed redeclared smtlibv2 tests (#1513) Update manticore.py (#1508) Improve smemory tests (#1506) Manticore 0.3.1 (#1503) Optimize repeated division in CMPXCHG8B (#1501) Detecting the use of BALANCE in a strict comparison (#1481) Initial master merge into experimental state merging for native (#1482) Update crackme example to match the description (#1502) Add SHL/SHR/SAR (#1498) Add deprecation warnings for outdated API members (#1500) Patching STAICCALL (#1494) WIP: Support lsr.w on ARMv7 THUMB (#1363) Update evm examples (#1486) Logic Bomb Bugfixes (#1485) Add error for unsupported solc versions (#1488) Fix documentation typo in ManticoreBase (#1492) Add crytic-compile support (#1406)
2 parents c45c56b + 6171924 commit 806bbfa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2108
-413
lines changed

CHANGELOG.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
# Change Log
22

3-
## [Unreleased](https://github.com/trailofbits/manticore/compare/0.3.0...HEAD)
3+
## [Unreleased](https://github.com/trailofbits/manticore/compare/0.3.1...HEAD)
4+
5+
## 0.3.1 - 2019-08-06
6+
7+
Thanks to our external contributors!
8+
9+
- [arcz](https://github.com/trailofbits/manticore/commits?author=arcz)
10+
11+
### Ethereum
12+
* Smart contracts are now compiled using [Crytic-Compile](https://github.com/crytic/crytic-compile) [#1406](https://github.com/trailofbits/manticore/pull/1406)
13+
* Added detector for strict comparisons to BALANCE [#1481](https://github.com/trailofbits/manticore/pull/1481)
14+
* Added bitshift instructions [#1498](https://github.com/trailofbits/manticore/pull/1498)
15+
* Added stub for STATICCALL (does not enforce static nature) [#1494](https://github.com/trailofbits/manticore/pull/1494)
16+
* Updated EVM Examples [#1486](https://github.com/trailofbits/manticore/pull/1486)
17+
18+
### Native
19+
* Fixed `getdents` syscall [#1472](https://github.com/trailofbits/manticore/pull/1472)
20+
* Fixed state merging examples [#1482](https://github.com/trailofbits/manticore/pull/1482)
21+
* Support LSR.W on ARMV7 [#1363](https://github.com/trailofbits/manticore/pull/1363)
22+
* Fixed CrackMe Example [#1502](https://github.com/trailofbits/manticore/pull/1502)
23+
* Optimize CMPXCHG8B [#1501](https://github.com/trailofbits/manticore/pull/1501)
24+
* Added `fast_crash` configuration setting that causes Manticore to immediately produce a finding on memory unsafety [#1485](https://github.com/trailofbits/manticore/pull/1485)
25+
26+
### Other
27+
* **[changed API]** Moved `issymbolic` into SMTLib to improve performance [#1456](https://github.com/trailofbits/manticore/pull/1456)
28+
* Refactored API Docs [#1469](https://github.com/trailofbits/manticore/pull/1469)
29+
* Fixed `FileNotFound` Error on state loading [#1480](https://github.com/trailofbits/manticore/pull/1480)
430

531
## 0.3.0 - 2019-06-06
632

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ value = m.make_symbolic_value()
7676

7777
contract_account.incremented(value)
7878

79-
for state in m.running_states:
79+
for state in m.ready_states:
8080
print("can value be 1? {}".format(state.can_be_true(value == 1)))
8181
print("can value be 200? {}".format(state.can_be_true(value == 200)))
8282
```
@@ -98,7 +98,7 @@ def hook(state):
9898
print('eax', cpu.EAX)
9999
print(cpu.read_int(cpu.ESP))
100100

101-
m.terminate() # tell Manticore to stop
101+
m.kill() # tell Manticore to stop
102102

103103
m.run()
104104
```
@@ -215,6 +215,10 @@ brew install unicorn
215215
UNICORN_QEMU_FLAGS="--python=`whereis python`" pip install unicorn
216216
```
217217

218+
### Solidity Versions
219+
Note that we're still in the process of implementing full support for the EVM Constantinople instruction semantics, so certain opcodes may not be supported.
220+
You may want to consider using a version of `solc` that's less likely to generate these opcodes (eg pre-0.5.0).
221+
218222
## Getting Help
219223

220224
Feel free to stop by our #manticore slack channel in [Empire Hacking](https://empireslacking.herokuapp.com/) for help using or extending Manticore.

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@
5454
# built documents.
5555
#
5656
# The short X.Y version.
57-
version = "0.3.0"
57+
version = "0.3.1"
5858
# The full version, including alpha/beta/rc tags.
59-
release = "0.3.0"
59+
release = "0.3.1"
6060

6161
# The language for content autogenerated by Sphinx. Refer to documentation
6262
# for a list of supported languages.

examples/evm/complete.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
)
3838

3939
print("[+] Resulting balances are:")
40-
for state in m.running_states:
40+
for state in m.all_states:
4141
balance = state.platform.get_balance(int(user_account))
4242
print(state.solve_one(balance))
4343

examples/evm/coverage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
)
3030

3131
print(f"[+] There are {m.count_terminated_states()} reverted states now")
32-
print(f"[+] There are {m.count_running_states()} alive states now")
32+
print(f"[+] There are {m.count_busy_states()} alive states now")
3333
# for state_id in m.running_state_ids:
3434
# print(m.report(state_id))
3535

examples/evm/reentrancy_concrete.py

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
1111
contract Reentrance {
1212
mapping (address => uint) userBalance;
13-
13+
1414
function getBalance(address u) constant returns(uint){
1515
return userBalance[u];
1616
}
1717
1818
function addToBalance() payable{
1919
userBalance[msg.sender] += msg.value;
20-
}
20+
}
2121
2222
function withdrawBalance(){
2323
// send userBalance[msg.sender] ethers to msg.sender
@@ -26,9 +26,9 @@
2626
revert();
2727
}
2828
userBalance[msg.sender] = 0;
29-
}
29+
}
3030
}
31-
//Function signatures:
31+
//Function signatures:
3232
//c0e317fb: addToBalance()
3333
//f8b2cb4f: getBalance(address)
3434
//5fd8c710: withdrawBalance()
@@ -38,7 +38,7 @@
3838
pragma solidity ^0.4.15;
3939
4040
contract GenericReentranceExploit {
41-
int reentry_reps=10;
41+
int reentry_reps=10;
4242
address vulnerable_contract;
4343
address owner;
4444
bytes reentry_attack_string;
@@ -87,7 +87,8 @@
8787
contract_account = m.solidity_create_contract(
8888
contract_source_code, owner=user_account
8989
) # Not payable
90-
m.world.set_balance(contract_account, 1000000000000000000) # give it some ether
90+
for i in m.all_states:
91+
i.platform.set_balance(contract_account, 1000000000000000000) # give it some ether
9192

9293
exploit_account = m.solidity_create_contract(exploit_source_code, owner=attacker_account)
9394

@@ -101,16 +102,18 @@
101102
exploit_account.set_reentry_attack_string(reentry_string)
102103

103104
print("[+] Initial world state")
104-
print(
105-
f" attacker_account {attacker_account.address:x} balance: {m.get_balance(attacker_account.address)}"
106-
)
107-
print(
108-
f" exploit_account {exploit_account.address} balance: {m.get_balance(exploit_account.address)}"
109-
)
110-
print(f" user_account {user_account.address:x} balance: {m.get_balance(user_account.address)}")
111-
print(
112-
f" contract_account {contract_account.address:x} balance: {m.get_balance(contract_account.address)}"
113-
)
105+
for i in m.all_states:
106+
i = i.platform
107+
print(
108+
f" attacker_account {attacker_account.address:x} balance: {i.get_balance(attacker_account.address)}"
109+
)
110+
print(
111+
f" exploit_account {exploit_account.address} balance: {i.get_balance(exploit_account.address)}"
112+
)
113+
print(f" user_account {user_account.address:x} balance: {i.get_balance(user_account.address)}")
114+
print(
115+
f" contract_account {contract_account.address:x} balance: {i.get_balance(contract_account.address)}"
116+
)
114117

115118

116119
# User deposits all in contract
@@ -127,13 +130,15 @@
127130
print("[+] Let attacker destroy the exploit contract and profit")
128131
exploit_account.get_money()
129132

130-
print(
131-
f" attacker_account {attacker_account.address:x} balance: {m.get_balance(attacker_account.address)}"
132-
)
133-
print(f" user_account {user_account.address:x} balance: {m.get_balance(user_account.address)}")
134-
print(
135-
f" contract_account {contract_account.address:x} balance: {m.get_balance(contract_account.address)}"
136-
)
133+
for i in m.all_states:
134+
i = i.platform
135+
print(
136+
f" attacker_account {attacker_account.address:x} balance: {i.get_balance(attacker_account.address)}"
137+
)
138+
print(f" user_account {user_account.address:x} balance: {i.get_balance(user_account.address)}")
139+
print(
140+
f" contract_account {contract_account.address:x} balance: {i.get_balance(contract_account.address)}"
141+
)
137142

138143
m.finalize()
139144
print(f"[+] Look for results in {m.workspace}")

examples/evm/use_def.py

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
################ Script #######################
66

77
m = ManticoreEVM()
8-
m.verbosity(0)
98
# And now make the contract account to analyze
109
# cat | solc --bin
1110
source_code = """
@@ -18,80 +17,63 @@
1817
c =0;
1918
enabled = false;
2019
i = false;
21-
20+
2221
}
2322
function f1() public {
2423
c+=1;
2524
}
2625
function f2() public {
2726
if(c>100)
2827
enabled=true;
29-
28+
3029
}
3130
function f3() public{
32-
if (!enabled)
31+
if (!enabled)
3332
return;
3433
i = true;
35-
34+
3635
}
3736
}
3837
"""
3938
print(source_code)
4039

4140

4241
class EVMUseDef(Plugin):
43-
def _get_concrete_hex(self, state, array):
44-
r = ""
45-
for i in array:
46-
l = state.solve_n(i, 2)
47-
if len(l) == 1:
48-
r += "%02x" % l[0]
49-
if len(r) != 8:
50-
return
51-
return r
52-
5342
def did_evm_write_storage_callback(self, state, address, offset, value):
5443
m = self.manticore
5544
world = state.platform
5645
tx = world.all_transactions[-1]
5746
md = m.get_metadata(tx.address)
58-
59-
r = self._get_concrete_hex(state, tx.data[0:4])
60-
if r is None:
61-
return
62-
63-
offsets = state.solve_n(offset, 3000)
64-
with self.locked_context("storage_writes", dict) as storage_writes:
65-
contract_function = (md.name, md.get_func_name(r))
66-
if contract_function not in storage_writes:
67-
storage_writes[contract_function] = set()
68-
for off in offsets:
69-
storage_writes[contract_function].add(off)
47+
if md:
48+
offsets = state.solve_n(offset, 3000)
49+
with self.locked_context("storage_writes", dict) as storage_writes:
50+
contract_function = (md.name, md.get_func_name(state.solve_one(tx.data[0:4])))
51+
if contract_function not in storage_writes:
52+
storage_writes[contract_function] = set()
53+
for off in offsets:
54+
storage_writes[contract_function].add(off)
7055

7156
def did_evm_read_storage_callback(self, state, address, offset, value):
7257
m = self.manticore
7358
world = state.platform
7459
tx = world.all_transactions[-1]
7560
md = m.get_metadata(tx.address)
61+
if md:
62+
offsets = state.solve_n(offset, 3000)
63+
with self.locked_context("storage_reads", dict) as storage_reads:
64+
contract_function = (md.name, md.get_func_name(state.solve_one(tx.data[0:4])))
65+
if contract_function not in storage_reads:
66+
storage_reads[contract_function] = set()
67+
for off in offsets:
68+
storage_reads[contract_function].add(off)
7669

77-
r = self._get_concrete_hex(state, tx.data[0:4])
78-
if r is None:
79-
return
80-
81-
offsets = state.solve_n(offset, 3000)
82-
with self.locked_context("storage_reads", dict) as storage_reads:
83-
contract_function = (md.name, md.get_func_name(r))
84-
if contract_function not in storage_reads:
85-
storage_reads[contract_function] = set()
86-
for off in offsets:
87-
storage_reads[contract_function].add(off)
8870

71+
p = EVMUseDef()
72+
m.register_plugin(p)
8973

9074
# Initialize accounts
9175
user_account = m.create_account(balance=1000)
9276
contract_account = m.solidity_create_contract(source_code, owner=user_account)
93-
p = EVMUseDef()
94-
m.register_plugin(p)
9577

9678
symbolic_data = m.make_symbolic_buffer(320)
9779
symbolic_value = m.make_symbolic_value()

examples/linux/Makefile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ PYTHON=python3
66
EXAMPLES=basic sindex strncmp arguments ibranch sendmail crackme indexhell helloworld simple_copy simpleassert
77
OTHER_EXAMPLES=nostdlib
88

9-
all: $(EXAMPLES) $(OTHER_EXAMPLES)
9+
all: $(EXAMPLES) $(OTHER_EXAMPLES)
1010

1111
arm: CC=arm-linux-gnueabi-gcc
1212
arm: $(EXAMPLES)
@@ -21,7 +21,7 @@ clean:
2121
% : %.c
2222
$(CC) $(CFLAGS) $< -o $@
2323

24-
nostdlib: nostdlib.c
24+
nostdlib: nostdlib.c
2525
$(CC) -m32 $(NOSTDLIBFLAGS) $< -o $@
2626

2727
# simpleassert needs -O0
@@ -32,3 +32,5 @@ simpleassert: simpleassert.c
3232
crackme.c: crackme.py
3333
$(PYTHON) crackme.py > $@
3434

35+
crackme: crackme.c
36+
$(CC) $(CFLAGS) -O0 $< -o $@

examples/linux/basic_state_merging.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Symbolic values are read from stdin using standard libc calls.
3+
* Program compares if two binary packed integers at the input with 0x41.
4+
*
5+
* Compile with :
6+
* $ gcc -static -Os basic_statemerging.c -o basic_statemerging
7+
*
8+
* Analyze it with:
9+
* $ python examples/script/basic_statemerging.py examples/linux/basic_statemerging
10+
*
11+
* The Merger plugin used in basic_statemerging.py will find two states with state IDs 2, 4 to be at the same program
12+
* location (0x40060d) and merge their CPU states which should only require the value for RDI to be merged.
13+
*
14+
* Expected output:
15+
* $ python /Users/vaibhav/git_repos/manticore/examples/script/basic_statemerging.py examples/linux/basic_statemerging-Os
16+
about to load state_id = 0
17+
loaded state_id = 0 at cpu = 0x4008e0
18+
about to load state_id = 1
19+
loaded state_id = 1 at cpu = 0x400604
20+
about to load state_id = 2
21+
Merged registers:
22+
RDI
23+
at PC = 0x40060d, merge succeeded for state id = 2 and 4
24+
loaded state_id = 2 at cpu = 0x40060d
25+
about to load state_id = 3
26+
loaded state_id = 3 at cpu = 0x400612
27+
*
28+
*/
29+
30+
#include <stdio.h>
31+
#include <stdlib.h>
32+
#include <unistd.h>
33+
#include <stdbool.h>
34+
35+
int main(int argc, char* argv[], char* envp[]){
36+
unsigned int cmd1, cmd2;
37+
unsigned int cmdChanged = 0;
38+
39+
if (read(0, &cmd1, sizeof(cmd1)) != sizeof(cmd1))
40+
{
41+
printf("Error reading stdin!");
42+
exit(-1);
43+
}
44+
if (read(0, &cmd2, sizeof(cmd2)) != sizeof(cmd2))
45+
{
46+
printf("Error reading stdin!");
47+
exit(-1);
48+
}
49+
50+
if (cmd1 > 0x41)
51+
{
52+
cmdChanged = cmd1 - 0x42;
53+
}
54+
if (cmd2 < 0x41)
55+
{
56+
cmdChanged = cmd2 + 0x42;
57+
}
58+
59+
if (cmdChanged == 0) printf("equal\n");
60+
else printf("not equal\n");
61+
62+
return 0;
63+
}

0 commit comments

Comments
 (0)