diff options
| author | Theofilos Augoustis <theofilos.augoustis@gmail.com> | 2025-10-14 09:09:29 +0000 |
|---|---|---|
| committer | Theofilos Augoustis <theofilos.augoustis@gmail.com> | 2025-10-14 09:09:29 +0000 |
| commit | 579cf1d03fb932083e6317967d1613d5c2587fb6 (patch) | |
| tree | 629f039935382a2a7391bce9253f6c9968159049 /src/miasm/jitter/vm_mngr_py.c | |
| parent | 51c15d3ea2e16d4fc5f0f01a3b9befc66b1f982e (diff) | |
| download | focaccia-miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.tar.gz focaccia-miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.zip | |
Convert to src-layout ta/nix
Diffstat (limited to 'src/miasm/jitter/vm_mngr_py.c')
| -rw-r--r-- | src/miasm/jitter/vm_mngr_py.c | 1089 |
1 files changed, 1089 insertions, 0 deletions
diff --git a/src/miasm/jitter/vm_mngr_py.c b/src/miasm/jitter/vm_mngr_py.c new file mode 100644 index 00000000..dd1bd9b1 --- /dev/null +++ b/src/miasm/jitter/vm_mngr_py.c @@ -0,0 +1,1089 @@ +/* +** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net> +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License along +** with this program; if not, write to the Free Software Foundation, Inc., +** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include <Python.h> +#include "structmember.h" +#include <stdint.h> +#include <inttypes.h> +#include <signal.h> +#include "compat_py23.h" +#include "queue.h" +#include "vm_mngr.h" +#include "bn.h" +#include "vm_mngr_py.h" + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +extern struct memory_page_list_head memory_page_pool; +extern struct code_bloc_list_head code_bloc_pool; + +#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;} + + + +/* XXX POC signals */ +VmMngr* global_vmmngr; + +PyObject* _vm_get_exception(unsigned int xcpt) +{ + PyObject*p; + + if (!xcpt) + p = NULL; + else if (xcpt & EXCEPT_CODE_AUTOMOD) + p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_CODE_AUTOMOD" ); + else if (xcpt & EXCEPT_UNK_EIP) + p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNK_EIP" ); + else if (xcpt & EXCEPT_UNK_MEM_AD) + p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNK_MEM_AD" ); + + else p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNKNOWN" ); + return p; +} + +static void sig_alarm(int signo) +{ + global_vmmngr->vm_mngr.exception_flags |= BREAK_SIGALARM; + return; +} + +PyObject* set_alarm(VmMngr* self) +{ + global_vmmngr = self; + signal(SIGALRM, sig_alarm); + + Py_INCREF(Py_None); + return Py_None; +} + + + +PyObject* vm_add_memory_page(VmMngr* self, PyObject* args) +{ + PyObject *addr; + PyObject *access; + PyObject *item_str; + PyObject *name=NULL; + uint64_t buf_size; + size_t buf_size_st; + char* buf_data; + Py_ssize_t length; + uint64_t page_addr; + uint64_t page_access; + const char *name_ptr; + + struct memory_page_node * mpn; + + if (!PyArg_ParseTuple(args, "OOO|O", &addr, &access, &item_str, &name)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(addr, page_addr); + PyGetInt_uint64_t(access, page_access); + + if(!PyBytes_Check(item_str)) + RAISE(PyExc_TypeError,"arg must be bytes"); + + buf_size = PyBytes_Size(item_str); + PyBytes_AsStringAndSize(item_str, &buf_data, &length); + + if (name == NULL) { + name_ptr = (char*)""; + } else { + PyGetStr(name_ptr, name); + } + mpn = create_memory_page_node(page_addr, (size_t)buf_size, (unsigned int)page_access, name_ptr); + if (mpn == NULL) + RAISE(PyExc_TypeError,"cannot create page"); + if (is_mpn_in_tab(&self->vm_mngr, mpn)) { + free(mpn->ad_hp); + free(mpn); + RAISE(PyExc_TypeError,"known page in memory"); + } + + if (buf_size > SIZE_MAX) { + fprintf(stderr, "Size too big\n"); + exit(EXIT_FAILURE); + } + buf_size_st = (size_t) buf_size; + + memcpy(mpn->ad_hp, buf_data, buf_size_st); + add_memory_page(&self->vm_mngr, mpn); + + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* vm_remove_memory_page(VmMngr* self, PyObject* args) +{ + PyObject *addr; + uint64_t page_addr; + + if (!PyArg_ParseTuple(args, "O", &addr)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(addr, page_addr); + + remove_memory_page(&self->vm_mngr, page_addr); + + Py_INCREF(Py_None); + return Py_None; + + +} + +PyObject* vm_set_mem_access(VmMngr* self, PyObject* args) +{ + PyObject *addr; + PyObject *access; + uint64_t page_addr; + uint64_t page_access; + struct memory_page_node * mpn; + + if (!PyArg_ParseTuple(args, "OO", &addr, &access)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(addr, page_addr); + PyGetInt_uint64_t(access, page_access); + + mpn = get_memory_page_from_address(&self->vm_mngr, page_addr, 1); + if (!mpn){ + PyErr_SetString(PyExc_RuntimeError, "cannot find address"); + return 0; + } + + mpn->access = page_access; + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_set_mem(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + PyObject *py_buffer; + Py_ssize_t py_length; + + char * buffer; + Py_ssize_t pysize; + uint64_t addr; + int ret; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_buffer)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + + if (!PyBytes_Check(py_buffer)) + RAISE(PyExc_TypeError,"arg must be bytes"); + + pysize = PyBytes_Size(py_buffer); + if (pysize < 0) { + RAISE(PyExc_TypeError,"Python error"); + } + PyBytes_AsStringAndSize(py_buffer, &buffer, &py_length); + + ret = vm_write_mem(&self->vm_mngr, addr, buffer, pysize); + if (ret < 0) + RAISE(PyExc_TypeError, "Error in set_mem"); + + add_mem_write(&self->vm_mngr, addr, (size_t)pysize); + check_invalid_code_blocs(&self->vm_mngr); + + Py_INCREF(Py_None); + return Py_None; +} + + + +PyObject* vm_get_mem_access(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + uint64_t page_addr; + struct memory_page_node * mpn; + + if (!PyArg_ParseTuple(args, "O", &py_addr)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, page_addr); + + mpn = get_memory_page_from_address(&self->vm_mngr, page_addr, 1); + if (!mpn){ + PyErr_SetString(PyExc_RuntimeError, "cannot find address"); + return 0; + } + + return PyLong_FromUnsignedLongLong((uint64_t)mpn->access); +} + +PyObject* vm_get_mem(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + PyObject *py_len; + + uint64_t addr; + uint64_t size; + size_t size_st; + PyObject *obj_out; + char * buf_out; + int ret; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_len)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + PyGetInt_uint64_t(py_len, size); + + if (size > SIZE_MAX) { + fprintf(stderr, "Size too big\n"); + exit(EXIT_FAILURE); + } + size_st = (size_t) size; + + ret = vm_read_mem(&self->vm_mngr, addr, &buf_out, size_st); + if (ret < 0) { + RAISE(PyExc_RuntimeError,"Cannot find address"); + } + + obj_out = PyBytes_FromStringAndSize(buf_out, size_st); + free(buf_out); + return obj_out; +} + +PyObject* vm_get_u8(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + + uint64_t addr; + PyObject *obj_out; + char * buf_out; + int ret; + uint32_t value; + + if (!PyArg_ParseTuple(args, "O", &py_addr)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + + ret = vm_read_mem(&self->vm_mngr, addr, &buf_out, 1); + if (ret < 0) { + RAISE(PyExc_RuntimeError,"Cannot find address"); + } + + value = *(uint8_t*)buf_out; + + obj_out = PyLong_FromUnsignedLongLong(value); + free(buf_out); + return obj_out; +} + +PyObject* vm_get_u16(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + + uint64_t addr; + PyObject *obj_out; + char * buf_out; + int ret; + uint16_t value; + + if (!PyArg_ParseTuple(args, "O", &py_addr)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + + ret = vm_read_mem(&self->vm_mngr, addr, &buf_out, 2); + if (ret < 0) { + RAISE(PyExc_RuntimeError,"Cannot find address"); + } + + value = set_endian16(&self->vm_mngr, *(uint16_t*)buf_out); + + obj_out = PyLong_FromUnsignedLongLong(value); + free(buf_out); + return obj_out; +} + +PyObject* vm_get_u32(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + + uint64_t addr; + PyObject *obj_out; + char * buf_out; + int ret; + uint32_t value; + + if (!PyArg_ParseTuple(args, "O", &py_addr)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + + ret = vm_read_mem(&self->vm_mngr, addr, &buf_out, 4); + if (ret < 0) { + RAISE(PyExc_RuntimeError,"Cannot find address"); + } + + value = set_endian32(&self->vm_mngr, *(uint32_t*)buf_out); + + obj_out = PyLong_FromUnsignedLongLong(value); + free(buf_out); + return obj_out; +} + + +PyObject* vm_get_u64(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + + uint64_t addr; + PyObject *obj_out; + char * buf_out; + int ret; + uint64_t value; + + if (!PyArg_ParseTuple(args, "O", &py_addr)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + + ret = vm_read_mem(&self->vm_mngr, addr, &buf_out, 8); + if (ret < 0) { + RAISE(PyExc_RuntimeError,"Cannot find address"); + } + + value = set_endian64(&self->vm_mngr, *(uint64_t*)buf_out); + + obj_out = PyLong_FromUnsignedLongLong(value); + free(buf_out); + return obj_out; +} + + +PyObject* vm_set_u8(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + PyObject *py_val; + uint8_t value; + uint64_t addr; + int ret; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_val)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + PyGetInt_uint8_t(py_val, value); + + ret = vm_write_mem(&self->vm_mngr, addr, (char*)&value, 1); + if (ret < 0) + RAISE(PyExc_TypeError, "Error in set_mem"); + + add_mem_write(&self->vm_mngr, addr, 1); + check_invalid_code_blocs(&self->vm_mngr); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_set_u16(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + PyObject *py_val; + uint16_t value; + + uint64_t addr; + int ret; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_val)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + PyGetInt_uint16_t(py_val, value); + + value = set_endian16(&self->vm_mngr, value); + ret = vm_write_mem(&self->vm_mngr, addr, (char*)&value, 2); + if (ret < 0) + RAISE(PyExc_TypeError, "Error in set_mem"); + + add_mem_write(&self->vm_mngr, addr, 2); + check_invalid_code_blocs(&self->vm_mngr); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_set_u32(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + PyObject *py_val; + uint32_t value; + uint64_t addr; + int ret; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_val)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + PyGetInt_uint32_t(py_val, value); + + value = set_endian32(&self->vm_mngr, value); + + ret = vm_write_mem(&self->vm_mngr, addr, (char*)&value, 4); + if (ret < 0) + RAISE(PyExc_TypeError, "Error in set_mem"); + + add_mem_write(&self->vm_mngr, addr, 4); + check_invalid_code_blocs(&self->vm_mngr); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_set_u64(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + PyObject *py_val; + uint64_t value; + uint64_t addr; + int ret; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_val)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + PyGetInt_uint64_t(py_val, value); + + value = set_endian64(&self->vm_mngr, value); + + ret = vm_write_mem(&self->vm_mngr, addr, (char*)&value, 8); + if (ret < 0) + RAISE(PyExc_TypeError, "Error in set_mem"); + + add_mem_write(&self->vm_mngr, addr, 8); + check_invalid_code_blocs(&self->vm_mngr); + + Py_INCREF(Py_None); + return Py_None; +} + + + + + +PyObject* vm_add_memory_breakpoint(VmMngr* self, PyObject* args) +{ + PyObject *ad; + PyObject *size; + PyObject *access; + + uint64_t b_ad; + uint64_t b_size; + uint64_t b_access; + + if (!PyArg_ParseTuple(args, "OOO", &ad, &size, &access)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(ad, b_ad); + PyGetInt_uint64_t(size, b_size); + PyGetInt_uint64_t(access, b_access); + + add_memory_breakpoint(&self->vm_mngr, b_ad, b_size, (unsigned int)b_access); + + /* Raise exception in the following pattern: + - set_mem(XXX) + - add_memory_breakpoint(XXX) + -> Here, there is a pending breakpoint not raise + */ + check_memory_breakpoint(&self->vm_mngr); + + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* vm_remove_memory_breakpoint(VmMngr* self, PyObject* args) +{ + PyObject *ad; + PyObject *access; + uint64_t b_ad; + uint64_t b_access; + + if (!PyArg_ParseTuple(args, "OO", &ad, &access)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(ad, b_ad); + PyGetInt_uint64_t(access, b_access); + remove_memory_breakpoint(&self->vm_mngr, b_ad, (unsigned int)b_access); + + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* vm_set_exception(VmMngr* self, PyObject* args) +{ + PyObject *item1; + uint64_t exception_flags; + + if (!PyArg_ParseTuple(args, "O", &item1)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(item1, exception_flags); + + self->vm_mngr.exception_flags = exception_flags; + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_get_exception(VmMngr* self, PyObject* args) +{ + return PyLong_FromUnsignedLongLong((uint64_t)self->vm_mngr.exception_flags); +} + + + + +PyObject* vm_init_memory_page_pool(VmMngr* self, PyObject* args) +{ + init_memory_page_pool(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_init_code_bloc_pool(VmMngr* self, PyObject* args) +{ + init_code_bloc_pool(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; + +} + +PyObject* vm_init_memory_breakpoint(VmMngr* self, PyObject* args) +{ + init_memory_breakpoint(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; + +} + +PyObject* vm_reset_memory_breakpoint(VmMngr* self, PyObject* args) +{ + reset_memory_breakpoint(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; + +} + +PyObject* vm_reset_memory_access(VmMngr* self, PyObject* args) +{ + reset_memory_access(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* py_add_mem_read(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + PyObject *py_size; + uint64_t addr; + uint64_t size; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_size)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + PyGetInt_uint64_t(py_size, size); + add_mem_read(&self->vm_mngr, addr, size); + Py_INCREF(Py_None); + return Py_None; + +} + +PyObject* py_add_mem_write(VmMngr* self, PyObject* args) +{ + PyObject *py_addr; + PyObject *py_size; + uint64_t addr; + uint64_t size; + + if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_size)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(py_addr, addr); + PyGetInt_uint64_t(py_size, size); + add_mem_write(&self->vm_mngr, addr, size); + Py_INCREF(Py_None); + return Py_None; + +} + +PyObject* vm_check_invalid_code_blocs(VmMngr* self, PyObject* args) +{ + check_invalid_code_blocs(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_check_memory_breakpoint(VmMngr* self, PyObject* args) +{ + check_memory_breakpoint(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; +} + +PyObject *vm_dump(PyObject* self) +{ + char* buf_final; + PyObject* ret_obj; + + buf_final = dump(&((VmMngr* )self)->vm_mngr); + ret_obj = PyUnicode_FromString(buf_final); + free(buf_final); + return ret_obj; +} + +PyObject* vm_dump_memory_breakpoint(VmMngr* self, PyObject* args) +{ + dump_memory_breakpoint_pool(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* vm_get_all_memory(VmMngr* self, PyObject* args) +{ + PyObject *o; + struct memory_page_node * mpn; + PyObject *dict; + PyObject *dict2; + int i; + + + dict = PyDict_New(); + + for (i=0;i<self->vm_mngr.memory_pages_number; i++) { + mpn = &self->vm_mngr.memory_pages_array[i]; + + dict2 = PyDict_New(); + + o = PyBytes_FromStringAndSize(mpn->ad_hp, mpn->size); + PyDict_SetItemString(dict2, "data", o); + Py_DECREF(o); + + o = PyLong_FromLong((long)mpn->size); + PyDict_SetItemString(dict2, "size", o); + Py_DECREF(o); + + o = PyLong_FromLong((long)mpn->access); + PyDict_SetItemString(dict2, "access", o); + Py_DECREF(o); + + o = PyLong_FromUnsignedLongLong(mpn->ad); + PyDict_SetItem(dict, o, dict2); + Py_DECREF(o); + Py_DECREF(dict2); + } + return dict; +} + + +PyObject* vm_reset_memory_page_pool(VmMngr* self, PyObject* args) +{ + reset_memory_page_pool(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; + +} + +PyObject* vm_reset_code_bloc_pool(VmMngr* self, PyObject* args) +{ + reset_code_bloc_pool(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; + +} + + +PyObject* vm_add_code_bloc(VmMngr *self, PyObject *args) +{ + PyObject *item1; + PyObject *item2; + uint64_t ad_start, ad_stop, ad_code = 0; + + struct code_bloc_node * cbp; + + if (!PyArg_ParseTuple(args, "OO", &item1, &item2)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(item1, ad_start); + PyGetInt_uint64_t(item2, ad_stop); + + cbp = create_code_bloc_node(ad_start, ad_stop); + cbp->ad_start = ad_start; + cbp->ad_stop = ad_stop; + cbp->ad_code = ad_code; + add_code_bloc(&self->vm_mngr, cbp); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_dump_code_bloc_pool(VmMngr* self) +{ + dump_code_bloc_pool(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; + +} + + + +PyObject* vm_is_mapped(VmMngr* self, PyObject* args) +{ + PyObject *ad; + PyObject *size; + uint64_t b_ad; + size_t b_size; + int ret; + + if (!PyArg_ParseTuple(args, "OO", &ad, &size)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt_uint64_t(ad, b_ad); + PyGetInt_size_t(size, b_size); + ret = is_mapped(&self->vm_mngr, b_ad, b_size); + return PyLong_FromUnsignedLongLong((uint64_t)ret); +} + +PyObject* vm_get_memory_read(VmMngr* self, PyObject* args) +{ + PyObject* result; + result = get_memory_read(&self->vm_mngr); + Py_INCREF(result); + return result; +} + +PyObject* vm_get_memory_write(VmMngr* self, PyObject* args) +{ + PyObject* result; + result = get_memory_write(&self->vm_mngr); + Py_INCREF(result); + return result; +} + + + +static PyObject * +vm_set_big_endian(VmMngr *self, PyObject *value, void *closure) +{ + self->vm_mngr.sex = __BIG_ENDIAN; + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +vm_set_little_endian(VmMngr *self, PyObject *value, void *closure) +{ + self->vm_mngr.sex = __LITTLE_ENDIAN; + Py_INCREF(Py_None); + return Py_None; +} + + +static PyObject * +vm_is_little_endian(VmMngr *self, PyObject *value, void *closure) +{ + if (self->vm_mngr.sex == __BIG_ENDIAN) { + return PyLong_FromUnsignedLongLong(0); + } else { + return PyLong_FromUnsignedLongLong(1); + } +} + + +static void +VmMngr_dealloc(VmMngr* self) +{ + vm_reset_memory_page_pool(self, NULL); + vm_reset_code_bloc_pool(self, NULL); + vm_reset_memory_breakpoint(self, NULL); + Py_TYPE(self)->tp_free((PyObject*)self); +} + + +static PyObject * +VmMngr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + VmMngr *self; + + self = (VmMngr *)type->tp_alloc(type, 0); + return (PyObject *)self; +} + +static PyObject * +VmMngr_get_vmmngr(VmMngr *self, void *closure) +{ + return PyLong_FromUnsignedLongLong((uint64_t)(intptr_t)&(self->vm_mngr)); +} + +static int +VmMngr_set_vmmngr(VmMngr *self, PyObject *value, void *closure) +{ + PyErr_SetString(PyExc_TypeError, "immutable vmmngr"); + return -1; +} + +static PyMemberDef VmMngr_members[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef VmMngr_methods[] = { + {"init_memory_page_pool", (PyCFunction)vm_init_memory_page_pool, METH_VARARGS, + "init_memory_page_pool() -> Initialize the VmMngr memory"}, + {"init_memory_breakpoint", (PyCFunction)vm_init_memory_breakpoint, METH_VARARGS, + "init_memory_breakpoint() -> Initialize the VmMngr memory breakpoints"}, + {"init_code_bloc_pool",(PyCFunction)vm_init_code_bloc_pool, METH_VARARGS, + "init_code_bloc_pool() -> Initialize the VmMngr jitted code blocks"}, + {"set_mem_access", (PyCFunction)vm_set_mem_access, METH_VARARGS, + "set_mem_access(address, access) -> Change the protection of the page at @address with @access"}, + {"set_mem", (PyCFunction)vm_set_mem, METH_VARARGS, + "set_mem(address, data) -> Set a @data in memory at @address"}, + {"is_mapped", (PyCFunction)vm_is_mapped, METH_VARARGS, + "is_mapped(address, size) -> Check if the memory region at @address of @size bytes is fully mapped"}, + {"add_code_bloc",(PyCFunction)vm_add_code_bloc, METH_VARARGS, + "add_code_bloc(address_start, address_stop) -> Add a jitted code block between [@address_start, @address_stop["}, + {"get_mem_access", (PyCFunction)vm_get_mem_access, METH_VARARGS, + "get_mem_access(address) -> Retrieve the memory protection of the page at @address"}, + {"get_mem", (PyCFunction)vm_get_mem, METH_VARARGS, + "get_mem(addr, size) -> Get the memory content at @address of @size bytes"}, + + {"get_u8", (PyCFunction)vm_get_u8, METH_VARARGS, + "get_u8(addr) -> Get a u8 at @address of @size bytes (vm endianness)"}, + {"get_u16", (PyCFunction)vm_get_u16, METH_VARARGS, + "get_u16(addr) -> Get a u16 at @address of @size bytes (vm endianness)"}, + {"get_u32", (PyCFunction)vm_get_u32, METH_VARARGS, + "get_u32(addr) -> Get a u32 at @address of @size bytes (vm endianness)"}, + {"get_u64", (PyCFunction)vm_get_u64, METH_VARARGS, + "get_u64(addr) -> Get a u64 at @address of @size bytes (vm endianness)"}, + + + {"set_u8", (PyCFunction)vm_set_u8, METH_VARARGS, + "set_u8(addr, value) -> Set a u8 at @address of @size bytes (vm endianness)"}, + {"set_u16", (PyCFunction)vm_set_u16, METH_VARARGS, + "set_u16(addr, value) -> Set a u16 at @address of @size bytes (vm endianness)"}, + {"set_u32", (PyCFunction)vm_set_u32, METH_VARARGS, + "set_u32(addr, value) -> Set a u32 at @address of @size bytes (vm endianness)"}, + {"set_u64", (PyCFunction)vm_set_u64, METH_VARARGS, + "set_u64(addr, value) -> Set a u64 at @address of @size bytes (vm endianness)"}, + + {"add_memory_page",(PyCFunction)vm_add_memory_page, METH_VARARGS, + "add_memory_page(address, access, content [, cmt]) -> Maps a memory page at @address of len(@content) bytes containing @content with protection @access\n" + "@cmt is a comment linked to the memory page"}, + {"remove_memory_page",(PyCFunction)vm_remove_memory_page, METH_VARARGS, + "remove_memory_page(address) -> removes a previously allocated memory page at @address"}, + {"add_memory_breakpoint",(PyCFunction)vm_add_memory_breakpoint, METH_VARARGS, + "add_memory_breakpoint(address, size, access) -> Add a memory breakpoint at @address of @size bytes with @access type"}, + {"remove_memory_breakpoint",(PyCFunction)vm_remove_memory_breakpoint, METH_VARARGS, + "remove_memory_breakpoint(address, access) -> Remove a memory breakpoint at @address with @access type"}, + {"set_exception", (PyCFunction)vm_set_exception, METH_VARARGS, + "set_exception(exception) -> Set the VmMngr exception flags to @exception"}, + {"dump_memory_breakpoint", (PyCFunction)vm_dump_memory_breakpoint, METH_VARARGS, + "dump_memory_breakpoint() -> Lists each memory breakpoint"}, + {"get_all_memory",(PyCFunction)vm_get_all_memory, METH_VARARGS, + "get_all_memory() -> Returns a dictionary representing the VmMngr memory.\n" + "Keys are the addresses of each memory page.\n" + "Values are another dictionary containing page properties ('data', 'size', 'access')" + }, + {"reset_memory_page_pool", (PyCFunction)vm_reset_memory_page_pool, METH_VARARGS, + "reset_memory_page_pool() -> Remove all memory pages"}, + {"reset_memory_breakpoint", (PyCFunction)vm_reset_memory_breakpoint, METH_VARARGS, + "reset_memory_breakpoint() -> Remove all memory breakpoints"}, + {"reset_code_bloc_pool", (PyCFunction)vm_reset_code_bloc_pool, METH_VARARGS, + "reset_code_bloc_pool() -> Remove all jitted blocks"}, + {"set_alarm", (PyCFunction)set_alarm, METH_VARARGS, + "set_alarm() -> Force a timer based alarm during a code emulation"}, + {"get_exception",(PyCFunction)vm_get_exception, METH_VARARGS, + "get_exception() -> Returns the VmMngr exception flags"}, + {"set_big_endian",(PyCFunction)vm_set_big_endian, METH_VARARGS, + "set_big_endian() -> Set the VmMngr to Big Endian"}, + {"set_little_endian",(PyCFunction)vm_set_little_endian, METH_VARARGS, + "set_little_endian() -> Set the VmMngr to Little Endian"}, + {"is_little_endian",(PyCFunction)vm_is_little_endian, METH_VARARGS, + "is_little_endian() -> Return True if the VmMngr is Little Endian"}, + {"get_memory_read",(PyCFunction)vm_get_memory_read, METH_VARARGS, + "get_memory_read() -> Retrieve last instruction READ access\n" + "This function is only valid in a memory breakpoint callback." + }, + {"get_memory_write",(PyCFunction)vm_get_memory_write, METH_VARARGS, + "get_memory_write() -> Retrieve last instruction WRITE access\n" + "This function is only valid in a memory breakpoint callback." + }, + {"reset_memory_access",(PyCFunction)vm_reset_memory_access, METH_VARARGS, + "reset_memory_access() -> Reset last memory READ/WRITE"}, + {"add_mem_read",(PyCFunction)py_add_mem_read, METH_VARARGS, + "add_mem_read(address, size) -> Add a READ access at @address of @size bytes"}, + {"add_mem_write",(PyCFunction)py_add_mem_write, METH_VARARGS, + "add_mem_write(address, size) -> Add a WRITE access at @address of @size bytes"}, + {"check_invalid_code_blocs",(PyCFunction)vm_check_invalid_code_blocs, METH_VARARGS, + "check_invalid_code_blocs() -> Set the AUTOMOD flag in exception in case of automodified code"}, + {"check_memory_breakpoint",(PyCFunction)vm_check_memory_breakpoint, METH_VARARGS, + "check_memory_breakpoint() -> Set the BREAKPOINT_MEMORY flag in exception in case of memory breakpoint occurred"}, + + {NULL} /* Sentinel */ +}; + +static int +VmMngr_init(VmMngr *self, PyObject *args, PyObject *kwds) +{ + memset(&(self->vm_mngr), 0, sizeof(self->vm_mngr)); + return 0; +} + +static PyGetSetDef VmMngr_getseters[] = { + {"vmmngr", + (getter)VmMngr_get_vmmngr, (setter)VmMngr_set_vmmngr, + "vmmngr object", + NULL}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject VmMngrType = { + PyVarObject_HEAD_INIT(NULL, 0) + "VmMngr", /*tp_name*/ + sizeof(VmMngr), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)VmMngr_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + vm_dump, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "VmMngr object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + VmMngr_methods, /* tp_methods */ + VmMngr_members, /* tp_members */ + VmMngr_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)VmMngr_init, /* tp_init */ + 0, /* tp_alloc */ + VmMngr_new, /* tp_new */ +}; + +static PyMethodDef VmMngr_Methods[] = { + {NULL, NULL, 0, NULL} /* Sentinel */ + +}; + +char vm_mngr_mod_docs[] = "vm_mngr module."; +char vm_mngr_mod_name[] = "VmMngr"; + + +MOD_INIT(VmMngr) +{ + PyObject *module = NULL; + + MOD_DEF(module, "VmMngr", "vm_mngr module", VmMngr_Methods); + + if (module == NULL) + RET_MODULE; + + if (PyType_Ready(&VmMngrType) < 0) + RET_MODULE; + + Py_INCREF(&VmMngrType); + if (PyModule_AddObject(module, "Vm", (PyObject *)&VmMngrType) < 0) + RET_MODULE; + + RET_MODULE; +} + +bn_t PyLong_to_bn(PyObject* py_long) +{ + int j; + uint64_t tmp_mask; + PyObject* py_tmp; + PyObject* py_long_tmp; + PyObject* cst_32; + PyObject* cst_ffffffff; + bn_t bn; + + cst_ffffffff = PyLong_FromLong(0xffffffff); + cst_32 = PyLong_FromLong(32); + bn = bignum_from_int(0); + + for (j = 0; j < BN_BYTE_SIZE; j += 4) { + py_tmp = PyObject_CallMethod(py_long, "__and__", "O", cst_ffffffff); + py_long_tmp = PyObject_CallMethod(py_long, "__rshift__", "O", cst_32); + Py_DECREF(py_long); + py_long = py_long_tmp; + tmp_mask = PyLong_AsUnsignedLongLongMask(py_tmp); + Py_DECREF(py_tmp); + bn = bignum_or(bn, bignum_lshift(bignum_from_uint64(tmp_mask), 8 * j)); + } + + Py_DECREF(cst_32); + Py_DECREF(cst_ffffffff); + + return bn; +} + +PyObject* bn_to_PyLong(bn_t bn) +{ + int j; + PyObject* py_long; + PyObject* py_long_new; + PyObject* py_tmp; + PyObject* cst_32; + uint64_t tmp; + + py_long = PyLong_FromLong(0); + cst_32 = PyLong_FromLong(32); + + for (j = BN_BYTE_SIZE - 4; j >= 0 ; j -= 4) { + tmp = bignum_to_uint64(bignum_mask(bignum_rshift(bn, 8 * j), 32)); + py_tmp = PyLong_FromUnsignedLong((unsigned long)tmp); + py_long_new = PyObject_CallMethod(py_long, "__lshift__", "O", cst_32); + Py_DECREF(py_long); + py_long = PyObject_CallMethod(py_long_new, "__add__", "O", py_tmp); + Py_DECREF(py_long_new); + Py_DECREF(py_tmp); + } + + Py_DECREF(cst_32); + + return py_long; +} |