Merge branch 'merge-mui-server'

* merge-mui-server: (32 commits)
  [Server] Fix README on usage and installation directions
  [Server] Remove duplicated dependency
  [Server] Add notes about duplicated CLI parsing
  [Server] Support PEP 518 minimum build requirements
  [Server] Use logger for messages
  [Server] Fix linting commands
  [Server] Add CI
  [Server] Manticore black exclude formatting of server
  [Server] Remove test binaries
  [Server] Remove all references to "MUI"
  [Server] Fixes to dependency and project setup
  [Server] Add .gitignore, add missing dev-requirement (#101)
  [Server] Support manual state control (Pause/Kill) (#96)
  [Server] Add explicit field presence (#88)
  [Server] Implement native Unicorn emulate until address (#86)
  [Server] Fix some justfile commands
  Fix broken CI paths, update documentation
  [Server] Add tests for starting execution with hooks
  [Ghidra] Support find/avoid for stateless server
  [Server] Support all hooks as StartNative field
  ...
This commit is contained in:
Eric Kilmer
2022-10-28 12:46:56 -04:00
22 changed files with 3012 additions and 0 deletions
+30
View File
@@ -115,6 +115,36 @@ jobs:
env:
COVERALLS_PARALLEL: true
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
manticore-server:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: 3.7
- name: 'Install tools'
run: |
# just command runner https://github.com/casey/just#pre-built-binaries
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to "${HOME}/.local/bin"
sudo wget -O /usr/bin/solc https://github.com/ethereum/solidity/releases/download/v0.4.24/solc-static-linux
sudo chmod +x /usr/bin/solc
- name: 'Lint MUI Server'
working-directory: server
run: |
just init
source venv/bin/activate
just lint
- name: 'Test MUI Server'
working-directory: server
run: |
source venv/bin/activate
just test
# Send notification when all tests have finished to combine coverage results
coverage-finish:
needs: tests
+6
View File
@@ -1,3 +1,9 @@
[tool.black]
target-version = ['py36']
line-length = 100
extend-exclude = '''
(
venv
| server # Has its own formatting
)
'''
+4
View File
@@ -0,0 +1,4 @@
manticore_server.egg-info/**
**/__pycache__
dist/**
.mypy_cache/**
+20
View File
@@ -0,0 +1,20 @@
# Manticore Server
Manticore Server is a gRPC service that acts as a wrapper around [Manticore](https://github.com/trailofbits/manticore), to support projects like the [Manticore User Interface (MUI)](https://github.com/trailofbits/ManticoreUI). Manticore Server is designed to allow developers to more easily create tools around Manticore that aren't in Python or to allow for Manticore to be run and managed in the cloud/remotely.
❗NOTE❗: The server is not published or packaged anywhere and is intended to be installed from source in a clean Python virtual environment. The server is only tested for compatibility with the version of Manticore living in the parent directory; this version of Manticore is installed when installing the server.
# Usage
Create a new Python virtual environment:
```bash
python3 -m venv venv
source venv/bin/activate
```
Install the server with `pip install .`. This will install Manticore from the parent directory.
The Manticore Server can be run via `manticore_server`, and it will run on port `50010`.
Your Manticore Server client will require the relevant gRPC client code. You can find out how to generate gRPC client code in your desired language from [the gRPC website](https://grpc.io/docs/languages/).
You may refer to the [Protobuf Specification](manticore_server/ManticoreServer.proto) for information about the RPC services provided and the message types.
+25
View File
@@ -0,0 +1,25 @@
init:
test -d venv || python3 -m venv venv
. venv/bin/activate; pip install -U setuptools pip wheel; pip install -e .[dev]
format:
black .
isort .
lint:
black --check .
isort --check .
mypy
generate:
python3 setup.py generate
build: generate
#!/usr/bin/env bash
set -euo
mkdir -p dist
py_ver=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
python3 -m shiv -c manticore_server -o dist/manticore_server --reproducible --no-modify --python "/usr/bin/env python${py_ver}" --compressed .
test:
python3 -m unittest tests/test_*.py
@@ -0,0 +1,107 @@
syntax = "proto3";
package manticore_server;
service ManticoreServer {
rpc StartNative(NativeArguments) returns (ManticoreInstance) {}
rpc StartEVM(EVMArguments) returns (ManticoreInstance) {}
rpc Terminate(ManticoreInstance) returns (TerminateResponse) {}
rpc GetStateList(ManticoreInstance) returns (ManticoreStateList) {}
rpc GetMessageList(ManticoreInstance) returns (ManticoreMessageList) {}
rpc CheckManticoreRunning(ManticoreInstance) returns (ManticoreRunningStatus) {}
rpc StopServer(StopServerRequest) returns (StopServerResponse) {}
rpc ControlState(ControlStateRequest) returns (ControlStateResponse) {}
}
// LogMessage and StateList message types have "Manticore" in their names to distinguish them from those in mserialize
message ManticoreLogMessage {
string content = 1;
}
message ManticoreMessageList {
repeated ManticoreLogMessage messages = 2;
}
message ManticoreState {
int32 state_id = 3;
uint64 pc = 10;
optional int32 parent_id = 28;
repeated int32 children_ids = 29;
}
message ManticoreStateList {
// state categories in Manticore - based on manticore enums StateStatus and StateList
repeated ManticoreState active_states = 4;
repeated ManticoreState waiting_states = 5;
repeated ManticoreState forked_states = 6;
repeated ManticoreState errored_states = 7;
repeated ManticoreState complete_states = 8;
repeated ManticoreState paused_states = 33;
}
message ManticoreInstance {
string uuid = 9;
}
message TerminateResponse {}
message Hook {
enum HookType {
FIND = 0;
AVOID = 1;
CUSTOM = 2;
GLOBAL = 3;
}
optional uint64 address = 26;
HookType type = 27;
optional string func_text = 31;
}
message NativeArguments {
string program_path = 11;
repeated string binary_args = 16;
repeated string envp = 17;
repeated string symbolic_files = 18;
optional string concrete_start = 19;
optional string stdin_size = 20;
optional string additional_mcore_args = 21;
repeated Hook hooks = 30;
optional uint64 emulate_until = 32;
}
message EVMArguments {
string contract_path = 12;
string contract_name = 13;
string solc_bin = 14;
optional string tx_limit = 22;
optional string tx_account = 23;
repeated string detectors_to_exclude = 24;
optional string additional_flags = 25;
}
message ManticoreRunningStatus {
bool is_running = 15;
}
message StopServerRequest {}
message StopServerResponse {}
message ControlStateRequest {
enum StateAction {
RESUME = 0;
PAUSE = 1;
KILL = 2;
}
int32 state_id = 34;
ManticoreInstance manticore_instance = 35;
StateAction action = 36;
}
message ControlStateResponse {}
@@ -0,0 +1,173 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: manticore_server/ManticoreServer.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&manticore_server/ManticoreServer.proto\x12\x10manticore_server\"&\n\x13ManticoreLogMessage\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\"O\n\x14ManticoreMessageList\x12\x37\n\x08messages\x18\x02 \x03(\x0b\x32%.manticore_server.ManticoreLogMessage\"j\n\x0eManticoreState\x12\x10\n\x08state_id\x18\x03 \x01(\x05\x12\n\n\x02pc\x18\n \x01(\x04\x12\x16\n\tparent_id\x18\x1c \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x63hildren_ids\x18\x1d \x03(\x05\x42\x0c\n\n_parent_id\"\xee\x02\n\x12ManticoreStateList\x12\x37\n\ractive_states\x18\x04 \x03(\x0b\x32 .manticore_server.ManticoreState\x12\x38\n\x0ewaiting_states\x18\x05 \x03(\x0b\x32 .manticore_server.ManticoreState\x12\x37\n\rforked_states\x18\x06 \x03(\x0b\x32 .manticore_server.ManticoreState\x12\x38\n\x0e\x65rrored_states\x18\x07 \x03(\x0b\x32 .manticore_server.ManticoreState\x12\x39\n\x0f\x63omplete_states\x18\x08 \x03(\x0b\x32 .manticore_server.ManticoreState\x12\x37\n\rpaused_states\x18! \x03(\x0b\x32 .manticore_server.ManticoreState\"!\n\x11ManticoreInstance\x12\x0c\n\x04uuid\x18\t \x01(\t\"\x13\n\x11TerminateResponse\"\xb6\x01\n\x04Hook\x12\x14\n\x07\x61\x64\x64ress\x18\x1a \x01(\x04H\x00\x88\x01\x01\x12-\n\x04type\x18\x1b \x01(\x0e\x32\x1f.manticore_server.Hook.HookType\x12\x16\n\tfunc_text\x18\x1f \x01(\tH\x01\x88\x01\x01\"7\n\x08HookType\x12\x08\n\x04\x46IND\x10\x00\x12\t\n\x05\x41VOID\x10\x01\x12\n\n\x06\x43USTOM\x10\x02\x12\n\n\x06GLOBAL\x10\x03\x42\n\n\x08_addressB\x0c\n\n_func_text\"\xcd\x02\n\x0fNativeArguments\x12\x14\n\x0cprogram_path\x18\x0b \x01(\t\x12\x13\n\x0b\x62inary_args\x18\x10 \x03(\t\x12\x0c\n\x04\x65nvp\x18\x11 \x03(\t\x12\x16\n\x0esymbolic_files\x18\x12 \x03(\t\x12\x1b\n\x0e\x63oncrete_start\x18\x13 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nstdin_size\x18\x14 \x01(\tH\x01\x88\x01\x01\x12\"\n\x15\x61\x64\x64itional_mcore_args\x18\x15 \x01(\tH\x02\x88\x01\x01\x12%\n\x05hooks\x18\x1e \x03(\x0b\x32\x16.manticore_server.Hook\x12\x1a\n\remulate_until\x18 \x01(\x04H\x03\x88\x01\x01\x42\x11\n\x0f_concrete_startB\r\n\x0b_stdin_sizeB\x18\n\x16_additional_mcore_argsB\x10\n\x0e_emulate_until\"\xec\x01\n\x0c\x45VMArguments\x12\x15\n\rcontract_path\x18\x0c \x01(\t\x12\x15\n\rcontract_name\x18\r \x01(\t\x12\x10\n\x08solc_bin\x18\x0e \x01(\t\x12\x15\n\x08tx_limit\x18\x16 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ntx_account\x18\x17 \x01(\tH\x01\x88\x01\x01\x12\x1c\n\x14\x64\x65tectors_to_exclude\x18\x18 \x03(\t\x12\x1d\n\x10\x61\x64\x64itional_flags\x18\x19 \x01(\tH\x02\x88\x01\x01\x42\x0b\n\t_tx_limitB\r\n\x0b_tx_accountB\x13\n\x11_additional_flags\",\n\x16ManticoreRunningStatus\x12\x12\n\nis_running\x18\x0f \x01(\x08\"\x13\n\x11StopServerRequest\"\x14\n\x12StopServerResponse\"\xdb\x01\n\x13\x43ontrolStateRequest\x12\x10\n\x08state_id\x18\" \x01(\x05\x12?\n\x12manticore_instance\x18# \x01(\x0b\x32#.manticore_server.ManticoreInstance\x12\x41\n\x06\x61\x63tion\x18$ \x01(\x0e\x32\x31.manticore_server.ControlStateRequest.StateAction\".\n\x0bStateAction\x12\n\n\x06RESUME\x10\x00\x12\t\n\x05PAUSE\x10\x01\x12\x08\n\x04KILL\x10\x02\"\x16\n\x14\x43ontrolStateResponse2\xfa\x05\n\x0fManticoreServer\x12W\n\x0bStartNative\x12!.manticore_server.NativeArguments\x1a#.manticore_server.ManticoreInstance\"\x00\x12Q\n\x08StartEVM\x12\x1e.manticore_server.EVMArguments\x1a#.manticore_server.ManticoreInstance\"\x00\x12W\n\tTerminate\x12#.manticore_server.ManticoreInstance\x1a#.manticore_server.TerminateResponse\"\x00\x12[\n\x0cGetStateList\x12#.manticore_server.ManticoreInstance\x1a$.manticore_server.ManticoreStateList\"\x00\x12_\n\x0eGetMessageList\x12#.manticore_server.ManticoreInstance\x1a&.manticore_server.ManticoreMessageList\"\x00\x12h\n\x15\x43heckManticoreRunning\x12#.manticore_server.ManticoreInstance\x1a(.manticore_server.ManticoreRunningStatus\"\x00\x12Y\n\nStopServer\x12#.manticore_server.StopServerRequest\x1a$.manticore_server.StopServerResponse\"\x00\x12_\n\x0c\x43ontrolState\x12%.manticore_server.ControlStateRequest\x1a&.manticore_server.ControlStateResponse\"\x00\x62\x06proto3')
_MANTICORELOGMESSAGE = DESCRIPTOR.message_types_by_name['ManticoreLogMessage']
_MANTICOREMESSAGELIST = DESCRIPTOR.message_types_by_name['ManticoreMessageList']
_MANTICORESTATE = DESCRIPTOR.message_types_by_name['ManticoreState']
_MANTICORESTATELIST = DESCRIPTOR.message_types_by_name['ManticoreStateList']
_MANTICOREINSTANCE = DESCRIPTOR.message_types_by_name['ManticoreInstance']
_TERMINATERESPONSE = DESCRIPTOR.message_types_by_name['TerminateResponse']
_HOOK = DESCRIPTOR.message_types_by_name['Hook']
_NATIVEARGUMENTS = DESCRIPTOR.message_types_by_name['NativeArguments']
_EVMARGUMENTS = DESCRIPTOR.message_types_by_name['EVMArguments']
_MANTICORERUNNINGSTATUS = DESCRIPTOR.message_types_by_name['ManticoreRunningStatus']
_STOPSERVERREQUEST = DESCRIPTOR.message_types_by_name['StopServerRequest']
_STOPSERVERRESPONSE = DESCRIPTOR.message_types_by_name['StopServerResponse']
_CONTROLSTATEREQUEST = DESCRIPTOR.message_types_by_name['ControlStateRequest']
_CONTROLSTATERESPONSE = DESCRIPTOR.message_types_by_name['ControlStateResponse']
_HOOK_HOOKTYPE = _HOOK.enum_types_by_name['HookType']
_CONTROLSTATEREQUEST_STATEACTION = _CONTROLSTATEREQUEST.enum_types_by_name['StateAction']
ManticoreLogMessage = _reflection.GeneratedProtocolMessageType('ManticoreLogMessage', (_message.Message,), {
'DESCRIPTOR' : _MANTICORELOGMESSAGE,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.ManticoreLogMessage)
})
_sym_db.RegisterMessage(ManticoreLogMessage)
ManticoreMessageList = _reflection.GeneratedProtocolMessageType('ManticoreMessageList', (_message.Message,), {
'DESCRIPTOR' : _MANTICOREMESSAGELIST,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.ManticoreMessageList)
})
_sym_db.RegisterMessage(ManticoreMessageList)
ManticoreState = _reflection.GeneratedProtocolMessageType('ManticoreState', (_message.Message,), {
'DESCRIPTOR' : _MANTICORESTATE,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.ManticoreState)
})
_sym_db.RegisterMessage(ManticoreState)
ManticoreStateList = _reflection.GeneratedProtocolMessageType('ManticoreStateList', (_message.Message,), {
'DESCRIPTOR' : _MANTICORESTATELIST,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.ManticoreStateList)
})
_sym_db.RegisterMessage(ManticoreStateList)
ManticoreInstance = _reflection.GeneratedProtocolMessageType('ManticoreInstance', (_message.Message,), {
'DESCRIPTOR' : _MANTICOREINSTANCE,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.ManticoreInstance)
})
_sym_db.RegisterMessage(ManticoreInstance)
TerminateResponse = _reflection.GeneratedProtocolMessageType('TerminateResponse', (_message.Message,), {
'DESCRIPTOR' : _TERMINATERESPONSE,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.TerminateResponse)
})
_sym_db.RegisterMessage(TerminateResponse)
Hook = _reflection.GeneratedProtocolMessageType('Hook', (_message.Message,), {
'DESCRIPTOR' : _HOOK,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.Hook)
})
_sym_db.RegisterMessage(Hook)
NativeArguments = _reflection.GeneratedProtocolMessageType('NativeArguments', (_message.Message,), {
'DESCRIPTOR' : _NATIVEARGUMENTS,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.NativeArguments)
})
_sym_db.RegisterMessage(NativeArguments)
EVMArguments = _reflection.GeneratedProtocolMessageType('EVMArguments', (_message.Message,), {
'DESCRIPTOR' : _EVMARGUMENTS,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.EVMArguments)
})
_sym_db.RegisterMessage(EVMArguments)
ManticoreRunningStatus = _reflection.GeneratedProtocolMessageType('ManticoreRunningStatus', (_message.Message,), {
'DESCRIPTOR' : _MANTICORERUNNINGSTATUS,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.ManticoreRunningStatus)
})
_sym_db.RegisterMessage(ManticoreRunningStatus)
StopServerRequest = _reflection.GeneratedProtocolMessageType('StopServerRequest', (_message.Message,), {
'DESCRIPTOR' : _STOPSERVERREQUEST,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.StopServerRequest)
})
_sym_db.RegisterMessage(StopServerRequest)
StopServerResponse = _reflection.GeneratedProtocolMessageType('StopServerResponse', (_message.Message,), {
'DESCRIPTOR' : _STOPSERVERRESPONSE,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.StopServerResponse)
})
_sym_db.RegisterMessage(StopServerResponse)
ControlStateRequest = _reflection.GeneratedProtocolMessageType('ControlStateRequest', (_message.Message,), {
'DESCRIPTOR' : _CONTROLSTATEREQUEST,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.ControlStateRequest)
})
_sym_db.RegisterMessage(ControlStateRequest)
ControlStateResponse = _reflection.GeneratedProtocolMessageType('ControlStateResponse', (_message.Message,), {
'DESCRIPTOR' : _CONTROLSTATERESPONSE,
'__module__' : 'manticore_server.ManticoreServer_pb2'
# @@protoc_insertion_point(class_scope:manticore_server.ControlStateResponse)
})
_sym_db.RegisterMessage(ControlStateResponse)
_MANTICORESERVER = DESCRIPTOR.services_by_name['ManticoreServer']
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_MANTICORELOGMESSAGE._serialized_start=60
_MANTICORELOGMESSAGE._serialized_end=98
_MANTICOREMESSAGELIST._serialized_start=100
_MANTICOREMESSAGELIST._serialized_end=179
_MANTICORESTATE._serialized_start=181
_MANTICORESTATE._serialized_end=287
_MANTICORESTATELIST._serialized_start=290
_MANTICORESTATELIST._serialized_end=656
_MANTICOREINSTANCE._serialized_start=658
_MANTICOREINSTANCE._serialized_end=691
_TERMINATERESPONSE._serialized_start=693
_TERMINATERESPONSE._serialized_end=712
_HOOK._serialized_start=715
_HOOK._serialized_end=897
_HOOK_HOOKTYPE._serialized_start=816
_HOOK_HOOKTYPE._serialized_end=871
_NATIVEARGUMENTS._serialized_start=900
_NATIVEARGUMENTS._serialized_end=1233
_EVMARGUMENTS._serialized_start=1236
_EVMARGUMENTS._serialized_end=1472
_MANTICORERUNNINGSTATUS._serialized_start=1474
_MANTICORERUNNINGSTATUS._serialized_end=1518
_STOPSERVERREQUEST._serialized_start=1520
_STOPSERVERREQUEST._serialized_end=1539
_STOPSERVERRESPONSE._serialized_start=1541
_STOPSERVERRESPONSE._serialized_end=1561
_CONTROLSTATEREQUEST._serialized_start=1564
_CONTROLSTATEREQUEST._serialized_end=1783
_CONTROLSTATEREQUEST_STATEACTION._serialized_start=1737
_CONTROLSTATEREQUEST_STATEACTION._serialized_end=1783
_CONTROLSTATERESPONSE._serialized_start=1785
_CONTROLSTATERESPONSE._serialized_end=1807
_MANTICORESERVER._serialized_start=1810
_MANTICORESERVER._serialized_end=2572
# @@protoc_insertion_point(module_scope)
@@ -0,0 +1,346 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""
import builtins
import collections.abc
import google.protobuf.descriptor
import google.protobuf.internal.containers
import google.protobuf.internal.enum_type_wrapper
import google.protobuf.message
import sys
import typing
if sys.version_info >= (3, 10):
import typing as typing_extensions
else:
import typing_extensions
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
class ManticoreLogMessage(google.protobuf.message.Message):
"""LogMessage and StateList message types have "Manticore" in their names to distinguish them from those in mserialize"""
DESCRIPTOR: google.protobuf.descriptor.Descriptor
CONTENT_FIELD_NUMBER: builtins.int
content: builtins.str
def __init__(
self,
*,
content: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing_extensions.Literal["content", b"content"]) -> None: ...
global___ManticoreLogMessage = ManticoreLogMessage
class ManticoreMessageList(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
MESSAGES_FIELD_NUMBER: builtins.int
@property
def messages(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ManticoreLogMessage]: ...
def __init__(
self,
*,
messages: collections.abc.Iterable[global___ManticoreLogMessage] | None = ...,
) -> None: ...
def ClearField(self, field_name: typing_extensions.Literal["messages", b"messages"]) -> None: ...
global___ManticoreMessageList = ManticoreMessageList
class ManticoreState(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
STATE_ID_FIELD_NUMBER: builtins.int
PC_FIELD_NUMBER: builtins.int
PARENT_ID_FIELD_NUMBER: builtins.int
CHILDREN_IDS_FIELD_NUMBER: builtins.int
state_id: builtins.int
pc: builtins.int
parent_id: builtins.int
@property
def children_ids(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ...
def __init__(
self,
*,
state_id: builtins.int = ...,
pc: builtins.int = ...,
parent_id: builtins.int | None = ...,
children_ids: collections.abc.Iterable[builtins.int] | None = ...,
) -> None: ...
def HasField(self, field_name: typing_extensions.Literal["_parent_id", b"_parent_id", "parent_id", b"parent_id"]) -> builtins.bool: ...
def ClearField(self, field_name: typing_extensions.Literal["_parent_id", b"_parent_id", "children_ids", b"children_ids", "parent_id", b"parent_id", "pc", b"pc", "state_id", b"state_id"]) -> None: ...
def WhichOneof(self, oneof_group: typing_extensions.Literal["_parent_id", b"_parent_id"]) -> typing_extensions.Literal["parent_id"] | None: ...
global___ManticoreState = ManticoreState
class ManticoreStateList(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
ACTIVE_STATES_FIELD_NUMBER: builtins.int
WAITING_STATES_FIELD_NUMBER: builtins.int
FORKED_STATES_FIELD_NUMBER: builtins.int
ERRORED_STATES_FIELD_NUMBER: builtins.int
COMPLETE_STATES_FIELD_NUMBER: builtins.int
PAUSED_STATES_FIELD_NUMBER: builtins.int
@property
def active_states(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ManticoreState]:
"""state categories in Manticore - based on manticore enums StateStatus and StateList"""
@property
def waiting_states(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ManticoreState]: ...
@property
def forked_states(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ManticoreState]: ...
@property
def errored_states(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ManticoreState]: ...
@property
def complete_states(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ManticoreState]: ...
@property
def paused_states(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___ManticoreState]: ...
def __init__(
self,
*,
active_states: collections.abc.Iterable[global___ManticoreState] | None = ...,
waiting_states: collections.abc.Iterable[global___ManticoreState] | None = ...,
forked_states: collections.abc.Iterable[global___ManticoreState] | None = ...,
errored_states: collections.abc.Iterable[global___ManticoreState] | None = ...,
complete_states: collections.abc.Iterable[global___ManticoreState] | None = ...,
paused_states: collections.abc.Iterable[global___ManticoreState] | None = ...,
) -> None: ...
def ClearField(self, field_name: typing_extensions.Literal["active_states", b"active_states", "complete_states", b"complete_states", "errored_states", b"errored_states", "forked_states", b"forked_states", "paused_states", b"paused_states", "waiting_states", b"waiting_states"]) -> None: ...
global___ManticoreStateList = ManticoreStateList
class ManticoreInstance(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
UUID_FIELD_NUMBER: builtins.int
uuid: builtins.str
def __init__(
self,
*,
uuid: builtins.str = ...,
) -> None: ...
def ClearField(self, field_name: typing_extensions.Literal["uuid", b"uuid"]) -> None: ...
global___ManticoreInstance = ManticoreInstance
class TerminateResponse(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
def __init__(
self,
) -> None: ...
global___TerminateResponse = TerminateResponse
class Hook(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _HookType:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _HookTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Hook._HookType.ValueType], builtins.type): # noqa: F821
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
FIND: Hook._HookType.ValueType # 0
AVOID: Hook._HookType.ValueType # 1
CUSTOM: Hook._HookType.ValueType # 2
GLOBAL: Hook._HookType.ValueType # 3
class HookType(_HookType, metaclass=_HookTypeEnumTypeWrapper): ...
FIND: Hook.HookType.ValueType # 0
AVOID: Hook.HookType.ValueType # 1
CUSTOM: Hook.HookType.ValueType # 2
GLOBAL: Hook.HookType.ValueType # 3
ADDRESS_FIELD_NUMBER: builtins.int
TYPE_FIELD_NUMBER: builtins.int
FUNC_TEXT_FIELD_NUMBER: builtins.int
address: builtins.int
type: global___Hook.HookType.ValueType
func_text: builtins.str
def __init__(
self,
*,
address: builtins.int | None = ...,
type: global___Hook.HookType.ValueType = ...,
func_text: builtins.str | None = ...,
) -> None: ...
def HasField(self, field_name: typing_extensions.Literal["_address", b"_address", "_func_text", b"_func_text", "address", b"address", "func_text", b"func_text"]) -> builtins.bool: ...
def ClearField(self, field_name: typing_extensions.Literal["_address", b"_address", "_func_text", b"_func_text", "address", b"address", "func_text", b"func_text", "type", b"type"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_address", b"_address"]) -> typing_extensions.Literal["address"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_func_text", b"_func_text"]) -> typing_extensions.Literal["func_text"] | None: ...
global___Hook = Hook
class NativeArguments(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
PROGRAM_PATH_FIELD_NUMBER: builtins.int
BINARY_ARGS_FIELD_NUMBER: builtins.int
ENVP_FIELD_NUMBER: builtins.int
SYMBOLIC_FILES_FIELD_NUMBER: builtins.int
CONCRETE_START_FIELD_NUMBER: builtins.int
STDIN_SIZE_FIELD_NUMBER: builtins.int
ADDITIONAL_MCORE_ARGS_FIELD_NUMBER: builtins.int
HOOKS_FIELD_NUMBER: builtins.int
EMULATE_UNTIL_FIELD_NUMBER: builtins.int
program_path: builtins.str
@property
def binary_args(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ...
@property
def envp(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ...
@property
def symbolic_files(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ...
concrete_start: builtins.str
stdin_size: builtins.str
additional_mcore_args: builtins.str
@property
def hooks(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Hook]: ...
emulate_until: builtins.int
def __init__(
self,
*,
program_path: builtins.str = ...,
binary_args: collections.abc.Iterable[builtins.str] | None = ...,
envp: collections.abc.Iterable[builtins.str] | None = ...,
symbolic_files: collections.abc.Iterable[builtins.str] | None = ...,
concrete_start: builtins.str | None = ...,
stdin_size: builtins.str | None = ...,
additional_mcore_args: builtins.str | None = ...,
hooks: collections.abc.Iterable[global___Hook] | None = ...,
emulate_until: builtins.int | None = ...,
) -> None: ...
def HasField(self, field_name: typing_extensions.Literal["_additional_mcore_args", b"_additional_mcore_args", "_concrete_start", b"_concrete_start", "_emulate_until", b"_emulate_until", "_stdin_size", b"_stdin_size", "additional_mcore_args", b"additional_mcore_args", "concrete_start", b"concrete_start", "emulate_until", b"emulate_until", "stdin_size", b"stdin_size"]) -> builtins.bool: ...
def ClearField(self, field_name: typing_extensions.Literal["_additional_mcore_args", b"_additional_mcore_args", "_concrete_start", b"_concrete_start", "_emulate_until", b"_emulate_until", "_stdin_size", b"_stdin_size", "additional_mcore_args", b"additional_mcore_args", "binary_args", b"binary_args", "concrete_start", b"concrete_start", "emulate_until", b"emulate_until", "envp", b"envp", "hooks", b"hooks", "program_path", b"program_path", "stdin_size", b"stdin_size", "symbolic_files", b"symbolic_files"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_additional_mcore_args", b"_additional_mcore_args"]) -> typing_extensions.Literal["additional_mcore_args"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_concrete_start", b"_concrete_start"]) -> typing_extensions.Literal["concrete_start"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_emulate_until", b"_emulate_until"]) -> typing_extensions.Literal["emulate_until"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_stdin_size", b"_stdin_size"]) -> typing_extensions.Literal["stdin_size"] | None: ...
global___NativeArguments = NativeArguments
class EVMArguments(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
CONTRACT_PATH_FIELD_NUMBER: builtins.int
CONTRACT_NAME_FIELD_NUMBER: builtins.int
SOLC_BIN_FIELD_NUMBER: builtins.int
TX_LIMIT_FIELD_NUMBER: builtins.int
TX_ACCOUNT_FIELD_NUMBER: builtins.int
DETECTORS_TO_EXCLUDE_FIELD_NUMBER: builtins.int
ADDITIONAL_FLAGS_FIELD_NUMBER: builtins.int
contract_path: builtins.str
contract_name: builtins.str
solc_bin: builtins.str
tx_limit: builtins.str
tx_account: builtins.str
@property
def detectors_to_exclude(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.str]: ...
additional_flags: builtins.str
def __init__(
self,
*,
contract_path: builtins.str = ...,
contract_name: builtins.str = ...,
solc_bin: builtins.str = ...,
tx_limit: builtins.str | None = ...,
tx_account: builtins.str | None = ...,
detectors_to_exclude: collections.abc.Iterable[builtins.str] | None = ...,
additional_flags: builtins.str | None = ...,
) -> None: ...
def HasField(self, field_name: typing_extensions.Literal["_additional_flags", b"_additional_flags", "_tx_account", b"_tx_account", "_tx_limit", b"_tx_limit", "additional_flags", b"additional_flags", "tx_account", b"tx_account", "tx_limit", b"tx_limit"]) -> builtins.bool: ...
def ClearField(self, field_name: typing_extensions.Literal["_additional_flags", b"_additional_flags", "_tx_account", b"_tx_account", "_tx_limit", b"_tx_limit", "additional_flags", b"additional_flags", "contract_name", b"contract_name", "contract_path", b"contract_path", "detectors_to_exclude", b"detectors_to_exclude", "solc_bin", b"solc_bin", "tx_account", b"tx_account", "tx_limit", b"tx_limit"]) -> None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_additional_flags", b"_additional_flags"]) -> typing_extensions.Literal["additional_flags"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_tx_account", b"_tx_account"]) -> typing_extensions.Literal["tx_account"] | None: ...
@typing.overload
def WhichOneof(self, oneof_group: typing_extensions.Literal["_tx_limit", b"_tx_limit"]) -> typing_extensions.Literal["tx_limit"] | None: ...
global___EVMArguments = EVMArguments
class ManticoreRunningStatus(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
IS_RUNNING_FIELD_NUMBER: builtins.int
is_running: builtins.bool
def __init__(
self,
*,
is_running: builtins.bool = ...,
) -> None: ...
def ClearField(self, field_name: typing_extensions.Literal["is_running", b"is_running"]) -> None: ...
global___ManticoreRunningStatus = ManticoreRunningStatus
class StopServerRequest(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
def __init__(
self,
) -> None: ...
global___StopServerRequest = StopServerRequest
class StopServerResponse(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
def __init__(
self,
) -> None: ...
global___StopServerResponse = StopServerResponse
class ControlStateRequest(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
class _StateAction:
ValueType = typing.NewType("ValueType", builtins.int)
V: typing_extensions.TypeAlias = ValueType
class _StateActionEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ControlStateRequest._StateAction.ValueType], builtins.type): # noqa: F821
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
RESUME: ControlStateRequest._StateAction.ValueType # 0
PAUSE: ControlStateRequest._StateAction.ValueType # 1
KILL: ControlStateRequest._StateAction.ValueType # 2
class StateAction(_StateAction, metaclass=_StateActionEnumTypeWrapper): ...
RESUME: ControlStateRequest.StateAction.ValueType # 0
PAUSE: ControlStateRequest.StateAction.ValueType # 1
KILL: ControlStateRequest.StateAction.ValueType # 2
STATE_ID_FIELD_NUMBER: builtins.int
MANTICORE_INSTANCE_FIELD_NUMBER: builtins.int
ACTION_FIELD_NUMBER: builtins.int
state_id: builtins.int
@property
def manticore_instance(self) -> global___ManticoreInstance: ...
action: global___ControlStateRequest.StateAction.ValueType
def __init__(
self,
*,
state_id: builtins.int = ...,
manticore_instance: global___ManticoreInstance | None = ...,
action: global___ControlStateRequest.StateAction.ValueType = ...,
) -> None: ...
def HasField(self, field_name: typing_extensions.Literal["manticore_instance", b"manticore_instance"]) -> builtins.bool: ...
def ClearField(self, field_name: typing_extensions.Literal["action", b"action", "manticore_instance", b"manticore_instance", "state_id", b"state_id"]) -> None: ...
global___ControlStateRequest = ControlStateRequest
class ControlStateResponse(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
def __init__(
self,
) -> None: ...
global___ControlStateResponse = ControlStateResponse
@@ -0,0 +1,297 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
from manticore_server import ManticoreServer_pb2 as manticore__server_dot_ManticoreServer__pb2
class ManticoreServerStub(object):
"""Missing associated documentation comment in .proto file."""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.StartNative = channel.unary_unary(
'/manticore_server.ManticoreServer/StartNative',
request_serializer=manticore__server_dot_ManticoreServer__pb2.NativeArguments.SerializeToString,
response_deserializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.FromString,
)
self.StartEVM = channel.unary_unary(
'/manticore_server.ManticoreServer/StartEVM',
request_serializer=manticore__server_dot_ManticoreServer__pb2.EVMArguments.SerializeToString,
response_deserializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.FromString,
)
self.Terminate = channel.unary_unary(
'/manticore_server.ManticoreServer/Terminate',
request_serializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.SerializeToString,
response_deserializer=manticore__server_dot_ManticoreServer__pb2.TerminateResponse.FromString,
)
self.GetStateList = channel.unary_unary(
'/manticore_server.ManticoreServer/GetStateList',
request_serializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.SerializeToString,
response_deserializer=manticore__server_dot_ManticoreServer__pb2.ManticoreStateList.FromString,
)
self.GetMessageList = channel.unary_unary(
'/manticore_server.ManticoreServer/GetMessageList',
request_serializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.SerializeToString,
response_deserializer=manticore__server_dot_ManticoreServer__pb2.ManticoreMessageList.FromString,
)
self.CheckManticoreRunning = channel.unary_unary(
'/manticore_server.ManticoreServer/CheckManticoreRunning',
request_serializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.SerializeToString,
response_deserializer=manticore__server_dot_ManticoreServer__pb2.ManticoreRunningStatus.FromString,
)
self.StopServer = channel.unary_unary(
'/manticore_server.ManticoreServer/StopServer',
request_serializer=manticore__server_dot_ManticoreServer__pb2.StopServerRequest.SerializeToString,
response_deserializer=manticore__server_dot_ManticoreServer__pb2.StopServerResponse.FromString,
)
self.ControlState = channel.unary_unary(
'/manticore_server.ManticoreServer/ControlState',
request_serializer=manticore__server_dot_ManticoreServer__pb2.ControlStateRequest.SerializeToString,
response_deserializer=manticore__server_dot_ManticoreServer__pb2.ControlStateResponse.FromString,
)
class ManticoreServerServicer(object):
"""Missing associated documentation comment in .proto file."""
def StartNative(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def StartEVM(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def Terminate(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetStateList(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def GetMessageList(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def CheckManticoreRunning(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def StopServer(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def ControlState(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_ManticoreServerServicer_to_server(servicer, server):
rpc_method_handlers = {
'StartNative': grpc.unary_unary_rpc_method_handler(
servicer.StartNative,
request_deserializer=manticore__server_dot_ManticoreServer__pb2.NativeArguments.FromString,
response_serializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.SerializeToString,
),
'StartEVM': grpc.unary_unary_rpc_method_handler(
servicer.StartEVM,
request_deserializer=manticore__server_dot_ManticoreServer__pb2.EVMArguments.FromString,
response_serializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.SerializeToString,
),
'Terminate': grpc.unary_unary_rpc_method_handler(
servicer.Terminate,
request_deserializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.FromString,
response_serializer=manticore__server_dot_ManticoreServer__pb2.TerminateResponse.SerializeToString,
),
'GetStateList': grpc.unary_unary_rpc_method_handler(
servicer.GetStateList,
request_deserializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.FromString,
response_serializer=manticore__server_dot_ManticoreServer__pb2.ManticoreStateList.SerializeToString,
),
'GetMessageList': grpc.unary_unary_rpc_method_handler(
servicer.GetMessageList,
request_deserializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.FromString,
response_serializer=manticore__server_dot_ManticoreServer__pb2.ManticoreMessageList.SerializeToString,
),
'CheckManticoreRunning': grpc.unary_unary_rpc_method_handler(
servicer.CheckManticoreRunning,
request_deserializer=manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.FromString,
response_serializer=manticore__server_dot_ManticoreServer__pb2.ManticoreRunningStatus.SerializeToString,
),
'StopServer': grpc.unary_unary_rpc_method_handler(
servicer.StopServer,
request_deserializer=manticore__server_dot_ManticoreServer__pb2.StopServerRequest.FromString,
response_serializer=manticore__server_dot_ManticoreServer__pb2.StopServerResponse.SerializeToString,
),
'ControlState': grpc.unary_unary_rpc_method_handler(
servicer.ControlState,
request_deserializer=manticore__server_dot_ManticoreServer__pb2.ControlStateRequest.FromString,
response_serializer=manticore__server_dot_ManticoreServer__pb2.ControlStateResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'manticore_server.ManticoreServer', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class ManticoreServer(object):
"""Missing associated documentation comment in .proto file."""
@staticmethod
def StartNative(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/manticore_server.ManticoreServer/StartNative',
manticore__server_dot_ManticoreServer__pb2.NativeArguments.SerializeToString,
manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def StartEVM(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/manticore_server.ManticoreServer/StartEVM',
manticore__server_dot_ManticoreServer__pb2.EVMArguments.SerializeToString,
manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def Terminate(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/manticore_server.ManticoreServer/Terminate',
manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.SerializeToString,
manticore__server_dot_ManticoreServer__pb2.TerminateResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def GetStateList(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/manticore_server.ManticoreServer/GetStateList',
manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.SerializeToString,
manticore__server_dot_ManticoreServer__pb2.ManticoreStateList.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def GetMessageList(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/manticore_server.ManticoreServer/GetMessageList',
manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.SerializeToString,
manticore__server_dot_ManticoreServer__pb2.ManticoreMessageList.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def CheckManticoreRunning(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/manticore_server.ManticoreServer/CheckManticoreRunning',
manticore__server_dot_ManticoreServer__pb2.ManticoreInstance.SerializeToString,
manticore__server_dot_ManticoreServer__pb2.ManticoreRunningStatus.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def StopServer(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/manticore_server.ManticoreServer/StopServer',
manticore__server_dot_ManticoreServer__pb2.StopServerRequest.SerializeToString,
manticore__server_dot_ManticoreServer__pb2.StopServerResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
@staticmethod
def ControlState(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/manticore_server.ManticoreServer/ControlState',
manticore__server_dot_ManticoreServer__pb2.ControlStateRequest.SerializeToString,
manticore__server_dot_ManticoreServer__pb2.ControlStateResponse.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
+1
View File
@@ -0,0 +1 @@
from . import manticore_server
+200
View File
@@ -0,0 +1,200 @@
import argparse
import logging
import shlex
from typing import List, Type
from crytic_compile import cryticparser
from manticore.core.plugin import Profiler
from manticore.ethereum import (
DetectDelegatecall,
DetectEnvInstruction,
DetectExternalCallAndLeak,
DetectIntegerOverflow,
DetectInvalid,
DetectManipulableBalance,
Detector,
DetectReentrancyAdvanced,
DetectReentrancySimple,
DetectSuicidal,
DetectUninitializedMemory,
DetectUninitializedStorage,
DetectUnusedRetVal,
ManticoreEVM,
)
from manticore.ethereum.plugins import (
FilterFunctions,
KeepOnlyIfStorageChanges,
LoopDepthLimiter,
SkipRevertBasicBlocks,
VerboseTrace,
)
from manticore.utils import config
logger = logging.getLogger(__name__)
def get_detectors_classes() -> List[Type[Detector]]:
return [
DetectInvalid,
DetectIntegerOverflow,
DetectUninitializedStorage,
DetectUninitializedMemory,
DetectReentrancySimple,
DetectReentrancyAdvanced,
DetectUnusedRetVal,
DetectSuicidal,
DetectDelegatecall,
DetectExternalCallAndLeak,
DetectEnvInstruction,
DetectManipulableBalance,
# The RaceCondition detector has been disabled for now as it seems to collide with IntegerOverflow detector
# DetectRaceCondition
]
def parse_detectors(detectors_to_exclude: List[str]) -> List[Type[Detector]]:
"""returns a list of detectors that should be used"""
all_detector_classes = get_detectors_classes()
all_detector_args = map(lambda x: x.ARGUMENT, all_detector_classes)
for d in detectors_to_exclude:
if d not in all_detector_args:
raise Exception(
f"{d} is not a detector name, must be one of {list(all_detector_args)}. See also `--list-detectors`."
)
return [d for d in all_detector_classes if d.ARGUMENT not in detectors_to_exclude]
# TODO(ekilmer): This could be refactored to reduce duplication in main manticore package
def setup_detectors_flags(
detectors_to_exclude: List[str], additional_flags: str, m: ManticoreEVM
) -> argparse.Namespace:
"""parse and apply additional arguments for manticore EVM execution, CLI-style"""
parser = argparse.ArgumentParser(
description="Symbolic execution tool",
prog="manticore",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
consts = config.get_group("main")
consts.add("profile", default=False, description="Enable worker profiling mode")
consts.add(
"explore_balance",
default=False,
description="Explore states in which only the balance was changed",
)
consts.add(
"skip_reverts",
default=False,
description="Simply avoid exploring basic blocks that end in a REVERT",
)
# Add crytic compile arguments
# See https://github.com/crytic/crytic-compile/wiki/Configuration
cryticparser.init(parser)
eth_flags = parser.add_argument_group("Ethereum flags")
eth_flags.add_argument(
"--verbose-trace",
action="store_true",
help="Dump an extra verbose trace for each state",
)
eth_flags.add_argument(
"--txnocoverage",
action="store_true",
help="Do not use coverage as stopping criteria",
)
eth_flags.add_argument(
"--txnoether",
action="store_true",
help="Do not attempt to send ether to contract",
)
eth_flags.add_argument(
"--txpreconstrain",
action="store_true",
help="Constrain human transactions to avoid exceptions in the contract function dispatcher",
)
eth_flags.add_argument(
"--avoid-constant",
action="store_true",
help="Avoid exploring constant functions for human transactions",
)
eth_flags.add_argument(
"--limit-loops",
action="store_true",
help="Limit loops depth",
)
eth_flags.add_argument(
"--no-testcases",
action="store_true",
help="Do not generate testcases for discovered states when analysis finishes",
)
eth_flags.add_argument(
"--only-alive-testcases",
action="store_true",
help="Do not generate testcases for invalid/throwing states when analysis finishes",
)
eth_flags.add_argument(
"--thorough-mode",
action="store_true",
help="Configure Manticore for more exhaustive exploration. Evaluate gas, generate testcases for dead states, "
"explore constant functions, and run a small suite of detectors.",
)
config_flags = parser.add_argument_group("Constants")
config.add_config_vars_to_argparse(config_flags)
args = parser.parse_args(shlex.split(additional_flags))
config.process_config_values(parser, args)
if not args.thorough_mode:
args.avoid_constant = True
args.exclude_all = True
args.only_alive_testcases = True
consts_evm = config.get_group("evm")
consts_evm.oog = "ignore"
consts.skip_reverts = True
if consts.skip_reverts:
m.register_plugin(SkipRevertBasicBlocks())
if consts.explore_balance:
m.register_plugin(KeepOnlyIfStorageChanges())
if args.verbose_trace:
m.register_plugin(VerboseTrace())
if args.limit_loops:
m.register_plugin(LoopDepthLimiter())
for detector in parse_detectors(detectors_to_exclude):
m.register_plugin(detector())
if consts.profile:
profiler = Profiler()
m.register_plugin(profiler)
if args.avoid_constant:
# avoid all human level tx that has no effect on the storage
filter_nohuman_constants = FilterFunctions(
regexp=r".*", depth="human", mutability="constant", include=False
)
m.register_plugin(filter_nohuman_constants)
if m.plugins:
logger.info(
f'Registered plugins: {", ".join(d.name for d in m.plugins.values())}'
)
return args
@@ -0,0 +1,45 @@
import logging
from datetime import datetime
from manticore.core.plugin import IntrospectionAPIPlugin, StateDescriptor
from manticore.core.state import StateBase
from manticore.utils.enums import StateLists
logger = logging.getLogger(__name__)
class ManticoreServerIntrospectionPlugin(IntrospectionAPIPlugin):
NAME = "ManticoreServerIntrospectionPlugin"
@property
def name(self) -> str:
return "ManticoreServerIntrospectionPlugin"
def create_state(self, state_id: int):
"""Override create_state to force a state update right after creation.
This is helpful when retrieving info from a state yet to execute."""
super().create_state(state_id)
state = self.manticore._load(state_id)
self._force_update_state_descriptor(state)
def will_fork_state_callback(self, state: StateBase, expression, solutions, policy):
self._force_update_state_descriptor(state)
def will_transition_state_callback(
self, state_id: int, from_list: StateLists, to_list: StateLists
):
state = self.manticore._load(state_id)
self._force_update_state_descriptor(state)
def _force_update_state_descriptor(self, state: StateBase):
"""Force a given state to update its information, which can include the current PC, etc.
Calling _update_state_descriptor directly may become an issue if specific state implementations
start to require additional arguments for this method."""
with self.locked_context("manticore_state", dict) as context:
state._update_state_descriptor(
context.setdefault(state.id, StateDescriptor(state_id=state.id)),
)
context[state.id].last_intermittent_update = datetime.now()
def did_terminate_worker_callback(self, worker_id: int):
logger.debug(f"worker exits (id: {worker_id})")
+552
View File
@@ -0,0 +1,552 @@
import argparse
import dataclasses
import logging
import shutil
import time
import uuid
from collections import defaultdict
from concurrent import futures
from pathlib import Path
from threading import Event, Thread
from typing import Any, Callable, Dict, Optional, Set
import grpc
from grpc._server import _Context
from manticore.core.plugin import (
InstructionCounter,
RecordSymbolicBranches,
StateDescriptor,
Tracer,
Visited,
)
from manticore.core.state import StateBase, TerminateState
from manticore.core.worker import WorkerProcess, WorkerThread
from manticore.ethereum import ManticoreEVM
from manticore.native import Manticore
from manticore.utils.enums import StateLists, StateStatus
from manticore.utils.helpers import deque
from manticore.utils.log import CallbackStream, ManticoreContextFilter
from .evm_utils import setup_detectors_flags
from .introspect_plugin import ManticoreServerIntrospectionPlugin
from .ManticoreServer_pb2 import *
from .ManticoreServer_pb2_grpc import (
ManticoreServerServicer,
add_ManticoreServerServicer_to_server,
)
from .native_plugin import UnicornEmulatePlugin
from .native_utils import parse_native_arguments
logger = logging.getLogger(__name__)
class ManticoreWrapper:
def __init__(
self, mcore_object: Manticore, thread_target: Callable, *thread_args: Any
):
self.uuid: str = uuid.uuid4().hex
self.manticore_object: Manticore = mcore_object
# mimics Manticore repository, reasoning for the queue size difference is provided in Manticore:
# https://github.com/trailofbits/manticore/blob/5a258f499098394c0af25e2e3f00b1b603c2334d/manticore/core/manticore.py#L133-L135
self.log_queue = (
mcore_object._manager.Queue(15000)
if mcore_object._worker_type == WorkerProcess
else deque(maxlen=5000)
)
# contains the state ids of all states paused by the user through the ControlState rpc
self.paused_states: Set[int] = set()
# saves a copy of all state descriptors after analysis is complete or terminated
# but before the finalize() operation which destroys all states
self.final_states: Optional[Dict[int, StateDescriptor]] = None
self.state_callbacks: Dict[int, Set[Callable]] = defaultdict(set)
self.thread: Thread = Thread(
target=thread_target,
args=(self,) + thread_args,
daemon=True,
name=self.uuid,
)
def start(self) -> None:
self.thread.start()
def append_log(self, msg: str) -> None:
q = self.log_queue
try:
q.append(msg)
except AttributeError:
# mimics Manticore repository, reasoning for using append and catching an AttributeError is provided in Manticore:
# https://github.com/trailofbits/manticore/blob/5a258f499098394c0af25e2e3f00b1b603c2334d/manticore/core/worker.py#L297-L303
if q.full():
q.get()
q.put(msg)
class ManticoreServicer(ManticoreServerServicer):
"""Provides functionality for the methods set out in the protobuf spec"""
def __init__(self, stop_event: Event):
"""Initializes the dict that keeps track of all created manticore instances, as well as avoid/find address set"""
self.manticore_instances: Dict[str, ManticoreWrapper] = {}
self.stop_event: Event = stop_event
manticore_logger = logging.getLogger("manticore")
manticore_logger.parent = None
manticore_logger.setLevel(logging.WARNING)
custom_log_handler = logging.StreamHandler(CallbackStream(self.log_callback))
custom_log_handler.setFormatter(
logging.Formatter(
"%(threadName)s %(asctime)s: [%(process)d] %(name)s:%(levelname)s %(message)s"
)
)
custom_log_handler.addFilter(ManticoreContextFilter())
manticore_logger.addHandler(custom_log_handler)
def log_callback(self, msg: str):
logger.debug(msg)
thread_name, msg_content = msg.split(" ", 1)
if thread_name in self.manticore_instances:
# This will always be True if multiprocessing or single is used, since all WorkerProcess/WorkerSingle
# instances will share the same Thread name as the ManticoreWrapper's mthread which is added on Start
self.manticore_instances[thread_name].append_log(msg_content)
else:
for mwrapper in filter(
lambda x: x.manticore_object._worker_type == WorkerThread,
list(self.manticore_instances.values())[::-1],
): # Thread name/idents can be reused, so start search from most recently-started instance
for worker in mwrapper.manticore_object._workers + list(
mwrapper.manticore_object._daemon_threads.values()
):
if type(worker._t) == Thread and worker._t.name == thread_name:
worker._t.name = mwrapper.uuid
mwrapper.append_log(msg_content)
return
def StartNative(
self, native_arguments: NativeArguments, context: _Context
) -> ManticoreInstance:
"""Starts a singular Manticore instance to analyze a native binary"""
try:
parsed = parse_native_arguments(native_arguments.additional_mcore_args)
except Exception as e:
logger.debug(e)
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details("Additional arguments could not be parsed!")
return ManticoreInstance()
try:
m = Manticore.linux(
native_arguments.program_path,
argv=None
if not native_arguments.binary_args
else list(native_arguments.binary_args),
envp=None
if not native_arguments.envp
else {
key: val
for key, val in [e.split("=") for e in native_arguments.envp]
},
symbolic_files=None
if not native_arguments.symbolic_files
else list(native_arguments.symbolic_files),
concrete_start=""
if not native_arguments.concrete_start
else native_arguments.concrete_start,
stdin_size=265
if not native_arguments.stdin_size
else int(native_arguments.stdin_size),
workspace_url=parsed.workspace,
introspection_plugin_type=ManticoreServerIntrospectionPlugin,
)
except Exception as e:
logger.warning(e)
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details("Basic arguments are invalid!")
return ManticoreInstance()
try:
m.register_plugin(InstructionCounter())
m.register_plugin(Visited(parsed.coverage))
m.register_plugin(Tracer())
m.register_plugin(RecordSymbolicBranches())
if native_arguments.emulate_until:
m.register_plugin(UnicornEmulatePlugin(native_arguments.emulate_until))
if parsed.names is not None:
m.apply_model_hooks(parsed.names)
if parsed.assertions:
m.load_assertions(parsed.assertions)
def find_f(state: StateBase):
bufs = state.solve_one_n_batched(state.input_symbols)
for symbol, buf in zip(state.input_symbols, bufs):
logger.info(f"{symbol.name}: {buf!r}\n")
with m.locked_context() as context:
m.kill()
state.abandon()
def avoid_f(state: StateBase):
state.abandon()
for hook in native_arguments.hooks:
if hook.type == Hook.HookType.FIND:
m.add_hook(hook.address, find_f)
elif hook.type == Hook.HookType.AVOID:
m.add_hook(hook.address, avoid_f)
elif hook.type == Hook.HookType.CUSTOM:
exec(hook.func_text, {"addr": hook.address, "m": m})
elif hook.type == Hook.HookType.GLOBAL:
exec(hook.func_text, {"m": m})
except Exception as e:
logger.warning(e)
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details("Hooks set are invalid!")
return ManticoreInstance()
try:
def manticore_native_runner(mcore_wrapper: ManticoreWrapper):
mcore_wrapper.manticore_object.run()
mcore_wrapper.final_states = {
k: dataclasses.replace(v)
for k, v in mcore_wrapper.manticore_object.introspect().items()
}
mcore_wrapper.manticore_object.finalize()
manticore_wrapper = ManticoreWrapper(m, manticore_native_runner)
self.manticore_instances[manticore_wrapper.uuid] = manticore_wrapper
def state_callback_hook(state: StateBase):
callbacks = manticore_wrapper.state_callbacks[state.id]
for callback in callbacks:
callback(state)
m.hook(None)(state_callback_hook)
manticore_wrapper.start()
except Exception as e:
logger.warning(e)
context.set_code(grpc.StatusCode.INTERNAL)
context.set_details(
"Manticore failed to start or crashed during execution!"
)
return ManticoreInstance()
return ManticoreInstance(uuid=manticore_wrapper.uuid)
def StartEVM(
self, evm_arguments: EVMArguments, context: _Context
) -> ManticoreInstance:
"""Starts a singular Manticore instance to analyze a solidity contract"""
if evm_arguments.contract_path == "":
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details("Contract path not specified!")
return ManticoreInstance()
if not Path(evm_arguments.contract_path).is_file():
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details(
f"Contract path invalid: '{evm_arguments.contract_path}'"
)
return ManticoreInstance()
if evm_arguments.solc_bin:
solc_bin_path = evm_arguments.solc_bin
elif shutil.which("solc"):
solc_bin_path = str(shutil.which("solc"))
else:
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
context.set_details(
f"solc binary neither specified in EVMArguments nor found in PATH!"
)
return ManticoreInstance()
try:
m = ManticoreEVM()
args = setup_detectors_flags(
list(evm_arguments.detectors_to_exclude),
evm_arguments.additional_flags,
m,
)
def manticore_evm_runner(
mcore_wrapper: ManticoreWrapper, args: argparse.Namespace
):
mcore_wrapper.manticore_object.multi_tx_analysis(
evm_arguments.contract_path,
contract_name=evm_arguments.contract_name,
tx_limit=-1
if not evm_arguments.tx_limit
else evm_arguments.tx_limit,
tx_use_coverage=True
if args.txnocoverage == None
else args.txnocoverage,
tx_send_ether=True if args.txnoether == None else args.txnoether,
tx_account="attacker"
if not evm_arguments.tx_account
else evm_arguments.tx_account,
tx_preconstrain=False
if args.txpreconstrain == None
else args.txpreconstrain,
compile_args={"solc_solcs_bin": solc_bin_path},
)
mcore_wrapper.final_states = {
k: dataclasses.replace(v)
for k, v in mcore_wrapper.manticore_object.introspect().items()
}
if not args.no_testcases:
mcore_wrapper.manticore_object.finalize(
only_alive_states=args.only_alive_testcases
)
else:
mcore_wrapper.manticore_object.kill()
manticore_wrapper = ManticoreWrapper(m, manticore_evm_runner, args)
self.manticore_instances[manticore_wrapper.uuid] = manticore_wrapper
manticore_wrapper.start()
except Exception as e:
logger.warning(e)
context.set_code(grpc.StatusCode.INTERNAL)
context.set_details(
"Manticore failed to start or crashed during execution!"
)
return ManticoreInstance()
return ManticoreInstance(uuid=manticore_wrapper.uuid)
def Terminate(
self, mcore_instance: ManticoreInstance, context: _Context
) -> TerminateResponse:
"""Terminates the specified Manticore instance."""
if mcore_instance.uuid not in self.manticore_instances:
context.set_code(grpc.StatusCode.FAILED_PRECONDITION)
context.set_details("Specified Manticore instance not found!")
return TerminateResponse()
m_wrapper = self.manticore_instances[mcore_instance.uuid]
if not (
m_wrapper.manticore_object.is_running() and m_wrapper.thread.is_alive()
):
return TerminateResponse()
m_wrapper.manticore_object.kill()
return TerminateResponse()
def GetStateList(
self, mcore_instance: ManticoreInstance, context: _Context
) -> ManticoreStateList:
"""Returns full list of states for given ManticoreInstance."""
active_states = []
waiting_states = []
paused_states = []
forked_states = []
errored_states = []
complete_states = []
if mcore_instance.uuid not in self.manticore_instances:
context.set_code(grpc.StatusCode.FAILED_PRECONDITION)
context.set_details("Specified Manticore instance not found!")
return ManticoreStateList()
mcore_wrapper = self.manticore_instances[mcore_instance.uuid]
states = (
mcore_wrapper.final_states
if mcore_wrapper.final_states is not None
else mcore_wrapper.manticore_object.introspect()
)
for state_id, state_desc in states.items():
state_args = {"state_id": state_id}
if isinstance(state_desc.pc, int):
state_args["pc"] = state_desc.pc
elif isinstance(state_desc.last_pc, int):
state_args["pc"] = state_desc.last_pc
if isinstance(state_desc.parent, int):
state_args["parent_id"] = state_desc.parent
state_args["children_ids"] = list(state_desc.children)
s = ManticoreState(**state_args)
if state_desc.status == StateStatus.running:
active_states.append(s)
elif state_desc.status in (
StateStatus.waiting_for_solver,
StateStatus.waiting_for_worker,
):
waiting_states.append(s)
elif state_desc.status == StateStatus.destroyed:
forked_states.append(s)
elif state_desc.status == StateStatus.stopped:
if state_id in mcore_wrapper.paused_states:
paused_states.append(s)
elif state_desc.state_list == StateLists.killed:
errored_states.append(s)
else:
complete_states.append(s)
else:
raise ValueError(f"Unknown status {state_desc.status}")
return ManticoreStateList(
active_states=active_states,
waiting_states=waiting_states,
paused_states=paused_states,
forked_states=forked_states,
errored_states=errored_states,
complete_states=complete_states,
)
def GetMessageList(
self, mcore_instance: ManticoreInstance, context: _Context
) -> ManticoreMessageList:
"""Returns any new log messages for given ManticoreInstance since the previous call.
Currently, implementation is based on TUI."""
if mcore_instance.uuid not in self.manticore_instances:
context.set_code(grpc.StatusCode.FAILED_PRECONDITION)
context.set_details("Specified Manticore instance not found!")
return ManticoreMessageList()
q = self.manticore_instances[mcore_instance.uuid].log_queue
i = 0
messages = []
while not q.empty():
msg = ManticoreLogMessage(content=q.get())
messages.append(msg)
i += 1
return ManticoreMessageList(messages=messages)
def CheckManticoreRunning(
self, mcore_instance: ManticoreInstance, context: _Context
) -> ManticoreRunningStatus:
if mcore_instance.uuid not in self.manticore_instances:
context.set_code(grpc.StatusCode.FAILED_PRECONDITION)
context.set_details("Specified Manticore instance not found!")
return ManticoreRunningStatus()
m_wrapper = self.manticore_instances[mcore_instance.uuid]
return ManticoreRunningStatus(is_running=(m_wrapper.thread.is_alive()))
def StopServer(
self, request: StopServerRequest, context: _Context
) -> StopServerResponse:
to_warn = False
for mwrapper in self.manticore_instances.values():
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.thread.is_alive():
time.sleep(1)
if (time.time() - stime) > 10:
to_warn = True
break
if to_warn:
warning_message = "WARNING: Not all Manticore processes were shut down successfully before timeout. There may be extra processes running even after the server has stopped."
context.set_code(grpc.StatusCode.INTERNAL)
context.set_details(warning_message)
logger.warning(warning_message)
self.stop_event.set()
return StopServerResponse()
def ControlState(
self, request: ControlStateRequest, context: _Context
) -> ControlStateResponse:
if request.manticore_instance.uuid not in self.manticore_instances:
context.set_code(grpc.StatusCode.FAILED_PRECONDITION)
context.set_details("Specified Manticore instance not found!")
return ControlStateResponse()
mcore_wrapper = self.manticore_instances[request.manticore_instance.uuid]
mcore_object = mcore_wrapper.manticore_object
states = (
mcore_wrapper.final_states
if mcore_wrapper.final_states is not None
else mcore_object.introspect()
)
if request.state_id not in states:
context.set_code(grpc.StatusCode.FAILED_PRECONDITION)
context.set_details("Specified state not found!")
return ControlStateResponse()
# Pause / Resume / Kill should have no effect if Manticore is no longer running,
# but we do not raise an error to account for latency between CheckStatus() calls
if not mcore_object.is_running():
return ControlStateResponse()
# helper callbacks for state control
def state_pause_hook(state: StateBase) -> None:
mcore_wrapper.state_callbacks[state.id].discard(state_pause_hook)
raise TerminateState("Pausing state")
def state_kill_hook(state: StateBase) -> None:
mcore_wrapper.state_callbacks[state.id].discard(state_kill_hook)
state.abandon()
try:
if request.action == ControlStateRequest.StateAction.PAUSE:
if len(mcore_wrapper.paused_states) == 0:
with mcore_object._lock:
mcore_object._busy_states.append(-1)
mcore_object._lock.notify_all()
mcore_wrapper.state_callbacks[request.state_id].add(state_pause_hook)
mcore_wrapper.paused_states.add(request.state_id)
elif request.action == ControlStateRequest.StateAction.RESUME:
mcore_wrapper.paused_states.discard(request.state_id)
with mcore_object._lock:
mcore_object._revive_state(request.state_id)
if len(mcore_wrapper.paused_states) == 0:
mcore_object._busy_states.remove(-1)
mcore_object._lock.notify_all()
elif request.action == ControlStateRequest.StateAction.KILL:
if request.state_id in mcore_wrapper.paused_states:
mcore_wrapper.paused_states.remove(request.state_id)
if len(mcore_wrapper.paused_states) == 0:
with mcore_object._lock:
mcore_object._busy_states.remove(-1)
mcore_object._lock.notify_all()
else:
mcore_wrapper.state_callbacks[request.state_id].add(state_kill_hook)
except:
context.set_code(grpc.StatusCode.INTERNAL)
context.set_details(
f"Failed apply action {request.action} to state {request.state_id}"
)
return ControlStateResponse()
def main():
logger.setLevel(logging.DEBUG)
port = "[::]:50010"
logger.info(f"server starting at '{port}' ...")
stop_event = Event()
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
add_ManticoreServerServicer_to_server(ManticoreServicer(stop_event), server)
server.add_insecure_port(port)
server.start()
logger.info(f"server started.")
stop_event.wait()
server.stop(None)
logger.info("shutdown gracefully!")
+13
View File
@@ -0,0 +1,13 @@
from manticore.core.plugin import Plugin
class UnicornEmulatePlugin(Plugin):
"""Manticore plugin to speed up emulation using unicorn until `start`"""
def __init__(self, start: int):
super().__init__()
self.start = start
def will_run_callback(self, ready_states):
for state in ready_states:
state.cpu.emulate_until(self.start)
+122
View File
@@ -0,0 +1,122 @@
import argparse
import shlex
import pkg_resources
from manticore.utils import config
from manticore.utils.log import set_verbosity
# TODO(ekilmer): This should be refactored to reduce duplication in main
# manticore package
def parse_native_arguments(additional_args: str) -> argparse.Namespace:
"""parse additional arguments for manticore native execution, CLI-style"""
def positive(value):
ivalue = int(value)
if ivalue <= 0:
raise argparse.ArgumentTypeError("Argument must be positive")
return ivalue
parser = argparse.ArgumentParser(
description="Symbolic execution tool",
prog="manticore",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument("--context", type=str, default=None, help=argparse.SUPPRESS)
parser.add_argument(
"--coverage",
type=str,
default="visited.txt",
help="Where to write the coverage data",
)
parser.add_argument("--names", type=str, default=None, help=argparse.SUPPRESS)
parser.add_argument(
"--no-colors",
action="store_true",
help="Disable ANSI color escape sequences in output",
)
parser.add_argument("--offset", type=int, default=16, help=argparse.SUPPRESS)
parser.add_argument(
"--policy",
type=str,
default="random",
help=(
"Search policy. random|adhoc|uncovered|dicount"
"|icount|syscount|depth. (use + (max) or - (min)"
" to specify order. e.g. +random)"
),
)
parser.add_argument(
"-v", action="count", default=1, help="Specify verbosity level from -v to -vvvv"
)
parser.add_argument(
"--workspace",
type=str,
default=None,
help=("A folder name for temporaries and results." "(default mcore_?????)"),
)
current_version = pkg_resources.get_distribution("manticore").version
parser.add_argument(
"--version",
action="version",
version=f"Manticore {current_version}",
help="Show program version information",
)
parser.add_argument(
"--config",
type=str,
help="Manticore config file (.yml) to use. (default config file pattern is: ./[.]m[anti]core.yml)",
)
bin_flags = parser.add_argument_group("Binary flags")
bin_flags.add_argument(
"--entrysymbol", type=str, default=None, help="Symbol as entry point"
)
bin_flags.add_argument(
"--assertions", type=str, default=None, help=argparse.SUPPRESS
)
bin_flags.add_argument("--buffer", type=str, help=argparse.SUPPRESS)
bin_flags.add_argument(
"--data",
type=str,
default="",
help="Initial concrete concrete_data for the input symbolic buffer",
)
bin_flags.add_argument(
"--file",
type=str,
default=[],
action="append",
dest="files",
help="Specify symbolic input file, '+' marks symbolic bytes",
)
bin_flags.add_argument(
"--env",
type=str,
nargs=1,
default=[],
action="append",
help='Add an environment variable. Use "+" for symbolic bytes. (VARNAME=++++)',
)
bin_flags.add_argument(
"--pure-symbolic",
action="store_true",
help="Treat all writable memory as symbolic",
)
config_flags = parser.add_argument_group("Constants")
config.add_config_vars_to_argparse(config_flags)
parsed = parser.parse_args(shlex.split(additional_args))
config.process_config_values(parser, parsed)
if parsed.policy.startswith("min"):
parsed.policy = "-" + parsed.policy[3:]
elif parsed.policy.startswith("max"):
parsed.policy = "+" + parsed.policy[3:]
set_verbosity(parsed.v)
return parsed
+23
View File
@@ -0,0 +1,23 @@
[build-system]
# Minimum requirements for the build system to execute.
requires = ["setuptools>=49.0.0", "wheel"] # PEP 518 specifications.
[tool.mypy]
files = ["manticore_server", "tests"]
ignore_missing_imports = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_unreachable = true
[tool.isort]
profile = "black"
skip = ["venv", "build", "manticore_server/ManticoreServer_pb2.py", "manticore_server/ManticoreServer_pb2_grpc.py"]
[tool.black]
line-length = 88
extend-exclude = '''
ManticoreServer_pb2_grpc\.py
| ManticoreServer_pb2\.py
| ManticoreServer_pb2\.pyi
| venv
'''
+62
View File
@@ -0,0 +1,62 @@
from pathlib import Path
from setuptools import Command, find_packages, setup
class GenerateCommand(Command):
description = "generates manticore_server server protobuf + grpc code from protobuf specification file"
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
from grpc.tools import protoc
protoc.main(
[
"grpc_tools.protoc",
"-I.",
"--python_out=.",
"--grpc_python_out=.",
"--mypy_out=.",
"./manticore_server/ManticoreServer.proto",
]
)
setup(
name="manticore_server",
version="0.0.1",
packages=find_packages(exclude=["tests", "tests.*"]),
python_requires=">=3.7",
install_requires=[
f"manticore[native] @ file://{Path(__file__).parent.resolve()}/..",
"protobuf~=3.20",
"grpcio~=1.46",
"crytic-compile>=0.2.2",
],
extras_require={
"dev": [
"grpcio-tools",
"mypy-protobuf",
"shiv~=1.0.1",
"types-setuptools",
"black~=22.0",
"isort==5.10.1",
"mypy==0.942",
]
},
entry_points={
"console_scripts": [
"manticore_server=manticore_server.manticore_server:main",
],
"distutils.commands": ["generate = GenerateCommand"],
},
cmdclass={
"generate": GenerateCommand,
},
)
View File
+7
View File
@@ -0,0 +1,7 @@
contract Adder {
function incremented(uint value) public returns (uint){
if (value == 1)
revert();
return value + 1;
}
}
+18
View File
@@ -0,0 +1,18 @@
import grpc
from grpc._server import _Context
class MockContext(_Context):
def __init__(self) -> None:
self.code: grpc.StatusCode = grpc.StatusCode.OK
self.details: str = ""
def set_details(self, details: str) -> None:
self.details = details
def set_code(self, code: grpc.StatusCode) -> None:
self.code = code
def reset(self):
self.code: grpc.StatusCode = grpc.StatusCode.OK
self.details: str = ""
+343
View File
@@ -0,0 +1,343 @@
import glob
import os
import threading
import time
import unittest
import unittest.mock
from inspect import currentframe, getframeinfo
from pathlib import Path
from shutil import rmtree, which
from uuid import UUID, uuid4
import grpc
from manticore_server import manticore_server
from manticore_server.ManticoreServer_pb2 import *
from tests.mock_classes import MockContext
class ManticoreServerEVMTest(unittest.TestCase):
def setUp(self):
self.dirname = str(Path(getframeinfo(currentframe()).filename).resolve().parent)
self.contract_path = str(self.dirname / Path("contracts") / Path("adder.sol"))
self.test_event = threading.Event()
self.servicer = manticore_server.ManticoreServicer(self.test_event)
self.solc_path = which("solc")
self.context = MockContext()
def tearDown(self):
for mwrapper in self.servicer.manticore_instances.values():
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.thread.is_alive():
time.sleep(1)
if (time.time() - stime) > 15:
break
@classmethod
def tearDownClass(cls):
for f in glob.glob("mcore_*"):
if Path(f).is_dir():
rmtree(f, ignore_errors=True)
def test_start_with_no_or_invalid_contract_path(self):
self.servicer.StartEVM(EVMArguments(solc_bin=self.solc_path), self.context)
self.assertEqual(self.context.code, grpc.StatusCode.INVALID_ARGUMENT)
self.assertEqual(self.context.details, "Contract path not specified!")
self.context.reset()
invalid_contract_path = str(
self.dirname / Path("contracts") / Path("invalid_contract")
)
self.servicer.StartEVM(
EVMArguments(contract_path=invalid_contract_path, solc_bin=self.solc_path),
self.context,
)
self.assertEqual(self.context.code, grpc.StatusCode.INVALID_ARGUMENT)
self.assertEqual(
self.context.details, f"Contract path invalid: '{invalid_contract_path}'"
)
def test_start_with_no_solc_specified_or_in_path(self):
path_to_use = os.environ["PATH"]
solc_on_path = which("solc")
if solc_on_path:
solc_dir = str(Path(solc_on_path).parent)
cur_paths = os.environ["PATH"].split(os.pathsep)
path_to_use = str(os.pathsep).join(
[dir for dir in cur_paths if dir != solc_dir]
)
with unittest.mock.patch.dict(os.environ, {"PATH": ""}):
mcore_instance = self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path),
self.context,
)
self.assertEqual(self.context.code, grpc.StatusCode.INVALID_ARGUMENT)
self.assertEqual(
self.context.details,
"solc binary neither specified in EVMArguments nor found in PATH!",
)
def test_start(self):
mcore_instance = self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path, solc_bin=self.solc_path),
self.context,
)
try:
UUID(mcore_instance.uuid)
except ValueError:
self.fail(
"Start() returned ManticoreInstance with missing or malformed UUID"
)
self.assertTrue(mcore_instance.uuid in self.servicer.manticore_instances)
mcore = self.servicer.manticore_instances[mcore_instance.uuid].manticore_object
self.assertTrue(Path(mcore.workspace).is_dir())
def test_terminate_running_manticore(self):
mcore_instance = self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path, solc_bin=self.solc_path),
self.context,
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
stime = time.time()
while not mwrapper.manticore_object.is_running():
if (time.time() - stime) > 5:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to start running before timeout"
)
time.sleep(1)
self.context.reset()
self.servicer.Terminate(mcore_instance, self.context)
self.assertEqual(self.context.code, grpc.StatusCode.OK)
self.assertTrue(mwrapper.manticore_object.is_killed())
stime = time.time()
while mwrapper.manticore_object.is_running():
if (time.time() - stime) > 10:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to stop running before timeout"
)
time.sleep(1)
def test_terminate_killed_manticore(self):
mcore_instance = self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path, solc_bin=self.solc_path),
self.context,
)
self.context.reset()
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.manticore_object.is_running():
if (time.time() - stime) > 10:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to stop running before timeout"
)
time.sleep(1)
self.servicer.Terminate(mcore_instance, self.context)
self.assertEqual(self.context.code, grpc.StatusCode.OK)
def test_terminate_invalid_manticore(self):
t_status = self.servicer.Terminate(
ManticoreInstance(uuid=uuid4().hex), self.context
)
self.assertEqual(self.context.code, grpc.StatusCode.FAILED_PRECONDITION)
def test_get_message_list_running_manticore(self):
mcore_instance = self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path, solc_bin=self.solc_path),
self.context,
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
stime = time.time()
while mwrapper.manticore_object._log_queue.empty() and time.time() - stime < 5:
time.sleep(1)
if not mwrapper.manticore_object._log_queue.empty():
deque_messages = list(mwrapper.manticore_object._log_queue)
messages = self.servicer.GetMessageList(
mcore_instance, self.context
).messages
for i in range(len(messages)):
self.assertEqual(messages[i].content, deque_messages[i])
break
def test_get_message_list_stopped_manticore(self):
mcore_instance = self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path, solc_bin=self.solc_path),
self.context,
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.manticore_object.is_running():
if (time.time() - stime) > 10:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to stop running before timeout"
)
time.sleep(1)
stime = time.time()
while mwrapper.manticore_object._log_queue.empty() and time.time() - stime < 5:
time.sleep(1)
if not mwrapper.manticore_object._log_queue.empty():
deque_messages = list(mwrapper.manticore_object._log_queue)
messages = self.servicer.GetMessageList(
mcore_instance, self.context
).messages
for i in range(len(messages)):
self.assertEqual(messages[i].content, deque_messages[i])
break
def test_get_message_list_invalid_manticore(self):
message_list = self.servicer.GetMessageList(
ManticoreInstance(uuid=uuid4().hex), self.context
)
self.assertEqual(self.context.code, grpc.StatusCode.FAILED_PRECONDITION)
self.assertEqual(
self.context.details, "Specified Manticore instance not found!"
)
self.assertEqual(len(message_list.messages), 0)
def test_get_state_list_running_manticore(self):
mcore_instance = self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path, solc_bin=self.solc_path),
self.context,
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
for i in range(5):
time.sleep(1)
state_list = self.servicer.GetStateList(mcore_instance, self.context)
all_states = list(
map(
lambda x: x.state_id,
list(state_list.active_states)
+ list(state_list.waiting_states)
+ list(state_list.forked_states)
+ list(state_list.errored_states)
+ list(state_list.complete_states),
)
)
state_ids = mwrapper.manticore_object.introspect().keys()
for sid in state_ids:
self.assertIn(sid, all_states)
def test_get_state_list_stopped_manticore(self):
mcore_instance = self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path, solc_bin=self.solc_path),
self.context,
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.manticore_object.is_running():
if (time.time() - stime) > 10:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to stop running before timeout"
)
time.sleep(1)
stime = time.time()
for i in range(5):
time.sleep(1)
state_list = self.servicer.GetStateList(mcore_instance, self.context)
all_states = list(
map(
lambda x: x.state_id,
list(state_list.active_states)
+ list(state_list.waiting_states)
+ list(state_list.forked_states)
+ list(state_list.errored_states)
+ list(state_list.complete_states),
)
)
state_ids = mwrapper.manticore_object.introspect().keys()
for sid in state_ids:
self.assertIn(sid, all_states)
def test_get_state_list_invalid_manticore(self):
state_list = self.servicer.GetStateList(
ManticoreInstance(uuid=uuid4().hex), self.context
)
self.assertFalse(state_list.active_states)
self.assertFalse(state_list.waiting_states)
self.assertFalse(state_list.forked_states)
self.assertFalse(state_list.errored_states)
self.assertFalse(state_list.complete_states)
def test_check_manticore_running(self):
mcore_instance = self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path, solc_bin=self.solc_path),
self.context,
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
stime = time.time()
while not mwrapper.manticore_object.is_running():
if (time.time() - stime) > 10:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to start running before timeout"
)
time.sleep(1)
self.assertTrue(
self.servicer.CheckManticoreRunning(mcore_instance, self.context).is_running
)
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.thread.is_alive():
if (time.time() - stime) > 45:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to stop running and finish generating reports before timeout"
)
time.sleep(1)
self.assertFalse(
self.servicer.CheckManticoreRunning(mcore_instance, self.context).is_running
)
def test_check_manticore_running_invalid_manticore(self):
self.assertFalse(
self.servicer.CheckManticoreRunning(
ManticoreInstance(uuid=uuid4().hex), self.context
).is_running
)
def test_stop_server(self):
self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path, solc_bin=self.solc_path),
self.context,
)
self.servicer.StartEVM(
EVMArguments(contract_path=self.contract_path, solc_bin=self.solc_path),
self.context,
)
self.servicer.StopServer(StopServerRequest(), self.context)
self.assertTrue(self.test_event.is_set())
for mwrapper in self.servicer.manticore_instances.values():
self.assertFalse(mwrapper.manticore_object.is_running())
+618
View File
@@ -0,0 +1,618 @@
import glob
import threading
import time
import unittest
from inspect import currentframe, getframeinfo
from pathlib import Path
from shutil import rmtree
from uuid import UUID, uuid4
import grpc
from manticore_server import manticore_server
from manticore_server.ManticoreServer_pb2 import *
from tests.mock_classes import MockContext
class ManticoreServerCoreNativeTest(unittest.TestCase):
def setUp(self):
this_dir = Path(getframeinfo(currentframe()).filename).resolve().parent
self.dirname = str(this_dir)
self.binary_path = str(
this_dir.parent.parent
/ "tests"
/ "native"
/ "binaries"
/ "arguments_linux_amd64"
)
print(self.binary_path)
self.test_event = threading.Event()
self.servicer = manticore_server.ManticoreServicer(self.test_event)
self.context = MockContext()
def tearDown(self):
for mwrapper in self.servicer.manticore_instances.values():
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.thread.is_alive():
time.sleep(1)
if (time.time() - stime) > 15:
break
@classmethod
def tearDownClass(cls):
for f in glob.glob("mcore_*"):
if Path(f).is_dir():
rmtree(f, ignore_errors=True)
def test_start_with_no_or_invalid_binary_path(self):
self.servicer.StartNative(NativeArguments(), self.context)
self.assertEquals(self.context.code, grpc.StatusCode.INVALID_ARGUMENT)
self.assertEquals(self.context.details, "Basic arguments are invalid!")
self.context.reset()
invalid_binary_path = str(
self.dirname / Path("binaries") / Path("invalid_binary")
)
self.servicer.StartNative(
NativeArguments(program_path=invalid_binary_path), self.context
)
self.assertEquals(self.context.code, grpc.StatusCode.INVALID_ARGUMENT)
self.assertEquals(self.context.details, "Basic arguments are invalid!")
def test_start(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
try:
UUID(mcore_instance.uuid)
except ValueError:
self.fail(
"Start() returned ManticoreInstance with missing or malformed UUID"
)
self.assertTrue(mcore_instance.uuid in self.servicer.manticore_instances)
mcore = self.servicer.manticore_instances[mcore_instance.uuid].manticore_object
self.assertTrue(Path(mcore.workspace).is_dir())
def test_start_with_find_avoid_hooks(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(
program_path=str(self.binary_path),
hooks=[
Hook(type=Hook.HookType.FIND, address=0x40100C),
Hook(type=Hook.HookType.AVOID, address=0x401018),
],
),
self.context,
)
self.assertTrue(mcore_instance.uuid in self.servicer.manticore_instances)
# TODO: Once logging is improved, check that find_f outputs successful stdin. Might require different test binary.
def test_start_with_global_hook(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(
program_path=str(self.binary_path),
hooks=[
Hook(
type=Hook.HookType.GLOBAL,
func_text="\n".join(
(
"global m",
"def hook(state):",
" m.test_attribute = True",
" m.kill()",
"m.hook(None)(hook)",
)
),
),
],
),
self.context,
)
self.assertTrue(mcore_instance.uuid in self.servicer.manticore_instances)
m = self.servicer.manticore_instances[mcore_instance.uuid].manticore_object
stime = time.time()
while not hasattr(m, "test_attribute"):
if (time.time() - stime) > 10:
self.fail(
f"Global hook failed to trigger on {mcore_instance.uuid} before timeout"
)
time.sleep(1)
self.assertTrue(m.test_attribute)
def test_start_with_custom_hook(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(
program_path=str(self.binary_path),
hooks=[
Hook(
type=Hook.HookType.CUSTOM,
func_text="\n".join(
(
"global m, addr",
"def hook(state):",
" m.test_attribute = addr",
" m.kill()",
"m.hook(addr)(hook)",
)
),
address=0x400FDC,
),
],
),
self.context,
)
self.assertTrue(mcore_instance.uuid in self.servicer.manticore_instances)
m = self.servicer.manticore_instances[mcore_instance.uuid].manticore_object
stime = time.time()
while not hasattr(m, "test_attribute"):
if (time.time() - stime) > 10:
self.fail(
f"Custom hook failed to trigger on {mcore_instance.uuid} before timeout"
)
time.sleep(1)
self.assertTrue(m.test_attribute == 0x400FDC)
def test_start_with_invalid_custom_and_global_hook(self):
self.servicer.StartNative(
NativeArguments(
program_path=str(self.binary_path),
hooks=[
Hook(
type=Hook.HookType.CUSTOM,
func_text="this is an invalid hook",
address=0x400FDC,
),
],
),
self.context,
)
self.assertEquals(self.context.code, grpc.StatusCode.INVALID_ARGUMENT)
self.assertEquals(self.context.details, "Hooks set are invalid!")
self.context.reset()
self.servicer.StartNative(
NativeArguments(
program_path=str(self.binary_path),
hooks=[
Hook(
type=Hook.HookType.GLOBAL,
func_text="this is another invalid hook",
),
],
),
self.context,
)
self.assertEquals(self.context.code, grpc.StatusCode.INVALID_ARGUMENT)
self.assertEquals(self.context.details, "Hooks set are invalid!")
def test_terminate_running_manticore(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
stime = time.time()
while not mwrapper.manticore_object.is_running():
if (time.time() - stime) > 5:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to start running before timeout"
)
time.sleep(1)
self.context.reset()
self.servicer.Terminate(mcore_instance, self.context)
self.assertEqual(self.context.code, grpc.StatusCode.OK)
self.assertTrue(mwrapper.manticore_object.is_killed())
stime = time.time()
while mwrapper.manticore_object.is_running():
if (time.time() - stime) > 10:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to stop running before timeout"
)
time.sleep(1)
def test_terminate_killed_manticore(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.manticore_object.is_running():
if (time.time() - stime) > 10:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to stop running before timeout"
)
time.sleep(1)
t_status = self.servicer.Terminate(mcore_instance, self.context)
self.assertEquals(self.context.code, grpc.StatusCode.OK)
def test_terminate_invalid_manticore(self):
t_status = self.servicer.Terminate(
ManticoreInstance(uuid=uuid4().hex), self.context
)
self.assertEqual(self.context.code, grpc.StatusCode.FAILED_PRECONDITION)
def test_get_message_list_running_manticore(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
stime = time.time()
while mwrapper.manticore_object._log_queue.empty() and time.time() - stime < 5:
time.sleep(1)
if not mwrapper.manticore_object._log_queue.empty():
deque_messages = list(mwrapper.manticore_object._log_queue)
messages = self.servicer.GetMessageList(
mcore_instance, self.context
).messages
for i in range(len(messages)):
self.assertEqual(messages[i].content, deque_messages[i])
break
def test_get_message_list_stopped_manticore(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.manticore_object.is_running():
if (time.time() - stime) > 10:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to stop running before timeout"
)
time.sleep(1)
stime = time.time()
while mwrapper.manticore_object._log_queue.empty() and time.time() - stime < 5:
time.sleep(1)
if not mwrapper.manticore_object._log_queue.empty():
deque_messages = list(mwrapper.manticore_object._log_queue)
messages = self.servicer.GetMessageList(
mcore_instance, self.context
).messages
for i in range(len(messages)):
self.assertEqual(messages[i].content, deque_messages[i])
break
def test_get_message_list_invalid_manticore(self):
message_list = self.servicer.GetMessageList(
ManticoreInstance(uuid=uuid4().hex), self.context
)
self.assertEqual(self.context.code, grpc.StatusCode.FAILED_PRECONDITION)
self.assertEqual(
self.context.details, "Specified Manticore instance not found!"
)
self.assertEqual(len(message_list.messages), 0)
def test_get_state_list_running_manticore(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
for i in range(5):
time.sleep(1)
state_list = self.servicer.GetStateList(mcore_instance, self.context)
all_states = list(
map(
lambda x: x.state_id,
list(state_list.active_states)
+ list(state_list.waiting_states)
+ list(state_list.forked_states)
+ list(state_list.errored_states)
+ list(state_list.complete_states),
)
)
state_ids = mwrapper.manticore_object.introspect().keys()
for sid in state_ids:
self.assertIn(sid, all_states)
def test_get_state_list_stopped_manticore(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.manticore_object.is_running():
if (time.time() - stime) > 10:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to stop running before timeout"
)
time.sleep(1)
stime = time.time()
for i in range(5):
time.sleep(1)
state_list = self.servicer.GetStateList(mcore_instance, self.context)
all_states = list(
map(
lambda x: x.state_id,
list(state_list.active_states)
+ list(state_list.waiting_states)
+ list(state_list.forked_states)
+ list(state_list.errored_states)
+ list(state_list.complete_states),
)
)
state_ids = mwrapper.manticore_object.introspect().keys()
for sid in state_ids:
self.assertIn(sid, all_states)
def test_get_state_list_invalid_manticore(self):
state_list = self.servicer.GetStateList(
ManticoreInstance(uuid=uuid4().hex), self.context
)
self.assertFalse(state_list.active_states)
self.assertFalse(state_list.waiting_states)
self.assertFalse(state_list.forked_states)
self.assertFalse(state_list.errored_states)
self.assertFalse(state_list.complete_states)
def test_check_manticore_running(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
stime = time.time()
while not mwrapper.manticore_object.is_running():
if (time.time() - stime) > 10:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to start running before timeout"
)
time.sleep(1)
self.assertTrue(
self.servicer.CheckManticoreRunning(mcore_instance, self.context).is_running
)
mwrapper.manticore_object.kill()
stime = time.time()
while mwrapper.thread.is_alive():
if (time.time() - stime) > 45:
self.fail(
f"Manticore instance {mcore_instance.uuid} failed to stop running and finish generating reports before timeout"
)
time.sleep(1)
self.assertFalse(
self.servicer.CheckManticoreRunning(mcore_instance, self.context).is_running
)
def test_check_manticore_running_invalid_manticore(self):
self.assertFalse(
self.servicer.CheckManticoreRunning(
ManticoreInstance(uuid=uuid4().hex), self.context
).is_running
)
def test_control_state_invalid_manticore(self):
self.servicer.ControlState(
ControlStateRequest(
manticore_instance=ManticoreInstance(uuid=uuid4().hex),
state_id=1,
action=ControlStateRequest.StateAction.PAUSE,
),
self.context,
)
self.assertEqual(self.context.code, grpc.StatusCode.FAILED_PRECONDITION)
self.assertEqual(
self.context.details, "Specified Manticore instance not found!"
)
def test_control_state_invalid_state(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
self.servicer.ControlState(
ControlStateRequest(
manticore_instance=mcore_instance,
state_id=-1,
action=ControlStateRequest.StateAction.PAUSE,
),
self.context,
)
self.assertEqual(self.context.code, grpc.StatusCode.FAILED_PRECONDITION)
self.assertEqual(self.context.details, "Specified state not found!")
def test_control_state_pause_state(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
stime = time.time()
active_states = self.servicer.GetStateList(
mcore_instance, self.context
).active_states
while len(active_states) == 0:
time.sleep(1)
if (time.time() - stime) > 30:
self.fail("Manticore did not create an active state before timeout")
active_states = self.servicer.GetStateList(
mcore_instance, self.context
).active_states
candidate_state_id = list(active_states)[0].state_id
self.servicer.ControlState(
ControlStateRequest(
manticore_instance=mcore_instance,
state_id=candidate_state_id,
action=ControlStateRequest.StateAction.PAUSE,
),
self.context,
)
self.assertEqual(self.context.code, grpc.StatusCode.OK)
self.assertEqual(self.context.details, "")
self.assertTrue(candidate_state_id in mwrapper.paused_states)
self.assertTrue(-1 in mwrapper.manticore_object._busy_states)
stime = time.time()
paused_states = self.servicer.GetStateList(
mcore_instance, self.context
).paused_states
while len(paused_states) == 0:
time.sleep(1)
if (time.time() - stime) > 30:
self.fail(
f"Manticore did not pause the state {candidate_state_id} before timeout"
)
paused_states = self.servicer.GetStateList(
mcore_instance, self.context
).paused_states
self.assertTrue(candidate_state_id == list(paused_states)[0].state_id)
def test_control_state_resume_paused_state(self):
self.test_control_state_pause_state()
self.assertTrue(len(self.servicer.manticore_instances) == 1)
mwrapper = list(self.servicer.manticore_instances.values())[0]
paused_state_id = list(mwrapper.paused_states)[0]
self.servicer.ControlState(
ControlStateRequest(
manticore_instance=ManticoreInstance(uuid=mwrapper.uuid),
state_id=paused_state_id,
action=ControlStateRequest.StateAction.RESUME,
),
self.context,
)
self.assertEqual(self.context.code, grpc.StatusCode.OK)
self.assertEqual(self.context.details, "")
self.assertTrue(len(mwrapper.paused_states) == 0)
self.assertTrue(-1 not in mwrapper.manticore_object._busy_states)
self.assertTrue(
paused_state_id
not in map(
lambda x: x.state_id,
self.servicer.GetStateList(
ManticoreInstance(uuid=mwrapper.uuid), self.context
).paused_states,
)
)
def test_control_state_kill_active_state(self):
mcore_instance = self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
mwrapper = self.servicer.manticore_instances[mcore_instance.uuid]
stime = time.time()
active_states = self.servicer.GetStateList(
mcore_instance, self.context
).active_states
while len(active_states) == 0:
time.sleep(1)
if (time.time() - stime) > 30:
self.fail("Manticore did not create an active state before timeout")
active_states = self.servicer.GetStateList(
mcore_instance, self.context
).active_states
candidate_state_id = list(active_states)[0].state_id
self.servicer.ControlState(
ControlStateRequest(
manticore_instance=mcore_instance,
state_id=candidate_state_id,
action=ControlStateRequest.StateAction.KILL,
),
self.context,
)
self.assertEqual(self.context.code, grpc.StatusCode.OK)
self.assertEqual(self.context.details, "")
stime = time.time()
active_states = self.servicer.GetStateList(
mcore_instance, self.context
).active_states
while len(active_states) != 0:
time.sleep(1)
if (time.time() - stime) > 30:
self.fail(
f"Manticore did not kill the state {candidate_state_id} before timeout"
)
active_states = self.servicer.GetStateList(
mcore_instance, self.context
).active_states
def test_control_state_kill_paused_state(self):
self.test_control_state_pause_state()
self.assertTrue(len(self.servicer.manticore_instances) == 1)
mwrapper = list(self.servicer.manticore_instances.values())[0]
paused_state_id = list(mwrapper.paused_states)[0]
self.servicer.ControlState(
ControlStateRequest(
manticore_instance=ManticoreInstance(uuid=mwrapper.uuid),
state_id=paused_state_id,
action=ControlStateRequest.StateAction.KILL,
),
self.context,
)
self.assertEqual(self.context.code, grpc.StatusCode.OK)
self.assertEqual(self.context.details, "")
self.assertTrue(len(mwrapper.paused_states) == 0)
self.assertTrue(-1 not in mwrapper.manticore_object._busy_states)
self.assertTrue(
paused_state_id
not in map(
lambda x: x.state_id,
self.servicer.GetStateList(
ManticoreInstance(uuid=mwrapper.uuid), self.context
).paused_states,
)
)
def test_stop_server(self):
self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
self.servicer.StartNative(
NativeArguments(program_path=self.binary_path), self.context
)
self.servicer.StopServer(StopServerRequest(), self.context)
self.assertTrue(self.test_event.is_set())
for mwrapper in self.servicer.manticore_instances.values():
self.assertFalse(mwrapper.manticore_object.is_running())