Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ cmake-build-*/
prefix/
CMakeLists.txt.user
CMakeUserPresets.json
src/LIEF
install/
maat_state_*
__pycache__
25 changes: 25 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ project(
LANGUAGES C CXX
)

if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_CXX_FLAGS "-g")
endif()


include(cmake/project-is-top-level.cmake)
include(cmake/variables.cmake)

Expand All @@ -20,6 +25,8 @@ include(cmake/variables.cmake)
add_library(maat_maat
src/arch/arch_EVM.cpp
src/arch/arch_X86.cpp
src/arch/arch_RISCV.cpp
src/arch/arch_ARM32.cpp
src/arch/lifter.cpp
src/arch/register_aliases.cpp
src/engine/callother.cpp
Expand Down Expand Up @@ -180,15 +187,33 @@ macro(maat_sleigh_compile ARCH_DIR ARCH)
configure_file("${spec_dir}/${ARCH_DIR}/data/languages/${ARCH}.pspec" "${spec_out_dir}/${ARCH}.pspec")
endmacro()

macro(maat_sleigh_compile_files ARCH_DIR ARCH SLASPEC PSPEC)
# ARCH_DIR is the directory that appears in Ghidra's source code hierarchy
# ARCH appears in the name of the '.slaspec' and '.pspec' file (they should be the same)
# Creates a target maat_sleigh_spec_${ARCH}
sleigh_compile(
TARGET maat_sleigh_spec_${ARCH}
COMPILER "${maat_SLEIGH_COMPILER}"
SLASPEC "${spec_dir}/${ARCH_DIR}/data/languages/${SLASPEC}.slaspec"
LOG_FILE "${PROJECT_BINARY_DIR}/sleigh-log/${ARCH}.log"
OUT_FILE "${spec_out_dir}/${SLASPEC}.sla"
)
configure_file("${spec_dir}/${ARCH_DIR}/data/languages/${PSPEC}.pspec" "${spec_out_dir}/${PSPEC}.pspec")
endmacro()

maat_sleigh_compile(x86 x86-64)
maat_sleigh_compile(x86 x86)
maat_sleigh_compile(EVM EVM)
maat_sleigh_compile_files(RISCV RISCV riscv.lp64d RV64G)
maat_sleigh_compile_files(ARM ARM32 ARM7_le ARMt)

# All of the sla spec targets are combined into this one
add_custom_target(maat_all_sla_specs DEPENDS
maat_sleigh_spec_x86-64
maat_sleigh_spec_x86
maat_sleigh_spec_EVM
maat_sleigh_spec_RISCV
maat_sleigh_spec_ARM32
)

# Add sla specs as dependencies to our targets
Expand Down
2 changes: 1 addition & 1 deletion Version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.6.7
0.6.8
2 changes: 2 additions & 0 deletions bindings/python/py_arch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ void init_arch(PyObject* module)
PyDict_SetItemString(arch_enum, "X86", PyLong_FromLong((int)Arch::Type::X86));
PyDict_SetItemString(arch_enum, "X64", PyLong_FromLong((int)Arch::Type::X64));
PyDict_SetItemString(arch_enum, "EVM", PyLong_FromLong((int)Arch::Type::EVM));
PyDict_SetItemString(arch_enum, "RISCV", PyLong_FromLong((int)Arch::Type::RISCV));
PyDict_SetItemString(arch_enum, "ARM32", PyLong_FromLong((int)Arch::Type::ARM32));

PyObject* arch_class = create_class(PyUnicode_FromString("ARCH"), PyTuple_New(0), arch_enum);
PyModule_AddObject(module, "ARCH", arch_class);
Expand Down
2 changes: 1 addition & 1 deletion bindings/python/py_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ static PyObject* MaatEngine_load(PyObject* self, PyObject* args, PyObject* keywo
char * arg_bytes = nullptr;
Py_ssize_t arg_bytes_len = 0;
PyBytes_AsStringAndSize(arg, &arg_bytes, &arg_bytes_len);
cmdline_args.push_back(loader::CmdlineArg(std::string(arg_bytes)));
cmdline_args.push_back(loader::CmdlineArg(std::string(arg_bytes, arg_bytes_len)));
}
else if (PyList_Check(arg))
{
Expand Down
84 changes: 82 additions & 2 deletions bindings/python/py_env_EVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,11 @@ static PyObject* EVMTransaction_get_value(PyObject* self, void* closure)
return PyValue_FromValue(as_tx_object(self).transaction->value);
}

static PyObject* EVMTransaction_get_gas_price(PyObject* self, void* closure)
{
return PyValue_FromValue(as_tx_object(self).transaction->gas_price);
}

static PyObject* EVMTransaction_get_data(PyObject* self, void* closure)
{
// TODO(boyan): factorize this code with other places where we translate
Expand Down Expand Up @@ -682,6 +687,7 @@ static PyGetSetDef EVMTransaction_getset[] = {
{"ret_offset", EVMTransaction_get_ret_offset, NULL, "Return offset", NULL},
{"ret_len", EVMTransaction_get_ret_len, NULL, "Return length", NULL},
{"value", EVMTransaction_get_value, NULL, "Value in WEI", NULL},
{"gas_price", EVMTransaction_get_gas_price, NULL, "Gas price", NULL},
{NULL}
};

Expand Down Expand Up @@ -917,15 +923,25 @@ PyObject* maat_contract(PyObject* mod, PyObject* args)
PyObject* maat_new_evm_runtime(PyObject* mod, PyObject* args)
{
PyObject *new_engine, *old_engine;
if( !PyArg_ParseTuple(args, "O!O!", get_MaatEngine_Type(), &new_engine, get_MaatEngine_Type(), &old_engine))
PyObject* py_share_storage_uid = nullptr;
std::optional<int> share_storage_uid;
if( !PyArg_ParseTuple(args, "O!O!|O", get_MaatEngine_Type(), &new_engine, get_MaatEngine_Type(), &old_engine, &share_storage_uid))
{
return NULL;
}
try
{
if (py_share_storage_uid == nullptr or py_share_storage_uid == Py_None)
share_storage_uid = std::nullopt;
else if (PyLong_Check(py_share_storage_uid))
share_storage_uid = PyLong_AsLongLong(py_share_storage_uid);
else
return PyErr_Format(PyExc_TypeError, "share_storage_uid should be None or int");

env::EVM::new_evm_runtime(
*as_engine_object(new_engine).engine,
*as_engine_object(old_engine).engine
*as_engine_object(old_engine).engine,
share_storage_uid
);
}
catch(maat::env_exception& e)
Expand Down Expand Up @@ -1035,6 +1051,67 @@ PyObject* maat_allow_symbolic_keccak(PyObject* mod, PyObject* args)
}
}

PyObject* maat_evm_get_static_flag(PyObject* mod, PyObject* args)
{
PyObject* engine;
if( !PyArg_ParseTuple(args, "O!", get_MaatEngine_Type(), &engine))
return NULL;

try
{
auto eth = env::EVM::get_ethereum(*as_engine_object(engine).engine);
if (eth == nullptr)
return PyErr_Format(PyExc_RuntimeError, "No environment for this engine");
return PyBool_FromLong(eth->static_flag);
}
catch(const std::exception& e)
{
return PyErr_Format(PyExc_RuntimeError, e.what());
}
}

PyObject* maat_evm_set_static_flag(PyObject* mod, PyObject* args)
{
PyObject* engine;
int flag = 0;
if( !PyArg_ParseTuple(args, "O!p", get_MaatEngine_Type(), &engine, &flag))
return NULL;

try
{
auto eth = env::EVM::get_ethereum(*as_engine_object(engine).engine);
if (eth == nullptr)
return PyErr_Format(PyExc_RuntimeError, "No environment for this engine");
eth->static_flag = flag;
Py_RETURN_NONE;
}
catch(const std::exception& e)
{
return PyErr_Format(PyExc_RuntimeError, e.what());
}
}

PyObject* maat_evm_set_gas_price(PyObject* mod, PyObject* args)
{
PyObject* engine;
PyObject* price;
if( !PyArg_ParseTuple(args, "O!O!", get_MaatEngine_Type(), &engine, get_Value_Type(), &price))
return NULL;

try
{
auto eth = env::EVM::get_ethereum(*as_engine_object(engine).engine);
if (eth == nullptr)
return PyErr_Format(PyExc_RuntimeError, "No environment for this engine");
eth->gas_price = *as_value_object(price).value;
Py_RETURN_NONE;
}
catch(const std::exception& e)
{
return PyErr_Format(PyExc_RuntimeError, e.what());
}
}

void init_evm(PyObject* module)
{
/* TX_END enum */
Expand Down Expand Up @@ -1072,6 +1149,9 @@ void init_evm(PyObject* module)
PyDict_SetItemString(tx_enum, "DELEGATECALL", PyLong_FromLong(
(int)env::EVM::Transaction::Type::DELEGATECALL)
);
PyDict_SetItemString(tx_enum, "STATICCALL", PyLong_FromLong(
(int)env::EVM::Transaction::Type::STATICCALL)
);
PyDict_SetItemString(tx_enum, "EOA", PyLong_FromLong(
(int)env::EVM::Transaction::Type::EOA)
);
Expand Down
12 changes: 11 additions & 1 deletion bindings/python/py_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,16 @@ static PyObject* Branch_get_taken(PyObject* self, void* closure){
return PyBool_FromLong(as_branch_object(self).branch->taken.value());
}

static int Branch_set_taken(PyObject* self, PyObject* val, void* closure){
std::optional<bool> taken;
if (val == Py_None)
taken = std::nullopt;
else
taken = (bool)PyObject_IsTrue(val);
as_branch_object(self).branch->taken = taken;
return 0;
}

static PyObject* Branch_get_target(PyObject* self, void* closure){
if( as_branch_object(self).branch->target.is_none() ){
return PyErr_Format(PyExc_AttributeError, "'target' property is not set currently");
Expand All @@ -316,7 +326,7 @@ static PyGetSetDef Branch_getset[] = {
{"cond", Branch_get_cond, NULL, "Branch condition (if applicable)", NULL},
{"target", Branch_get_target, NULL, "Target instruction if branch is taken", NULL},
{"next", Branch_get_next, NULL, "Next instruction if branch is not taken", NULL},
{"taken", Branch_get_taken, NULL, "Is the branch taken or not", NULL},
{"taken", Branch_get_taken, Branch_set_taken, "Is the branch taken or not", NULL},
{NULL}
};

Expand Down
3 changes: 3 additions & 0 deletions bindings/python/py_maat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ PyMethodDef module_methods[] = {
{"increment_block_timestamp", (PyCFunction)maat_increment_block_timestamp, METH_VARARGS, "Increment the current block timestamp by an abstract value"},
{"set_evm_bytecode", (PyCFunction)maat_set_evm_bytecode, METH_VARARGS, "Set runtime bytecode for the contract associated to an engine"},
{"allow_symbolic_keccak", (PyCFunction)maat_allow_symbolic_keccak, METH_VARARGS, "Enable/disable symbolic KECCAK hashes"},
{"evm_get_static_flag", (PyCFunction)maat_evm_get_static_flag, METH_VARARGS, "Get EVM static flag"},
{"evm_set_static_flag", (PyCFunction)maat_evm_set_static_flag, METH_VARARGS, "Set EVM static flag"},
{"evm_set_gas_price", (PyCFunction)maat_evm_set_gas_price, METH_VARARGS, "Set EVM gas price"},
{NULL}
};

Expand Down
12 changes: 12 additions & 0 deletions bindings/python/py_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ static PyObject* Value_as_float(PyObject* self, PyObject* args)
}
}

static PyObject* Value_eq(PyObject* self, PyObject* args)
{
PyObject* other = nullptr;
if( !PyArg_ParseTuple(args, "O!", get_Value_Type(), &other)){
return NULL;
}
return PyBool_FromLong(
as_value_object(self).value->eq(*as_value_object(other).value)
);
}

static PyObject* Value_get_size(PyObject* self, void* closure)
{
return PyLong_FromLong((*as_value_object(self).value).size());
Expand Down Expand Up @@ -230,6 +241,7 @@ static PyMethodDef Value_methods[] =
{"as_int", (PyCFunction)Value_as_int, METH_VARARGS, "Concretize the value interpreted as a signed value"},
{"as_uint", (PyCFunction)Value_as_uint, METH_VARARGS, "Concretize the value interpreted as an unsigned value"},
{"as_float", (PyCFunction)Value_as_float, METH_VARARGS, "Concretize the value interpreted as a floating point value"},
{"eq", (PyCFunction)Value_eq, METH_VARARGS, "Return True if two values are identical (same abstract syntax tree)"},
{NULL, NULL, 0, NULL}
};

Expand Down
3 changes: 3 additions & 0 deletions bindings/python/python_bindings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,9 @@ PyObject* maat_increment_block_timestamp(PyObject* mod, PyObject* args);
PyObject* maat_increment_block_number(PyObject* mod, PyObject* args);
PyObject* maat_set_evm_bytecode(PyObject* mod, PyObject* args);
PyObject* maat_allow_symbolic_keccak(PyObject* mod, PyObject* args);
PyObject* maat_evm_get_static_flag(PyObject* mod, PyObject* args);
PyObject* maat_evm_set_static_flag(PyObject* mod, PyObject* args);
PyObject* maat_evm_set_gas_price(PyObject* mod, PyObject* args);

// ====== Utils =======
// Transform a list of values into a list of python values,
Expand Down
Loading