diff options
Diffstat (limited to 'miasm2/jitter')
26 files changed, 13097 insertions, 0 deletions
diff --git a/miasm2/jitter/Jitllvm.c b/miasm2/jitter/Jitllvm.c new file mode 100644 index 00000000..ab077b05 --- /dev/null +++ b/miasm2/jitter/Jitllvm.c @@ -0,0 +1,36 @@ +#include <Python.h> + +#include <inttypes.h> + +#include <stdint.h> + +PyObject* llvm_exec_bloc(PyObject* self, PyObject* args) +{ + uint64_t (*func)(void*, void*); + uint64_t vm; + uint64_t cpu; + uint64_t ret; + + if (!PyArg_ParseTuple(args, "KKK", &func, &cpu, &vm)) + return NULL; + ret = func((void*)cpu, (void*)vm); + return PyLong_FromUnsignedLongLong( (uint64_t)ret); +} + + +static PyMethodDef LLVMMethods[] = { + {"llvm_exec_bloc", llvm_exec_bloc, METH_VARARGS, + "llvm exec bloc"}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +PyMODINIT_FUNC +initJitllvm(void) +{ + PyObject *m; + + m = Py_InitModule("Jitllvm", LLVMMethods); + if (m == NULL) + return; + +} diff --git a/miasm2/jitter/Jittcc.c b/miasm2/jitter/Jittcc.c new file mode 100644 index 00000000..4b16f0b1 --- /dev/null +++ b/miasm2/jitter/Jittcc.c @@ -0,0 +1,226 @@ +/* +** 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 <inttypes.h> +#include <libtcc.h> + +#include <stdint.h> + + + +/* tcc global state */ +TCCState *tcc_state = NULL; + + +int include_array_count = 0; +char **include_array = NULL; + + +int lib_array_count = 0; +char **lib_array = NULL; + +//char *libcodenat_path = NULL; + + +void tcc_init_state(void) +{ + int i; + + tcc_state = tcc_new(); + if (!tcc_state) { + fprintf(stderr, "Impossible de creer un contexte TCC\n"); + exit(1); + } + tcc_set_output_type(tcc_state, TCC_OUTPUT_MEMORY); + + //tcc_add_file(tcc_state, libcodenat_path); + for (i=0;i<lib_array_count; i++){ + tcc_add_file(tcc_state, lib_array[i]); + } + + for (i=0;i<include_array_count; i++){ + tcc_add_include_path(tcc_state, include_array[i]); + } +} + + + + +PyObject* tcc_set_emul_lib_path(PyObject* self, PyObject* args) +{ + char* include_arg; + char* lib_arg; + + char* str1, * str2; + + if (!PyArg_ParseTuple(args, "ss", + &include_arg, + &lib_arg)) + return NULL; + /* + if (include_array) + free(include_array); + */ + + str2 = strdup(include_arg); + while (str2){ + str1 = strsep(&str2, ";"); + if (str1){ + include_array_count ++; + include_array = realloc(include_array, + include_array_count * sizeof(char*)); + include_array[include_array_count-1] = strdup(str1); + fprintf(stderr, "adding include file: %s\n", str1); + } + } + + + str2 = strdup(lib_arg); + while (str2){ + str1 = strsep(&str2, ";"); + if (str1){ + lib_array_count ++; + lib_array = realloc(lib_array, + lib_array_count * sizeof(char*)); + lib_array[lib_array_count-1] = strdup(str1); + fprintf(stderr, "adding lib file: %s\n", str1); + } + } + + /* + libcodenat_path = (char*)malloc(strlen(libcodenat_path_arg)+1); + strcpy(libcodenat_path, libcodenat_path_arg); + */ + Py_INCREF(Py_None); + + + return Py_None; +} + + +PyObject* tcc_exec_bloc(PyObject* self, PyObject* args) +{ + PyObject* (*func)(void*, void*); + uint64_t vm; + uint64_t cpu; + PyObject* ret; + + if (!PyArg_ParseTuple(args, "KKK", &func, &cpu, &vm)) + return NULL; + ret = func((void*)cpu, (void*)vm); + return ret; +} + +PyObject* tcc_compil(PyObject* self, PyObject* args) +{ + char* func_name; + char* func_code; + int (*entry)(void); + + tcc_init_state(); + + if (!PyArg_ParseTuple(args, "ss", &func_name, &func_code)) + return NULL; + + if (tcc_compile_string(tcc_state, func_code) != 0) { + fprintf(stderr, "Erreur de compilation !\n"); + fprintf(stderr, "%s\n", func_code); + exit(0); + } + /* XXX use tinycc devel with -fPIC patch in makefile */ + if (tcc_relocate(tcc_state, TCC_RELOCATE_AUTO) < 0) { + fprintf(stderr, "tcc relocate error\n"); + exit(0); + } + entry = tcc_get_symbol(tcc_state, func_name); + if (!entry){ + fprintf(stderr, "Erreur de symbole %s!\n", func_name); + fprintf(stderr, "%s\n", func_name); + exit(0); + } + return PyLong_FromUnsignedLongLong((uint64_t)entry); + +} + + + +PyObject* tcc_loop_exec(PyObject* self, PyObject* args) +{ + //PyObject* (*func)(void*, void*); + uint64_t* vm; + uint64_t* cpu; + PyObject* ret; + PyObject* func; + PyObject* pArgs; + + + if (!PyArg_ParseTuple(args, "OKK", &func, &cpu, &vm)) + return NULL; + + while (1) { + if (!PyCallable_Check (func)) { + fprintf(stderr, "function not callable!\n"); + exit(0); + } + + pArgs = PyTuple_New(2); + PyTuple_SetItem(pArgs, 0, PyLong_FromUnsignedLongLong((uint64_t)cpu)); + PyTuple_SetItem(pArgs, 1, PyLong_FromUnsignedLongLong((uint64_t)vm)); + ret = PyObject_CallObject(func, pArgs); + Py_DECREF(2); + + if (ret == Py_None) { + Py_INCREF(Py_None); + return Py_None; + } + func = ret; + } + + return ret; +} + + + +static PyObject *TccError; + + +static PyMethodDef TccMethods[] = { + {"tcc_set_emul_lib_path", tcc_set_emul_lib_path, METH_VARARGS, + "init tcc path"}, + {"tcc_exec_bloc", tcc_exec_bloc, METH_VARARGS, + "tcc exec bloc"}, + {"tcc_compil", tcc_compil, METH_VARARGS, + "tcc compil"}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +PyMODINIT_FUNC +initJittcc(void) +{ + PyObject *m; + + m = Py_InitModule("Jittcc", TccMethods); + if (m == NULL) + return; + + TccError = PyErr_NewException("tcc.error", NULL, NULL); + Py_INCREF(TccError); + PyModule_AddObject(m, "error", TccError); +} + diff --git a/miasm2/jitter/Makefile b/miasm2/jitter/Makefile new file mode 100644 index 00000000..7d43f28c --- /dev/null +++ b/miasm2/jitter/Makefile @@ -0,0 +1,17 @@ +all: vm_mngr.so Jit_x86.so Jittcc.so + + +vm_mngr.so: vm_mngr.c vm_mngr.h vm_mngr_py.c + gcc -I /usr/include/python2.7 -shared -fPIC vm_mngr.c vm_mngr_py.c -o vm_mngr.so + +Jit_x86.so: arch/Jit_x86.c + gcc -I /usr/include/python2.7 -shared -fPIC arch/Jit_x86.c -o arch/Jit_x86.so + +Jit_arm.so: arch/Jit_arm.c + gcc -I /usr/include/python2.7 -shared -fPIC arch/Jit_arm.c -o arch/Jit_arm.so + +Jittcc.so: Jittcc.c + gcc -I /usr/include/python2.7 -shared -fPIC Jittcc.c -o Jittcc.so -ltcc + +clean: + rm vm_mngr.so Jittcc.so arch/Jit_x86.so \ No newline at end of file diff --git a/miasm2/jitter/__init__.py b/miasm2/jitter/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/miasm2/jitter/__init__.py diff --git a/miasm2/jitter/arch/JitCore.h b/miasm2/jitter/arch/JitCore.h new file mode 100644 index 00000000..2686cb46 --- /dev/null +++ b/miasm2/jitter/arch/JitCore.h @@ -0,0 +1,66 @@ + +#define PyGetInt(item, value) \ + if (PyInt_Check(item)){ \ + value = (uint64_t)PyInt_AsLong(item); \ + } \ + else if (PyLong_Check(item)){ \ + value = (uint64_t)PyLong_AsUnsignedLongLong(item); \ + } \ + else{ \ + RAISE(PyExc_TypeError,"arg must be int"); \ + } \ + + +#define PyGetInt_ret0(item, value) \ + if (PyInt_Check(item)){ \ + value = (uint64_t)PyInt_AsLong(item); \ + } \ + else if (PyLong_Check(item)){ \ + value = (uint64_t)PyLong_AsUnsignedLongLong(item); \ + } \ + else{ \ + printf("error\n"); return 0; \ + } \ + + + +#define getset_reg_u64(regname) \ + static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ + { \ + return PyLong_FromUnsignedLongLong((uint64_t)(self->vmcpu. regname )); \ + } \ + static int JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ + { \ + uint64_t val; \ + PyGetInt_ret0(value, val); \ + self->vmcpu. regname = val; \ + return 0; \ + } + +#define getset_reg_u32(regname) \ + static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ + { \ + return PyLong_FromUnsignedLongLong((uint32_t)(self->vmcpu. regname )); \ + } \ + static int JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ + { \ + uint32_t val; \ + PyGetInt_ret0(value, val); \ + self->vmcpu. regname = val; \ + return 0; \ + } + + +#define getset_reg_u16(regname) \ + static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ + { \ + return PyLong_FromUnsignedLongLong((uint16_t)(self->vmcpu. regname )); \ + } \ + static int JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ + { \ + uint16_t val; \ + PyGetInt_ret0(value, val); \ + self->vmcpu. regname = val; \ + return 0; \ + } + diff --git a/miasm2/jitter/arch/JitCore_arm.c b/miasm2/jitter/arch/JitCore_arm.c new file mode 100644 index 00000000..7e64ae77 --- /dev/null +++ b/miasm2/jitter/arch/JitCore_arm.c @@ -0,0 +1,388 @@ +#include <Python.h> +#include "JitCore.h" +#include "structmember.h" +#include <stdint.h> +#include <inttypes.h> +#include "JitCore_arm.h" + +#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;} + +typedef struct _reg_dict{ + char* name; + unsigned long offset; +} reg_dict; + + +#define PyGetInt(item, value) \ + if (PyInt_Check(item)){ \ + value = (uint64_t)PyInt_AsLong(item); \ + } \ + else if (PyLong_Check(item)){ \ + value = (uint64_t)PyLong_AsUnsignedLongLong(item); \ + } \ + else{ \ + RAISE(PyExc_TypeError,"arg must be int"); \ + } \ + +reg_dict gpreg_dict[] = { {.name = "R0", .offset = offsetof(vm_cpu_t, R0)}, + {.name = "R1", .offset = offsetof(vm_cpu_t, R1)}, + {.name = "R2", .offset = offsetof(vm_cpu_t, R2)}, + {.name = "R3", .offset = offsetof(vm_cpu_t, R3)}, + {.name = "R4", .offset = offsetof(vm_cpu_t, R4)}, + {.name = "R5", .offset = offsetof(vm_cpu_t, R5)}, + {.name = "R6", .offset = offsetof(vm_cpu_t, R6)}, + {.name = "R7", .offset = offsetof(vm_cpu_t, R7)}, + {.name = "R8", .offset = offsetof(vm_cpu_t, R8)}, + {.name = "R9", .offset = offsetof(vm_cpu_t, R9)}, + {.name = "R10", .offset = offsetof(vm_cpu_t, R10)}, + {.name = "R11", .offset = offsetof(vm_cpu_t, R11)}, + {.name = "R12", .offset = offsetof(vm_cpu_t, R12)}, + {.name = "SP", .offset = offsetof(vm_cpu_t, SP)}, + {.name = "LR", .offset = offsetof(vm_cpu_t, LR)}, + {.name = "PC", .offset = offsetof(vm_cpu_t, PC)}, + + {.name = "zf", .offset = offsetof(vm_cpu_t, zf)}, + {.name = "nf", .offset = offsetof(vm_cpu_t, nf)}, + {.name = "of", .offset = offsetof(vm_cpu_t, of)}, + {.name = "cf", .offset = offsetof(vm_cpu_t, cf)}, +}; + +/************************** JitCpu object **************************/ + +typedef struct { + PyObject_HEAD + PyObject *cpu; /* cpu */ + vm_cpu_t vmcpu; +} JitCpu; + + + +#define get_reg(reg) do { \ + o = PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.reg); \ + PyDict_SetItemString(dict, #reg, o); \ + Py_DECREF(o); \ + } while(0); + + + +PyObject* vm_get_gpreg(JitCpu* self) +{ + PyObject *dict = PyDict_New(); + PyObject *o; + + get_reg(R0); + get_reg(R1); + get_reg(R2); + get_reg(R3); + get_reg(R4); + get_reg(R5); + get_reg(R6); + get_reg(R7); + get_reg(R8); + get_reg(R9); + get_reg(R10); + get_reg(R11); + get_reg(R12); + get_reg(SP); + get_reg(LR); + get_reg(PC); + + get_reg(zf); + get_reg(nf); + get_reg(of); + get_reg(cf); + + return dict; +} + +PyObject* _vm_set_gpreg(JitCpu* self, PyObject *dict) +{ + PyObject *d_key, *d_value = NULL; + Py_ssize_t pos = 0; + uint64_t val; + unsigned int i, found; + + if(!PyDict_Check(dict)) + RAISE(PyExc_TypeError, "arg must be dict"); + while(PyDict_Next(dict, &pos, &d_key, &d_value)){ + if(!PyString_Check(d_key)) + RAISE(PyExc_TypeError, "key must be str"); + + PyGetInt(d_value, val); + + + found = 0; + for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ + if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name)) + continue; + *((uint32_t*)(((char*)&(self->vmcpu)) + gpreg_dict[i].offset)) = val; + found = 1; + break; + } + + if (found) + continue; + fprintf(stderr, "unkown key: %s\n", PyString_AsString(d_key)); + RAISE(PyExc_ValueError, "unkown reg"); + } + return NULL; +} + +PyObject* vm_set_gpreg(JitCpu* self, PyObject *args) +{ + PyObject* dict; + if (!PyArg_ParseTuple(args, "O", &dict)) + return NULL; + _vm_set_gpreg(self, dict); + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* vm_set_exception(JitCpu* self, PyObject* args) +{ + PyObject *item1; + uint64_t i; + + if (!PyArg_ParseTuple(args, "O", &item1)) + return NULL; + + PyGetInt(item1, i); + + self->vmcpu.exception_flags = i; + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_get_exception(JitCpu* self, PyObject* args) +{ + return PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.exception_flags); +} + + +PyObject * vm_init_regs(JitCpu* self) +{ + memset(&self->vmcpu, 0, sizeof(vm_cpu_t)); + + Py_INCREF(Py_None); + return Py_None; + +} + +void dump_gpregs(vm_cpu_t* vmcpu) +{ + printf("R0 %.16"PRIX32" R1 %.16"PRIX32" R2 %.16"PRIX32" R3 %.16"PRIX32"\n", + vmcpu->R0, vmcpu->R1, vmcpu->R2, vmcpu->R3); + printf("R4 %.16"PRIX32" R5 %.16"PRIX32" R6 %.16"PRIX32" R7 %.16"PRIX32"\n", + vmcpu->R4, vmcpu->R5, vmcpu->R6, vmcpu->R7); + printf("R8 %.16"PRIX32" R9 %.16"PRIX32" R10 %.16"PRIX32" R11 %.16"PRIX32"\n", + vmcpu->R8, vmcpu->R9, vmcpu->R10, vmcpu->R11); + printf("R12 %.16"PRIX32" SP %.16"PRIX32" LR %.16"PRIX32" PC %.16"PRIX32"\n", + vmcpu->R12, vmcpu->SP, vmcpu->LR, vmcpu->PC); + printf("zf %.16"PRIX32" nf %.16"PRIX32" of %.16"PRIX32" cf %.16"PRIX32"\n", + vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf); +} + + +PyObject * vm_dump_gpregs(JitCpu* self, PyObject* args) +{ + vm_cpu_t* vmcpu; + + vmcpu = &self->vmcpu; + dump_gpregs(vmcpu); + Py_INCREF(Py_None); + return Py_None; +} + + + +static void +JitCpu_dealloc(JitCpu* self) +{ + self->ob_type->tp_free((PyObject*)self); +} + + +static PyObject * +JitCpu_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + JitCpu *self; + + self = (JitCpu *)type->tp_alloc(type, 0); + return (PyObject *)self; +} + +static PyObject * +JitCpu_get_cpu(JitCpu *self, void *closure) +{ + return PyLong_FromUnsignedLongLong((uint64_t)&(self->vmcpu)); +} + +static int +JitCpu_set_cpu(JitCpu *self, PyObject *value, void *closure) +{ + PyErr_SetString(PyExc_TypeError, "immutable cpu"); + return -1; +} + +static PyMemberDef JitCpu_members[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef JitCpu_methods[] = { + {"vm_init_regs", (PyCFunction)vm_init_regs, METH_NOARGS, + "X"}, + {"vm_dump_gpregs", (PyCFunction)vm_dump_gpregs, METH_NOARGS, + "X"}, + {"vm_get_gpreg", (PyCFunction)vm_get_gpreg, METH_NOARGS, + "X"}, + {"vm_set_gpreg", (PyCFunction)vm_set_gpreg, METH_VARARGS, + "X"}, + {"vm_get_exception", (PyCFunction)vm_get_exception, METH_VARARGS, + "X"}, + {"vm_set_exception", (PyCFunction)vm_set_exception, METH_VARARGS, + "X"}, + {NULL} /* Sentinel */ +}; + +static int +JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) +{ + + + fprintf(stderr, "ad cpu: %p\n", &(self->vmcpu)); + + return 0; +} + +getset_reg_u32(R0); +getset_reg_u32(R1); +getset_reg_u32(R2); +getset_reg_u32(R3); +getset_reg_u32(R4); +getset_reg_u32(R5); +getset_reg_u32(R6); +getset_reg_u32(R7); +getset_reg_u32(R8); +getset_reg_u32(R9); +getset_reg_u32(R10); +getset_reg_u32(R11); +getset_reg_u32(R12); +getset_reg_u32(SP); +getset_reg_u32(LR); +getset_reg_u32(PC); + +getset_reg_u32(zf); +getset_reg_u32(nf); +getset_reg_u32(of); +getset_reg_u32(cf); + + +static PyGetSetDef JitCpu_getseters[] = { + {"cpu", + (getter)JitCpu_get_cpu, (setter)JitCpu_set_cpu, + "first name", + NULL}, + + {"R0" , (getter)JitCpu_get_R0 , (setter)JitCpu_set_R0 , "R0" , NULL}, + {"R1" , (getter)JitCpu_get_R1 , (setter)JitCpu_set_R1 , "R1" , NULL}, + {"R2" , (getter)JitCpu_get_R2 , (setter)JitCpu_set_R2 , "R2" , NULL}, + {"R3" , (getter)JitCpu_get_R3 , (setter)JitCpu_set_R3 , "R3" , NULL}, + {"R4" , (getter)JitCpu_get_R4 , (setter)JitCpu_set_R4 , "R4" , NULL}, + {"R5" , (getter)JitCpu_get_R5 , (setter)JitCpu_set_R5 , "R5" , NULL}, + {"R6" , (getter)JitCpu_get_R6 , (setter)JitCpu_set_R6 , "R6" , NULL}, + {"R7" , (getter)JitCpu_get_R7 , (setter)JitCpu_set_R7 , "R7" , NULL}, + {"R8" , (getter)JitCpu_get_R8 , (setter)JitCpu_set_R8 , "R8" , NULL}, + {"R9" , (getter)JitCpu_get_R9 , (setter)JitCpu_set_R9 , "R9" , NULL}, + {"R10", (getter)JitCpu_get_R10, (setter)JitCpu_set_R10, "R10", NULL}, + {"R11", (getter)JitCpu_get_R11, (setter)JitCpu_set_R11, "R11", NULL}, + {"R12", (getter)JitCpu_get_R12, (setter)JitCpu_set_R12, "R12", NULL}, + {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL}, + {"LR" , (getter)JitCpu_get_LR , (setter)JitCpu_set_LR , "LR" , NULL}, + {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL}, + + {"zf", (getter)JitCpu_get_zf, (setter)JitCpu_set_zf, "zf", NULL}, + {"nf", (getter)JitCpu_get_nf, (setter)JitCpu_set_nf, "nf", NULL}, + {"of", (getter)JitCpu_get_of, (setter)JitCpu_set_of, "of", NULL}, + {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL}, + + {NULL} /* Sentinel */ +}; + + +static PyTypeObject JitCpuType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "JitCore_arm.JitCpu", /*tp_name*/ + sizeof(JitCpu), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)JitCpu_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*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*/ + "JitCpu objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + JitCpu_methods, /* tp_methods */ + JitCpu_members, /* tp_members */ + JitCpu_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)JitCpu_init, /* tp_init */ + 0, /* tp_alloc */ + JitCpu_new, /* tp_new */ +}; + + + +static PyMethodDef JitCore_arm_Methods[] = { + + /* + + */ + {NULL, NULL, 0, NULL} /* Sentinel */ + +}; + +static PyObject *JitCore_arm_Error; + +PyMODINIT_FUNC +initJitCore_arm(void) +{ + PyObject *m; + + if (PyType_Ready(&JitCpuType) < 0) + return; + + m = Py_InitModule("JitCore_arm", JitCore_arm_Methods); + if (m == NULL) + return; + + JitCore_arm_Error = PyErr_NewException("JitCore_arm.error", NULL, NULL); + Py_INCREF(JitCore_arm_Error); + PyModule_AddObject(m, "error", JitCore_arm_Error); + + Py_INCREF(&JitCpuType); + PyModule_AddObject(m, "JitCpu", (PyObject *)&JitCpuType); + +} + diff --git a/miasm2/jitter/arch/JitCore_arm.h b/miasm2/jitter/arch/JitCore_arm.h new file mode 100644 index 00000000..e92db860 --- /dev/null +++ b/miasm2/jitter/arch/JitCore_arm.h @@ -0,0 +1,147 @@ + +typedef struct { + uint32_t exception_flags; + uint32_t exception_flags_new; + + /* gpregs */ + uint32_t R0; + uint32_t R1; + uint32_t R2; + uint32_t R3; + uint32_t R4; + uint32_t R5; + uint32_t R6; + uint32_t R7; + uint32_t R8; + uint32_t R9; + uint32_t R10; + uint32_t R11; + uint32_t R12; + uint32_t SP; + uint32_t LR; + uint32_t PC; + + uint32_t R0_new; + uint32_t R1_new; + uint32_t R2_new; + uint32_t R3_new; + uint32_t R4_new; + uint32_t R5_new; + uint32_t R6_new; + uint32_t R7_new; + uint32_t R8_new; + uint32_t R9_new; + uint32_t R10_new; + uint32_t R11_new; + uint32_t R12_new; + uint32_t SP_new; + uint32_t LR_new; + uint32_t PC_new; + + /* eflag */ + uint32_t zf; + uint32_t nf; + uint32_t of; + uint32_t cf; + + uint32_t zf_new; + uint32_t nf_new; + uint32_t of_new; + uint32_t cf_new; + + + uint8_t pfmem08_0; + uint8_t pfmem08_1; + uint8_t pfmem08_2; + uint8_t pfmem08_3; + uint8_t pfmem08_4; + uint8_t pfmem08_5; + uint8_t pfmem08_6; + uint8_t pfmem08_7; + uint8_t pfmem08_8; + uint8_t pfmem08_9; + uint8_t pfmem08_10; + uint8_t pfmem08_11; + uint8_t pfmem08_12; + uint8_t pfmem08_13; + uint8_t pfmem08_14; + uint8_t pfmem08_15; + uint8_t pfmem08_16; + uint8_t pfmem08_17; + uint8_t pfmem08_18; + uint8_t pfmem08_19; + + + uint16_t pfmem16_0; + uint16_t pfmem16_1; + uint16_t pfmem16_2; + uint16_t pfmem16_3; + uint16_t pfmem16_4; + uint16_t pfmem16_5; + uint16_t pfmem16_6; + uint16_t pfmem16_7; + uint16_t pfmem16_8; + uint16_t pfmem16_9; + uint16_t pfmem16_10; + uint16_t pfmem16_11; + uint16_t pfmem16_12; + uint16_t pfmem16_13; + uint16_t pfmem16_14; + uint16_t pfmem16_15; + uint16_t pfmem16_16; + uint16_t pfmem16_17; + uint16_t pfmem16_18; + uint16_t pfmem16_19; + + + uint32_t pfmem32_0; + uint32_t pfmem32_1; + uint32_t pfmem32_2; + uint32_t pfmem32_3; + uint32_t pfmem32_4; + uint32_t pfmem32_5; + uint32_t pfmem32_6; + uint32_t pfmem32_7; + uint32_t pfmem32_8; + uint32_t pfmem32_9; + uint32_t pfmem32_10; + uint32_t pfmem32_11; + uint32_t pfmem32_12; + uint32_t pfmem32_13; + uint32_t pfmem32_14; + uint32_t pfmem32_15; + uint32_t pfmem32_16; + uint32_t pfmem32_17; + uint32_t pfmem32_18; + uint32_t pfmem32_19; + + + uint64_t pfmem64_0; + uint64_t pfmem64_1; + uint64_t pfmem64_2; + uint64_t pfmem64_3; + uint64_t pfmem64_4; + uint64_t pfmem64_5; + uint64_t pfmem64_6; + uint64_t pfmem64_7; + uint64_t pfmem64_8; + uint64_t pfmem64_9; + uint64_t pfmem64_10; + uint64_t pfmem64_11; + uint64_t pfmem64_12; + uint64_t pfmem64_13; + uint64_t pfmem64_14; + uint64_t pfmem64_15; + uint64_t pfmem64_16; + uint64_t pfmem64_17; + uint64_t pfmem64_18; + uint64_t pfmem64_19; + + + uint32_t segm_base[0x10000]; + +}vm_cpu_t; + + + +#define RETURN_PC return PyLong_FromUnsignedLongLong(vmcpu->PC); diff --git a/miasm2/jitter/arch/JitCore_msp430.c b/miasm2/jitter/arch/JitCore_msp430.c new file mode 100644 index 00000000..17c1497e --- /dev/null +++ b/miasm2/jitter/arch/JitCore_msp430.c @@ -0,0 +1,694 @@ +#include <Python.h> +#include "JitCore.h" +#include "structmember.h" +#include <stdint.h> +#include <inttypes.h> +#include "JitCore_msp430.h" + +#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;} + +/* +void check_align(uint64_t addr) +{ + if (addr & 1) { + printf("unaligned mem lookup %X\n", addr); + exit(0); + } +} + +void VM_MEM_WRITE_08(vm_mngr_t* vm_mngr, uint64_t addr, unsigned char src) +{ + //check_align(addr); + MEM_WRITE_08(vm_mngr, addr, src); +} + +void VM_MEM_WRITE_16(vm_mngr_t* vm_mngr, uint64_t addr, unsigned short src) +{ + check_align(addr); + MEM_WRITE_16(vm_mngr, addr, src); +} + +void VM_MEM_WRITE_32(vm_mngr_t* vm_mngr, uint64_t addr, unsigned int src) +{ + check_align(addr); + MEM_WRITE_32(vm_mngr, addr, src); +} + +void VM_MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src) +{ + check_align(addr); + MEM_WRITE_64(vm_mngr, addr, src); +} +*/ + +typedef struct _reg_dict{ + char* name; + unsigned long offset; +} reg_dict; + + +#define PyGetInt(item, value) \ + if (PyInt_Check(item)){ \ + value = (uint64_t)PyInt_AsLong(item); \ + } \ + else if (PyLong_Check(item)){ \ + value = (uint64_t)PyLong_AsUnsignedLongLong(item); \ + } \ + else{ \ + RAISE(PyExc_TypeError,"arg must be int"); \ + } \ + +reg_dict gpreg_dict[] = { {.name = "PC", .offset = offsetof(vm_cpu_t, PC)}, + {.name = "SP", .offset = offsetof(vm_cpu_t, SP)}, + //{.name = "SR", .offset = offsetof(vm_cpu_t, SR)}, + {.name = "R3", .offset = offsetof(vm_cpu_t, R3)}, + {.name = "R4", .offset = offsetof(vm_cpu_t, R4)}, + {.name = "R5", .offset = offsetof(vm_cpu_t, R5)}, + {.name = "R6", .offset = offsetof(vm_cpu_t, R6)}, + {.name = "R7", .offset = offsetof(vm_cpu_t, R7)}, + {.name = "R8", .offset = offsetof(vm_cpu_t, R8)}, + {.name = "R9", .offset = offsetof(vm_cpu_t, R9)}, + {.name = "R10", .offset = offsetof(vm_cpu_t, R10)}, + {.name = "R11", .offset = offsetof(vm_cpu_t, R11)}, + {.name = "R12", .offset = offsetof(vm_cpu_t, R12)}, + {.name = "R13", .offset = offsetof(vm_cpu_t, R13)}, + {.name = "R14", .offset = offsetof(vm_cpu_t, R14)}, + {.name = "R15", .offset = offsetof(vm_cpu_t, R15)}, + + {.name = "zf", .offset = offsetof(vm_cpu_t, zf)}, + {.name = "nf", .offset = offsetof(vm_cpu_t, nf)}, + {.name = "of", .offset = offsetof(vm_cpu_t, of)}, + {.name = "cf", .offset = offsetof(vm_cpu_t, cf)}, + + {.name = "cpuoff", .offset = offsetof(vm_cpu_t, zf)}, + {.name = "gie", .offset = offsetof(vm_cpu_t, zf)}, + {.name = "osc", .offset = offsetof(vm_cpu_t, zf)}, + {.name = "scg0", .offset = offsetof(vm_cpu_t, zf)}, + {.name = "scg1", .offset = offsetof(vm_cpu_t, zf)}, + {.name = "res", .offset = offsetof(vm_cpu_t, zf)}, + +}; + +/************************** JitCpu object **************************/ + +typedef struct { + PyObject_HEAD + PyObject *cpu; /* cpu */ + vm_cpu_t vmcpu; +} JitCpu; + + + +#define get_reg(reg) do { \ + o = PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.reg); \ + PyDict_SetItemString(dict, #reg, o); \ + Py_DECREF(o); \ + } while(0); + + + +PyObject* vm_get_gpreg(JitCpu* self) +{ + PyObject *dict = PyDict_New(); + PyObject *o; + + get_reg(PC); + get_reg(SP); + //get_reg(SR); + get_reg(R3); + get_reg(R4); + get_reg(R5); + get_reg(R6); + get_reg(R7); + get_reg(R8); + get_reg(R9); + get_reg(R10); + get_reg(R11); + get_reg(R12); + get_reg(R13); + get_reg(R14); + get_reg(R15); + + get_reg(zf); + get_reg(nf); + get_reg(of); + get_reg(cf); + + get_reg(cpuoff); + get_reg(gie); + get_reg(osc); + get_reg(scg0); + get_reg(scg1); + get_reg(res); + + + return dict; +} + +#define get_reg_off(reg) do { \ + o = PyLong_FromUnsignedLongLong((uint64_t)offsetof(vm_cpu_t, reg)); \ + PyDict_SetItemString(dict, #reg, o); \ + Py_DECREF(o); \ + } while(0); + + +PyObject* get_gpreg_offset_all(void) +{ + PyObject *dict = PyDict_New(); + PyObject *o; + get_reg_off(exception_flags); + get_reg_off(exception_flags_new); + get_reg_off(PC); + get_reg_off(SP); + get_reg_off(R3); + get_reg_off(R4); + get_reg_off(R5); + get_reg_off(R6); + get_reg_off(R7); + get_reg_off(R8); + get_reg_off(R9); + get_reg_off(R10); + get_reg_off(R11); + get_reg_off(R12); + get_reg_off(R13); + get_reg_off(R14); + get_reg_off(R15); + get_reg_off(PC_new); + get_reg_off(SP_new); + get_reg_off(SR_new); + get_reg_off(R3_new); + get_reg_off(R4_new); + get_reg_off(R5_new); + get_reg_off(R6_new); + get_reg_off(R7_new); + get_reg_off(R8_new); + get_reg_off(R9_new); + get_reg_off(R10_new); + get_reg_off(R11_new); + get_reg_off(R12_new); + get_reg_off(R13_new); + get_reg_off(R14_new); + get_reg_off(R15_new); + get_reg_off(zf); + get_reg_off(nf); + get_reg_off(of); + get_reg_off(cf); + get_reg_off(cpuoff); + get_reg_off(gie); + get_reg_off(osc); + get_reg_off(scg0); + get_reg_off(scg1); + get_reg_off(res); + get_reg_off(zf_new); + get_reg_off(nf_new); + get_reg_off(of_new); + get_reg_off(cf_new); + get_reg_off(cpuoff_new); + get_reg_off(gie_new); + get_reg_off(osc_new); + get_reg_off(scg0_new); + get_reg_off(scg1_new); + get_reg_off(res_new); + get_reg_off(pfmem08_0); + get_reg_off(pfmem08_1); + get_reg_off(pfmem08_2); + get_reg_off(pfmem08_3); + get_reg_off(pfmem08_4); + get_reg_off(pfmem08_5); + get_reg_off(pfmem08_6); + get_reg_off(pfmem08_7); + get_reg_off(pfmem08_8); + get_reg_off(pfmem08_9); + get_reg_off(pfmem08_10); + get_reg_off(pfmem08_11); + get_reg_off(pfmem08_12); + get_reg_off(pfmem08_13); + get_reg_off(pfmem08_14); + get_reg_off(pfmem08_15); + get_reg_off(pfmem08_16); + get_reg_off(pfmem08_17); + get_reg_off(pfmem08_18); + get_reg_off(pfmem08_19); + get_reg_off(pfmem16_0); + get_reg_off(pfmem16_1); + get_reg_off(pfmem16_2); + get_reg_off(pfmem16_3); + get_reg_off(pfmem16_4); + get_reg_off(pfmem16_5); + get_reg_off(pfmem16_6); + get_reg_off(pfmem16_7); + get_reg_off(pfmem16_8); + get_reg_off(pfmem16_9); + get_reg_off(pfmem16_10); + get_reg_off(pfmem16_11); + get_reg_off(pfmem16_12); + get_reg_off(pfmem16_13); + get_reg_off(pfmem16_14); + get_reg_off(pfmem16_15); + get_reg_off(pfmem16_16); + get_reg_off(pfmem16_17); + get_reg_off(pfmem16_18); + get_reg_off(pfmem16_19); + get_reg_off(pfmem32_0); + get_reg_off(pfmem32_1); + get_reg_off(pfmem32_2); + get_reg_off(pfmem32_3); + get_reg_off(pfmem32_4); + get_reg_off(pfmem32_5); + get_reg_off(pfmem32_6); + get_reg_off(pfmem32_7); + get_reg_off(pfmem32_8); + get_reg_off(pfmem32_9); + get_reg_off(pfmem32_10); + get_reg_off(pfmem32_11); + get_reg_off(pfmem32_12); + get_reg_off(pfmem32_13); + get_reg_off(pfmem32_14); + get_reg_off(pfmem32_15); + get_reg_off(pfmem32_16); + get_reg_off(pfmem32_17); + get_reg_off(pfmem32_18); + get_reg_off(pfmem32_19); + get_reg_off(pfmem64_0); + get_reg_off(pfmem64_1); + get_reg_off(pfmem64_2); + get_reg_off(pfmem64_3); + get_reg_off(pfmem64_4); + get_reg_off(pfmem64_5); + get_reg_off(pfmem64_6); + get_reg_off(pfmem64_7); + get_reg_off(pfmem64_8); + get_reg_off(pfmem64_9); + get_reg_off(pfmem64_10); + get_reg_off(pfmem64_11); + get_reg_off(pfmem64_12); + get_reg_off(pfmem64_13); + get_reg_off(pfmem64_14); + get_reg_off(pfmem64_15); + get_reg_off(pfmem64_16); + get_reg_off(pfmem64_17); + get_reg_off(pfmem64_18); + get_reg_off(pfmem64_19); + return dict; +} + + +PyObject* _vm_set_gpreg(JitCpu* self, PyObject *dict) +{ + PyObject *d_key, *d_value = NULL; + Py_ssize_t pos = 0; + uint64_t val; + unsigned int i, found; + + if(!PyDict_Check(dict)) + RAISE(PyExc_TypeError, "arg must be dict"); + while(PyDict_Next(dict, &pos, &d_key, &d_value)){ + if(!PyString_Check(d_key)) + RAISE(PyExc_TypeError, "key must be str"); + + PyGetInt(d_value, val); + + + found = 0; + for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ + if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name)) + continue; + *((uint32_t*)(((char*)&(self->vmcpu)) + gpreg_dict[i].offset)) = val; + found = 1; + break; + } + + if (found) + continue; + fprintf(stderr, "unkown key: %s\n", PyString_AsString(d_key)); + RAISE(PyExc_ValueError, "unkown reg"); + } + return NULL; +} + +uint8_t const bcd2bin_data[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 0, 0, 0, 0, 0, 0, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 0, 0, 0, 0, 0, 0, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 0, 0, 0, 0, 0, 0, + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 0, 0, 0, 0, 0, 0, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0, 0, 0, 0, 0, 0, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 +}; + +uint8_t const bin2bcd_data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99 +}; + +inline uint16_t bcdadd_16(uint16_t a, uint16_t b) +{ + int carry = 0; + int i,j = 0; + uint16_t res = 0; + int nib_a, nib_b; + for (i = 0; i < 16; i += 4) { + nib_a = (a >> i) & (0xF); + nib_b = (b >> i) & (0xF); + + j = (carry + nib_a + nib_b); + if (j >= 10) { + carry = 1; + j -= 10; + j &=0xf; + } + else { + carry = 0; + } + res += j << i; + } + return res; +} + +inline uint16_t bcdadd_cf_16(uint16_t a, uint16_t b) +{ + int carry = 0; + int i,j = 0; + int nib_a, nib_b; + for (i = 0; i < 16; i += 4) { + nib_a = (a >> i) & (0xF); + nib_b = (b >> i) & (0xF); + + j = (carry + nib_a + nib_b); + if (j >= 10) { + carry = 1; + j -= 10; + j &=0xf; + } + else { + carry = 0; + } + } + return carry; +} + + +inline uint16_t hex2bcd_16(uint16_t a) +{ + return bcd2bin_data[a & 0xFF] + (bcd2bin_data[(a >> 8) & 0xFF] * 100); +} + +inline uint8_t hex2bcd_8(uint8_t a) +{ + return bcd2bin_data[a & 0xFF]; +} + +inline uint8_t bcd2hex_8(uint8_t a) +{ + return bin2bcd_data[a & 0xFF]; +} + +inline uint16_t bcd2hex_16(uint16_t a) +{ + return bcd2bin_data[a % 100] | (bcd2bin_data[(a / 100)] << 8); +} + + +PyObject* vm_set_gpreg(JitCpu* self, PyObject *args) +{ + PyObject* dict; + if (!PyArg_ParseTuple(args, "O", &dict)) + return NULL; + _vm_set_gpreg(self, dict); + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* vm_set_exception(JitCpu* self, PyObject* args) +{ + PyObject *item1; + uint64_t i; + + if (!PyArg_ParseTuple(args, "O", &item1)) + return NULL; + + PyGetInt(item1, i); + + self->vmcpu.exception_flags = i; + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_get_exception(JitCpu* self, PyObject* args) +{ + return PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.exception_flags); +} + + +PyObject * vm_init_regs(JitCpu* self) +{ + memset(&self->vmcpu, 0, sizeof(vm_cpu_t)); + + Py_INCREF(Py_None); + return Py_None; + +} + +void dump_gpregs(vm_cpu_t* vmcpu) +{ + + printf("PC %.4"PRIX32" SP %.4"PRIX32" R3 %.4"PRIX32" ", + vmcpu->PC, vmcpu->SP, vmcpu->R3); + printf("R4 %.4"PRIX32" R5 %.4"PRIX32" R6 %.4"PRIX32" R7 %.4"PRIX32"\n", + vmcpu->R4, vmcpu->R5, vmcpu->R6, vmcpu->R7); + printf("R8 %.4"PRIX32" R9 %.4"PRIX32" R10 %.4"PRIX32" R11 %.4"PRIX32" ", + vmcpu->R8, vmcpu->R9, vmcpu->R10, vmcpu->R11); + printf("R12 %.4"PRIX32" R13 %.4"PRIX32" R14 %.4"PRIX32" R15 %.4"PRIX32"\n", + vmcpu->R12, vmcpu->R13, vmcpu->R14, vmcpu->R15); + printf("zf %.4"PRIX32" nf %.4"PRIX32" of %.4"PRIX32" cf %.4"PRIX32"\n", + vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf); +} + + +PyObject * vm_dump_gpregs(JitCpu* self, PyObject* args) +{ + vm_cpu_t* vmcpu; + + vmcpu = &self->vmcpu; + dump_gpregs(vmcpu); + Py_INCREF(Py_None); + return Py_None; +} + + + +static void +JitCpu_dealloc(JitCpu* self) +{ + self->ob_type->tp_free((PyObject*)self); +} + + +static PyObject * +JitCpu_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + JitCpu *self; + + self = (JitCpu *)type->tp_alloc(type, 0); + return (PyObject *)self; +} + +static PyObject * +JitCpu_get_cpu(JitCpu *self, void *closure) +{ + return PyLong_FromUnsignedLongLong((uint64_t)&(self->vmcpu)); +} + +static int +JitCpu_set_cpu(JitCpu *self, PyObject *value, void *closure) +{ + PyErr_SetString(PyExc_TypeError, "immutable cpu"); + return -1; +} + +static PyMemberDef JitCpu_members[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef JitCpu_methods[] = { + {"vm_init_regs", (PyCFunction)vm_init_regs, METH_NOARGS, + "X"}, + {"vm_dump_gpregs", (PyCFunction)vm_dump_gpregs, METH_NOARGS, + "X"}, + {"vm_get_gpreg", (PyCFunction)vm_get_gpreg, METH_NOARGS, + "X"}, + {"vm_set_gpreg", (PyCFunction)vm_set_gpreg, METH_VARARGS, + "X"}, + {"vm_get_exception", (PyCFunction)vm_get_exception, METH_VARARGS, + "X"}, + {"vm_set_exception", (PyCFunction)vm_set_exception, METH_VARARGS, + "X"}, + {NULL} /* Sentinel */ +}; + +static int +JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) +{ + + + fprintf(stderr, "ad cpu: %p\n", &(self->vmcpu)); + + return 0; +} + +getset_reg_u16(PC); +getset_reg_u16(SP); +getset_reg_u16(R3); +getset_reg_u16(R4); +getset_reg_u16(R5); +getset_reg_u16(R6); +getset_reg_u16(R7); +getset_reg_u16(R8); +getset_reg_u16(R9); +getset_reg_u16(R10); +getset_reg_u16(R11); +getset_reg_u16(R12); +getset_reg_u16(R13); +getset_reg_u16(R14); +getset_reg_u16(R15); +getset_reg_u16(zf); +getset_reg_u16(nf); +getset_reg_u16(of); +getset_reg_u16(cf); +getset_reg_u16(cpuoff); +getset_reg_u16(gie); +getset_reg_u16(osc); +getset_reg_u16(scg0); +getset_reg_u16(scg1); +getset_reg_u16(res); + + + + +static PyGetSetDef JitCpu_getseters[] = { + {"cpu", + (getter)JitCpu_get_cpu, (setter)JitCpu_set_cpu, + "first name", + NULL}, + + + {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL}, + {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL}, + {"R3" , (getter)JitCpu_get_R3 , (setter)JitCpu_set_R3 , "R3" , NULL}, + {"R4" , (getter)JitCpu_get_R4 , (setter)JitCpu_set_R4 , "R4" , NULL}, + {"R5" , (getter)JitCpu_get_R5 , (setter)JitCpu_set_R5 , "R5" , NULL}, + {"R6" , (getter)JitCpu_get_R6 , (setter)JitCpu_set_R6 , "R6" , NULL}, + {"R7" , (getter)JitCpu_get_R7 , (setter)JitCpu_set_R7 , "R7" , NULL}, + {"R8" , (getter)JitCpu_get_R8 , (setter)JitCpu_set_R8 , "R8" , NULL}, + {"R9" , (getter)JitCpu_get_R9 , (setter)JitCpu_set_R9 , "R9" , NULL}, + {"R10" , (getter)JitCpu_get_R10 , (setter)JitCpu_set_R10 , "R10" , NULL}, + {"R11" , (getter)JitCpu_get_R11 , (setter)JitCpu_set_R11 , "R11" , NULL}, + {"R12" , (getter)JitCpu_get_R12 , (setter)JitCpu_set_R12 , "R12" , NULL}, + {"R13" , (getter)JitCpu_get_R13 , (setter)JitCpu_set_R13 , "R13" , NULL}, + {"R14" , (getter)JitCpu_get_R14 , (setter)JitCpu_set_R14 , "R14" , NULL}, + {"R15" , (getter)JitCpu_get_R15 , (setter)JitCpu_set_R15 , "R15" , NULL}, + {"zf" , (getter)JitCpu_get_zf , (setter)JitCpu_set_zf , "zf" , NULL}, + {"nf" , (getter)JitCpu_get_nf , (setter)JitCpu_set_nf , "nf" , NULL}, + {"of" , (getter)JitCpu_get_of , (setter)JitCpu_set_of , "of" , NULL}, + {"cf" , (getter)JitCpu_get_cf , (setter)JitCpu_set_cf , "cf" , NULL}, + {"cpuoff" , (getter)JitCpu_get_cpuoff , (setter)JitCpu_set_cpuoff , "cpuoff" , NULL}, + {"gie" , (getter)JitCpu_get_gie , (setter)JitCpu_set_gie , "gie" , NULL}, + {"osc" , (getter)JitCpu_get_osc , (setter)JitCpu_set_osc , "osc" , NULL}, + {"scg0" , (getter)JitCpu_get_scg0 , (setter)JitCpu_set_scg0 , "scg0" , NULL}, + {"scg1" , (getter)JitCpu_get_scg1 , (setter)JitCpu_set_scg1 , "scg1" , NULL}, + {"res" , (getter)JitCpu_get_res , (setter)JitCpu_set_res , "res" , NULL}, + + {NULL} /* Sentinel */ +}; + + + +static PyTypeObject JitCpuType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "JitCore_msp430.JitCpu", /*tp_name*/ + sizeof(JitCpu), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)JitCpu_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*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*/ + "JitCpu objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + JitCpu_methods, /* tp_methods */ + JitCpu_members, /* tp_members */ + JitCpu_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)JitCpu_init, /* tp_init */ + 0, /* tp_alloc */ + JitCpu_new, /* tp_new */ +}; + + + +static PyMethodDef JitCore_msp430_Methods[] = { + + /* + + */ + {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, + {NULL, NULL, 0, NULL} /* Sentinel */ + +}; + +static PyObject *JitCore_msp430_Error; + +PyMODINIT_FUNC +initJitCore_msp430(void) +{ + PyObject *m; + + if (PyType_Ready(&JitCpuType) < 0) + return; + + m = Py_InitModule("JitCore_msp430", JitCore_msp430_Methods); + if (m == NULL) + return; + + JitCore_msp430_Error = PyErr_NewException("JitCore_msp430.error", NULL, NULL); + Py_INCREF(JitCore_msp430_Error); + PyModule_AddObject(m, "error", JitCore_msp430_Error); + + Py_INCREF(&JitCpuType); + PyModule_AddObject(m, "JitCpu", (PyObject *)&JitCpuType); + +} + diff --git a/miasm2/jitter/arch/JitCore_msp430.h b/miasm2/jitter/arch/JitCore_msp430.h new file mode 100644 index 00000000..c65989b0 --- /dev/null +++ b/miasm2/jitter/arch/JitCore_msp430.h @@ -0,0 +1,171 @@ + +typedef struct { + uint32_t exception_flags; + uint32_t exception_flags_new; + + /* gpregs */ + uint32_t PC; + uint32_t SP; + uint32_t R3; + uint32_t R4; + uint32_t R5; + uint32_t R6; + uint32_t R7; + uint32_t R8; + uint32_t R9; + uint32_t R10; + uint32_t R11; + uint32_t R12; + uint32_t R13; + uint32_t R14; + uint32_t R15; + + uint32_t PC_new; + uint32_t SP_new; + uint32_t SR_new; + uint32_t R3_new; + uint32_t R4_new; + uint32_t R5_new; + uint32_t R6_new; + uint32_t R7_new; + uint32_t R8_new; + uint32_t R9_new; + uint32_t R10_new; + uint32_t R11_new; + uint32_t R12_new; + uint32_t R13_new; + uint32_t R14_new; + uint32_t R15_new; + + /* eflag */ + uint32_t zf; + uint32_t nf; + uint32_t of; + uint32_t cf; + + uint32_t cpuoff; + uint32_t gie; + uint32_t osc; + uint32_t scg0; + uint32_t scg1; + uint32_t res; + + + uint32_t zf_new; + uint32_t nf_new; + uint32_t of_new; + uint32_t cf_new; + + uint32_t cpuoff_new; + uint32_t gie_new; + uint32_t osc_new; + uint32_t scg0_new; + uint32_t scg1_new; + uint32_t res_new; + + + uint8_t pfmem08_0; + uint8_t pfmem08_1; + uint8_t pfmem08_2; + uint8_t pfmem08_3; + uint8_t pfmem08_4; + uint8_t pfmem08_5; + uint8_t pfmem08_6; + uint8_t pfmem08_7; + uint8_t pfmem08_8; + uint8_t pfmem08_9; + uint8_t pfmem08_10; + uint8_t pfmem08_11; + uint8_t pfmem08_12; + uint8_t pfmem08_13; + uint8_t pfmem08_14; + uint8_t pfmem08_15; + uint8_t pfmem08_16; + uint8_t pfmem08_17; + uint8_t pfmem08_18; + uint8_t pfmem08_19; + + + uint16_t pfmem16_0; + uint16_t pfmem16_1; + uint16_t pfmem16_2; + uint16_t pfmem16_3; + uint16_t pfmem16_4; + uint16_t pfmem16_5; + uint16_t pfmem16_6; + uint16_t pfmem16_7; + uint16_t pfmem16_8; + uint16_t pfmem16_9; + uint16_t pfmem16_10; + uint16_t pfmem16_11; + uint16_t pfmem16_12; + uint16_t pfmem16_13; + uint16_t pfmem16_14; + uint16_t pfmem16_15; + uint16_t pfmem16_16; + uint16_t pfmem16_17; + uint16_t pfmem16_18; + uint16_t pfmem16_19; + + + uint32_t pfmem32_0; + uint32_t pfmem32_1; + uint32_t pfmem32_2; + uint32_t pfmem32_3; + uint32_t pfmem32_4; + uint32_t pfmem32_5; + uint32_t pfmem32_6; + uint32_t pfmem32_7; + uint32_t pfmem32_8; + uint32_t pfmem32_9; + uint32_t pfmem32_10; + uint32_t pfmem32_11; + uint32_t pfmem32_12; + uint32_t pfmem32_13; + uint32_t pfmem32_14; + uint32_t pfmem32_15; + uint32_t pfmem32_16; + uint32_t pfmem32_17; + uint32_t pfmem32_18; + uint32_t pfmem32_19; + + + uint64_t pfmem64_0; + uint64_t pfmem64_1; + uint64_t pfmem64_2; + uint64_t pfmem64_3; + uint64_t pfmem64_4; + uint64_t pfmem64_5; + uint64_t pfmem64_6; + uint64_t pfmem64_7; + uint64_t pfmem64_8; + uint64_t pfmem64_9; + uint64_t pfmem64_10; + uint64_t pfmem64_11; + uint64_t pfmem64_12; + uint64_t pfmem64_13; + uint64_t pfmem64_14; + uint64_t pfmem64_15; + uint64_t pfmem64_16; + uint64_t pfmem64_17; + uint64_t pfmem64_18; + uint64_t pfmem64_19; + + + uint32_t segm_base[0x10000]; + +}vm_cpu_t; + +#define RETURN_PC return PyLong_FromUnsignedLongLong(vmcpu->PC); + +uint16_t bcdadd_16(uint16_t a, uint16_t b); + +uint16_t bcdadd_cf_16(uint16_t a, uint16_t b); + +uint16_t hex2bcd_16(uint16_t a); + +uint8_t hex2bcd_8(uint8_t a); + +uint8_t bcd2hex_8(uint8_t a); + +uint16_t bcd2hex_16(uint16_t a); diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c new file mode 100644 index 00000000..107491c1 --- /dev/null +++ b/miasm2/jitter/arch/JitCore_x86.c @@ -0,0 +1,873 @@ +#include <Python.h> +#include "JitCore.h" +#include "structmember.h" +#include <stdint.h> +#include <inttypes.h> +#include "../queue.h" +#include "../vm_mngr.h" +#include "JitCore_x86.h" + +#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;} +#define RAISE_ret0(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return 0;} + +typedef struct _reg_dict{ + char* name; + size_t offset; +} reg_dict; + + +reg_dict gpreg_dict[] = { {.name = "RAX", .offset = offsetof(vm_cpu_t, RAX)}, + {.name = "RBX", .offset = offsetof(vm_cpu_t, RBX)}, + {.name = "RCX", .offset = offsetof(vm_cpu_t, RCX)}, + {.name = "RDX", .offset = offsetof(vm_cpu_t, RDX)}, + {.name = "RSI", .offset = offsetof(vm_cpu_t, RSI)}, + {.name = "RDI", .offset = offsetof(vm_cpu_t, RDI)}, + {.name = "RSP", .offset = offsetof(vm_cpu_t, RSP)}, + {.name = "RBP", .offset = offsetof(vm_cpu_t, RBP)}, + + {.name = "R8", .offset = offsetof(vm_cpu_t, R8)}, + {.name = "R9", .offset = offsetof(vm_cpu_t, R9)}, + {.name = "R10", .offset = offsetof(vm_cpu_t, R10)}, + {.name = "R11", .offset = offsetof(vm_cpu_t, R11)}, + {.name = "R12", .offset = offsetof(vm_cpu_t, R12)}, + {.name = "R13", .offset = offsetof(vm_cpu_t, R13)}, + {.name = "R14", .offset = offsetof(vm_cpu_t, R14)}, + {.name = "R15", .offset = offsetof(vm_cpu_t, R15)}, + + {.name = "RIP", .offset = offsetof(vm_cpu_t, RIP)}, + + {.name = "zf", .offset = offsetof(vm_cpu_t, zf)}, + {.name = "nf", .offset = offsetof(vm_cpu_t, nf)}, + {.name = "pf", .offset = offsetof(vm_cpu_t, pf)}, + {.name = "of", .offset = offsetof(vm_cpu_t, of)}, + {.name = "cf", .offset = offsetof(vm_cpu_t, cf)}, + {.name = "af", .offset = offsetof(vm_cpu_t, af)}, + {.name = "df", .offset = offsetof(vm_cpu_t, df)}, + + {.name = "ES", .offset = offsetof(vm_cpu_t, ES)}, + {.name = "CS", .offset = offsetof(vm_cpu_t, CS)}, + {.name = "SS", .offset = offsetof(vm_cpu_t, SS)}, + {.name = "DS", .offset = offsetof(vm_cpu_t, DS)}, + {.name = "FS", .offset = offsetof(vm_cpu_t, FS)}, + {.name = "GS", .offset = offsetof(vm_cpu_t, GS)}, + +}; + + + +/************************** JitCpu object **************************/ + +typedef struct { + PyObject_HEAD + PyObject *cpu; /* cpu */ + vm_cpu_t vmcpu; +} JitCpu; + + + +#define get_reg(reg) do { \ + o = PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.reg); \ + PyDict_SetItemString(dict, #reg, o); \ + Py_DECREF(o); \ + } while(0); + + +PyObject* vm_get_gpreg(JitCpu* self) +{ + PyObject *dict = PyDict_New(); + PyObject *o; + + get_reg(RAX); + get_reg(RBX); + get_reg(RCX); + get_reg(RDX); + get_reg(RSI); + get_reg(RDI); + get_reg(RSP); + get_reg(RBP); + + get_reg(R8); + get_reg(R9); + get_reg(R10); + get_reg(R11); + get_reg(R12); + get_reg(R13); + get_reg(R14); + get_reg(R15); + + get_reg(RIP); + + get_reg(zf); + get_reg(nf); + get_reg(pf); + get_reg(of); + get_reg(cf); + get_reg(af); + get_reg(df); + + + get_reg(ES); + get_reg(CS); + get_reg(SS); + get_reg(DS); + get_reg(FS); + get_reg(GS); + + return dict; +} + + + + +PyObject* _vm_set_gpreg(JitCpu* self, PyObject *dict) +{ + PyObject *d_key, *d_value = NULL; + Py_ssize_t pos = 0; + uint64_t val; + unsigned int i, found; + + if(!PyDict_Check(dict)) + RAISE(PyExc_TypeError, "arg must be dict"); + while(PyDict_Next(dict, &pos, &d_key, &d_value)){ + if(!PyString_Check(d_key)) + RAISE(PyExc_TypeError, "key must be str"); + + PyGetInt(d_value, val); + + found = 0; + for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ + if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name)) + continue; + *((uint64_t*)(((char*)&(self->vmcpu)) + gpreg_dict[i].offset)) = val; + found = 1; + break; + } + + if (found) + continue; + fprintf(stderr, "unkown key: %s\n", PyString_AsString(d_key)); + RAISE(PyExc_ValueError, "unkown reg"); + } + return NULL; +} + +PyObject* vm_set_gpreg(JitCpu* self, PyObject *args) +{ + PyObject* dict; + if (!PyArg_ParseTuple(args, "O", &dict)) + return NULL; + _vm_set_gpreg(self, dict); + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject * vm_init_regs(JitCpu* self) +{ + memset(&self->vmcpu, 0, sizeof(vm_cpu_t)); + + self->vmcpu.tsc1 = 0x22222222; + self->vmcpu.tsc2 = 0x11111111; + self->vmcpu.i_f = 1; + + Py_INCREF(Py_None); + return Py_None; + +} + +void dump_gpregs(vm_cpu_t* vmcpu) +{ + + printf("RAX %.16"PRIX64" RBX %.16"PRIX64" RCX %.16"PRIX64" RDX %.16"PRIX64"\n", + vmcpu->RAX, vmcpu->RBX, vmcpu->RCX, vmcpu->RDX); + printf("RSI %.16"PRIX64" RDI %.16"PRIX64" RSP %.16"PRIX64" RBP %.16"PRIX64"\n", + vmcpu->RSI, vmcpu->RDI, vmcpu->RSP, vmcpu->RBP); + printf("zf %.16"PRIX64" nf %.16"PRIX64" of %.16"PRIX64" cf %.16"PRIX64"\n", + vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf); + printf("RIP %.16"PRIX64"\n", + vmcpu->RIP); + +} + +PyObject * vm_dump_gpregs(JitCpu* self, PyObject* args) +{ + vm_cpu_t* vmcpu; + + vmcpu = &self->vmcpu; + dump_gpregs(vmcpu); + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* vm_set_segm_base(JitCpu* self, PyObject* args) +{ + PyObject *item1, *item2; + uint64_t segm_num, segm_base; + + if (!PyArg_ParseTuple(args, "OO", &item1, &item2)) + return NULL; + + PyGetInt(item1, segm_num); + PyGetInt(item2, segm_base); + self->vmcpu.segm_base[segm_num] = segm_base; + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_get_segm_base(JitCpu* self, PyObject* args) +{ + PyObject *item1; + uint64_t segm_num; + PyObject* v; + + if (!PyArg_ParseTuple(args, "O", &item1)) + return NULL; + PyGetInt(item1, segm_num); + v = PyInt_FromLong((long)self->vmcpu.segm_base[segm_num]); + return v; +} + +uint64_t segm2addr(vm_cpu_t* vmcpu, uint64_t segm, uint64_t addr) +{ + return addr + vmcpu->segm_base[segm]; +} + + +PyObject* vm_set_exception(JitCpu* self, PyObject* args) +{ + PyObject *item1; + uint64_t i; + + if (!PyArg_ParseTuple(args, "O", &item1)) + return NULL; + + PyGetInt(item1, i); + + self->vmcpu.exception_flags = i; + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_get_exception(JitCpu* self, PyObject* args) +{ + return PyLong_FromUnsignedLongLong((uint64_t)self->vmcpu.exception_flags); +} + + + +#define UDIV(sizeA, sizeB) \ + uint ## sizeA ## _t udiv ## sizeB (vm_cpu_t* vmcpu, uint ## sizeB ## _t a, uint ## sizeB ## _t b) \ + { \ + uint ## sizeA ## _t r; \ + if (b == 0) { \ + vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ + return 0; \ + } \ + r = a/b; \ + return r; \ + } + + +#define UMOD(sizeA, sizeB) \ + uint ## sizeA ## _t umod ## sizeB (vm_cpu_t* vmcpu, uint ## sizeB ## _t a, uint ## sizeB ## _t b) \ + { \ + uint ## sizeA ## _t r; \ + if (b == 0) { \ + vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ + return 0; \ + } \ + r = a%b; \ + return r; \ + } + + +#define IDIV(sizeA) \ + int ## sizeA ## _t idiv ## sizeA (vm_cpu_t* vmcpu, int ## sizeA ## _t a, int ## sizeA ## _t b) \ + { \ + int ## sizeA ## _t r; \ + if (b == 0) { \ + vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ + return 0; \ + } \ + r = a/b; \ + return r; \ + } + + +#define IMOD(sizeA) \ + int ## sizeA ## _t imod ## sizeA (vm_cpu_t* vmcpu, int ## sizeA ## _t a, int ## sizeA ## _t b) \ + { \ + int ## sizeA ## _t r; \ + if (b == 0) { \ + vmcpu->exception_flags |= EXCEPT_INT_DIV_BY_ZERO; \ + return 0; \ + } \ + r = a%b; \ + return r; \ + } + +UDIV(8, 16) +UDIV(16, 32) +UDIV(32, 64) + +UMOD(8, 16) +UMOD(16, 32) +UMOD(32, 64) + + +IDIV(16) +IDIV(32) +IDIV(64) + +IMOD(16) +IMOD(32) +IMOD(64) + + + + +static void +JitCpu_dealloc(JitCpu* self) +{ + self->ob_type->tp_free((PyObject*)self); +} + + +static PyObject * +JitCpu_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + JitCpu *self; + + self = (JitCpu *)type->tp_alloc(type, 0); + return (PyObject *)self; +} + +static PyObject * +JitCpu_get_cpu(JitCpu *self, void *closure) +{ + return PyLong_FromUnsignedLongLong((uint64_t)&(self->vmcpu)); +} + +static int +JitCpu_set_cpu(JitCpu *self, PyObject *value, void *closure) +{ + PyErr_SetString(PyExc_TypeError, "immutable cpu"); + return -1; +} + +static PyMemberDef JitCpu_members[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef JitCpu_methods[] = { + {"vm_init_regs", (PyCFunction)vm_init_regs, METH_NOARGS, + "X"}, + {"vm_dump_gpregs", (PyCFunction)vm_dump_gpregs, METH_NOARGS, + "X"}, + {"vm_get_gpreg", (PyCFunction)vm_get_gpreg, METH_NOARGS, + "X"}, + {"vm_set_gpreg", (PyCFunction)vm_set_gpreg, METH_VARARGS, + "X"}, + {"vm_get_segm_base", (PyCFunction)vm_get_segm_base, METH_VARARGS, + "X"}, + {"vm_set_segm_base", (PyCFunction)vm_set_segm_base, METH_VARARGS, + "X"}, + {"vm_get_exception", (PyCFunction)vm_get_exception, METH_VARARGS, + "X"}, + {"vm_set_exception", (PyCFunction)vm_set_exception, METH_VARARGS, + "X"}, + {NULL} /* Sentinel */ +}; + +static int +JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) +{ + + + fprintf(stderr, "ad cpu: %p\n", &(self->vmcpu)); + + return 0; +} +/* +static PyObject *JitCpu_get_RAX(JitCpu *self, void *closure) +{ + return PyLong_FromUnsignedLongLong((uint64_t)(self->vmcpu.RAX)); +} + +static int JitCpu_set_RAX(JitCpu *self, PyObject *value, void *closure) +{ + uint64_t val; + PyGetInt_ret0(value, val); + self->vmcpu.RAX = val; + return 0; +} +*/ + + +#define getset_reg_E_u32(regname) \ + static PyObject *JitCpu_get_E ## regname (JitCpu *self, void *closure) \ + { \ + return PyLong_FromUnsignedLongLong((uint32_t)(self->vmcpu.R ## regname & 0xFFFFFFFF )); \ + } \ + static int JitCpu_set_E ## regname (JitCpu *self, PyObject *value, void *closure) \ + { \ + uint64_t val; \ + PyGetInt_ret0(value, val); \ + val &= 0xFFFFFFFF; \ + val |= self->vmcpu.R ##regname & 0xFFFFFFFF00000000ULL; \ + self->vmcpu.R ## regname = val; \ + return 0; \ + } + + + +#define getset_reg_R_u16(regname) \ + static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ + { \ + return PyLong_FromUnsignedLongLong((uint16_t)(self->vmcpu.R ## regname & 0xFFFF )); \ + } \ + static int JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ + { \ + uint64_t val; \ + PyGetInt_ret0(value, val); \ + val &= 0xFFFF; \ + val |= self->vmcpu.R ##regname & 0xFFFFFFFFFFFF0000ULL; \ + self->vmcpu.R ## regname = val; \ + return 0; \ + } + + +getset_reg_u64(RAX); +getset_reg_u64(RBX); +getset_reg_u64(RCX); +getset_reg_u64(RDX); +getset_reg_u64(RSI); +getset_reg_u64(RDI); +getset_reg_u64(RSP); +getset_reg_u64(RBP); + +getset_reg_u64(R8); +getset_reg_u64(R9); +getset_reg_u64(R10); +getset_reg_u64(R11); +getset_reg_u64(R12); +getset_reg_u64(R13); +getset_reg_u64(R14); +getset_reg_u64(R15); + +getset_reg_u64(RIP); + +getset_reg_u64(zf); +getset_reg_u64(nf); +getset_reg_u64(pf); +getset_reg_u64(of); +getset_reg_u64(cf); +getset_reg_u64(af); +getset_reg_u64(df); + + +getset_reg_u64(ES); +getset_reg_u64(CS); +getset_reg_u64(SS); +getset_reg_u64(DS); +getset_reg_u64(FS); +getset_reg_u64(GS); + + +getset_reg_E_u32(AX); +getset_reg_E_u32(BX); +getset_reg_E_u32(CX); +getset_reg_E_u32(DX); +getset_reg_E_u32(SI); +getset_reg_E_u32(DI); +getset_reg_E_u32(SP); +getset_reg_E_u32(BP); +getset_reg_E_u32(IP); + +getset_reg_R_u16(AX); +getset_reg_R_u16(BX); +getset_reg_R_u16(CX); +getset_reg_R_u16(DX); +getset_reg_R_u16(SI); +getset_reg_R_u16(DI); +getset_reg_R_u16(SP); +getset_reg_R_u16(BP); + +#define get_reg_off(reg) do { \ + o = PyLong_FromUnsignedLongLong((uint64_t)offsetof(vm_cpu_t, reg)); \ + PyDict_SetItemString(dict, #reg, o); \ + Py_DECREF(o); \ + } while(0); + + +PyObject* get_gpreg_offset_all(void) +{ + PyObject *dict = PyDict_New(); + PyObject *o; + + get_reg_off(exception_flags); + get_reg_off(exception_flags_new); + + get_reg_off(RAX); + get_reg_off(RBX); + get_reg_off(RCX); + get_reg_off(RDX); + get_reg_off(RSI); + get_reg_off(RDI); + get_reg_off(RSP); + get_reg_off(RBP); + get_reg_off(R8); + get_reg_off(R9); + get_reg_off(R10); + get_reg_off(R11); + get_reg_off(R12); + get_reg_off(R13); + get_reg_off(R14); + get_reg_off(R15); + get_reg_off(RIP); + get_reg_off(RAX_new); + get_reg_off(RBX_new); + get_reg_off(RCX_new); + get_reg_off(RDX_new); + get_reg_off(RSI_new); + get_reg_off(RDI_new); + get_reg_off(RSP_new); + get_reg_off(RBP_new); + get_reg_off(R8_new); + get_reg_off(R9_new); + get_reg_off(R10_new); + get_reg_off(R11_new); + get_reg_off(R12_new); + get_reg_off(R13_new); + get_reg_off(R14_new); + get_reg_off(R15_new); + get_reg_off(RIP_new); + get_reg_off(zf); + get_reg_off(nf); + get_reg_off(pf); + get_reg_off(of); + get_reg_off(cf); + get_reg_off(af); + get_reg_off(df); + get_reg_off(zf_new); + get_reg_off(nf_new); + get_reg_off(pf_new); + get_reg_off(of_new); + get_reg_off(cf_new); + get_reg_off(af_new); + get_reg_off(df_new); + get_reg_off(tf); + get_reg_off(i_f); + get_reg_off(iopl_f); + get_reg_off(nt); + get_reg_off(rf); + get_reg_off(vm); + get_reg_off(ac); + get_reg_off(vif); + get_reg_off(vip); + get_reg_off(i_d); + get_reg_off(tf_new); + get_reg_off(i_f_new); + get_reg_off(iopl_f_new); + get_reg_off(nt_new); + get_reg_off(rf_new); + get_reg_off(vm_new); + get_reg_off(ac_new); + get_reg_off(vif_new); + get_reg_off(vip_new); + get_reg_off(i_d_new); + get_reg_off(my_tick); + get_reg_off(cond); + + get_reg_off(float_st0); + get_reg_off(float_st1); + get_reg_off(float_st2); + get_reg_off(float_st3); + get_reg_off(float_st4); + get_reg_off(float_st5); + get_reg_off(float_st6); + get_reg_off(float_st7); + get_reg_off(float_st0_new); + get_reg_off(float_st1_new); + get_reg_off(float_st2_new); + get_reg_off(float_st3_new); + get_reg_off(float_st4_new); + get_reg_off(float_st5_new); + get_reg_off(float_st6_new); + get_reg_off(float_st7_new); + + get_reg_off(ES); + get_reg_off(CS); + get_reg_off(SS); + get_reg_off(DS); + get_reg_off(FS); + get_reg_off(GS); + get_reg_off(ES_new); + get_reg_off(CS_new); + get_reg_off(SS_new); + get_reg_off(DS_new); + get_reg_off(FS_new); + get_reg_off(GS_new); + + get_reg_off(pfmem08_0); + get_reg_off(pfmem08_1); + get_reg_off(pfmem08_2); + get_reg_off(pfmem08_3); + get_reg_off(pfmem08_4); + get_reg_off(pfmem08_5); + get_reg_off(pfmem08_6); + get_reg_off(pfmem08_7); + get_reg_off(pfmem08_8); + get_reg_off(pfmem08_9); + get_reg_off(pfmem08_10); + get_reg_off(pfmem08_11); + get_reg_off(pfmem08_12); + get_reg_off(pfmem08_13); + get_reg_off(pfmem08_14); + get_reg_off(pfmem08_15); + get_reg_off(pfmem08_16); + get_reg_off(pfmem08_17); + get_reg_off(pfmem08_18); + get_reg_off(pfmem08_19); + get_reg_off(pfmem16_0); + get_reg_off(pfmem16_1); + get_reg_off(pfmem16_2); + get_reg_off(pfmem16_3); + get_reg_off(pfmem16_4); + get_reg_off(pfmem16_5); + get_reg_off(pfmem16_6); + get_reg_off(pfmem16_7); + get_reg_off(pfmem16_8); + get_reg_off(pfmem16_9); + get_reg_off(pfmem16_10); + get_reg_off(pfmem16_11); + get_reg_off(pfmem16_12); + get_reg_off(pfmem16_13); + get_reg_off(pfmem16_14); + get_reg_off(pfmem16_15); + get_reg_off(pfmem16_16); + get_reg_off(pfmem16_17); + get_reg_off(pfmem16_18); + get_reg_off(pfmem16_19); + get_reg_off(pfmem32_0); + get_reg_off(pfmem32_1); + get_reg_off(pfmem32_2); + get_reg_off(pfmem32_3); + get_reg_off(pfmem32_4); + get_reg_off(pfmem32_5); + get_reg_off(pfmem32_6); + get_reg_off(pfmem32_7); + get_reg_off(pfmem32_8); + get_reg_off(pfmem32_9); + get_reg_off(pfmem32_10); + get_reg_off(pfmem32_11); + get_reg_off(pfmem32_12); + get_reg_off(pfmem32_13); + get_reg_off(pfmem32_14); + get_reg_off(pfmem32_15); + get_reg_off(pfmem32_16); + get_reg_off(pfmem32_17); + get_reg_off(pfmem32_18); + get_reg_off(pfmem32_19); + get_reg_off(pfmem64_0); + get_reg_off(pfmem64_1); + get_reg_off(pfmem64_2); + get_reg_off(pfmem64_3); + get_reg_off(pfmem64_4); + get_reg_off(pfmem64_5); + get_reg_off(pfmem64_6); + get_reg_off(pfmem64_7); + get_reg_off(pfmem64_8); + get_reg_off(pfmem64_9); + get_reg_off(pfmem64_10); + get_reg_off(pfmem64_11); + get_reg_off(pfmem64_12); + get_reg_off(pfmem64_13); + get_reg_off(pfmem64_14); + get_reg_off(pfmem64_15); + get_reg_off(pfmem64_16); + get_reg_off(pfmem64_17); + get_reg_off(pfmem64_18); + get_reg_off(pfmem64_19); + + get_reg_off(MM0); + get_reg_off(MM1); + get_reg_off(MM2); + get_reg_off(MM3); + get_reg_off(MM4); + get_reg_off(MM5); + get_reg_off(MM6); + get_reg_off(MM7); + get_reg_off(MM0_new); + get_reg_off(MM1_new); + get_reg_off(MM2_new); + get_reg_off(MM3_new); + get_reg_off(MM4_new); + get_reg_off(MM5_new); + get_reg_off(MM6_new); + get_reg_off(MM7_new); + return dict; +} + + +static PyGetSetDef JitCpu_getseters[] = { + {"cpu", + (getter)JitCpu_get_cpu, (setter)JitCpu_set_cpu, + "first name", + NULL}, + + {"RAX", (getter)JitCpu_get_RAX, (setter)JitCpu_set_RAX, "RAX", NULL}, + {"RBX", (getter)JitCpu_get_RBX, (setter)JitCpu_set_RBX, "RBX", NULL}, + {"RCX", (getter)JitCpu_get_RCX, (setter)JitCpu_set_RCX, "RCX", NULL}, + {"RDX", (getter)JitCpu_get_RDX, (setter)JitCpu_set_RDX, "RDX", NULL}, + {"RSI", (getter)JitCpu_get_RSI, (setter)JitCpu_set_RSI, "RSI", NULL}, + {"RDI", (getter)JitCpu_get_RDI, (setter)JitCpu_set_RDI, "RDI", NULL}, + {"RSP", (getter)JitCpu_get_RSP, (setter)JitCpu_set_RSP, "RSP", NULL}, + {"RBP", (getter)JitCpu_get_RBP, (setter)JitCpu_set_RBP, "RBP", NULL}, + {"R8", (getter)JitCpu_get_R8, (setter)JitCpu_set_R8, "R8", NULL}, + {"R9", (getter)JitCpu_get_R9, (setter)JitCpu_set_R9, "R9", NULL}, + {"R10", (getter)JitCpu_get_R10, (setter)JitCpu_set_R10, "R10", NULL}, + {"R11", (getter)JitCpu_get_R11, (setter)JitCpu_set_R11, "R11", NULL}, + {"R12", (getter)JitCpu_get_R12, (setter)JitCpu_set_R12, "R12", NULL}, + {"R13", (getter)JitCpu_get_R13, (setter)JitCpu_set_R13, "R13", NULL}, + {"R14", (getter)JitCpu_get_R14, (setter)JitCpu_set_R14, "R14", NULL}, + {"R15", (getter)JitCpu_get_R15, (setter)JitCpu_set_R15, "R15", NULL}, + {"RIP", (getter)JitCpu_get_RIP, (setter)JitCpu_set_RIP, "RIP", NULL}, + {"zf", (getter)JitCpu_get_zf, (setter)JitCpu_set_zf, "zf", NULL}, + {"nf", (getter)JitCpu_get_nf, (setter)JitCpu_set_nf, "nf", NULL}, + {"pf", (getter)JitCpu_get_pf, (setter)JitCpu_set_pf, "pf", NULL}, + {"of", (getter)JitCpu_get_of, (setter)JitCpu_set_of, "of", NULL}, + {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL}, + {"af", (getter)JitCpu_get_af, (setter)JitCpu_set_af, "af", NULL}, + {"df", (getter)JitCpu_get_df, (setter)JitCpu_set_df, "df", NULL}, + {"ES", (getter)JitCpu_get_ES, (setter)JitCpu_set_ES, "ES", NULL}, + {"CS", (getter)JitCpu_get_CS, (setter)JitCpu_set_CS, "CS", NULL}, + {"SS", (getter)JitCpu_get_SS, (setter)JitCpu_set_SS, "SS", NULL}, + {"DS", (getter)JitCpu_get_DS, (setter)JitCpu_set_DS, "DS", NULL}, + {"FS", (getter)JitCpu_get_FS, (setter)JitCpu_set_FS, "FS", NULL}, + {"GS", (getter)JitCpu_get_GS, (setter)JitCpu_set_GS, "GS", NULL}, + + {"EAX", (getter)JitCpu_get_EAX, (setter)JitCpu_set_EAX, "EAX", NULL}, + {"EBX", (getter)JitCpu_get_EBX, (setter)JitCpu_set_EBX, "EBX", NULL}, + {"ECX", (getter)JitCpu_get_ECX, (setter)JitCpu_set_ECX, "ECX", NULL}, + {"EDX", (getter)JitCpu_get_EDX, (setter)JitCpu_set_EDX, "EDX", NULL}, + {"ESI", (getter)JitCpu_get_ESI, (setter)JitCpu_set_ESI, "ESI", NULL}, + {"EDI", (getter)JitCpu_get_EDI, (setter)JitCpu_set_EDI, "EDI", NULL}, + {"ESP", (getter)JitCpu_get_ESP, (setter)JitCpu_set_ESP, "ESP", NULL}, + {"EBP", (getter)JitCpu_get_EBP, (setter)JitCpu_set_EBP, "EBP", NULL}, + {"EIP", (getter)JitCpu_get_EIP, (setter)JitCpu_set_EIP, "EIP", NULL}, + + {"AX", (getter)JitCpu_get_AX, (setter)JitCpu_set_AX, "AX", NULL}, + {"BX", (getter)JitCpu_get_BX, (setter)JitCpu_set_BX, "BX", NULL}, + {"CX", (getter)JitCpu_get_CX, (setter)JitCpu_set_CX, "CX", NULL}, + {"DX", (getter)JitCpu_get_DX, (setter)JitCpu_set_DX, "DX", NULL}, + {"SI", (getter)JitCpu_get_SI, (setter)JitCpu_set_SI, "SI", NULL}, + {"DI", (getter)JitCpu_get_DI, (setter)JitCpu_set_DI, "DI", NULL}, + {"SP", (getter)JitCpu_get_SP, (setter)JitCpu_set_SP, "SP", NULL}, + {"BP", (getter)JitCpu_get_BP, (setter)JitCpu_set_BP, "BP", NULL}, + + + {NULL} /* Sentinel */ +}; + + +static PyTypeObject JitCpuType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "JitCore_x86.JitCpu", /*tp_name*/ + sizeof(JitCpu), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)JitCpu_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*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*/ + "JitCpu objects", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + JitCpu_methods, /* tp_methods */ + JitCpu_members, /* tp_members */ + JitCpu_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)JitCpu_init, /* tp_init */ + 0, /* tp_alloc */ + JitCpu_new, /* tp_new */ +}; + + + +static PyMethodDef JitCore_x86_Methods[] = { + + /* + + */ + {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, + {NULL, NULL, 0, NULL} /* Sentinel */ + +}; + +static PyObject *JitCore_x86_Error; + +PyMODINIT_FUNC +initJitCore_x86(void) +{ + PyObject *m; + + if (PyType_Ready(&JitCpuType) < 0) + return; + + m = Py_InitModule("JitCore_x86", JitCore_x86_Methods); + if (m == NULL) + return; + + JitCore_x86_Error = PyErr_NewException("JitCore_x86.error", NULL, NULL); + Py_INCREF(JitCore_x86_Error); + PyModule_AddObject(m, "error", JitCore_x86_Error); + + Py_INCREF(&JitCpuType); + PyModule_AddObject(m, "JitCpu", (PyObject *)&JitCpuType); + +} + + + + + + + + + + + + + + + + + + + + + + diff --git a/miasm2/jitter/arch/JitCore_x86.h b/miasm2/jitter/arch/JitCore_x86.h new file mode 100644 index 00000000..7d4379a8 --- /dev/null +++ b/miasm2/jitter/arch/JitCore_x86.h @@ -0,0 +1,293 @@ + +typedef struct { + uint32_t exception_flags; + uint32_t exception_flags_new; + + + /* gpregs */ + uint64_t RAX; + uint64_t RBX; + uint64_t RCX; + uint64_t RDX; + uint64_t RSI; + uint64_t RDI; + uint64_t RSP; + uint64_t RBP; + uint64_t R8; + uint64_t R9; + uint64_t R10; + uint64_t R11; + uint64_t R12; + uint64_t R13; + uint64_t R14; + uint64_t R15; + + uint64_t RIP; + + uint64_t RAX_new; + uint64_t RBX_new; + uint64_t RCX_new; + uint64_t RDX_new; + uint64_t RSI_new; + uint64_t RDI_new; + uint64_t RSP_new; + uint64_t RBP_new; + uint64_t R8_new; + uint64_t R9_new; + uint64_t R10_new; + uint64_t R11_new; + uint64_t R12_new; + uint64_t R13_new; + uint64_t R14_new; + uint64_t R15_new; + + uint64_t RIP_new; + + /* eflag */ + uint64_t zf; + uint64_t nf; + uint64_t pf; + uint64_t of; + uint64_t cf; + uint64_t af; + uint64_t df; + + uint64_t zf_new; + uint64_t nf_new; + uint64_t pf_new; + uint64_t of_new; + uint64_t cf_new; + uint64_t af_new; + uint64_t df_new; + + uint64_t tf; + uint64_t i_f; + uint64_t iopl_f; + uint64_t nt; + uint64_t rf; + uint64_t vm; + uint64_t ac; + uint64_t vif; + uint64_t vip; + uint64_t i_d; + + uint64_t tf_new; + uint64_t i_f_new; + uint64_t iopl_f_new; + uint64_t nt_new; + uint64_t rf_new; + uint64_t vm_new; + uint64_t ac_new; + uint64_t vif_new; + uint64_t vip_new; + uint64_t i_d_new; + + uint64_t my_tick; + + uint64_t cond; + + double float_st0; + double float_st1; + double float_st2; + double float_st3; + double float_st4; + double float_st5; + double float_st6; + double float_st7; + + double float_st0_new; + double float_st1_new; + double float_st2_new; + double float_st3_new; + double float_st4_new; + double float_st5_new; + double float_st6_new; + double float_st7_new; + + unsigned int float_c0; + unsigned int float_c1; + unsigned int float_c2; + unsigned int float_c3; + + unsigned int float_c0_new; + unsigned int float_c1_new; + unsigned int float_c2_new; + unsigned int float_c3_new; + + unsigned int float_stack_ptr; + unsigned int float_stack_ptr_new; + + unsigned int reg_float_control; + unsigned int reg_float_control_new; + + unsigned int reg_float_eip; + unsigned int reg_float_eip_new; + unsigned int reg_float_cs; + unsigned int reg_float_cs_new; + unsigned int reg_float_address; + unsigned int reg_float_address_new; + unsigned int reg_float_ds; + unsigned int reg_float_ds_new; + + + unsigned int tsc1; + unsigned int tsc2; + + unsigned int tsc1_new; + unsigned int tsc2_new; + + + uint64_t ES; + uint64_t CS; + uint64_t SS; + uint64_t DS; + uint64_t FS; + uint64_t GS; + + uint64_t ES_new; + uint64_t CS_new; + uint64_t SS_new; + uint64_t DS_new; + uint64_t FS_new; + uint64_t GS_new; + + unsigned int cr0; + unsigned int cr0_new; + + unsigned int cr3; + unsigned int cr3_new; + + + + uint8_t pfmem08_0; + uint8_t pfmem08_1; + uint8_t pfmem08_2; + uint8_t pfmem08_3; + uint8_t pfmem08_4; + uint8_t pfmem08_5; + uint8_t pfmem08_6; + uint8_t pfmem08_7; + uint8_t pfmem08_8; + uint8_t pfmem08_9; + uint8_t pfmem08_10; + uint8_t pfmem08_11; + uint8_t pfmem08_12; + uint8_t pfmem08_13; + uint8_t pfmem08_14; + uint8_t pfmem08_15; + uint8_t pfmem08_16; + uint8_t pfmem08_17; + uint8_t pfmem08_18; + uint8_t pfmem08_19; + + + uint16_t pfmem16_0; + uint16_t pfmem16_1; + uint16_t pfmem16_2; + uint16_t pfmem16_3; + uint16_t pfmem16_4; + uint16_t pfmem16_5; + uint16_t pfmem16_6; + uint16_t pfmem16_7; + uint16_t pfmem16_8; + uint16_t pfmem16_9; + uint16_t pfmem16_10; + uint16_t pfmem16_11; + uint16_t pfmem16_12; + uint16_t pfmem16_13; + uint16_t pfmem16_14; + uint16_t pfmem16_15; + uint16_t pfmem16_16; + uint16_t pfmem16_17; + uint16_t pfmem16_18; + uint16_t pfmem16_19; + + + uint32_t pfmem32_0; + uint32_t pfmem32_1; + uint32_t pfmem32_2; + uint32_t pfmem32_3; + uint32_t pfmem32_4; + uint32_t pfmem32_5; + uint32_t pfmem32_6; + uint32_t pfmem32_7; + uint32_t pfmem32_8; + uint32_t pfmem32_9; + uint32_t pfmem32_10; + uint32_t pfmem32_11; + uint32_t pfmem32_12; + uint32_t pfmem32_13; + uint32_t pfmem32_14; + uint32_t pfmem32_15; + uint32_t pfmem32_16; + uint32_t pfmem32_17; + uint32_t pfmem32_18; + uint32_t pfmem32_19; + + + uint64_t pfmem64_0; + uint64_t pfmem64_1; + uint64_t pfmem64_2; + uint64_t pfmem64_3; + uint64_t pfmem64_4; + uint64_t pfmem64_5; + uint64_t pfmem64_6; + uint64_t pfmem64_7; + uint64_t pfmem64_8; + uint64_t pfmem64_9; + uint64_t pfmem64_10; + uint64_t pfmem64_11; + uint64_t pfmem64_12; + uint64_t pfmem64_13; + uint64_t pfmem64_14; + uint64_t pfmem64_15; + uint64_t pfmem64_16; + uint64_t pfmem64_17; + uint64_t pfmem64_18; + uint64_t pfmem64_19; + + + uint64_t MM0; + uint64_t MM1; + uint64_t MM2; + uint64_t MM3; + uint64_t MM4; + uint64_t MM5; + uint64_t MM6; + uint64_t MM7; + + uint64_t MM0_new; + uint64_t MM1_new; + uint64_t MM2_new; + uint64_t MM3_new; + uint64_t MM4_new; + uint64_t MM5_new; + uint64_t MM6_new; + uint64_t MM7_new; + + uint32_t segm_base[0x10000]; + +}vm_cpu_t; + + + +void dump_gpregs(vm_cpu_t* vmcpu); +uint64_t segm2addr(vm_cpu_t* vmcpu, uint64_t segm, uint64_t addr); + + +uint32_t udiv64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b); +uint32_t umod64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b); +int64_t idiv64(vm_cpu_t* vmcpu, int64_t a, int64_t b); +int64_t imod64(vm_cpu_t* vmcpu, int64_t a, int64_t b); + +uint16_t udiv32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); +uint16_t umod32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); +int32_t idiv32(vm_cpu_t* vmcpu, int32_t a, int32_t b); +int32_t imod32(vm_cpu_t* vmcpu, int32_t a, int32_t b); + +uint8_t udiv16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b); +uint8_t umod16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b); +int16_t idiv16(vm_cpu_t* vmcpu, int16_t a, int16_t b); +int16_t imod16(vm_cpu_t* vmcpu, int16_t a, int16_t b); + +#define RETURN_PC return PyLong_FromUnsignedLongLong(vmcpu->RIP); diff --git a/miasm2/jitter/arch/__init__.py b/miasm2/jitter/arch/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/miasm2/jitter/arch/__init__.py diff --git a/miasm2/jitter/csts.py b/miasm2/jitter/csts.py new file mode 100644 index 00000000..e4b315e1 --- /dev/null +++ b/miasm2/jitter/csts.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + + +# VM Mngr Exceptions +EXCEPT_DO_NOT_UPDATE_PC = 1 << 25 + +EXCEPT_CODE_AUTOMOD = (1 << 0) +EXCEPT_SOFT_BP = (1 << 1) +EXCEPT_INT_XX = (1 << 2) +EXCEPT_BREAKPOINT_INTERN = (1 << 10) + +EXCEPT_ACCESS_VIOL = ((1 << 14) | EXCEPT_DO_NOT_UPDATE_PC) +# VM Mngr constants + +PAGE_READ = 1 +PAGE_WRITE = 2 +PAGE_EXEC = 4 + +BREAKPOINT_READ = 1 +BREAKPOINT_WRITE = 2 + diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py new file mode 100644 index 00000000..34ae3be9 --- /dev/null +++ b/miasm2/jitter/jitcore.py @@ -0,0 +1,252 @@ +# +# 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. +# +from miasm2.core import asmbloc +from miasm2.core.interval import interval +from csts import * + + +class JitCore(object): + + "JiT management. This is an abstract class" + + def __init__(self, my_ir, bs=None): + """Initialise a JitCore instance. + @my_ir: ir instance for current architecture + @bs: bitstream + """ + + self.my_ir = my_ir + self.bs = bs + self.known_blocs = {} + self.lbl2jitbloc = {} + self.lbl2bloc = {} + self.log_mn = False + self.log_regs = False + self.log_newbloc = False + self.segm_to_do = set() + self.job_done = set() + self.jitcount = 0 + self.addr2obj = {} + self.addr2objref = {} + self.blocs_mem_interval = interval() + self.disasm_cb = None + self.split_dis = set() + + self.options = {"jit_maxline": 50 # Maximum number of line jitted + } + + def set_options(self, **kwargs): + "Set options relative to the backend" + + self.options.update(kwargs) + + def add_disassembly_splits(self, *args): + """The disassembly engine will stop on address in args if they + are not at the block beginning""" + self.split_dis.update(set(args)) + + def remove_disassembly_splits(self, *args): + """The disassembly engine will no longer stop on address in args""" + self.split_dis.difference_update(set(args)) + + def load(self, arch, attrib): + "Initialise the Jitter according to arch and attrib" + + raise Exception("DO NOT instanciate JitCore") + + def __get_bloc_min_max(self, cur_bloc): + "Update cur_bloc to set min/max address" + + if cur_bloc.lines: + cur_bloc.ad_min = cur_bloc.lines[0].offset + cur_bloc.ad_max = cur_bloc.lines[-1].offset + cur_bloc.lines[-1].l + + def __add_bloc_to_mem_interval(self, vm, bloc): + "Update vm to include bloc addresses in its memory range" + + self.blocs_mem_interval += interval([(bloc.ad_min, bloc.ad_max - 1)]) + + vm.vm_reset_code_bloc_pool() + for a, b in self.blocs_mem_interval: + vm.vm_add_code_bloc(a, b + 1) + + def jitirblocs(self, label, irblocs): + """JiT a group of irblocs. + @label: the label of the irblocs + @irblocs: a gorup of irblocs + """ + + raise Exception("DO NOT instanciate JitCore") + + def add_bloc(self, b): + """Add a bloc to JiT and JiT it. + @b: the bloc to add + """ + + irblocs = self.my_ir.add_bloc(b, gen_pc_updt = True) + b.irblocs = irblocs + self.jitirblocs(b.label, irblocs) + + def __disbloc(self, addr, cpu, vm): + "Disassemble a new bloc and JiT it" + + # Get the bloc + if isinstance(addr, asmbloc.asm_label): + addr = addr.offset + + l = self.my_ir.symbol_pool.getby_offset_create(addr) + cur_bloc = asmbloc.asm_bloc(l) + + # Disassemble it + try: + asmbloc.dis_bloc(self.my_ir.arch, self.bs, cur_bloc, addr, + set(), self.my_ir.symbol_pool, [], + follow_call=False, patch_instr_symb=True, + dontdis_retcall=False, + lines_wd=self.options["jit_maxline"], + # max 10 asm lines + attrib=self.my_ir.attrib, + split_dis=self.split_dis) + except IOError: + # vm_exception_flag is set + pass + + # Logging + if self.log_newbloc: + print cur_bloc + if self.disasm_cb is not None: + self.disasm_cb(cur_bloc) + # Update label -> bloc + self.lbl2bloc[l] = cur_bloc + + # Store min/max bloc address needed in jit automod code + self.__get_bloc_min_max(cur_bloc) + + # JiT it + self.add_bloc(cur_bloc) + + # Update jitcode mem range + self.__add_bloc_to_mem_interval(vm, cur_bloc) + + def jit_call(self, label, cpu, vmmngr): + """Call the function label with cpu and vmmngr states + @label: function's label + @cpu: address of the cpu state structure + @vmmngr: address of the memory state structure + """ + + fc_ptr = self.lbl2jitbloc[label] + return self.exec_wrapper(fc_ptr, cpu, vmmngr) + + def runbloc(self, cpu, vm, lbl): + """Run the bloc starting at lbl. + @cpu: JitCpu instance + @vm: VmMngr instance + @lbl: target label + """ + + if lbl is None: + lbl = cpu.vm_get_gpreg()[self.my_ir.pc.name] + + if not lbl in self.lbl2jitbloc: + # Need to JiT the bloc + self.__disbloc(lbl, cpu, vm) + + # Run the bloc and update cpu/vmmngr state + ret = self.jit_call(lbl, cpu.cpu, vm.vmmngr) + + return ret + + def __blocs2memrange(self, blocs): + """Return an interval instance standing for blocs addresses + @blocs: list of asm_bloc instances + """ + + mem_range = interval() + + for b in blocs: + mem_range += interval([(b.ad_min, b.ad_max - 1)]) + + return mem_range + + def __updt_jitcode_mem_range(self, vm): + """Rebuild the VM blocs address memory range + @vm: VmMngr instance + """ + + # Reset the current pool + vm.vm_reset_code_bloc_pool() + + # Add blocs in the pool + for a, b in self.blocs_mem_interval: + vm.vm_add_code_bloc(a, b + 1) + + def __del_bloc_in_range(self, ad1, ad2): + """Find and remove jitted bloc in range [ad1, ad2]. + Return the list of bloc removed. + @ad1: First address + @ad2: Last address + """ + + # Find concerned blocs + modified_blocs = set() + for b in self.lbl2bloc.values(): + if not b.lines: + continue + if b.ad_max <= ad1 or b.ad_min >= ad2: + # Bloc not modified + pass + else: + # Modified blocs + modified_blocs.add(b) + + # Generate interval to delete + del_interval = self.__blocs2memrange(modified_blocs) + + # Remove interval from monitored interval list + self.blocs_mem_interval -= del_interval + + # Remove modified blocs + for b in modified_blocs: + try: + for irbloc in b.irblocs: + + # Remove offset -> jitted bloc link + if irbloc.label.offset in self.lbl2jitbloc: + del(self.lbl2jitbloc[irbloc.label.offset]) + + except AttributeError: + # The bloc has never been translated in IR + if b.label.offset in self.lbl2jitbloc: + del(self.lbl2jitbloc[b.label.offset]) + + # Remove label -> bloc link + del(self.lbl2bloc[b.label]) + + return modified_blocs + + def updt_automod_code(self, vm, addr, size): + """Remove code jitted in range [addr, addr + size] + @vm: VmMngr instance + @addr: Address of modified code in sandbox + @size: Modification range size (in bits) + """ + + self.__del_bloc_in_range(addr, addr + size / 8) + self.__updt_jitcode_mem_range(vm) + diff --git a/miasm2/jitter/jitcore_llvm.py b/miasm2/jitter/jitcore_llvm.py new file mode 100644 index 00000000..f081d281 --- /dev/null +++ b/miasm2/jitter/jitcore_llvm.py @@ -0,0 +1,157 @@ +import os +import importlib +import hashlib +try: + from llvmconvert import * +except ImportError: + pass +import jitcore +import Jitllvm + + +class JitCore_LLVM(jitcore.JitCore): + + "JiT management, using LLVM as backend" + + # Architecture dependant libraries + arch_dependent_libs = {"x86": "arch/JitCore_x86.so"} + + def __init__(self, my_ir, bs=None): + super(JitCore_LLVM, self).__init__(my_ir, bs) + + self.options.update({"safe_mode": False, # Verify each function + "optimise": False, # Optimise functions + "log_func": False, # Print LLVM functions + "log_assembly": False, # Print assembly executed + "cache_ir": None # SaveDir for cached .ll + }) + + self.exec_wrapper = Jitllvm.llvm_exec_bloc + self.exec_engines = [] + + def load(self, arch): + + # Library to load within Jit context + libs_to_load = [] + + # Get the vm_mngr librairy + lib_dir = os.path.dirname(os.path.realpath(__file__)) + vm_mngr_path = os.path.join(lib_dir, 'vm_mngr.so') + libs_to_load.append(vm_mngr_path) + + # Get architecture dependant Jitcore library (if any) + try: + jit_lib = os.path.join( + lib_dir, self.arch_dependent_libs[arch.name]) + libs_to_load.append(jit_lib) + except KeyError: + pass + + # Create a context + self.context = LLVMContext_JIT(libs_to_load) + + # Set the optimisation level + self.context.optimise_level() + + # Save the current architecture parameters + self.arch = arch + + # Get the correspondance between registers and vmcpu struct + mod_name = "miasm2.jitter.arch.JitCore_%s" % (arch.name) + mod = importlib.import_module(mod_name) + self.context.set_vmcpu(mod.get_gpreg_offset_all()) + + # Save module base + self.mod_base_str = str(self.context.mod) + + # Set IRs transformation to apply + self.context.set_IR_transformation(self.my_ir.expr_fix_regs_for_mode) + + def add_bloc(self, bloc): + + # Search in IR cache + if self.options["cache_ir"] is not None: + + # /!\ This part is under development + # Use it at your own risk + + # Compute Hash : label + bloc binary + func_name = bloc.label.name + to_hash = func_name + + # Get binary from bloc + for line in bloc.lines: + b = line.b + to_hash += b + + # Compute Hash + md5 = hashlib.md5(to_hash).hexdigest() + + # Try to load the function from cache + filename = self.options["cache_ir"] + md5 + ".ll" + + try: + fcontent = open(filename) + content = fcontent.read() + fcontent.close() + + except IOError: + content = None + + if content is None: + # Compute the IR + super(JitCore_LLVM, self).add_bloc(bloc) + + # Save it + fdest = open(filename, "w") + dump = str(self.context.mod.get_function_named(func_name)) + my = "declare i16 @llvm.bswap.i16(i16) nounwind readnone\n" + + fdest.write(self.mod_base_str + my + dump) + fdest.close() + + else: + import llvm.core as llvm_c + import llvm.ee as llvm_e + my_mod = llvm_c.Module.from_assembly(content) + func = my_mod.get_function_named(func_name) + exec_en = llvm_e.ExecutionEngine.new(my_mod) + self.exec_engines.append(exec_en) + + # We can use the same exec_engine + ptr = self.exec_engines[0].get_pointer_to_function(func) + + # Store a pointer on the function jitted code + self.lbl2jitbloc[bloc.label.offset] = ptr + + else: + super(JitCore_LLVM, self).add_bloc(bloc) + + def jitirblocs(self, label, irblocs): + + # Build a function in the context + func = LLVMFunction(self.context, label.name) + + # Set log level + func.log_regs = self.log_regs + func.log_mn = self.log_mn + + # Import irblocs + func.from_blocs(irblocs) + + # Verify + if self.options["safe_mode"] is True: + func.verify() + + # Optimise + if self.options["optimise"] is True: + func.optimise() + + # Log + if self.options["log_func"] is True: + print func + if self.options["log_assembly"] is True: + print func.get_assembly() + + # Store a pointer on the function jitted code + self.lbl2jitbloc[label.offset] = func.get_function_pointer() diff --git a/miasm2/jitter/jitcore_tcc.py b/miasm2/jitter/jitcore_tcc.py new file mode 100644 index 00000000..ee33bcd0 --- /dev/null +++ b/miasm2/jitter/jitcore_tcc.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + +import os +from miasm2.ir.ir2C import irblocs2C +from subprocess import Popen, PIPE +import jitcore +from distutils.sysconfig import get_python_inc +import Jittcc + + +def jit_tcc_compil(func_name, func_code): + global Jittcc + c = Jittcc.tcc_compil(func_name, func_code) + return c + + +class jit_tcc_code(): + + def __init__(self, c): + self.c = c + + def __call__(self, cpu, vm): + return Jittcc.tcc_exec_bloc(self.c, cpu, vm) + + +def gen_core(arch, attrib): + lib_dir = os.path.dirname(os.path.realpath(__file__)) + + txt = "" + txt += '#include "%s/queue.h"\n' % lib_dir + txt += '#include "%s/vm_mngr.h"\n' % lib_dir + txt += '#include "%s/arch/JitCore_%s.h"\n' % (lib_dir, arch.name) + + txt += r''' +#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;} +''' + return txt + + +def gen_C_source(my_ir, func_code): + c_source = "" + c_source += "\n".join(func_code) + + c_source = gen_core(my_ir.arch, my_ir.attrib) + c_source + + c_source = """ + #ifdef __x86_64__ + #ifndef __LP64__ + /* + for ubuntu ?!? XXX TODO + /!\ force 64 bit system using 64 bits libc + change this to __ILP32__ to do so. + */ + #define __LP64__ + #endif + #endif + """ + "#include <Python.h>\n" + c_source + + return c_source + + +class objref: + + def __init__(self, obj): + self.obj = obj + + +class myresolver: + + def __init__(self, offset): + self.offset = offset + + def ret(self): + return "return PyLong_FromUnsignedLongLong(0x%X);" % self.offset + +from miasm2.core.utils import keydefaultdict + + +class resolver: + + def __init__(self): + self.resolvers = keydefaultdict(myresolver) + + def get_resolver(self, offset): + return self.resolvers[offset] + + +class JitCore_Tcc(jitcore.JitCore): + + "JiT management, using LibTCC as backend" + + def __init__(self, my_ir, bs=None): + super(JitCore_Tcc, self).__init__(my_ir, bs) + self.resolver = resolver() + self.exec_wrapper = Jittcc.tcc_exec_bloc + + def load(self, arch): + # os.path.join(os.path.dirname(os.path.realpath(__file__)), "jitter") + lib_dir = os.path.dirname(os.path.realpath(__file__)) + libs = [] + libs.append(os.path.join(lib_dir, 'vm_mngr.so')) + libs.append(os.path.join(lib_dir, 'arch/JitCore_%s.so' % (arch.name))) + libs = ';'.join(libs) + jittcc_path = Jittcc.__file__ + include_dir = os.path.dirname(jittcc_path) + include_dir += ";" + os.path.join(include_dir, "arch") + # print include_dir + + # XXX HACK + # As debian/ubuntu have moved some include files using arch directory, + # TCC doesn't know them, so we get the info from GCC + # For example /usr/include/x86_64-linux-gnu which contains limits.h + p = Popen(["cc", "-Wp,-v", "-E", "-"], + stdout=PIPE, stderr=PIPE, stdin=PIPE) + p.stdin.close() + include_files = p.stderr.read().split('\n') + include_files = [x[1:] + for x in include_files if x.startswith(' /usr/include')] + include_files += [include_dir, get_python_inc()] + + include_files = ";".join(include_files) + Jittcc.tcc_set_emul_lib_path(include_files, libs) + + def jitirblocs(self, label, irblocs): + # irbloc = self.lbl2irbloc[lbl] + f_name = "bloc_%s" % label.name + f_declaration = \ + 'PyObject* %s(vm_cpu_t* vmcpu, vm_mngr_t* vm_mngr)' % f_name + out = irblocs2C(self.my_ir, self.resolver, label, irblocs, + gen_exception_code=True, + log_mn=self.log_mn, + log_regs=self.log_regs) + out = [f_declaration + '{'] + out + ['}\n'] + c_code = out + + func_code = gen_C_source(self.my_ir, c_code) + # print func_code + # open('tmp_%.4d.c'%self.jitcount, "w").write(func_code) + self.jitcount += 1 + mcode = jit_tcc_compil(f_name, func_code) + jcode = jit_tcc_code(mcode) + self.lbl2jitbloc[label.offset] = mcode + self.addr2obj[label.offset] = jcode + self.addr2objref[label.offset] = objref(jcode) + # print "ADDR2CODE", hex(b.label.offset), hex(id(jcode)) diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py new file mode 100644 index 00000000..d9aca929 --- /dev/null +++ b/miasm2/jitter/jitload.py @@ -0,0 +1,1089 @@ +#!/usr/bin/env python + +import os +from miasm2.core import asmbloc +from collections import defaultdict +import struct +from elfesteem import pe +from elfesteem import cstruct +from elfesteem import * +from vm_mngr import * +from vm_mngr import VmMngr + +from csts import * +from miasm2.core.utils import * +from jitcore_tcc import JitCore_Tcc +from jitcore_llvm import JitCore_LLVM +from miasm2.core.bin_stream import bin_stream + +from miasm2.ir.ir2C import init_arch_C +import inspect + +import logging + +log = logging.getLogger('jitload.py') +hnd = logging.StreamHandler() +hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s")) +log.addHandler(hnd) +log.setLevel(logging.CRITICAL) + +""" +name2jit = {'x86':JitCore_x86, + 'arm':JitCore_arm, + 'msp430':JitCore_msp430, + } +""" + + +def whoami(): + return inspect.stack()[2][3] + + +class bin_stream_vm(bin_stream): + + def __init__(self, vm, offset=0L, base_offset=0L): + self.offset = offset + self.base_offset = base_offset + self.vm = vm + + def getlen(self): + return 0xFFFFFFFFFFFFFFFF + + def getbytes(self, start, l=1): + try: + s = self.vm.vm_get_mem(start + self.base_offset, l) + except: + raise IOError('cannot get mem ad', hex(start)) + return s + + def readbs(self, l=1): + try: + s = self.vm.vm_get_mem(self.offset + self.base_offset, l) + except: + raise IOError('cannot get mem ad', hex(self.offset)) + self.offset += l + return s + + def writebs(self, l=1): + raise ValueError('writebs unsupported') + + def setoffset(self, val): + self.offset = val + + +def get_import_address(e): + import2addr = defaultdict(set) + if e.DirImport.impdesc is None: + return import2addr + for s in e.DirImport.impdesc: + # fthunk = e.rva2virt(s.firstthunk) + # l = "%2d %-25s %s" % (i, repr(s.dlldescname), repr(s)) + libname = s.dlldescname.name.lower() + for ii, imp in enumerate(s.impbynames): + if isinstance(imp, pe.ImportByName): + funcname = imp.name + else: + funcname = imp + # l = " %2d %-16s" % (ii, repr(funcname)) + import2addr[(libname, funcname)].add( + e.rva2virt(s.firstthunk + e._wsize * ii / 8)) + return import2addr + + +def preload_pe(vm, e, runtime_lib, patch_vm_imp=True): + fa = get_import_address(e) + dyn_funcs = {} + # log.debug('imported funcs: %s' % fa) + for (libname, libfunc), ads in fa.items(): + for ad in ads: + ad_base_lib = runtime_lib.lib_get_add_base(libname) + ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad) + + libname_s = canon_libname_libfunc(libname, libfunc) + dyn_funcs[libname_s] = ad_libfunc + if patch_vm_imp: + vm.vm_set_mem( + ad, struct.pack(cstruct.size2type[e._wsize], ad_libfunc)) + return dyn_funcs + + +def get_import_address_elf(e): + import2addr = defaultdict(set) + for sh in e.sh: + if not hasattr(sh, 'rel'): + continue + for k, v in sh.rel.items(): + import2addr[('xxx', k)].add(v.offset) + return import2addr + + +def preload_elf(vm, e, runtime_lib, patch_vm_imp=True): + # XXX quick hack + fa = get_import_address_elf(e) + dyn_funcs = {} + # log.debug('imported funcs: %s' % fa) + for (libname, libfunc), ads in fa.items(): + for ad in ads: + ad_base_lib = runtime_lib.lib_get_add_base(libname) + ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad) + + libname_s = canon_libname_libfunc(libname, libfunc) + dyn_funcs[libname_s] = ad_libfunc + if patch_vm_imp: + log.debug('patch %s %s %s' % + (hex(ad), hex(ad_libfunc), libfunc)) + vm.vm_set_mem( + ad, struct.pack(cstruct.size2type[e.size], ad_libfunc)) + return runtime_lib, dyn_funcs + + +def is_redirected_export(e, ad): + # test is ad points to code or dll name + out = '' + for i in xrange(0x200): + c = e.virt(ad + i) + if c == "\x00": + break + out += c + if not (c.isalnum() or c in "_.-+*$@&#()[]={}"): + return False + if not "." in out: + return False + i = out.find('.') + return out[:i], out[i + 1:] + + +def get_export_name_addr_list(e): + out = [] + # add func name + for i, n in enumerate(e.DirExport.f_names): + addr = e.DirExport.f_address[e.DirExport.f_nameordinals[i].ordinal] + f_name = n.name.name + # log.debug('%s %s' % (f_name, hex(e.rva2virt(addr.rva)))) + out.append((f_name, e.rva2virt(addr.rva))) + + # add func ordinal + for i, o in enumerate(e.DirExport.f_nameordinals): + addr = e.DirExport.f_address[o.ordinal] + # log.debug('%s %s %s' % (o.ordinal, e.DirExport.expdesc.base, + # hex(e.rva2virt(addr.rva)))) + out.append( + (o.ordinal + e.DirExport.expdesc.base, e.rva2virt(addr.rva))) + return out + + +def canon_libname_libfunc(libname, libfunc): + dn = libname.split('.')[0] + if type(libfunc) == str: + return "%s_%s" % (dn, libfunc) + else: + return str(dn), libfunc + + +class libimp: + + def __init__(self, lib_base_ad=0x71111000, **kargs): + self.name2off = {} + self.libbase2lastad = {} + self.libbase_ad = lib_base_ad + self.lib_imp2ad = {} + self.lib_imp2dstad = {} + self.fad2cname = {} + self.fad2info = {} + self.all_exported_lib = [] + + def lib_get_add_base(self, name): + name = name.lower().strip(' ') + if not "." in name: + log.debug('warning adding .dll to modulename') + name += '.dll' + log.debug('%s' % name) + + if name in self.name2off: + ad = self.name2off[name] + else: + ad = self.libbase_ad + log.debug('new lib %s %s' % (name, hex(ad))) + self.name2off[name] = ad + self.libbase2lastad[ad] = ad + 0x1 + self.lib_imp2ad[ad] = {} + self.lib_imp2dstad[ad] = {} + self.libbase_ad += 0x1000 + return ad + + def lib_get_add_func(self, libad, imp_ord_or_name, dst_ad=None): + if not libad in self.name2off.values(): + raise ValueError('unknown lib base!', hex(libad)) + + # test if not ordinatl + # if imp_ord_or_name >0x10000: + # imp_ord_or_name = vm_get_str(imp_ord_or_name, 0x100) + # imp_ord_or_name = imp_ord_or_name[:imp_ord_or_name.find('\x00')] + + #/!\ can have multiple dst ad + if not imp_ord_or_name in self.lib_imp2dstad[libad]: + self.lib_imp2dstad[libad][imp_ord_or_name] = set() + self.lib_imp2dstad[libad][imp_ord_or_name].add(dst_ad) + + if imp_ord_or_name in self.lib_imp2ad[libad]: + return self.lib_imp2ad[libad][imp_ord_or_name] + # log.debug('new imp %s %s' % (imp_ord_or_name, dst_ad)) + ad = self.libbase2lastad[libad] + self.libbase2lastad[libad] += 0x11 # arbitrary + self.lib_imp2ad[libad][imp_ord_or_name] = ad + + name_inv = dict([(x[1], x[0]) for x in self.name2off.items()]) + c_name = canon_libname_libfunc(name_inv[libad], imp_ord_or_name) + self.fad2cname[ad] = c_name + self.fad2info[ad] = libad, imp_ord_or_name + return ad + + def check_dst_ad(self): + for ad in self.lib_imp2dstad: + all_ads = self.lib_imp2dstad[ad].values() + all_ads.sort() + for i, x in enumerate(all_ads[:-1]): + if x is None or all_ads[i + 1] is None: + return False + if x + 4 != all_ads[i + 1]: + return False + return True + + def add_export_lib(self, e, name): + self.all_exported_lib.append(e) + # will add real lib addresses to database + if name in self.name2off: + ad = self.name2off[name] + else: + log.debug('new lib %s' % name) + ad = e.NThdr.ImageBase + libad = ad + self.name2off[name] = ad + self.libbase2lastad[ad] = ad + 0x1 + self.lib_imp2ad[ad] = {} + self.lib_imp2dstad[ad] = {} + self.libbase_ad += 0x1000 + + ads = get_export_name_addr_list(e) + todo = ads + # done = [] + while todo: + # for imp_ord_or_name, ad in ads: + imp_ord_or_name, ad = todo.pop() + + # if export is a redirection, search redirected dll + # and get function real addr + ret = is_redirected_export(e, ad) + if ret: + exp_dname, exp_fname = ret + # log.debug('export redirection %s' % imp_ord_or_name) + # log.debug('source %s %s' % (exp_dname, exp_fname)) + exp_dname = exp_dname + '.dll' + exp_dname = exp_dname.lower() + # if dll auto refes in redirection + if exp_dname == name: + libad_tmp = self.name2off[exp_dname] + if not exp_fname in self.lib_imp2ad[libad_tmp]: + # schedule func + todo = [(imp_ord_or_name, ad)] + todo + continue + elif not exp_dname in self.name2off: + raise ValueError('load %r first' % exp_dname) + c_name = canon_libname_libfunc(exp_dname, exp_fname) + libad_tmp = self.name2off[exp_dname] + ad = self.lib_imp2ad[libad_tmp][exp_fname] + # log.debug('%s' % hex(ad)) + # if not imp_ord_or_name in self.lib_imp2dstad[libad]: + # self.lib_imp2dstad[libad][imp_ord_or_name] = set() + # self.lib_imp2dstad[libad][imp_ord_or_name].add(dst_ad) + + # log.debug('new imp %s %s' % (imp_ord_or_name, hex(ad))) + self.lib_imp2ad[libad][imp_ord_or_name] = ad + + name_inv = dict([(x[1], x[0]) for x in self.name2off.items()]) + c_name = canon_libname_libfunc( + name_inv[libad], imp_ord_or_name) + self.fad2cname[ad] = c_name + self.fad2info[ad] = libad, imp_ord_or_name + + def gen_new_lib(self, e, filter=lambda x: True): + new_lib = [] + for n, ad in self.name2off.items(): + out_ads = dict() + for k, vs in self.lib_imp2dstad[ad].items(): + for v in vs: + out_ads[v] = k + all_ads = self.lib_imp2dstad[ad].values() + all_ads = reduce(lambda x, y: x + list(y), all_ads, []) + all_ads = [x for x in all_ads if filter(x)] + # log.debug('%s' % [hex(x) for x in all_ads]) + all_ads.sort() + # first, drop None + if not all_ads: + continue + for i, x in enumerate(all_ads): + if not x in [0, None]: + break + all_ads = all_ads[i:] + while all_ads: + othunk = all_ads[0] + i = 0 + while i + 1 < len(all_ads) and all_ads[i] + 4 == all_ads[i + 1]: + i += 1 + funcs = [out_ads[x] for x in all_ads[:i + 1]] + try: + off = e.virt2off(othunk) + except pe.InvalidOffset: + off = None + if off is not None: # e.is_in_virt_address(othunk): + new_lib.append(({"name": n, + "firstthunk": off}, + funcs) + ) + all_ads = all_ads[i + 1:] + return new_lib + + +def vm_load_pe(vm, fname, align_s=True, load_hdr=True, + **kargs): + e = pe_init.PE(open(fname, 'rb').read(), **kargs) + + aligned = True + for s in e.SHList: + if s.addr & 0xFFF: + aligned = False + break + + if aligned: + if load_hdr: + hdr_len = max(0x200, e.NThdr.sectionalignment) + min_len = min(e.SHList[0].addr, hdr_len) + pe_hdr = e.content[:hdr_len] + pe_hdr = pe_hdr + min_len * "\x00" + pe_hdr = pe_hdr[:min_len] + vm.vm_add_memory_page( + e.NThdr.ImageBase, PAGE_READ | PAGE_WRITE, pe_hdr) + if align_s: + for i, s in enumerate(e.SHList[:-1]): + s.size = e.SHList[i + 1].addr - s.addr + s.rawsize = s.size + s.data = strpatchwork.StrPatchwork(s.data[:s.size]) + s.offset = s.addr + s = e.SHList[-1] + s.size = (s.size + 0xfff) & 0xfffff000 + for s in e.SHList: + data = str(s.data) + data += "\x00" * (s.size - len(data)) + # log.debug('SECTION %s %s' % (hex(s.addr), + # hex(e.rva2virt(s.addr)))) + vm.vm_add_memory_page( + e.rva2virt(s.addr), PAGE_READ | PAGE_WRITE, data) + # s.offset = s.addr + return e + + # not aligned + log.warning('pe is not aligned, creating big section') + min_addr = None + max_addr = None + data = "" + + if load_hdr: + data = e.content[:0x400] + data += (e.SHList[0].addr - len(data)) * "\x00" + min_addr = 0 + + for i, s in enumerate(e.SHList): + if i < len(e.SHList) - 1: + s.size = e.SHList[i + 1].addr - s.addr + s.rawsize = s.size + s.offset = s.addr + + if min_addr is None or s.addr < min_addr: + min_addr = s.addr + if max_addr is None or s.addr + s.size > max_addr: + max_addr = s.addr + max(s.size, len(s.data)) + min_addr = e.rva2virt(min_addr) + max_addr = e.rva2virt(max_addr) + log.debug('%s %s %s' % + (hex(min_addr), hex(max_addr), hex(max_addr - min_addr))) + + vm.vm_add_memory_page(min_addr, + PAGE_READ | PAGE_WRITE, + (max_addr - min_addr) * "\x00") + for s in e.SHList: + log.debug('%s %s' % (hex(e.rva2virt(s.addr)), len(s.data))) + vm.vm_set_mem(e.rva2virt(s.addr), str(s.data)) + return e + + +def vm_load_elf(vm, fname, **kargs): + e = elf_init.ELF(open(fname, 'rb').read(), **kargs) + for p in e.ph.phlist: + if p.ph.type != 1: + continue + log.debug('%s %s %s' % + (hex(p.ph.vaddr), hex(p.ph.offset), hex(p.ph.filesz))) + data = e._content[p.ph.offset:p.ph.offset + p.ph.filesz] + r_vaddr = p.ph.vaddr & ~0xFFF + data = (p.ph.vaddr - r_vaddr) * "\x00" + data + data += (((len(data) + 0xFFF) & ~0xFFF) - len(data)) * "\x00" + vm.vm_add_memory_page(r_vaddr, PAGE_READ | PAGE_WRITE, data) + return e +""" +def init_jitter(arch, attrib): + jitarch = name2jit[(arch.name, attrib)] + jitarch.vm_init_regs() + init_memory_page_pool() + init_code_bloc_pool() + init_memory_breakpoint() + jit_tcc_init(arch, attrib) + +def init_stack(arch, attrib, stack_size = 0x10000, stack_base = 0x1230000, **kargs): + jitarch = name2jit[(arch.name, attrib)] + + vm_add_memory_page(stack_base, PAGE_READ|PAGE_WRITE, "\x00"*stack_size) + regs = jitarch.vm_get_gpreg() + regs[arch.sp[attrib].name] = stack_base+stack_size + jitarch.vm_set_gpreg(regs) + regs = jitarch.vm_get_gpreg() +""" + + +def vm_load_pe_lib(fname_in, libs, lib_path_base, patch_vm_imp, **kargs): + fname = os.path.join(lib_path_base, fname_in) + e = vm_load_pe(fname, **kargs) + libs.add_export_lib(e, fname_in) + # preload_pe(e, libs, patch_vm_imp) + return e + + +def vm_load_pe_libs(libs_name, libs, lib_path_base="win_dll", + patch_vm_imp=True, **kargs): + lib_imgs = {} + for fname in libs_name: + e = vm_load_pe_lib(fname, libs, lib_path_base, patch_vm_imp) + lib_imgs[fname] = e + return lib_imgs + + +def vm_fix_imports_pe_libs(lib_imgs, libs, lib_path_base="win_dll", + patch_vm_imp=True, **kargs): + for e in lib_imgs.values(): + preload_pe(e, libs, patch_vm_imp) + + + +class CallbackHandler(object): + + "Handle a list of callback" + + def __init__(self): + self.callbacks = {} # Key -> [callback list] + + def add_callback(self, name, callback): + "Add a callback to the key 'name'" + self.callbacks[name] = self.callbacks.get(name, []) + [callback] + + def set_callback(self, name, *args): + "Set the list of callback for key 'name'" + self.callbacks[name] = args + + def get_callbacks(self, name): + "Return the list of callbacks associated to key 'name'" + return self.callbacks.get(name, []) + + def remove_callback(self, callback): + """Remove the callback from the list. + Return the list of empty keys (removed)""" + + to_check = set() + for key, cb_list in self.callbacks.items(): + try: + cb_list.remove(callback) + to_check.add(key) + except ValueError: + pass + + empty_keys = [] + for key in to_check: + if len(self.callbacks[key]) == 0: + empty_keys.append(key) + del(self.callbacks[key]) + + return empty_keys + + def call_callbacks(self, name, *args): + """Call callbacks associated to key 'name' with arguments args. While + callbacks return True, continue with next callback. + Iterator on other results.""" + + res = True + + for c in self.get_callbacks(name): + res = c(*args) + if res is not True: + yield res + + def __call__(self, name, *args): + "Wrapper for call_callbacks" + return self.call_callbacks(name, *args) + + +class CallbackHandlerBitflag(CallbackHandler): + + "Handle a list of callback with conditions on bitflag" + + def __call__(self, bitflag, *args): + """Call each callbacks associated with bit set in bitflag. While + callbacks return True, continue with next callback. + Iterator on other results""" + + res = True + for b in self.callbacks.keys(): + + if b & bitflag != 0: + # If the flag matched + for res in self.call_callbacks(b, *args): + if res is not True: + yield res + + +class ExceptionHandle(): + + "Return type for exception handler" + + def __init__(self, except_flag): + self.except_flag = except_flag + + @classmethod + def memoryBreakpoint(cls): + return cls(EXCEPT_BREAKPOINT_INTERN) + + def __eq__(self, to_cmp): + if not isinstance(to_cmp, ExceptionHandle): + return False + return (self.except_flag == to_cmp.except_flag) + + +class jitter: + + "Main class for JIT handling" + + def __init__(self, my_ir, jit_type="tcc"): + """Init an instance of jitter. + @my_ir: ir instance for this architecture + @jit_type: JiT backend to use. Available options are: + - "tcc" + - "llvm" + """ + + self.arch = my_ir.arch + self.attrib = my_ir.attrib + arch_name = my_ir.arch.name # (my_ir.arch.name, my_ir.attrib) + if arch_name == "x86": + from arch import JitCore_x86 as jcore + elif arch_name == "arm": + from arch import JitCore_arm as jcore + elif arch_name == "msp430": + from arch import JitCore_msp430 as jcore + else: + raise ValueError("unsupported jit arch!") + + self.cpu = jcore.JitCpu() + self.vm = VmMngr() + self.bs = bin_stream_vm(self.vm) + self.my_ir = my_ir + init_arch_C(self.arch) + + if jit_type == "tcc": + self.jit = JitCore_Tcc(self.my_ir, self.bs) + elif jit_type == "llvm": + self.jit = JitCore_LLVM(self.my_ir, self.bs) + else: + raise Exception("Unkown JiT Backend") + + self.cpu.vm_init_regs() + self.vm.vm_init_memory_page_pool() + self.vm.vm_init_code_bloc_pool() + self.vm.vm_init_memory_breakpoint() + + self.vm.vm_set_addr2obj(self.jit.addr2obj) + + self.jit.load(self.arch) + self.stack_size = 0x10000 + self.stack_base = 0x1230000 + + # Init callback handler + self.breakpoints_handler = CallbackHandler() + self.exceptions_handler = CallbackHandlerBitflag() + self.init_exceptions_handler() + self.exec_cb = None + + def init_exceptions_handler(self): + "Add common exceptions handlers" + + def exception_automod(jitter): + "Tell the JiT backend to update blocs modified" + addr = self.vm.vm_get_last_write_ad() + size = self.vm.vm_get_last_write_size() + + self.jit.updt_automod_code(self.vm, addr, size) + self.vm.vm_set_exception(0) + + return True + + def exception_memory_breakpoint(jitter): + "Stop the execution and return an identifier" + return ExceptionHandle.memoryBreakpoint() + + self.add_exception_handler(EXCEPT_CODE_AUTOMOD, exception_automod) + self.add_exception_handler(EXCEPT_BREAKPOINT_INTERN, + exception_memory_breakpoint) + + def add_breakpoint(self, addr, callback): + """Add a callback associated with addr. + @addr: breakpoint address + @callback: function with definition (jitter instance) + """ + self.breakpoints_handler.add_callback(addr, callback) + self.jit.add_disassembly_splits(addr) + + def remove_breakpoints_by_callback(self, callback): + """Remove callbacks associated with breakpoint. + @callback: callback to remove + """ + empty_keys = self.breakpoints_handler.remove_callback(callback) + for key in empty_keys: + self.jit.remove_disassembly_splits(key) + + def add_exception_handler(self, flag, callback): + """Add a callback associated with an exception flag. + @flag: bitflag + @callback: function with definition (jitter instance) + """ + self.exceptions_handler.add_callback(flag, callback) + + def runbloc(self, pc): + """Wrapper on JiT backend. Run the code at PC and return the next PC. + @pc: address of code to run""" + + return self.jit.runbloc(self.cpu, self.vm, pc) + + def runiter_once(self, pc): + """Iterator on callbacks results on code running from PC. + Check exceptions before breakpoints.""" + + self.pc = pc + + # Callback called before exec + if self.exec_cb is not None: + res = self.exec_cb(self) + if res is not True: + yield res + + # Check breakpoints + old_pc = self.pc + for res in self.breakpoints_handler(self.pc, self): + if res is not True: + yield res + + # If a callback changed pc, re call every callback + if old_pc != self.pc: + return + + # Exceptions should never be activated before run + assert(self.get_exception() == 0) + + # Run the bloc at PC + self.pc = self.runbloc(self.pc) + + # Check exceptions + exception_flag = self.get_exception() + for res in self.exceptions_handler(exception_flag, self): + if res is not True: + yield res + + def init_run(self, pc): + """Create an iterator on pc with runiter. + @pc: address of code to run + """ + self.run_iterator = self.runiter_once(pc) + self.pc = pc + self.run = True + + def continue_run(self, step=False): + """PRE: init_run. + Continue the run of the current session until iterator returns or run is + set to False. + If step is True, run only one time. + Return the iterator value""" + + while self.run: + try: + return self.run_iterator.next() + except StopIteration: + pass + + self.run_iterator = self.runiter_once(self.pc) + + if step is True: + return None + + return None + + def init_stack(self): + self.vm.vm_add_memory_page( + self.stack_base, PAGE_READ | PAGE_WRITE, "\x00" * self.stack_size) + sp = self.arch.getsp(self.attrib) + setattr(self.cpu, sp.name, self.stack_base + self.stack_size) + # regs = self.cpu.vm_get_gpreg() + # regs[sp.name] = self.stack_base+self.stack_size + # self.cpu.vm_set_gpreg(regs) + + def get_exception(self): + return self.cpu.vm_get_exception() | self.vm.vm_get_exception() + + # commun functions + def get_str_ansi(self, addr, max_char=None): + """Get ansi str from vm. + @addr: address in memory + @max_char: maximum len""" + l = 0 + tmp = addr + while ((max_char is None or l < max_char) and + self.vm.vm_get_mem(tmp, 1) != "\x00"): + tmp += 1 + l += 1 + return self.vm.vm_get_mem(addr, l) + + def get_str_unic(self, addr, max_char=None): + """Get unicode str from vm. + @addr: address in memory + @max_char: maximum len""" + l = 0 + tmp = addr + while ((max_char is None or l < max_char) and + self.vm.vm_get_mem(tmp, 2) != "\x00\x00"): + tmp += 2 + l += 2 + s = self.vm.vm_get_mem(addr, l) + s = s[::2] # TODO: real unicode decoding + return s + + def set_str_ansi(self, addr, s): + """Set an ansi string in memory""" + s = s + "\x00" + self.vm.vm_set_mem(addr, s) + + def set_str_unic(self, addr, s): + """Set an unicode string in memory""" + s = "\x00".join(list(s)) + '\x00' * 3 + self.vm.vm_set_mem(addr, s) + + +class jitter_x86_16(jitter): + + def __init__(self, *args, **kwargs): + from miasm2.arch.x86.sem import ir_x86_16 + sp = asmbloc.asm_symbol_pool() + jitter.__init__(self, ir_x86_16(sp), *args, **kwargs) + self.my_ir.jit_pc = self.my_ir.arch.regs.RIP + self.my_ir.do_stk_segm = False + self.orig_irbloc_fix_regs_for_mode = self.my_ir.irbloc_fix_regs_for_mode + self.my_ir.irbloc_fix_regs_for_mode = self.my_irbloc_fix_regs_for_mode + + def my_irbloc_fix_regs_for_mode(self, irbloc, attrib=64): + self.orig_irbloc_fix_regs_for_mode(irbloc, 64) + + def vm_push_uint16_t(self, v): + self.cpu.SP -= self.my_ir.sp.size / 8 + self.vm.vm_set_mem(self.cpu.SP, pck16(v)) + + def vm_pop_uint16_t(self): + x = upck16(self.vm.vm_get_mem(self.cpu.SP, self.my_ir.sp.size / 8)) + self.cpu.SP += self.my_ir.sp.size / 8 + return x + + def get_stack_arg(self, n): + x = upck16(self.vm.vm_get_mem(self.cpu.SP + 4 * n, 4)) + return x + + def init_run(self, *args, **kwargs): + jitter.init_run(self, *args, **kwargs) + self.cpu.IP = self.pc + + +class jitter_x86_32(jitter): + + def __init__(self, *args, **kwargs): + from miasm2.arch.x86.sem import ir_x86_32 + sp = asmbloc.asm_symbol_pool() + jitter.__init__(self, ir_x86_32(sp), *args, **kwargs) + self.my_ir.jit_pc = self.my_ir.arch.regs.RIP + self.my_ir.do_stk_segm = False + + self.orig_irbloc_fix_regs_for_mode = self.my_ir.irbloc_fix_regs_for_mode + self.my_ir.irbloc_fix_regs_for_mode = self.my_irbloc_fix_regs_for_mode + + def my_irbloc_fix_regs_for_mode(self, irbloc, attrib=64): + self.orig_irbloc_fix_regs_for_mode(irbloc, 64) + + def vm_push_uint32_t(self, v): + self.cpu.ESP -= self.my_ir.sp.size / 8 + self.vm.vm_set_mem(self.cpu.ESP, pck32(v)) + + def vm_pop_uint32_t(self): + x = upck32(self.vm.vm_get_mem(self.cpu.ESP, self.my_ir.sp.size / 8)) + self.cpu.ESP += self.my_ir.sp.size / 8 + return x + + def get_stack_arg(self, n): + x = upck32(self.vm.vm_get_mem(self.cpu.ESP + 4 * n, 4)) + return x + + # calling conventions + + # stdcall + def func_args_stdcall(self, n_args): + ret_ad = self.vm_pop_uint32_t() + args = [] + for _ in xrange(n_args): + args.append(self.vm_pop_uint32_t()) + log.debug('%s %s %s' % (whoami(), hex(ret_ad), [hex(x) for x in args])) + return ret_ad, args + + def func_ret_stdcall(self, ret_addr, ret_value1=None, ret_value2=None): + self.cpu.EIP = ret_addr + if ret_value1 is not None: + self.cpu.EAX = ret_value1 + if ret_value2 is not None: + self.cpu.EDX = ret_value + + # cdecl + def func_args_cdecl(self, n_args, dolog=True): + ret_ad = self.vm_pop_uint32_t() + args = [] + for i in xrange(n_args): + args.append(self.get_stack_arg(i)) + if dolog: + log.debug('%s %s %s' % + (whoami(), hex(ret_ad), [hex(x) for x in args])) + return ret_ad, args + + def func_ret_cdecl(self, ret_addr, ret_value): + self.cpu.EIP = ret_addr + self.cpu.EAX = ret_value + + def add_lib_handler(self, libs, user_globals=None): + """Add a function to handle libs call with breakpoints + @libs: libimp instance + @user_globals: dictionnary for defined user function + """ + if user_globals is None: + user_globals = {} + + from miasm2.jitter.os_dep import win_api_x86_32 + + def handle_lib(jitter): + fname = libs.fad2cname[jitter.pc] + if fname in user_globals: + f = user_globals[fname] + elif fname in win_api_x86_32.__dict__: + f = win_api_x86_32.__dict__[fname] + else: + log.debug('%s' % repr(fname)) + raise ValueError('unknown api', hex(jitter.vm_pop_uint32_t()), repr(fname)) + f(jitter) + jitter.pc = getattr(jitter.cpu, jitter.my_ir.pc.name) + return True + + for f_addr in libs.fad2cname: + self.add_breakpoint(f_addr, handle_lib) + + def init_run(self, *args, **kwargs): + jitter.init_run(self, *args, **kwargs) + self.cpu.EIP = self.pc + + +class jitter_x86_64(jitter): + + def __init__(self, *args, **kwargs): + from miasm2.arch.x86.sem import ir_x86_64 + sp = asmbloc.asm_symbol_pool() + jitter.__init__(self, ir_x86_64(sp), *args, **kwargs) + self.my_ir.jit_pc = self.my_ir.arch.regs.RIP + self.my_ir.do_stk_segm = False + + self.orig_irbloc_fix_regs_for_mode = self.my_ir.irbloc_fix_regs_for_mode + self.my_ir.irbloc_fix_regs_for_mode = self.my_irbloc_fix_regs_for_mode + + def my_irbloc_fix_regs_for_mode(self, irbloc, attrib=64): + self.orig_irbloc_fix_regs_for_mode(irbloc, 64) + + def vm_push_uint64_t(self, v): + self.cpu.RSP -= self.my_ir.sp.size / 8 + self.vm.vm_set_mem(self.cpu.RSP, pck64(v)) + + def vm_pop_uint64_t(self): + x = upck64(self.vm.vm_get_mem(self.cpu.RSP, self.my_ir.sp.size / 8)) + self.cpu.RSP += self.my_ir.sp.size / 8 + return x + + def get_stack_arg(self, n): + x = upck64(self.vm.vm_get_mem(self.cpu.RSP + 4 * n, 4)) + return x + + def init_run(self, *args, **kwargs): + jitter.init_run(self, *args, **kwargs) + self.cpu.RIP = self.pc + + +class jitter_arm(jitter): + + def __init__(self, *args, **kwargs): + from miasm2.arch.arm.sem import ir_arm + sp = asmbloc.asm_symbol_pool() + jitter.__init__(self, ir_arm(sp), *args, **kwargs) + self.my_ir.jit_pc = self.my_ir.arch.regs.PC + + def vm_push_uint32_t(self, v): + self.cpu.SP -= 4 + self.vm.vm_set_mem(self.cpu.SP, pck32(v)) + + def vm_pop_uint32_t(self): + x = upck32(self.vm.vm_get_mem(self.cpu.SP, 4)) + self.cpu.SP += 4 + return x + + def get_stack_arg(self, n): + x = upck32(self.vm.vm_get_mem(self.cpu.SP + 4 * n, 4)) + return x + + # calling conventions + + def func_args_fastcall(self, n_args): + args = [] + for i in xrange(min(n_args, 4)): + args.append(self.cpu.vm_get_gpreg()['R%d' % i]) + for i in xrange(max(0, n_args - 4)): + args.append(self.get_stack_arg(i)) + log.debug('%s %s' % (whoami(), [hex(x) for x in args])) + return args + + def func_ret_fastcall(self, ret_value=None): + self.pc = self.cpu.PC = self.cpu.LR + if ret_value is not None: + self.cpu.R0 = ret_value + return True + + def add_lib_handler(self, libs): + from miasm2.jitter.os_dep import linux_stdlib + for offset, fname in libs.fad2cname.iteritems(): + if fname in linux_stdlib.__dict__: + self.add_breakpoint(offset, linux_stdlib.__dict__[fname]) + else: + log.warning( + 'jitter libhandler: %s function not found!' % fname) + + def init_run(self, *args, **kwargs): + jitter.init_run(self, *args, **kwargs) + self.cpu.PC = self.pc + + +def vm2pe(myjit, fname, libs=None, e_orig=None, + max_addr=1 << 64, min_addr=0x401000, + min_section_offset=0x1000, img_base=None, + added_funcs=None): + mye = pe_init.PE() + + if img_base is None: + img_base = e_orig.NThdr.ImageBase + + mye.NThdr.ImageBase = img_base + all_mem = myjit.vm.vm_get_all_memory() + addrs = all_mem.keys() + addrs.sort() + mye.Opthdr.AddressOfEntryPoint = mye.virt2rva(myjit.cpu.EIP) + first = True + for ad in addrs: + if not min_addr <= ad < max_addr: + continue + log.debug('%s' % hex(ad)) + if first: + mye.SHList.add_section( + "%.8X" % ad, + addr=ad - mye.NThdr.ImageBase, + data=all_mem[ad]['data'], + offset=min_section_offset) + else: + mye.SHList.add_section( + "%.8X" % ad, + addr=ad - mye.NThdr.ImageBase, + data=all_mem[ad]['data']) + first = False + if libs: + if added_funcs is not None: + # name_inv = dict([(x[1], x[0]) for x in libs.name2off.items()]) + + for addr, funcaddr in added_func: + libbase, dllname = libs.fad2info[funcaddr] + libs.lib_get_add_func(libbase, dllname, addr) + + new_dll = libs.gen_new_lib(mye, lambda x: mye.virt.is_addr_in(x)) + else: + new_dll = {} + + log.debug('%s' % new_dll) + + mye.DirImport.add_dlldesc(new_dll) + s_imp = mye.SHList.add_section("import", rawsize=len(mye.DirImport)) + mye.DirImport.set_rva(s_imp.addr) + log.debug('%s' % repr(mye.SHList)) + if e_orig: + # resource + xx = str(mye) + mye.content = xx + ad = e_orig.NThdr.optentries[pe.DIRECTORY_ENTRY_RESOURCE].rva + log.debug('dirres %s' % hex(ad)) + if ad != 0: + mye.NThdr.optentries[pe.DIRECTORY_ENTRY_RESOURCE].rva = ad + mye.DirRes = pe.DirRes.unpack(xx, ad, mye) + # log.debug('%s' % repr(mye.DirRes)) + s_res = mye.SHList.add_section( + name="myres", rawsize=len(mye.DirRes)) + mye.DirRes.set_rva(s_res.addr) + log.debug('%s' % repr(mye.DirRes)) + # generation + open(fname, 'w').write(str(mye)) + + +class jitter_msp430(jitter): + + def __init__(self, *args, **kwargs): + from miasm2.arch.msp430.sem import ir_msp430 + sp = asmbloc.asm_symbol_pool() + jitter.__init__(self, ir_msp430(sp), *args, **kwargs) + self.my_ir.jit_pc = self.my_ir.arch.regs.PC + + def vm_push_uint16_t(self, v): + regs = self.cpu.vm_get_gpreg() + regs['SP'] -= 2 + self.cpu.vm_set_gpreg(regs) + self.vm.vm_set_mem(regs['SP'], pck16(v)) + + def vm_pop_uint16_t(self): + regs = self.cpu.vm_get_gpreg() + x = upck16(self.vm.vm_get_mem(regs['SP'], 2)) + regs['SP'] += 2 + self.cpu.vm_set_gpreg(regs) + return x + + def get_stack_arg(self, n): + regs = self.cpu.vm_get_gpreg() + x = upck16(self.vm.vm_get_mem(regs['SP'] + 2 * n, 2)) + return x + + def init_run(self, *args, **kwargs): + jitter.init_run(self, *args, **kwargs) + self.cpu.PC = self.pc + diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py new file mode 100644 index 00000000..406a36c9 --- /dev/null +++ b/miasm2/jitter/llvmconvert.py @@ -0,0 +1,982 @@ +# +# +# Miasm2 Extension: # +# - Miasm2 IR to LLVM IR # +# - JiT # +# +# Requires: # +# - llvmpy (tested on v0.11.2) # +# +# Authors : Fabrice DESCLAUX (CEA/DAM), Camille MOUGEY (CEA/DAM) # +# +# + +import llvm +import llvm.core as llvm_c +import llvm.ee as llvm_e +import llvm.passes as llvm_p +import miasm2.expression.expression as m2_expr +import miasm2.jitter.csts as m2_csts +import miasm2.core.asmbloc as m2_asmbloc + + +class LLVMType(llvm_c.Type): + + "Handle LLVM Type" + + int_cache = {} + + @classmethod + def int(cls, size=32): + try: + return cls.int_cache[size] + except KeyError: + cls.int_cache[size] = llvm_c.Type.int(size) + return cls.int_cache[size] + + @classmethod + def pointer(cls, addr): + "Generic pointer for execution" + return llvm_e.GenericValue.pointer(addr) + + @classmethod + def generic(cls, e): + "Generic value for execution" + if isinstance(e, m2_expr.ExprInt): + return llvm_e.GenericValue.int(LLVMType.int(e.size), int(e.arg)) + elif isinstance(e, llvm_e.GenericValue): + return e + else: + raise ValueError() + + +class LLVMContext(): + + "Context for llvm binding. Stand for a LLVM Module" + + known_fc = {} + + def __init__(self, name="mod"): + "Initialize a context with a module named 'name'" + self.mod = llvm_c.Module.new(name) + self.pass_manager = llvm_p.FunctionPassManager.new(self.mod) + self.exec_engine = llvm_e.ExecutionEngine.new(self.mod) + self.add_fc(self.known_fc) + + def optimise_level(self, classic_passes=True, dead_passes=True): + """Set the optimisation level : + classic_passes : + - combine instruction + - reassociate + - global value numbering + - simplify cfg + + dead_passes : + - dead code + - dead store + - dead instructions + """ + + # Set up the optimiser pipeline + + if classic_passes is True: + # self.pass_manager.add(llvm_p.PASS_INSTCOMBINE) + self.pass_manager.add(llvm_p.PASS_REASSOCIATE) + self.pass_manager.add(llvm_p.PASS_GVN) + self.pass_manager.add(llvm_p.PASS_SIMPLIFYCFG) + + if dead_passes is True: + self.pass_manager.add(llvm_p.PASS_DCE) + self.pass_manager.add(llvm_p.PASS_DSE) + self.pass_manager.add(llvm_p.PASS_DIE) + + self.pass_manager.initialize() + + def get_execengine(self): + "Return the Execution Engine associated with this context" + return self.exec_engine + + def get_passmanager(self): + "Return the Pass Manager associated with this context" + return self.exec_engine + + def get_module(self): + "Return the module associated with this context" + return self.mod + + def add_shared_library(self, filename): + "Load the shared library 'filename'" + return llvm_c.load_library_permanently(filename) + + def add_fc(self, fc): + "Add function into known_fc" + + for name, detail in fc.items(): + self.mod.add_function(LLVMType.function(detail["ret"], + detail["args"]), + name) + + +class LLVMContext_JIT(LLVMContext): + + "Extend LLVMContext_JIT in order to handle memory management" + + def __init__(self, library_filenames, name="mod"): + "Init a LLVMContext object, and load the mem management shared library" + LLVMContext.__init__(self, name) + for lib_fname in library_filenames: + self.add_shared_library(lib_fname) + self.add_memlookups() + self.add_get_exceptionflag() + self.add_op() + self.add_log_functions() + self.vmcpu = {} + + def add_memlookups(self): + "Add MEM_LOOKUP functions" + + fc = {} + p8 = llvm_c.PointerType.pointer(LLVMType.int(8)) + for i in [8, 16, 32, 64]: + fc["MEM_LOOKUP_%02d" % i] = {"ret": LLVMType.int(i), + "args": [p8, + LLVMType.int(64)]} + + fc["MEM_WRITE_%02d" % i] = {"ret": LLVMType.void(), + "args": [p8, + LLVMType.int(64), + LLVMType.int(i)]} + + self.add_fc(fc) + + def add_get_exceptionflag(self): + "Add 'get_exception_flag' function" + p8 = llvm_c.PointerType.pointer(LLVMType.int(8)) + self.add_fc({"get_exception_flag": {"ret": LLVMType.int(64), + "args": [p8]}}) + + def add_op(self): + "Add operations functions" + + p8 = llvm_c.PointerType.pointer(LLVMType.int(8)) + self.add_fc({"parity": {"ret": LLVMType.int(), + "args": [LLVMType.int()]}}) + self.add_fc({"rot_left": {"ret": LLVMType.int(), + "args": [LLVMType.int(), + LLVMType.int(), + LLVMType.int()]}}) + self.add_fc({"rot_right": {"ret": LLVMType.int(), + "args": [LLVMType.int(), + LLVMType.int(), + LLVMType.int()]}}) + + self.add_fc({"segm2addr": {"ret": LLVMType.int(64), + "args": [p8, + LLVMType.int(64), + LLVMType.int(64)]}}) + + for k in [8, 16]: + self.add_fc({"bcdadd_%s" % k: {"ret": LLVMType.int(k), + "args": [LLVMType.int(k), + LLVMType.int(k)]}}) + self.add_fc({"bcdadd_cf_%s" % k: {"ret": LLVMType.int(k), + "args": [LLVMType.int(k), + LLVMType.int(k)]}}) + + for k in [16, 32, 64]: + self.add_fc({"imod%s" % k: {"ret": LLVMType.int(k), + "args": [p8, + LLVMType.int(k), + LLVMType.int(k)]}}) + self.add_fc({"idiv%s" % k: {"ret": LLVMType.int(k), + "args": [p8, + LLVMType.int(k), + LLVMType.int(k)]}}) + + def add_log_functions(self): + "Add functions for state logging" + + p8 = llvm_c.PointerType.pointer(LLVMType.int(8)) + self.add_fc({"dump_gpregs": {"ret": LLVMType.void(), + "args": [p8]}}) + + def set_vmcpu(self, lookup_table): + "Set the correspondance between register name and vmcpu offset" + + self.vmcpu = lookup_table + + def set_IR_transformation(self, *args): + """Set a list of transformation to apply on expression before their + treatments. + args: function Expr(Expr)""" + self.IR_transformation_functions = args + + +class LLVMFunction(): + + "Represent a llvm function" + + # Default logging values + log_mn = False + log_regs = False + + def __init__(self, llvm_context, name="fc"): + "Create a new function with name fc" + self.llvm_context = llvm_context + self.mod = self.llvm_context.get_module() + + self.my_args = [] # (Expr, LLVMType, Name) + self.ret_type = None + self.builder = None + self.entry_bbl = None + + self.branch_counter = 0 + self.name = name + + def new_branch_name(self): + "Return a new branch name" + + self.branch_counter += 1 + return "%s" % self.branch_counter + + def viewCFG(self): + "Show the CFG of the current function" + self.fc.viewCFG() + + def append_basic_block(self, label): + """Add a new basic block to the current function. + @label: str or asmlabel + Return the corresponding LLVM Basic Block""" + name = self.canonize_label_name(label) + bbl = self.fc.append_basic_block(name) + self.name2bbl[label] = bbl + + return bbl + + def init_fc(self): + "Init the function" + + # Build type for fc signature + fc_type = LLVMType.function( + self.ret_type, [k[1] for k in self.my_args]) + + # Add fc in module + try: + fc = self.mod.add_function(fc_type, self.name) + except llvm.LLVMException: + # Overwrite the previous function + previous_fc = self.mod.get_function_named(self.name) + previous_fc.delete() + fc = self.mod.add_function(fc_type, self.name) + + # Name args + for i, a in enumerate(self.my_args): + fc.args[i].name = a[2] + + # Initialize local variable pool + self.local_vars = {} + self.local_vars_pointers = {} + for i, a in enumerate(self.my_args): + self.local_vars[a[2]] = fc.args[i] + + # Init cache + self.expr_cache = {} + self.main_stream = True + self.name2bbl = {} + self.offsets_jitted = set() + + # Function link + self.fc = fc + + # Add a first BasicBlock + self.entry_bbl = self.append_basic_block("entry") + + # Instruction builder + self.builder = llvm_c.Builder.new(self.entry_bbl) + + def CreateEntryBlockAlloca(self, var_type): + "Create an alloca instruction at the beginning of the current fc" + builder = self.builder + current_bbl = builder.basic_block + builder.position_at_end(self.entry_bbl) + + ret = builder.alloca(var_type) + builder.position_at_end(current_bbl) + return ret + + def get_ptr_by_expr(self, expr): + """"Return a pointer casted corresponding to ExprId expr. If it is not + already computed, compute it at the end of entry_bloc""" + + name = expr.name + + try: + # If the pointer has already been computed + ptr_casted = self.local_vars_pointers[name] + + except KeyError: + # Get current objects + builder = self.builder + current_bbl = builder.basic_block + + # Go at the right position + entry_bloc_bbl = self.entry_bbl + builder.position_at_end(entry_bloc_bbl) + + # Compute the pointer address + offset = self.llvm_context.vmcpu[name] + + # Pointer cast + ptr = builder.gep(self.local_vars["vmcpu"], + [llvm_c.Constant.int(LLVMType.int(), + offset)]) + int_size = LLVMType.int(expr.size) + ptr_casted = builder.bitcast(ptr, + llvm_c.PointerType.pointer(int_size)) + # Store in cache + self.local_vars_pointers[name] = ptr_casted + + # Reset builder + builder.position_at_end(current_bbl) + + return ptr_casted + + def clear_cache(self, regs_updated): + "Remove from the cache values which depends on regs_updated" + + regs_updated_set = set(regs_updated) + + for expr in self.expr_cache.keys(): + if expr.get_r(True).isdisjoint(regs_updated_set) is not True: + self.expr_cache.pop(expr) + + def update_cache(self, name, value): + "Add 'name' = 'value' to the cache iff main_stream = True" + + if self.main_stream is True: + self.expr_cache[name] = value + + def add_ir(self, expr): + "Add a Miasm2 IR to the last bbl. Return the var created" + + if self.main_stream is True and expr in self.expr_cache: + return self.expr_cache[expr] + + builder = self.builder + + if isinstance(expr, m2_expr.ExprInt): + ret = llvm_c.Constant.int(LLVMType.int(expr.size), int(expr.arg)) + self.update_cache(expr, ret) + return ret + + if isinstance(expr, m2_expr.ExprId): + name = expr.name + if not isinstance(name, str): + # Resolve label + offset = name.offset + ret = llvm_c.Constant.int(LLVMType.int(expr.size), offset) + self.update_cache(expr, ret) + return ret + + try: + # If expr.name is already known (args) + return self.local_vars[name] + except KeyError: + pass + + ptr_casted = self.get_ptr_by_expr(expr) + + var = builder.load(ptr_casted, name) + self.update_cache(expr, var) + return var + + if isinstance(expr, m2_expr.ExprOp): + op = expr.op + + if op == "parity": + fc_ptr = self.mod.get_function_named("parity") + arg = builder.zext(self.add_ir(expr.args[0]), + LLVMType.int()) + ret = builder.call(fc_ptr, [arg]) + ret = builder.trunc(ret, LLVMType.int(expr.size)) + self.update_cache(expr, ret) + return ret + + if op in ["<<<", ">>>"]: + fc_name = "rot_left" if op == "<<<" else "rot_right" + fc_ptr = self.mod.get_function_named(fc_name) + args = [self.add_ir(arg) for arg in expr.args] + arg_size = expr.args[0].size + if arg_size < 32: + # Cast args + args = [builder.zext(arg, LLVMType.int(32)) + for arg in args] + arg_size_cst = llvm_c.Constant.int(LLVMType.int(), + arg_size) + ret = builder.call(fc_ptr, [arg_size_cst] + args) + if arg_size < 32: + # Cast ret + ret = builder.trunc(ret, LLVMType.int(arg_size)) + self.update_cache(expr, ret) + return ret + + if op == "bcdadd": + size = expr.args[0].size + fc_ptr = self.mod.get_function_named("bcdadd_%s" % size) + args = [self.add_ir(arg) for arg in expr.args] + ret = builder.call(fc_ptr, args) + self.update_cache(expr, ret) + return ret + + if op == "bcdadd_cf": + size = expr.args[0].size + fc_ptr = self.mod.get_function_named("bcdadd_cf_%s" % size) + args = [self.add_ir(arg) for arg in expr.args] + ret = builder.call(fc_ptr, args) + ret = builder.trunc(ret, LLVMType.int(expr.size)) + self.update_cache(expr, ret) + return ret + + if op == "-": + zero = llvm_c.Constant.int(LLVMType.int(expr.size), + 0) + ret = builder.sub(zero, self.add_ir(expr.args[0])) + self.update_cache(expr, ret) + return ret + + if op == "segm": + fc_ptr = self.mod.get_function_named("segm2addr") + args_casted = [builder.zext(self.add_ir(arg), LLVMType.int(64)) + for arg in expr.args] + args = [self.local_vars["vmcpu"]] + args_casted + ret = builder.call(fc_ptr, args) + ret = builder.trunc(ret, LLVMType.int(expr.size)) + self.update_cache(expr, ret) + return ret + + if op in ["imod", "idiv"]: + fc_ptr = self.mod.get_function_named( + "%s%s" % (op, expr.args[0].size)) + args_casted = [self.add_ir(arg) for arg in expr.args] + args = [self.local_vars["vmcpu"]] + args_casted + ret = builder.call(fc_ptr, args) + self.update_cache(expr, ret) + return ret + + if len(expr.args) > 1: + + if op == "*": + callback = builder.mul + elif op == "+": + callback = builder.add + elif op == "&": + callback = builder.and_ + elif op == "^": + callback = builder.xor + elif op == "|": + callback = builder.or_ + elif op == ">>": + callback = builder.lshr + elif op == "<<": + callback = builder.shl + elif op == "a>>": + callback = builder.ashr + elif op == "udiv": + callback = builder.udiv + elif op == "umod": + callback = builder.urem + else: + raise NotImplementedError('Unknown op: %s' % op) + + last = self.add_ir(expr.args[0]) + + for i in range(1, len(expr.args)): + last = callback(last, + self.add_ir(expr.args[i])) + + self.update_cache(expr, last) + + return last + + raise NotImplementedError() + + if isinstance(expr, m2_expr.ExprMem): + + fc_name = "MEM_LOOKUP_%02d" % expr.size + fc_ptr = self.mod.get_function_named(fc_name) + addr_casted = builder.zext(self.add_ir(expr.arg), + LLVMType.int(64)) + + ret = builder.call(fc_ptr, [self.local_vars["vmmngr"], + addr_casted]) + + self.update_cache(expr, ret) + return ret + + if isinstance(expr, m2_expr.ExprCond): + # Compute cond + cond = self.add_ir(expr.cond) + zero_casted = llvm_c.Constant.int(LLVMType.int(expr.cond.size), + 0) + condition_bool = builder.icmp(llvm_c.ICMP_NE, cond, + zero_casted) + + # Alloc return var + alloca = self.CreateEntryBlockAlloca(LLVMType.int(expr.size)) + + # Create bbls + branch_id = self.new_branch_name() + then_block = self.append_basic_block('then%s' % branch_id) + else_block = self.append_basic_block('else%s' % branch_id) + merge_block = self.append_basic_block('ifcond%s' % branch_id) + + builder.cbranch(condition_bool, then_block, else_block) + + # Deactivate object caching + current_main_stream = self.main_stream + self.main_stream = False + + # Then Bloc + builder.position_at_end(then_block) + then_value = self.add_ir(expr.src1) + builder.store(then_value, alloca) + builder.branch(merge_block) + + # Else Bloc + builder.position_at_end(else_block) + else_value = self.add_ir(expr.src2) + builder.store(else_value, alloca) + builder.branch(merge_block) + + # Merge bloc + builder.position_at_end(merge_block) + ret = builder.load(alloca) + + # Reactivate object caching + self.main_stream = current_main_stream + + self.update_cache(expr, ret) + return ret + + if isinstance(expr, m2_expr.ExprSlice): + + src = self.add_ir(expr.arg) + + # Remove trailing bits + if expr.start != 0: + to_shr = llvm_c.Constant.int(LLVMType.int(expr.arg.size), + expr.start) + shred = builder.lshr(src, + to_shr) + else: + shred = src + + # Remove leading bits + to_and = llvm_c.Constant.int(LLVMType.int(expr.arg.size), + (1 << (expr.stop - expr.start)) - 1) + anded = builder.and_(shred, + to_and) + + # Cast into e.size + ret = builder.trunc(anded, + LLVMType.int(expr.size)) + + self.update_cache(expr, ret) + return ret + + if isinstance(expr, m2_expr.ExprCompose): + + args = [] + + # Build each part + for arg in expr.args: + src, start, stop = arg + + # src & (stop - start) + src = self.add_ir(src) + src_casted = builder.zext(src, + LLVMType.int(expr.size)) + to_and = llvm_c.Constant.int(LLVMType.int(expr.size), + (1 << (stop - start)) - 1) + anded = builder.and_(src_casted, + to_and) + + if (start != 0): + # result << start + to_shl = llvm_c.Constant.int(LLVMType.int(expr.size), + start) + shled = builder.shl(anded, to_shl) + final = shled + else: + # Optimisation + final = anded + + args.append(final) + + # result = part1 | part2 | ... + last = args[0] + for i in xrange(1, len(expr.args)): + last = builder.or_(last, args[i]) + + self.update_cache(expr, last) + return last + + raise Exception("UnkownExpression", expr.__class__.__name__) + + def set_ret(self, var): + "Add a ret of var to the last bbl" + self.builder.ret(var) + + def from_expr(self, expr): + "Build the function from an expression" + + # Build function signature + args = expr.get_r(True) + for a in args: + if not isinstance(a, m2_expr.ExprMem): + self.my_args.append((a, LLVMType.int(a.size), a.name)) + + self.ret_type = LLVMType.int(expr.size) + + # Initialise the function + self.init_fc() + + ret = self.add_ir(expr) + + self.set_ret(ret) + + def affect(self, src, dst, add_new=True): + "Affect from M2 src to M2 dst. If add_new, add a suffix '_new' to dest" + + # Source + src = self.add_ir(src) + + # Destination + builder = self.builder + self.add_ir(m2_expr.ExprId("vmcpu")) + + if isinstance(dst, m2_expr.ExprId): + dst_name = dst.name + "_new" if add_new else dst.name + + ptr_casted = self.get_ptr_by_expr( + m2_expr.ExprId(dst_name, dst.size)) + builder.store(src, ptr_casted) + + elif isinstance(dst, m2_expr.ExprMem): + self.add_ir(dst.arg) + + # Function call + fc_name = "MEM_WRITE_%02d" % dst.size + fc_ptr = self.mod.get_function_named(fc_name) + dst = self.add_ir(dst.arg) + dst_casted = builder.zext(dst, LLVMType.int(64)) + builder.call(fc_ptr, [self.local_vars["vmmngr"], + dst_casted, + src]) + + else: + raise Exception("UnknownAffectationType") + + def check_error(self, line, except_do_not_update_pc=False): + """Add a check for memory errors. + @line: Irbloc line corresponding to the current instruction + If except_do_not_update_pc, check only for exception which do not + require a pc update""" + + # VmMngr "get_exception_flag" return's size + size = 64 + t_size = LLVMType.int(size) + + # Current address + pc_to_return = line.offset + + # Get exception flag value + builder = self.builder + fc_ptr = self.mod.get_function_named("get_exception_flag") + exceptionflag = builder.call(fc_ptr, [self.local_vars["vmmngr"]]) + + if except_do_not_update_pc is True: + auto_mod_flag = m2_csts.EXCEPT_DO_NOT_UPDATE_PC + m2_flag = llvm_c.Constant.int(t_size, auto_mod_flag) + exceptionflag = builder.and_(exceptionflag, m2_flag) + + # Compute cond + zero_casted = llvm_c.Constant.int(t_size, 0) + condition_bool = builder.icmp(llvm_c.ICMP_NE, + exceptionflag, + zero_casted) + + # Create bbls + branch_id = self.new_branch_name() + then_block = self.append_basic_block('then%s' % branch_id) + merge_block = self.append_basic_block('ifcond%s' % branch_id) + + builder.cbranch(condition_bool, then_block, merge_block) + + # Deactivate object caching + current_main_stream = self.main_stream + self.main_stream = False + + # Then Bloc + builder.position_at_end(then_block) + builder.ret(llvm_c.Constant.int(self.ret_type, pc_to_return)) + + builder.position_at_end(merge_block) + + # Reactivate object caching + self.main_stream = current_main_stream + + def log_instruction(self, instruction, line): + "Print current instruction and registers if options are set" + + # Get builder + builder = self.builder + + if self.log_mn is True: + print instruction # TODO + + if self.log_regs is True: + # Call dump general purpose registers + fc_ptr = self.mod.get_function_named("dump_gpregs") + builder.call(fc_ptr, [self.local_vars["vmcpu"]]) + + def add_bloc(self, bloc, lines): + "Add a bloc of instruction in the current function" + + for instruction, line in zip(bloc, lines): + new_reg = set() + + # Check general errors only at the beggining of instruction + if line.offset not in self.offsets_jitted: + self.offsets_jitted.add(line.offset) + self.check_error(line) + + # Log mn and registers if options is set + self.log_instruction(instruction, line) + + + # Pass on empty instruction + if len(instruction) == 0: + continue + + for expression in instruction: + # Apply preinit transformation + for func in self.llvm_context.IR_transformation_functions: + expression = func(expression) + + # Treat current expression + self.affect(expression.src, expression.dst) + + # Save registers updated + new_reg.update(expression.dst.get_w()) + + # Check for errors (without updating PC) + self.check_error(line, except_do_not_update_pc=True) + + # new -> normal + reg_written = [] + for r in new_reg: + if isinstance(r, m2_expr.ExprId): + r_new = m2_expr.ExprId(r.name + "_new", r.size) + reg_written += [r, r_new] + self.affect(r_new, r, add_new=False) + + # Clear cache + self.clear_cache(reg_written) + self.main_stream = True + + def from_bloc(self, bloc, final_expr): + """Build the function from a bloc, with the dst equation. + Prototype : f(i8* vmcpu, i8* vmmngr)""" + + # Build function signature + self.my_args.append((m2_expr.ExprId("vmcpu"), + llvm_c.PointerType.pointer(LLVMType.int(8)), + "vmcpu")) + self.my_args.append((m2_expr.ExprId("vmmngr"), + llvm_c.PointerType.pointer(LLVMType.int(8)), + "vmmngr")) + self.ret_type = LLVMType.int(final_expr.size) + + # Initialise the function + self.init_fc() + + # Add content + self.add_bloc(bloc, []) + + # Finalise the function + self.set_ret(self.add_ir(final_expr)) + + raise NotImplementedError("Not tested") + + def canonize_label_name(self, label): + """Canonize @label names to a common form. + @label: str or asmlabel instance""" + if isinstance(label, str): + return label + elif isinstance(label, m2_asmbloc.asm_label): + return "label_%s" % label.name + else: + raise ValueError("label must either be str or asmlabel") + + def get_basic_bloc_by_label(self, label): + "Return the bbl corresponding to label, None otherwise" + return self.name2bbl.get(self.canonize_label_name(label), None) + + def gen_ret_or_branch(self, dest): + """Manage the dest ExprId. If label, branch on it if it is known. + Otherwise, return the ExprId or the offset value""" + + builder = self.builder + + if isinstance(dest, m2_expr.ExprId): + dest_name = dest.name + elif isinstance(dest, m2_expr.ExprSlice) and \ + isinstance(dest.arg, m2_expr.ExprId): + # Manage ExprId mask case + dest_name = dest.arg.name + else: + raise ValueError() + + if not isinstance(dest_name, str): + label = dest_name + target_bbl = self.get_basic_bloc_by_label(label) + if target_bbl is None: + builder.ret(self.add_ir(dest)) + else: + builder.branch(target_bbl) + else: + builder.ret(self.add_ir(dest)) + + def add_irbloc(self, irbloc): + "Add the content of irbloc at the corresponding labeled block" + builder = self.builder + + bloc = irbloc.irs + dest = irbloc.dst + label = irbloc.label + lines = irbloc.lines + + # Get labeled basic bloc + label_block = self.get_basic_bloc_by_label(label) + builder.position_at_end(label_block) + + # Erase cache + self.expr_cache = {} + + # Add the content of the bloc with corresponding lines + self.add_bloc(bloc, lines) + + # Erase cache + self.expr_cache = {} + + # Manage ret + for func in self.llvm_context.IR_transformation_functions: + dest = func(dest) + + if isinstance(dest, m2_expr.ExprCond): + # Compute cond + cond = self.add_ir(dest.cond) + zero_casted = llvm_c.Constant.int(LLVMType.int(dest.cond.size), + 0) + condition_bool = builder.icmp(llvm_c.ICMP_NE, cond, + zero_casted) + + # Create bbls + branch_id = self.new_branch_name() + then_block = self.append_basic_block('then%s' % branch_id) + else_block = self.append_basic_block('else%s' % branch_id) + + builder.cbranch(condition_bool, then_block, else_block) + + # Then Bloc + builder.position_at_end(then_block) + self.gen_ret_or_branch(dest.src1) + + # Else Bloc + builder.position_at_end(else_block) + self.gen_ret_or_branch(dest.src2) + + elif isinstance(dest, m2_expr.ExprId): + self.gen_ret_or_branch(dest) + + elif isinstance(dest, m2_expr.ExprSlice): + self.gen_ret_or_branch(dest) + + else: + raise Exception("Bloc dst has to be an ExprId or an ExprCond") + + def from_blocs(self, blocs): + """Build the function from a list of bloc (irbloc instances). + Prototype : f(i8* vmcpu, i8* vmmngr)""" + + # Build function signature + self.my_args.append((m2_expr.ExprId("vmcpu"), + llvm_c.PointerType.pointer(LLVMType.int(8)), + "vmcpu")) + self.my_args.append((m2_expr.ExprId("vmmngr"), + llvm_c.PointerType.pointer(LLVMType.int(8)), + "vmmngr")) + ret_size = blocs[0].dst.size + + self.ret_type = LLVMType.int(ret_size) + + # Initialise the function + self.init_fc() + + # Create basic blocks (for label branchs) + entry_bbl, builder = self.entry_bbl, self.builder + + for irbloc in blocs: + name = self.canonize_label_name(irbloc.label) + self.append_basic_block(name) + + # Add content + builder.position_at_end(entry_bbl) + + for irbloc in blocs: + self.add_irbloc(irbloc) + + # Branch entry_bbl on first label + builder.position_at_end(entry_bbl) + first_label_bbl = self.get_basic_bloc_by_label(blocs[0].label) + builder.branch(first_label_bbl) + + def __str__(self): + "Print the llvm IR corresponding to the current module" + + return str(self.fc) + + def verify(self): + "Verify the module syntax" + + return self.mod.verify() + + def get_assembly(self): + "Return native assembly corresponding to the current module" + + return self.mod.to_native_assembly() + + def optimise(self): + "Optimise the function in place" + while self.llvm_context.pass_manager.run(self.fc): + continue + + def __call__(self, *args): + "Eval the function with arguments args" + + e = self.llvm_context.get_execengine() + + genargs = [LLVMType.generic(a) for a in args] + ret = e.run_function(self.fc, genargs) + + return ret.as_int() + + def get_function_pointer(self): + "Return a pointer on the Jitted function" + e = self.llvm_context.get_execengine() + + return e.get_pointer_to_function(self.fc) + +# TODO: +# - Add more expressions diff --git a/miasm2/jitter/os_dep/__init__.py b/miasm2/jitter/os_dep/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/miasm2/jitter/os_dep/__init__.py diff --git a/miasm2/jitter/os_dep/linux_stdlib.py b/miasm2/jitter/os_dep/linux_stdlib.py new file mode 100644 index 00000000..0a1e0bfb --- /dev/null +++ b/miasm2/jitter/os_dep/linux_stdlib.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + +from sys import stdout +from string import printable + + +def xxx_isprint(jitter): + ''' + #include <ctype.h> + int isprint(int c); + + checks for any printable character including space. + ''' + c, = jitter.func_args_fastcall(1) + ret = chr(c & 0xFF) in printable and 1 or 0 + return jitter.func_ret_fastcall(ret) + + +def xxx_memcpy(jitter): + ''' + #include <string.h> + void *memcpy(void *dest, const void *src, size_t n); + + copies n bytes from memory area src to memory area dest. + ''' + dest, src, n, = jitter.func_args_fastcall(3) + jitter.vm.vm_set_mem(dest, jitter.vm.vm_get_mem(src, n)) + return jitter.func_ret_fastcall(dest) + + +def xxx_puts(jitter): + ''' + #include <stdio.h> + int puts(const char *s); + + writes the string s and a trailing newline to stdout. + ''' + s, = jitter.func_args_fastcall(1) + while True: + c = jitter.vm.vm_get_mem(s, 1) + s += 1 + if c == '\x00': + break + stdout.write(c) + stdout.write('\n') + return jitter.func_ret_fastcall(1) + + +def xxx_snprintf(jitter): + ''' + #include <stdio.h> + int snprintf(char *str, size_t size, const char *format, ...); + + writes to string str according to format format and at most size bytes. + ''' + str, size, format, = jitter.func_args_fastcall(3) + curarg, output = 4, '' + while True: + c = jitter.vm.vm_get_mem(format, 1) + format += 1 + if c == '\x00': + break + if c == '%': + token = '%' + while True: + c = jitter.vm.vm_get_mem(format, 1) + format += 1 + token += c + if c in '%cdfsux': + break + c = token % jitter.func_args_fastcall(curarg)[-1] + curarg += 1 + output += c + output = output[:size - 1] + ret = len(output) + jitter.vm.vm_set_mem(str, output + '\x00') + return jitter.func_ret_fastcall(ret) diff --git a/miasm2/jitter/os_dep/win_api_x86_32.py b/miasm2/jitter/os_dep/win_api_x86_32.py new file mode 100644 index 00000000..b6813efc --- /dev/null +++ b/miasm2/jitter/os_dep/win_api_x86_32.py @@ -0,0 +1,3069 @@ +# +# 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. +# +import struct +try: + from Crypto.Hash import MD5, SHA +except ImportError: + print "cannot find crypto, skipping" +import inspect +from zlib import crc32 +import os +import stat +import time +from miasm2.jitter.csts import * +from miasm2.core.utils import * +import string + + +MAX_PATH = 260 + + +def get_next_alloc_addr(size): + global alloc_ad + ret = winobjs.alloc_ad + winobjs.alloc_ad = (winobjs.alloc_ad + size + winobjs.alloc_align - 1) + winobjs.alloc_ad &= (0xffffffff ^ (winobjs.alloc_align - 1)) + return ret + + +def alloc_mem(myjit, msize): + alloc_addr = get_next_alloc_addr(msize) + myjit.vm.vm_add_memory_page( + alloc_addr, PAGE_READ | PAGE_WRITE, "\x00" * msize) + return alloc_addr + +""" +typedef struct tagPROCESSENTRY32 { + DWORD dwSize; + DWORD cntUsage; + DWORD th32ProcessID; + ULONG_PTR th32DefaultHeapID; + DWORD th32ModuleID; + DWORD cntThreads; + DWORD th32ParentProcessID; + LONG pcPriClassBase; + DWORD dwFlags; + TCHAR szExeFile[MAX_PATH]; +} PROCESSENTRY32, *PPROCESSENTRY32; +""" + + +access_dict = {0x0: 0, + 0x1: 0, + 0x2: PAGE_READ, + 0x4: PAGE_READ | PAGE_WRITE, + 0x10: PAGE_EXEC, + 0x20: PAGE_EXEC | PAGE_READ, + 0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE, + 0x80: PAGE_EXEC | PAGE_READ | PAGE_WRITE, + # 0x80: PAGE_EXECUTE_WRITECOPY + 0x100: 0 + } + +access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()]) + + +class whandle(): + + def __init__(self, name, info): + self.name = name + self.info = info + + def __repr__(self): + return '<%r %r %r>' % (self.__class__.__name__, self.name, self.info) + + +class handle_generator(): + + def __init__(self): + self.offset = 600 + self.all_handles = {} + + def add(self, name, info=None): + self.offset += 1 + h = whandle(name, info) + self.all_handles[self.offset] = h + + print repr(self) + return self.offset + + def __repr__(self): + out = '<%r\n' % self.__class__.__name__ + ks = self.all_handles.keys() + ks.sort() + + for k in ks: + out += " %r %r\n" % (k, self.all_handles[k]) + out += '>' + return out + + def __contains__(self, e): + return e in self.all_handles + + def __getitem__(self, item): + return self.all_handles.__getitem__(item) + + def __delitem__(self, item): + self.all_handles.__delitem__(item) + + +class c_winobjs: + + def __init__(self): + self.alloc_ad = 0x20000000 + self.alloc_align = 0x1000 + self.handle_toolhelpsnapshot = 0xaaaa00 + self.toolhelpsnapshot_info = {} + self.handle_curprocess = 0xaaaa01 + self.dbg_present = 0 + self.tickcount = 0 + self.dw_pid_dummy1 = 0x111 + self.dw_pid_explorer = 0x222 + self.dw_pid_dummy2 = 0x333 + self.dw_pid_cur = 0x444 + self.module_fname_nux = None + self.module_name = "test.exe" + self.module_path = "c:\\mydir\\" + self.module_name + self.hcurmodule = None + self.module_filesize = None + self.getversion = 0x0A280105 + self.getforegroundwindow = 0x333333 + self.cryptcontext_hwnd = 0x44400 + self.cryptcontext_bnum = 0x44000 + self.cryptcontext_num = 0 + self.cryptcontext = {} + self.phhash_crypt_md5 = 0x55555 + self.files_hwnd = {} + self.windowlong_dw = 0x77700 + self.module_cur_hwnd = 0x88800 + self.module_file_nul = 0x999000 + self.runtime_dll = None + self.current_pe = None + self.tls_index = 0xf + self.tls_values = {} + self.handle_pool = handle_generator() + self.handle_mapped = {} + self.hkey_handles = {0x80000001: "hkey_current_user"} + + self.nt_mdl = {} + self.nt_mdl_ad = None + self.nt_mdl_cur = 0 + self.win_event_num = 0x13370 + self.cryptdll_md5_h = {} + + self.lastwin32error = 0 + self.mutex = {} + self.env_variables = {} + self.events_pool = {} + self.find_data = None +winobjs = c_winobjs() + + +process_list = [ + [ + 0x40, # DWORD dwSize; + 0, # DWORD cntUsage; + winobjs.dw_pid_dummy1, # DWORD th32ProcessID; + 0x11111111, # ULONG_PTR th32DefaultHeapID; + 0x11111112, # DWORD th32ModuleID; + 1, # DWORD cntThreads; + winobjs.dw_pid_explorer, # DWORD th32ParentProcessID; + 0xbeef, # LONG pcPriClassBase; + 0x0, # DWORD dwFlags; + "dummy1.exe" # TCHAR szExeFile[MAX_PATH]; + ], + [ + 0x40, # DWORD dwSize; + 0, # DWORD cntUsage; + winobjs.dw_pid_explorer, # DWORD th32ProcessID; + 0x11111111, # ULONG_PTR th32DefaultHeapID; + 0x11111112, # DWORD th32ModuleID; + 1, # DWORD cntThreads; + 4, # DWORD th32ParentProcessID; + 0xbeef, # LONG pcPriClassBase; + 0x0, # DWORD dwFlags; + "explorer.exe" # TCHAR szExeFile[MAX_PATH]; + ], + + [ + 0x40, # DWORD dwSize; + 0, # DWORD cntUsage; + winobjs.dw_pid_dummy2, # DWORD th32ProcessID; + 0x11111111, # ULONG_PTR th32DefaultHeapID; + 0x11111112, # DWORD th32ModuleID; + 1, # DWORD cntThreads; + winobjs.dw_pid_explorer, # DWORD th32ParentProcessID; + 0xbeef, # LONG pcPriClassBase; + 0x0, # DWORD dwFlags; + "dummy2.exe" # TCHAR szExeFile[MAX_PATH]; + ], + + [ + 0x40, # DWORD dwSize; + 0, # DWORD cntUsage; + winobjs.dw_pid_cur, # DWORD th32ProcessID; + 0x11111111, # ULONG_PTR th32DefaultHeapID; + 0x11111112, # DWORD th32ModuleID; + 1, # DWORD cntThreads; + winobjs.dw_pid_explorer, # DWORD th32ParentProcessID; + 0xbeef, # LONG pcPriClassBase; + 0x0, # DWORD dwFlags; + winobjs.module_name # TCHAR szExeFile[MAX_PATH]; + ], + + +] + + +def whoami(): + return inspect.stack()[1][3] + + +class hobj: + pass + + +class mdl: + + def __init__(self, ad, l): + self.ad = ad + self.l = l + + def __str__(self): + return struct.pack('LL', self.ad, self.l) + + +def get_str_ansi(myjit, ad_str, max_char=None): + l = 0 + tmp = ad_str + while ((max_char is None or l < max_char) and + myjit.vm.vm_get_mem(tmp, 1) != "\x00"): + tmp += 1 + l += 1 + return myjit.vm.vm_get_mem(ad_str, l) + + +def get_str_unic(myjit, ad_str, max_char=None): + l = 0 + tmp = ad_str + while ((max_char is None or l < max_char) and + myjit.vm.vm_get_mem(tmp, 2) != "\x00\x00"): + tmp += 2 + l += 2 + s = myjit.vm.vm_get_mem(ad_str, l) + s = s[::2] # TODO: real unicode decoding + return s + + +def set_str_ansi(s): + return s + "\x00" + + +def set_str_unic(s): + return "\x00".join(list(s)) + '\x00' * 3 + + +def kernel32_HeapAlloc(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + heap, flags, size = args + + alloc_addr = alloc_mem(myjit, size) + + myjit.func_ret_stdcall(ret_ad, alloc_addr) + + +def kernel32_HeapFree(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + heap, flags, pmem = args + + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_GlobalAlloc(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + uflags, msize = args + alloc_addr = get_next_alloc_addr(msize) + myjit.func_ret_stdcall(ret_ad, alloc_addr) + + +def kernel32_LocalFree(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + lpvoid, = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_LocalAlloc(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + uflags, msize = args + alloc_addr = alloc_mem(myjit, msize) + myjit.func_ret_stdcall(ret_ad, alloc_addr) + + +def kernel32_GlobalFree(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + ad, = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_IsDebuggerPresent(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, winobjs.dbg_present) + + +def kernel32_CreateToolhelp32Snapshot(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + dwflags, th32processid = args + myjit.func_ret_stdcall(ret_ad, winobjs.handle_toolhelpsnapshot) + + +def kernel32_GetCurrentProcess(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, winobjs.handle_curprocess) + + +def kernel32_GetCurrentProcessId(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, winobjs.dw_pid_cur) + + +def kernel32_Process32First(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + s_handle, ad_pentry = args + + pentry = struct.pack( + 'IIIIIIIII', *process_list[0][:-1]) + process_list[0][-1] + myjit.vm.vm_set_mem(ad_pentry, pentry) + winobjs.toolhelpsnapshot_info[s_handle] = 0 + + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_Process32Next(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + s_handle, ad_pentry = args + + winobjs.toolhelpsnapshot_info[s_handle] += 1 + if winobjs.toolhelpsnapshot_info[s_handle] >= len(process_list): + ret = 0 + else: + ret = 1 + n = winobjs.toolhelpsnapshot_info[s_handle] + print whoami(), hex(ret_ad), '(', hex(s_handle), hex(ad_pentry), ')' + pentry = struct.pack( + 'IIIIIIIII', *process_list[n][:-1]) + process_list[n][-1] + myjit.vm.vm_set_mem(ad_pentry, pentry) + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_GetTickCount(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + winobjs.tickcount += 1 + myjit.func_ret_stdcall(ret_ad, winobjs.tickcount) + + +def kernel32_GetVersion(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, winobjs.getversion) + + +def my_GetVersionEx(myjit, funcname, set_str): + ret_ad, args = myjit.func_args_stdcall(1) + ptr_struct, = args + + s = struct.pack("IIIII", + 0x114, # struct size + 0x5, # maj vers + 0x2, # min vers + 0xa28, # build nbr + 0x2, # platform id + ) + t = set_str("Service pack 4") + t = s + (t + '\x00' * 128 * 2)[:128 * 2] + t += struct.pack('HHHBB', 3, 0, 0x100, 1, 0) + s = t + myjit.vm.vm_set_mem(ptr_struct, s) + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_GetVersionExA(myjit): + my_GetVersionEx(myjit, whoami(), set_str_ansi) + + +def kernel32_GetVersionExW(myjit): + my_GetVersionEx(myjit, whoami(), set_str_unic) + + +def kernel32_GetPriorityClass(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + hwnd, = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_SetPriorityClass(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + hwnd, dwpclass = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_CloseHandle(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + hwnd, = args + myjit.func_ret_stdcall(ret_ad, 1) + + +def user32_GetForegroundWindow(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, winobjs.getforegroundwindow) + + +def user32_FindWindowA(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + pclassname, pwindowname = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def user32_GetTopWindow(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + hwnd, = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def user32_BlockInput(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + b, = args + myjit.func_ret_stdcall(ret_ad, 1) + + +def advapi32_CryptAcquireContext(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(5) + phprov, pszcontainer, pszprovider, dwprovtype, dwflags = args + + if pszprovider: + prov = get_str(myjit, pszprovider) + else: + prov = "NONE" + print 'prov:', prov + myjit.vm.vm_set_mem(phprov, pck32(winobjs.cryptcontext_hwnd)) + + myjit.func_ret_stdcall(ret_ad, 1) + + +def advapi32_CryptAcquireContextA(myjit): + advapi32_CryptAcquireContext(myjit, whoami(), get_str_ansi) + + +def advapi32_CryptAcquireContextW(myjit): + advapi32_CryptAcquireContext(myjit, whoami(), get_str_unic) + + +def advapi32_CryptCreateHash(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + hprov, algid, hkey, dwflags, phhash = args + + winobjs.cryptcontext_num += 1 + + if algid == 0x00008003: + print 'algo is MD5' + myjit.vm.vm_set_mem( + phhash, pck32(winobjs.cryptcontext_bnum + winobjs.cryptcontext_num)) + winobjs.cryptcontext[ + winobjs.cryptcontext_bnum + winobjs.cryptcontext_num] = hobj() + winobjs.cryptcontext[ + winobjs.cryptcontext_bnum + winobjs.cryptcontext_num].h = MD5.new() + elif algid == 0x00008004: + print 'algo is SHA1' + myjit.vm.vm_set_mem( + phhash, pck32(winobjs.cryptcontext_bnum + winobjs.cryptcontext_num)) + winobjs.cryptcontext[ + winobjs.cryptcontext_bnum + winobjs.cryptcontext_num] = hobj() + winobjs.cryptcontext[ + winobjs.cryptcontext_bnum + winobjs.cryptcontext_num].h = SHA.new() + else: + raise ValueError('un impl algo1') + myjit.func_ret_stdcall(ret_ad, 1) + + +def advapi32_CryptHashData(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + hhash, pbdata, dwdatalen, dwflags = args + + if not hhash in winobjs.cryptcontext: + raise ValueError("unknown crypt context") + + data = myjit.vm.vm_get_mem(pbdata, dwdatalen) + print 'will hash %X' % dwdatalen + print repr(data[:10]) + "..." + winobjs.cryptcontext[hhash].h.update(data) + myjit.func_ret_stdcall(ret_ad, 1) + + +def advapi32_CryptGetHashParam(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + hhash, param, pbdata, dwdatalen, dwflags = args + + if not hhash in winobjs.cryptcontext: + raise ValueError("unknown crypt context") + + if param == 2: + # XXX todo: save h state? + h = winobjs.cryptcontext[hhash].h.digest() + else: + raise ValueError('not impl', param) + myjit.vm.vm_set_mem(pbdata, h) + myjit.vm.vm_set_mem(dwdatalen, pck32(len(h))) + + myjit.func_ret_stdcall(ret_ad, 1) + + +def advapi32_CryptReleaseContext(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + hhash, flags = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def advapi32_CryptDeriveKey(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + hprov, algid, hbasedata, dwflags, phkey = args + + if algid == 0x6801: + print 'using DES' + else: + raise ValueError('un impl algo2') + h = winobjs.cryptcontext[hbasedata].h.digest() + print 'hash', repr(h) + winobjs.cryptcontext[hbasedata].h_result = h + myjit.vm.vm_set_mem(phkey, pck32(hbasedata)) + myjit.func_ret_stdcall(ret_ad, 1) + + +def advapi32_CryptDestroyHash(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + hhash, = args + myjit.func_ret_stdcall(ret_ad, 1) + + +def advapi32_CryptDecrypt(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + hkey, hhash, final, dwflags, pbdata, pdwdatalen = args + raise NotImplementedError() + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_CreateFile(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(7) + (lpfilename, access, dwsharedmode, lpsecurityattr, + dwcreationdisposition, dwflagsandattr, htemplatefile) = args + + fname = get_str(myjit, lpfilename) + print 'fname', fname + fname_o = fname[:] + ret = 0xffffffff + + # test if file is original binary + f = fname_o + """ + if "\\" in fname_o: + f = fname_o[fname_o.rfind('\\')+1:] + else: + f = fname_o + """ + print f.lower(), winobjs.module_path.lower() + is_original_file = f.lower() == winobjs.module_path.lower() + + if fname.upper() in [r"\\.\SICE", r"\\.\NTICE", r"\\.\SIWVID"]: + pass + elif fname.upper() in ['NUL']: + ret = winobjs.module_cur_hwnd + else: + # nuxify path + fname = fname.replace('\\', "/").lower() + # go in sandbox files + f = os.path.join('file_sb', fname) + if access & 0x80000000: + # read + if dwcreationdisposition == 2: + # create_always + if os.access(f, os.R_OK): + # but file exist + pass + else: + raise NotImplementedError("Untested case") # to test + h = open(f, 'rb+') + elif dwcreationdisposition == 3: + # open_existing + if os.access(f, os.R_OK): + s = os.stat(f) + if stat.S_ISDIR(s.st_mode): + ret = winobjs.handle_pool.add(f, 0x1337) + else: + h = open(f, 'rb+') + ret = winobjs.handle_pool.add(f, h) + else: + print "FILE %r DOES NOT EXIST!" % fname + pass + elif dwcreationdisposition == 1: + # create new + if os.access(f, os.R_OK): + # file exist + # ret = 80 + winobjs.lastwin32error = 80 + pass + else: + open(f, 'w') + h = open(f, 'rb+') + ret = winobjs.handle_pool.add(f, h) + else: + raise NotImplementedError("Untested case") + elif access & 0x40000000: + # write + if dwcreationdisposition == 3: + # open existing + if is_original_file: + # cannot open self in write mode! + pass + elif os.access(f, os.R_OK): + s = os.stat(f) + if stat.S_ISDIR(s.st_mode): + # open dir + ret = winobjs.handle_pool.add(f, 0x1337) + else: + h = open(f, 'rb+') + ret = winobjs.handle_pool.add(f, h) + else: + raise NotImplementedError("Untested case") # to test + elif dwcreationdisposition == 5: + # truncate_existing + if is_original_file: + pass + else: + raise NotImplementedError("Untested case") # to test + else: + # raise NotImplementedError("Untested case") # to test + h = open(f, 'w') + ret = winobjs.handle_pool.add(f, h) + else: + raise NotImplementedError("Untested case") + + # h = open(f, 'rb+') + # ret = winobjs.handle_pool.add(f, h) + print 'ret', hex(ret) + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_CreateFileA(myjit): + kernel32_CreateFile(myjit, whoami(), get_str_ansi) + + +def kernel32_CreateFileW(myjit): + kernel32_CreateFile(myjit, whoami(), lambda x, y: get_str_unic(myjit, y)) + + +def kernel32_ReadFile(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + (hwnd, lpbuffer, nnumberofbytestoread, + lpnumberofbytesread, lpoverlapped) = args + + if hwnd == winobjs.module_cur_hwnd: + pass + elif hwnd in winobjs.handle_pool: + pass + else: + raise ValueError('unknown hwnd!') + + eax = 0xffffffff + data = None + if hwnd in winobjs.files_hwnd: + data = winobjs.files_hwnd[ + winobjs.module_cur_hwnd].read(nnumberofbytestoread) + elif hwnd in winobjs.handle_pool: + wh = winobjs.handle_pool[hwnd] + data = wh.info.read(nnumberofbytestoread) + else: + raise ValueError('unknown filename') + + if data is not None: + if (lpnumberofbytesread): + myjit.vm.vm_set_mem(lpnumberofbytesread, pck32(len(data))) + myjit.vm.vm_set_mem(lpbuffer, data) + + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_GetFileSize(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + hwnd, lpfilesizehight = args + + if hwnd == winobjs.module_cur_hwnd: + ret = len(open(winobjs.module_fname_nux).read()) + elif hwnd in winobjs.handle_pool: + wh = winobjs.handle_pool[hwnd] + print wh + ret = len(open(wh.name).read()) + else: + raise ValueError('unknown hwnd!') + + if lpfilesizehight != 0: + myjit.vm.vm_set_mem(lpfilesizehight, pck32(ret)) + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_GetFileSizeEx(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + hwnd, lpfilesizehight = args + + if hwnd == winobjs.module_cur_hwnd: + l = len(open(winobjs.module_fname_nux).read()) + elif hwnd in winobjs.handle_pool: + wh = winobjs.handle_pool[hwnd] + print wh + l = len(open(wh.name).read()) + else: + raise ValueError('unknown hwnd!') + + if lpfilesizehight == 0: + raise NotImplementedError("Untested case") + myjit.vm.vm_set_mem(lpfilesizehight, pck32( + l & 0xffffffff) + pck32((l >> 32) & 0xffffffff)) + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_FlushInstructionCache(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + hprocess, lpbasead, dwsize = args + myjit.func_ret_stdcall(ret_ad, 0x1337) + + +def kernel32_VirtualProtect(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + lpvoid, dwsize, flnewprotect, lpfloldprotect = args + + # XXX mask hpart + flnewprotect &= 0xFFF + + if not flnewprotect in access_dict: + raise ValueError('unknown access dw!') + myjit.vm.vm_set_mem_access(lpvoid, access_dict[flnewprotect]) + + # XXX todo real old protect + if lpfloldprotect: + myjit.vm.vm_set_mem(lpfloldprotect, pck32(0x40)) + + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_VirtualAlloc(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + lpvoid, dwsize, alloc_type, flprotect = args + + access_dict = {0x0: 0, + 0x1: 0, + 0x2: PAGE_READ, + 0x4: PAGE_READ | PAGE_WRITE, + 0x10: PAGE_EXEC, + 0x20: PAGE_EXEC | PAGE_READ, + 0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE, + 0x100: 0 + } + + access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()]) + + if not flprotect in access_dict: + raise ValueError('unknown access dw!') + + if lpvoid == 0: + alloc_addr = get_next_alloc_addr(dwsize) + myjit.vm.vm_add_memory_page( + alloc_addr, access_dict[flprotect], "\x00" * dwsize) + else: + all_mem = myjit.vm.vm_get_all_memory() + if lpvoid in all_mem: + alloc_addr = lpvoid + myjit.vm.vm_set_mem_access(lpvoid, access_dict[flprotect]) + else: + alloc_addr = get_next_alloc_addr(dwsize) + # alloc_addr = lpvoid + myjit.vm.vm_add_memory_page( + alloc_addr, access_dict[flprotect], "\x00" * dwsize) + + print 'Memory addr:', hex(alloc_addr) + myjit.func_ret_stdcall(ret_ad, alloc_addr) + + +def kernel32_VirtualFree(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + lpvoid, dwsize, alloc_type = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def user32_GetWindowLongA(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + hwnd, nindex = args + myjit.func_ret_stdcall(ret_ad, winobjs.windowlong_dw) + + +def user32_SetWindowLongA(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + hwnd, nindex, newlong = args + myjit.func_ret_stdcall(ret_ad, winobjs.windowlong_dw) + + +def kernel32_GetModuleFileName(myjit, funcname, set_str): + ret_ad, args = myjit.func_args_stdcall(3) + hmodule, lpfilename, nsize = args + + if hmodule in [0, winobjs.hcurmodule]: + p = winobjs.module_path[:] + elif (winobjs.runtime_dll and + hmodule in winobjs.runtime_dll.name2off.values()): + name_inv = dict([(x[1], x[0]) + for x in winobjs.runtime_dll.name2off.items()]) + p = name_inv[hmodule] + else: + print ValueError('unknown module h', hex(hmodule)) + p = None + + if p is None: + l = 0 + elif nsize < len(p): + p = p[:nsize] + l = len(p) + else: + l = len(p) + + print repr(p) + if p: + myjit.vm.vm_set_mem(lpfilename, set_str(p)) + + myjit.func_ret_stdcall(ret_ad, l) + + +def kernel32_GetModuleFileNameA(myjit): + kernel32_GetModuleFileName(myjit, whoami(), set_str_ansi) + + +def kernel32_GetModuleFileNameW(myjit): + kernel32_GetModuleFileName(myjit, whoami(), set_str_unic) + + +def kernel32_CreateMutex(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(3) + print funcname + mutexattr, initowner, lpname = args + + if lpname: + name = get_str(myjit, lpname) + print repr(name) + else: + name = None + if initowner: + if name in winobjs.mutex: + raise NotImplementedError("Untested case") + ret = 0 + else: + winobjs.mutex[name] = id(name) + ret = winobjs.mutex[name] + else: + if name in winobjs.mutex: + raise NotImplementedError("Untested case") + ret = 0 + else: + winobjs.mutex[name] = id(name) + ret = winobjs.mutex[name] + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_CreateMutexA(myjit): + kernel32_CreateMutex(myjit, whoami(), get_str_ansi) + + +def kernel32_CreateMutexW(myjit): + kernel32_CreateMutex(myjit, whoami(), get_str_unic) + + +def shell32_SHGetSpecialFolderLocation(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + hwndowner, nfolder, ppidl = args + myjit.vm.vm_set_mem(ppidl, pck32(nfolder)) + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_SHGetPathFromIDList(myjit, funcname, set_str): + ret_ad, args = myjit.func_args_stdcall(2) + pidl, ppath = args + + if pidl == 7: # CSIDL_STARTUP: + s = "c:\\doc\\user\\startmenu\\programs\\startup" + s = set_str(s) + else: + raise ValueError('pidl not implemented', pidl) + myjit.vm.vm_set_mem(ppath, s) + myjit.func_ret_stdcall(ret_ad, 1) + + +def shell32_SHGetPathFromIDListW(myjit): + kernel32_SHGetPathFromIDList(myjit, whoami(), set_str_unic) + + +def shell32_SHGetPathFromIDListA(myjit): + kernel32_SHGetPathFromIDList(myjit, whoami(), set_str_ansi) + + +def kernel32_GetLastError(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, winobjs.lastwin32error) + + +def kernel32_SetLastError(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + e, = args + # lasterr addr + # ad = seh_helper.FS_0_AD + 0x34 + # myjit.vm.vm_set_mem(ad, pck32(e)) + winobjs.lastwin32error = e + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_RestoreLastError(myjit): + kernel32_SetLastError(myjit) + + +def kernel32_LoadLibraryA(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + dllname, = args + + libname = get_str_ansi(myjit, dllname, 0x100) + print repr(libname) + + ret = winobjs.runtime_dll.lib_get_add_base(libname) + print "ret", hex(ret) + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_LoadLibraryExA(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + dllname, hfile, flags = args + + if hfile != 0: + raise NotImplementedError("Untested case") + libname = get_str_ansi(myjit, dllname, 0x100) + print repr(libname) + + ret = winobjs.runtime_dll.lib_get_add_base(libname) + print "ret", hex(ret) + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_GetProcAddress(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + libbase, fname = args + fname = fname & 0xFFFFFFFF + if fname < 0x10000: + fname = fname + else: + fname = get_str_ansi(myjit, fname, 0x100) + if not fname: + fname = None + print repr(fname) + if fname is not None: + ad = winobjs.runtime_dll.lib_get_add_func(libbase, fname) + else: + ad = 0 + ad = winobjs.runtime_dll.lib_get_add_func(libbase, fname) + + myjit.func_ret_stdcall(ret_ad, ad) + + +def kernel32_LoadLibraryW(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + dllname, = args + + libname = get_str_unic(myjit, dllname, 0x100) + print repr(libname) + + ret = winobjs.runtime_dll.lib_get_add_base(libname) + print "ret", hex(ret) + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_GetModuleHandle(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(1) + dllname, = args + + if dllname: + libname = get_str(myjit, dllname) + print repr(libname) + if libname: + ret = winobjs.runtime_dll.lib_get_add_base(libname) + else: + print 'unknown module!' + ret = 0 + else: + ret = winobjs.current_pe.NThdr.ImageBase + print "default img base", hex(ret) + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_GetModuleHandleA(myjit): + kernel32_GetModuleHandle(myjit, whoami(), get_str_ansi) + + +def kernel32_GetModuleHandleW(myjit): + kernel32_GetModuleHandle(myjit, whoami(), get_str_unic) + + +def kernel32_VirtualLock(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + lpaddress, dwsize = args + myjit.func_ret_stdcall(ret_ad, 1) + + +class systeminfo: + oemId = 0 + dwPageSize = 0x1000 + lpMinimumApplicationAddress = 0x10000 + lpMaximumApplicationAddress = 0x7ffeffff + dwActiveProcessorMask = 0x1 + numberOfProcessors = 0x1 + ProcessorsType = 586 + dwAllocationgranularity = 0x10000 + wProcessorLevel = 0x6 + ProcessorRevision = 0xf0b + + def pack(self): + return struct.pack('IIIIIIIIHH', + self.oemId, + self.dwPageSize, + self.lpMinimumApplicationAddress, + self.lpMaximumApplicationAddress, + self.dwActiveProcessorMask, + self.numberOfProcessors, + self.ProcessorsType, + self.dwAllocationgranularity, + self.wProcessorLevel, + self.ProcessorRevision) + + +def kernel32_GetSystemInfo(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + sys_ptr, = args + sysinfo = systeminfo() + myjit.vm.vm_set_mem(sys_ptr, sysinfo.pack()) + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_IsWow64Process(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + h, bool_ptr = args + + myjit.vm.vm_set_mem(bool_ptr, pck32(0)) + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_GetCommandLineA(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + s = winobjs.module_path + '\x00' + s = '"%s"' % s + alloc_addr = alloc_mem(myjit, 0x1000) + myjit.vm.vm_set_mem(alloc_addr, s) + myjit.func_ret_stdcall(ret_ad, alloc_addr) + + +def kernel32_GetCommandLineW(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + s = winobjs.module_path + '\x00' + s = set_str_unic('"%s"' % s) + alloc_addr = alloc_mem(myjit, 0x1000) + myjit.vm.vm_set_mem(alloc_addr, s) + myjit.func_ret_stdcall(ret_ad, alloc_addr) + + +def shell32_CommandLineToArgvW(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + pcmd, pnumargs = args + cmd = get_str_unic(myjit, pcmd) + print repr(cmd) + tks = cmd.split(' ') + addr = alloc_mem(myjit, len(cmd) * 2 + 4 * len(tks)) + addr_ret = alloc_mem(myjit, 4 * (len(tks) + 1)) + o = 0 + for i, t in enumerate(tks): + x = set_str_unic(t) + "\x00\x00" + myjit.vm.vm_set_mem(addr_ret + 4 * i, pck32(addr + o)) + myjit.vm.vm_set_mem(addr + o, x) + o += len(x) + 2 + + myjit.vm.vm_set_mem(addr_ret + 4 * i, pck32(0)) + myjit.vm.vm_set_mem(pnumargs, pck32(len(tks))) + myjit.func_ret_stdcall(ret_ad, addr_ret) + + +def cryptdll_MD5Init(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + ad_ctx, = args + index = len(winobjs.cryptdll_md5_h) + h = MD5.new() + winobjs.cryptdll_md5_h[index] = h + + myjit.vm.vm_set_mem(ad_ctx, pck32(index)) + myjit.func_ret_stdcall(ret_ad, 0) + + +def cryptdll_MD5Update(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + ad_ctx, ad_input, inlen = args + + index = myjit.vm.vm_get_mem(ad_ctx, 4) + index = upck32(index) + if not index in winobjs.cryptdll_md5_h: + raise ValueError('unknown h context', index) + + data = myjit.vm.vm_get_mem(ad_input, inlen) + winobjs.cryptdll_md5_h[index].update(data) + print hexdump(data) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def cryptdll_MD5Final(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + ad_ctx, = args + + index = myjit.vm.vm_get_mem(ad_ctx, 4) + index = upck32(index) + if not index in winobjs.cryptdll_md5_h: + raise ValueError('unknown h context', index) + h = winobjs.cryptdll_md5_h[index].digest() + myjit.vm.vm_set_mem(ad_ctx + 88, h) + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_RtlInitAnsiString(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + ad_ctx, ad_str = args + + s = get_str_ansi(myjit, ad_str) + l = len(s) + print "string", l, s + myjit.vm.vm_set_mem(ad_ctx, pw(l) + pw(l + 1) + pck32(ad_str)) + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_RtlHashUnicodeString(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + ad_ctxu, case_i, h_id, phout = args + + print hex(h_id) + if h_id != 1: + raise ValueError('unk hash unicode', h_id) + + l1, l2, ptra = struct.unpack('HHL', myjit.vm.vm_get_mem(ad_ctxu, 8)) + print hex(l1), hex(l2), hex(ptra) + s = myjit.vm.vm_get_mem(ptra, l1) + print repr(s) + s = s[:-1] + print repr(s) + hv = 0 + + if case_i: + s = s.lower() + for c in s: + hv = ((65599 * hv) + ord(c)) & 0xffffffff + print "unicode h", hex(hv) + myjit.vm.vm_set_mem(phout, pck32(hv)) + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_RtlMoveMemory(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + ad_dst, ad_src, m_len = args + data = myjit.vm.vm_get_mem(ad_src, m_len) + myjit.vm.vm_set_mem(ad_dst, data) + print hexdump(data) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_RtlAnsiCharToUnicodeChar(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + ad_ad_ch, = args + ad_ch = upck32(myjit.vm.vm_get_mem(ad_ad_ch, 4)) + print hex(ad_ch) + ch = ord(myjit.vm.vm_get_mem(ad_ch, 1)) + myjit.vm.vm_set_mem(ad_ad_ch, pck32(ad_ch + 1)) + + print repr(ch), repr(chr(ch)) + myjit.func_ret_stdcall(ret_ad, ch) + + +def ntdll_RtlFindCharInUnicodeString(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + flags, main_str_ad, search_chars_ad, pos_ad = args + + print flags + if flags != 0: + raise ValueError('unk flags') + + ml1, ml2, mptra = struct.unpack('HHL', myjit.vm.vm_get_mem(main_str_ad, 8)) + print ml1, ml2, hex(mptra) + sl1, sl2, sptra = struct.unpack( + 'HHL', myjit.vm.vm_get_mem(search_chars_ad, 8)) + print sl1, sl2, hex(sptra) + main_data = myjit.vm.vm_get_mem(mptra, ml1)[:-1] + search_data = myjit.vm.vm_get_mem(sptra, sl1)[:-1] + + print repr(main_data) + print repr(search_data) + + pos = None + for i, c in enumerate(main_data): + for s in search_data: + if s == c: + pos = i + break + if pos: + break + print pos + if pos is None: + ret = 0xC0000225 + myjit.vm.vm_set_mem(pos_ad, pck32(0)) + else: + ret = 0 + myjit.vm.vm_set_mem(pos_ad, pck32(pos)) + + myjit.func_ret_stdcall(ret_ad, ret) + + +def ntdll_RtlComputeCrc32(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + dwinit, pdata, ilen = args + + data = myjit.vm.vm_get_mem(pdata, ilen) + print hex(dwinit) + print hexdump(data) + crc_r = crc32(data, dwinit) + print "crc32", hex(crc_r) + myjit.func_ret_stdcall(ret_ad, crc_r) + + +def ntdll_RtlExtendedIntegerMultiply(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + b2, b1, bm = args + a = (b1 << 32) + b2 + a = a * bm + print hex(a) + myjit.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff) + + +def ntdll_RtlLargeIntegerAdd(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + a2, a1, b2, b1 = args + a = (a1 << 32) + a2 + (b1 << 32) + b2 + print hex(a) + myjit.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff) + + +def ntdll_RtlLargeIntegerShiftRight(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + a2, a1, m = args + a = ((a1 << 32) + a2) >> m + print hex(a) + myjit.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff) + + +def ntdll_RtlEnlargedUnsignedMultiply(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + a, b = args + a = a * b + print hex(a) + myjit.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff) + + +def ntdll_RtlLargeIntegerSubtract(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + a2, a1, b2, b1 = args + a = (a1 << 32) + a2 - (b1 << 32) + b2 + print hex(a) + myjit.func_ret_stdcall(ret_ad, a & 0xffffffff, (a >> 32) & 0xffffffff) + + +def ntdll_RtlCompareMemory(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + ad1, ad2, m_len = args + data1 = myjit.vm.vm_get_mem(ad1, m_len) + data2 = myjit.vm.vm_get_mem(ad2, m_len) + + print hexdump(data1) + print hexdump(data2) + i = 0 + while data1[i] == data2[i]: + i += 1 + if i >= m_len: + break + + myjit.func_ret_stdcall(ret_ad, i) + + +def user32_GetMessagePos(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, 0x00110022) + + +def kernel32_Sleep(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + t, = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_ZwUnmapViewOfSection(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + h, ad = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_IsBadReadPtr(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + lp, ucb = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntoskrnl_KeInitializeEvent(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + my_event, my_type, my_state = args + myjit.vm.vm_set_mem(my_event, pck32(winobjs.win_event_num)) + winobjs.win_event_num += 1 + + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntoskrnl_RtlGetVersion(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + ptr_version, = args + + s = struct.pack("IIIII", + 0x114, # struct size + 0x5, # maj vers + 0x2, # min vers + 0x666, # build nbr + 0x2, # platform id + ) + set_str_unic("Service pack 4") + + myjit.vm.vm_set_mem(ptr_version, s) + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntoskrnl_RtlVerifyVersionInfo(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + ptr_version, = args + + s = myjit.vm.vm_get_mem(ptr_version, 0x5 * 4) + print repr(s) + s_size, s_majv, s_minv, s_buildn, s_platform = struct.unpack('IIIII', s) + print s_size, s_majv, s_minv, s_buildn, s_platform + raise NotImplementedError("Untested case") + myjit.vm.vm_set_mem(ptr_version, s) + myjit.func_ret_stdcall(ret_ad, 0) + + +def hal_ExAcquireFastMutex(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, 0) + + +def mdl2ad(n): + return winobjs.nt_mdl_ad + 0x10 * n + + +def ad2mdl(ad): + return ((ad - winobjs.nt_mdl_ad) & 0xFFFFFFFFL) / 0x10 + + +def ntoskrnl_IoAllocateMdl(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + v_addr, l, second_buf, chargequota, pirp = args + m = mdl(v_addr, l) + winobjs.nt_mdl[winobjs.nt_mdl_cur] = m + myjit.vm.vm_set_mem(mdl2ad(winobjs.nt_mdl_cur), str(m)) + myjit.func_ret_stdcall(ret_ad, mdl2ad(winobjs.nt_mdl_cur)) + winobjs.nt_mdl_cur += 1 + + +def ntoskrnl_MmProbeAndLockPages(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + p_mdl, access_mode, op = args + + if not ad2mdl(p_mdl) in winobjs.nt_mdl: + raise ValueError('unk mdl', hex(p_mdl)) + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntoskrnl_MmMapLockedPagesSpecifyCache(myjit): + ret_ad, args = myjit.func_args_stdcall(6) + p_mdl, access_mode, cache_type, base_ad, bugcheckonfailure, priority = args + if not ad2mdl(p_mdl) in winobjs.nt_mdl: + raise ValueError('unk mdl', hex(p_mdl)) + + myjit.func_ret_stdcall(ret_ad, winobjs.nt_mdl[ad2mdl(p_mdl)].ad) + + +def ntoskrnl_MmProtectMdlSystemAddress(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + p_mdl, prot = args + if not ad2mdl(p_mdl) in winobjs.nt_mdl: + raise ValueError('unk mdl', hex(p_mdl)) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntoskrnl_MmUnlockPages(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + p_mdl, = args + if not ad2mdl(p_mdl) in winobjs.nt_mdl: + raise ValueError('unk mdl', hex(p_mdl)) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntoskrnl_IoFreeMdl(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + p_mdl, = args + if not ad2mdl(p_mdl) in winobjs.nt_mdl: + raise ValueError('unk mdl', hex(p_mdl)) + del(winobjs.nt_mdl[ad2mdl(p_mdl)]) + myjit.func_ret_stdcall(ret_ad, 0) + + +def hal_ExReleaseFastMutex(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntoskrnl_RtlQueryRegistryValues(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + relativeto, path, querytable, context, environ = args + p = get_str_unic(myjit, path) + print repr(p) + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntoskrnl_ExAllocatePoolWithTagPriority(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + pool_type, nbr_of_bytes, tag, priority = args + + alloc_addr = get_next_alloc_addr(nbr_of_bytes) + myjit.vm.vm_add_memory_page( + alloc_addr, PAGE_READ | PAGE_WRITE, "\x00" * nbr_of_bytes) + + print "ad", hex(alloc_addr) + myjit.func_ret_stdcall(ret_ad, alloc_addr) + + +def my_lstrcmp(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(2) + ptr_str1, ptr_str2 = args + s1 = get_str(ptr_str1) + s2 = get_str(ptr_str2) + print '%s (%r, %r)' % (' ' * len(funcname), s1, s2) + myjit.func_ret_stdcall(ret_ad, cmp(s1, s2)) + + +def kernel32_lstrcmpA(myjit): + my_lstrcmp(myjit, whoami(), lambda x: get_str_ansi(myjit, x)) + + +def kernel32_lstrcmpiA(myjit): + my_lstrcmp(myjit, whoami(), lambda x: get_str_ansi(myjit, x).lower()) + + +def kernel32_lstrcmpW(myjit): + my_lstrcmp(myjit, whoami(), lambda x: get_str_unic(myjit, x)) + + +def kernel32_lstrcmpiW(myjit): + my_lstrcmp(myjit, whoami(), lambda x: get_str_unic(myjit, x).lower()) + + +def kernel32_lstrcmpi(myjit): + my_lstrcmp(myjit, whoami(), lambda x: get_str_ansi(myjit, x).lower()) + + +def my_strcpy(myjit, funcname, get_str, set_str): + ret_ad, args = myjit.func_args_stdcall(2) + ptr_str1, ptr_str2 = args + s2 = get_str(myjit, ptr_str2) + print '%s (%r)' % (funcname, s2) + myjit.vm.vm_set_mem(ptr_str1, set_str(s2)) + myjit.func_ret_stdcall(ret_ad, ptr_str1) + + +def kernel32_lstrcpyW(myjit): + my_strcpy(myjit, whoami(), get_str_unic, + lambda x: set_str_unic(x) + "\x00\x00") + + +def kernel32_lstrcpyA(myjit): + my_strcpy(myjit, whoami(), get_str_ansi, lambda x: x + "\x00") + + +def kernel32_lstrcpy(myjit): + my_strcpy(myjit, whoami(), get_str_ansi, lambda x: x + "\x00") + + +def kernel32_lstrcpyn(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + ptr_str1, ptr_str2, mlen = args + s2 = get_str_ansi(myjit, ptr_str2) + print repr(s2) + s2 = s2[:mlen] + myjit.vm.vm_set_mem(ptr_str1, s2) + + myjit.func_ret_stdcall(ret_ad, ptr_str1) + + +def my_strlen(myjit, funcname, get_str, mylen): + ret_ad, args = myjit.func_args_stdcall(1) + arg_src, = args + src = get_str(myjit, arg_src) + print funcname, repr(src) + myjit.func_ret_stdcall(ret_ad, mylen(src)) + + +def kernel32_lstrlenA(myjit): + my_strlen(myjit, whoami(), get_str_ansi, lambda x: len(x)) + + +def kernel32_lstrlenW(myjit): + my_strlen(myjit, whoami(), get_str_unic, lambda x: len(x)) + + +def kernel32_lstrlen(myjit): + my_strlen(myjit, whoami(), get_str_ansi, lambda x: len(x)) + + +def my_lstrcat(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(3) + ptr_str1, ptr_str2 = args + s1 = get_str(myjit, ptr_str1) + s2 = get_str(myjit, ptr_str2) + print '%s (%r, %r)' % (whoami(), s1, s2) + + s = s1 + s2 + print repr(s) + myjit.vm.vm_set_mem(ptr_str1, s1 + s2) + myjit.func_ret_stdcall(ret_ad, ptr_str1) + + +def kernel32_lstrcatA(myjit): + my_lstrcat(myjit, whoami(), get_str_ansi) + + +def kernel32_lstrcatW(myjit): + my_lstrcat(myjit, whoami(), get_str_unic) + + +def kernel32_GetUserGeoID(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + geoclass, = args + if geoclass == 14: + ret = 12345678 + elif geoclass == 16: + ret = 55667788 + else: + raise ValueError('unknown geolcass') + + myjit.func_ret_stdcall(ret_ad, ret) + + +def my_GetVolumeInformation(myjit, funcname, get_str, set_str): + ret_ad, args = myjit.func_args_stdcall(8) + (lprootpathname, lpvolumenamebuffer, nvolumenamesize, + lpvolumeserialnumber, lpmaximumcomponentlength, lpfilesystemflags, + lpfilesystemnamebuffer, nfilesystemnamesize) = args + + print funcname, hex(lprootpathname), hex(lpvolumenamebuffer), \ + hex(nvolumenamesize), hex(lpvolumeserialnumber), \ + hex(lpmaximumcomponentlength), hex(lpfilesystemflags), \ + hex(lpfilesystemnamebuffer), hex(nfilesystemnamesize) + + if lprootpathname: + s = get_str(myjit, lprootpathname) + print repr(s) + + if lpvolumenamebuffer: + s = "volumename" + s = s[:nvolumenamesize] + myjit.vm.vm_set_mem(lpvolumenamebuffer, set_str(s)) + + if lpvolumeserialnumber: + myjit.vm.vm_set_mem(lpvolumeserialnumber, pck32(11111111)) + if lpmaximumcomponentlength: + myjit.vm.vm_set_mem(lpmaximumcomponentlength, pck32(0xff)) + if lpfilesystemflags: + myjit.vm.vm_set_mem(lpfilesystemflags, pck32(22222222)) + + if lpfilesystemnamebuffer: + s = "filesystemname" + s = s[:nfilesystemnamesize] + myjit.vm.vm_set_mem(lpfilesystemnamebuffer, set_str(s)) + + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_GetVolumeInformationA(myjit): + my_GetVolumeInformation( + myjit, whoami(), get_str_ansi, lambda x: x + "\x00") + + +def kernel32_GetVolumeInformationW(myjit): + my_GetVolumeInformation(myjit, whoami(), get_str_unic, set_str_unic) + + +def kernel32_MultiByteToWideChar(myjit): + ret_ad, args = myjit.func_args_stdcall(6) + (codepage, dwflags, lpmultibytestr, + cbmultibyte, lpwidecharstr, cchwidechar) = args + + print whoami(), hex(ret_ad), \ + hex(codepage), hex(dwflags), hex(lpmultibytestr), hex( + cbmultibyte), hex(lpwidecharstr), hex(cchwidechar) + src = get_str_ansi(myjit, lpmultibytestr) + '\x00' + l = len(src) + print repr(src) + + src = "\x00".join(list(src)) + print repr(src), hex(len(src)) + myjit.vm.vm_set_mem(lpwidecharstr, src) + myjit.func_ret_stdcall(ret_ad, l) + + +def my_GetEnvironmentVariable(myjit, funcname, get_str, set_str, mylen): + ret_ad, args = myjit.func_args_stdcall(3) + lpname, lpbuffer, nsize = args + + s = get_str(myjit, lpname) + if get_str == get_str_unic: + s = s + print 'variable', repr(s) + if s in winobjs.env_variables: + v = set_str(winobjs.env_variables[s]) + else: + print 'WARNING unknown env variable', repr(s) + v = "" + print 'return', repr(v) + myjit.vm.vm_set_mem(lpbuffer, v) + myjit.func_ret_stdcall(ret_ad, mylen(v)) + + +def my_GetSystemDirectory(myjit, funcname, set_str): + ret_ad, args = myjit.func_args_stdcall(2) + lpbuffer, usize = args + print funcname + + s = "c:\\windows\\system32" + l = len(s) + s = set_str(s) + myjit.vm.vm_set_mem(lpbuffer, s) + + myjit.func_ret_stdcall(ret_ad, l) + + +def kernel32_GetSystemDirectoryA(myjit): + my_GetSystemDirectory(myjit, whoami(), set_str_ansi) + + +def kernel32_GetSystemDirectoryW(myjit): + my_GetSystemDirectory(myjit, whoami(), set_str_unic) + + +def my_CreateDirectory(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(2) + lppath, secattrib = args + p = get_str(myjit, lppath) + myjit.func_ret_stdcall(ret_ad, 0x1337) + + +def kernel32_CreateDirectoryW(myjit): + my_CreateDirectory(myjit, whoami(), get_str_unic) + + +def kernel32_CreateDirectoryA(myjit): + my_CreateDirectory(myjit, whoami(), get_str_ansi) + + +def kernel32_GetEnvironmentVariableA(myjit): + my_GetEnvironmentVariable(myjit, whoami(), + get_str_ansi, + lambda x: x + "\x00", + lambda x: len(x)) + + +def kernel32_GetEnvironmentVariableW(myjit): + my_GetEnvironmentVariable(myjit, whoami(), + get_str_unic, + lambda x: "\x00".join(list(x + "\x00")), + lambda x: len(x)) + + +def my_CreateEvent(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(4) + lpeventattributes, bmanualreset, binitialstate, lpname = args + if lpname: + s = get_str(myjit, lpname) + else: + s = None + print repr(s) + if not s in winobjs.events_pool: + winobjs.events_pool[s] = (bmanualreset, binitialstate) + else: + print 'WARNING: known event' + + myjit.func_ret_stdcall(ret_ad, id(s)) + + +def kernel32_CreateEventA(myjit): + my_CreateEvent(myjit, whoami(), get_str_ansi) + + +def kernel32_CreateEventW(myjit): + my_CreateEvent(myjit, whoami(), get_str_unic) + + +def kernel32_WaitForSingleObject(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + handle, dwms = args + + print whoami(), hex(ret_ad), hex(handle), hex(dwms) + + t_start = time.time() * 1000 + found = False + while True: + if dwms and dwms + t_start > time.time() * 1000: + ret = 0x102 + break + for k, v in winobjs.events_pool.items(): + if k != handle: + continue + found = True + if winobjs.events_pool[k][1] == 1: + ret = 0 + break + if not found: + print 'unknown handle' + ret = 0xffffffff + break + time.sleep(0.1) + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_SetFileAttributesA(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + lpfilename, dwfileattributes = args + print whoami(), hex(ret_ad), hex(lpfilename), hex(dwfileattributes) + + if lpfilename: + fname = get_str_ansi(myjit, lpfilename) + print "filename", repr(fname) + ret = 1 + else: + ret = 0 + myjit.vm.vm_set_mem(seh_helper.FS_0_AD + 0x34, pck32(3)) + + myjit.func_ret_stdcall(ret_ad, ret) + + +def ntdll_RtlMoveMemory(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + dst, src, l = args + s = myjit.vm.vm_get_mem(src, l) + myjit.vm.vm_set_mem(dst, s) + + myjit.func_ret_stdcall(ret_ad, 1) + + +def ntdll_ZwQuerySystemInformation(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + (systeminformationclass, systeminformation, + systeminformationl, returnl) = args + if systeminformationclass == 2: + # SYSTEM_PERFORMANCE_INFORMATION + o = struct.pack('II', 0x22222222, 0x33333333) + o += "\x00" * systeminformationl + o = o[:systeminformationl] + myjit.vm.vm_set_mem(systeminformation, o) + else: + raise ValueError('unknown sysinfo class', systeminformationclass) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_ZwProtectVirtualMemory(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + handle, lppvoid, pdwsize, flnewprotect, lpfloldprotect = args + + ad = upck32(myjit.vm.vm_get_mem(lppvoid, 4)) + dwsize = upck32(myjit.vm.vm_get_mem(pdwsize, 4)) + print 'ad', hex(ad), 'size', hex(dwsize) + # XXX mask hpart + flnewprotect &= 0xFFF + + if not flnewprotect in access_dict: + raise ValueError('unknown access dw!') + myjit.vm.vm_set_mem_access(ad, access_dict[flnewprotect]) + + # XXX todo real old protect + myjit.vm.vm_set_mem(lpfloldprotect, pck32(0x40)) + + dump_memory_page_pool_py() + myjit.func_ret_stdcall(ret_ad, 1) + + +def ntdll_ZwAllocateVirtualMemory(myjit): + ret_ad, args = myjit.func_args_stdcall(6) + handle, lppvoid, zerobits, pdwsize, alloc_type, flprotect = args + + ad = upck32(myjit.vm.vm_get_mem(lppvoid, 4)) + dwsize = upck32(myjit.vm.vm_get_mem(pdwsize, 4)) + print 'ad', hex(ad), 'size', hex(dwsize) + + access_dict = {0x0: 0, + 0x1: 0, + 0x2: PAGE_READ, + 0x4: PAGE_READ | PAGE_WRITE, + 0x10: PAGE_EXEC, + 0x20: PAGE_EXEC | PAGE_READ, + 0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE, + 0x100: 0 + } + + access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()]) + + if not flprotect in access_dict: + raise ValueError('unknown access dw!') + + alloc_addr = get_next_alloc_addr(dwsize) + myjit.vm.vm_add_memory_page( + alloc_addr, access_dict[flprotect], "\x00" * dwsize) + myjit.vm.vm_set_mem(lppvoid, pck32(alloc_addr)) + + print 'ret', hex(alloc_addr) + dump_memory_page_pool_py() + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_ZwFreeVirtualMemory(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + handle, lppvoid, pdwsize, alloc_type = args + ad = upck32(myjit.vm.vm_get_mem(lppvoid, 4)) + dwsize = upck32(myjit.vm.vm_get_mem(pdwsize, 4)) + print 'ad', hex(ad), 'size', hex(dwsize) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_RtlInitString(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + pstring, source = args + s = get_str_ansi(myjit, source) + print "str", repr(s) + + l = len(s) + 1 + + o = struct.pack('HHI', l, l, source) + myjit.vm.vm_set_mem(pstring, o) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_RtlAnsiStringToUnicodeString(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + dst, src, alloc_str = args + + l1, l2, p_src = struct.unpack('HHI', myjit.vm.vm_get_mem(src, 0x8)) + print hex(l1), hex(l2), hex(p_src) + s = get_str_ansi(myjit, p_src) + print "str", repr(s) + s = ("\x00".join(s + "\x00")) + l = len(s) + 1 + if alloc_str: + print 'alloc' + alloc_addr = get_next_alloc_addr(l) + myjit.vm.vm_add_memory_page( + alloc_addr, PAGE_READ | PAGE_WRITE, "\x00" * l) + else: + print 'use buf' + alloc_addr = p_src + myjit.vm.vm_set_mem(alloc_addr, s) + o = struct.pack('HHI', l, l, alloc_addr) + myjit.vm.vm_set_mem(dst, o) + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_LdrLoadDll(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + path, flags, modname, modhandle = args + + print whoami(), hex(ret_ad), + print '(', hex(path), hex(flags), hex(modname), hex(modhandle), ')' + l1, l2, p_src = struct.unpack('HHI', myjit.vm.vm_get_mem(modname, 0x8)) + print hex(l1), hex(l2), hex(p_src) + s = get_str_unic(myjit, p_src) + print repr(s) + libname = s.lower() + print repr(libname) + + ad = winobjs.runtime_dll.lib_get_add_base(libname) + print "ret", hex(ad) + myjit.vm.vm_set_mem(modhandle, pck32(ad)) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_RtlFreeUnicodeString(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + src, = args + + l1, l2, p_src = struct.unpack('HHI', myjit.vm.vm_get_mem(src, 0x8)) + print hex(l1), hex(l2), hex(p_src) + s = get_str_unic(myjit, p_src) + print "str", repr(s) + print repr(s) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_LdrGetProcedureAddress(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + libbase, pfname, opt, p_ad = args + + l1, l2, p_src = struct.unpack('HHI', myjit.vm.vm_get_mem(pfname, 0x8)) + print hex(l1), hex(l2), hex(p_src) + fname = get_str_ansi(myjit, p_src) + print "str", repr(fname) + + ad = winobjs.runtime_dll.lib_get_add_func(libbase, fname) + + myjit.vm.vm_set_mem(p_ad, pck32(ad)) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def ntdll_memset(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + arg_addr, arg_c, arg_size = args + + myjit.vm.vm_set_mem(arg_addr, chr(arg_c) * arg_size) + myjit.func_ret_stdcall(ret_ad, arg_addr) + + +def msvcrt_memset(myjit): + ret_ad, args = myjit.func_args_cdecl(3) + arg_addr, arg_c, arg_size = args + + myjit.vm.vm_set_mem(arg_addr, chr(arg_c) * arg_size) + myjit.func_ret_cdecl(ret_ad, arg_addr) + + +def msvcrt_memcpy(myjit): + ret_ad, args = myjit.func_args_cdecl(3) + dst, src, size = args + + s = myjit.vm.vm_get_mem(src, size) + myjit.vm.vm_set_mem(dst, s) + myjit.func_ret_cdecl(ret_ad, dst) + + +def msvcrt_memcmp(myjit): + ret_ad, args = myjit.func_args_cdecl(3) + ps1, ps2, size = args + + s1 = myjit.vm.vm_get_mem(ps1, size) + s2 = myjit.vm.vm_get_mem(ps2, size) + ret = cmp(s1, s2) + myjit.func_ret_cdecl(ret_ad, ret) + + +def shlwapi_PathFindExtensionA(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + path_ad, = args + + path = get_str_ansi(myjit, path_ad) + print repr(path) + i = path.rfind('.') + if i == -1: + i = path_ad + len(path) + else: + i = path_ad + i + myjit.func_ret_stdcall(ret_ad, i) + + +def shlwapi_PathRemoveFileSpecW(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + path_ad, = args + + path = get_str_unic(myjit, path_ad) + print repr(path) + i = path.rfind('\\') + if i == -1: + i = 0 + myjit.vm.vm_set_mem(path_ad + i * 2, "\x00\x00") + path = get_str_unic(myjit, path_ad) + print repr(path) + myjit.func_ret_stdcall(ret_ad, 1) + + +def shlwapi_PathIsPrefixW(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + ptr_prefix, ptr_path = args + prefix = get_str_unic(myjit, ptr_prefix) + path = get_str_unic(myjit, ptr_path) + print repr(prefix), repr(path) + + if path.startswith(prefix): + ret = 1 + else: + ret = 0 + myjit.func_ret_stdcall(ret_ad, ret) + + +def shlwapi_PathIsDirectoryW(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + ppath, = args + fname = get_str_unic(myjit, ppath) + + fname = fname.replace('\\', "/").lower() + f = os.path.join('file_sb', fname) + + s = os.stat(f) + ret = 0 + if stat.S_ISDIR(s.st_mode): + ret = 1 + + myjit.func_ret_cdecl(ret_ad, ret) + + +def shlwapi_PathIsFileSpec(funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(1) + path_ad, = args + path = get_str(myjit, path_ad) + print repr(path) + if path.find(':') != -1 and path.find('\\') != -1: + ret = 0 + else: + ret = 1 + + myjit.func_ret_stdcall(ret_ad, ret) + + +def shlwapi_PathGetDriveNumber(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(1) + path_ad, = args + path = get_str(myjit, path_ad) + print repr(path) + l = ord(path[0].upper()) - ord('A') + if 0 <= l <= 25: + ret = l + else: + ret = -1 + + myjit.func_ret_stdcall(ret_ad, ret) + + +def shlwapi_PathGetDriveNumberA(myjit): + shlwapi_PathGetDriveNumber(myjit, whoami(), get_str_ansi) + + +def shlwapi_PathGetDriveNumberW(myjit): + shlwapi_PathGetDriveNumber(myjit, whoami(), get_str_unic) + + +def shlwapi_PathIsFileSpecA(myjit): + shlwapi_PathIsFileSpec(whoami(), get_str_ansi) + + +def shlwapi_PathIsFileSpecW(myjit): + shlwapi_PathIsFileSpec(whoami(), get_str_unic) + + +def shlwapi_StrToIntA(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + i_str_ad, = args + i_str = get_str_ansi(myjit, i_str_ad) + print repr(i_str) + try: + i = int(i_str) + except: + print 'WARNING cannot convert int' + i = 0 + + myjit.func_ret_stdcall(ret_ad, i) + + +def shlwapi_StrToInt64Ex(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(3) + pstr, flags, pret = args + i_str = get_str(myjit, pstr) + if get_str is get_str_unic: + i_str = i_str + print repr(i_str) + + if flags == 0: + r = int(i_str) + elif flags == 1: + r = int(i_str, 16) + else: + raise ValueError('cannot decode int') + + myjit.vm.vm_set_mem(pret, struct.pack('q', r)) + + myjit.func_ret_stdcall(ret_ad, i) + + +def shlwapi_StrToInt64ExA(myjit): + shlwapi_StrToInt64Ex(myjit, whoami(), get_str_ansi) + + +def shlwapi_StrToInt64ExW(myjit): + shlwapi_StrToInt64Ex(myjit, whoami(), get_str_unic) + + +def user32_IsCharAlpha(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(1) + c, = args + try: + c = chr(c) + except: + print 'bad char', c + c = "\x00" + if c.isalpha(myjit): + ret = 1 + else: + ret = 0 + myjit.func_ret_stdcall(ret_ad, ret) + + +def user32_IsCharAlphaA(myjit): + user32_IsCharAlpha(myjit, whoami(), get_str_ansi) + + +def user32_IsCharAlphaW(myjit): + user32_IsCharAlpha(myjit, whoami(), get_str_unic) + + +def user32_IsCharAlphaNumericA(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + c, = args + c = chr(c) + if c.isalnum(myjit): + ret = 1 + else: + ret = 0 + myjit.func_ret_stdcall(ret_ad, ret) + + +def shlwapi_StrCmpNIA(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + ptr_str1, ptr_str2, nchar = args + s1 = get_str_ansi(myjit, ptr_str1).lower() + s2 = get_str_ansi(myjit, ptr_str2).lower() + s1 = s1[:nchar] + s2 = s2[:nchar] + + print repr(s1), repr(s2) + myjit.func_ret_stdcall(ret_ad, cmp(s1, s2)) + + +def advapi32_RegOpenKeyEx(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(5) + hkey, subkey, reserved, access, phandle = args + if subkey: + s_subkey = get_str(myjit, subkey).lower() + else: + s_subkey = "" + print hex(hkey) + print repr(s_subkey) + print winobjs.hkey_handles + + ret_hkey = 0 + ret = 2 + if hkey in winobjs.hkey_handles: + if s_subkey: + h = hash(s_subkey) & 0xffffffff + print hex(h) + if h in winobjs.hkey_handles: + ret_hkey = h + ret = 0 + else: + print 'unknown skey' + + print 'set hkey', hex(ret_hkey) + myjit.vm.vm_set_mem(phandle, pck32(ret_hkey)) + + myjit.func_ret_stdcall(ret_ad, ret) + + +def advapi32_RegOpenKeyExA(myjit): + advapi32_RegOpenKeyEx(myjit, whoami(), get_str_ansi) + + +def advapi32_RegOpenKeyExW(myjit): + advapi32_RegOpenKeyEx(myjit, whoami(), get_str_unic) + + +def advapi32_RegSetValue(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(5) + hkey, psubkey, valuetype, pvalue, length = args + if psubkey: + subkey = get_str(myjit, psubkey).lower() + else: + subkey = "" + print repr(subkey) + + if pvalue: + value = myjit.vm.vm_get_mem(pvalue, length) + else: + value = None + print repr(value) + myjit.func_ret_stdcall(ret_ad, 0) + + +def advapi32_RegSetValueA(myjit): + advapi32_RegSetValue(myjit, whoami(), get_str_ansi) + + +def advapi32_RegSetValueW(myjit): + advapi32_RegSetValue(myjit, whoami(), get_str_unic) + + +def kernel32_GetThreadLocale(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, 0x40c) + + +def kernel32_GetLocaleInfo(myjit, funcname, set_str): + ret_ad, args = myjit.func_args_stdcall(4) + localeid, lctype, lplcdata, cchdata = args + + buf = None + ret = 0 + if localeid == 0x40c: + if lctype == 0x3: + buf = "ENGLISH" + buf = buf[:cchdata - 1] + print 'SET', buf + myjit.vm.vm_set_mem(lplcdata, set_str(buf)) + ret = len(buf) + else: + raise ValueError('unimpl localeid') + + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_GetLocaleInfoA(myjit): + kernel32_GetLocaleInfo(myjit, whoami(), set_str_ansi) + + +def kernel32_GetLocaleInfoW(myjit): + kernel32_GetLocaleInfo(myjit, whoami(), set_str_unic) + + +def kernel32_TlsAlloc(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + winobjs.tls_index += 1 + myjit.func_ret_stdcall(ret_ad, winobjs.tls_index) + + +def kernel32_TlsFree(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_TlsSetValue(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + tlsindex, tlsvalue = args + winobjs.tls_values[tlsindex] = tlsvalue + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_TlsGetValue(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + tlsindex, = args + + print whoami(), hex(tlsindex) + + if not tlsindex in winobjs.tls_values: + raise ValueError("unknown tls val", repr(tlsindex)) + myjit.func_ret_stdcall(ret_ad, winobjs.tls_values[tlsindex]) + + +def user32_GetKeyboardType(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + typeflag, = args + + ret = 0 + if typeflag == 0: + ret = 4 + else: + raise ValueError('unimpl keyboard type') + + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_GetStartupInfo(myjit, funcname, set_str): + ret_ad, args = myjit.func_args_stdcall(1) + ptr, = args + + print funcname, hex(ptr) + + s = "\x00" * 0x2c + "\x81\x00\x00\x00" + "\x0a" + + myjit.vm.vm_set_mem(ptr, s) + myjit.func_ret_stdcall(ret_ad, ptr) + + +def kernel32_GetStartupInfoA(myjit): + kernel32_GetStartupInfo(myjit, whoami(), set_str_ansi) + + +def kernel32_GetStartupInfoW(myjit): + kernel32_GetStartupInfo(myjit, whoami(), set_str_unic) + + +def kernel32_GetCurrentThreadId(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, 0x113377) + + +def kernel32_InitializeCriticalSection(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + lpcritic, = args + myjit.func_ret_stdcall(ret_ad, 0) + + +def user32_GetSystemMetrics(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + nindex, = args + + ret = 0 + if nindex in [0x2a, 0x4a]: + ret = 0 + else: + raise ValueError('unimpl index') + myjit.func_ret_stdcall(ret_ad, ret) + + +def wsock32_WSAStartup(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + version, pwsadata = args + myjit.vm.vm_set_mem(pwsadata, "\x01\x01\x02\x02WinSock 2.0\x00") + + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_GetLocalTime(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + lpsystemtime, = args + + s = struct.pack('HHHHHHHH', + 2011, # year + 10, # month + 5, # dayofweek + 7, # day + 13, # hour + 37, # minutes + 00, # seconds + 999, # millisec + ) + myjit.vm.vm_set_mem(lpsystemtime, s) + myjit.func_ret_stdcall(ret_ad, lpsystemtime) + + +def kernel32_GetSystemTime(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + lpsystemtime, = args + + print whoami(), hex(ret_ad), hex(lpsystemtime) + + s = struct.pack('HHHHHHHH', + 2011, # year + 10, # month + 5, # dayofweek + 7, # day + 13, # hour + 37, # minutes + 00, # seconds + 999, # millisec + ) + myjit.vm.vm_set_mem(lpsystemtime, s) + myjit.func_ret_stdcall(ret_ad, lpsystemtime) + + +def kernel32_CreateFileMapping(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(6) + hfile, lpattr, flprotect, dwmaximumsizehigh, dwmaximumsizelow, lpname = args + + if lpname: + f = get_str(myjit, lpname) + else: + f = None + print repr(f) + + if not hfile in winobjs.handle_pool: + raise ValueError('unknown handle') + + ret = winobjs.handle_pool.add('filemapping', hfile) + + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_CreateFileMappingA(myjit): + kernel32_CreateFileMapping(myjit, whoami(), get_str_ansi) + + +def kernel32_CreateFileMappingW(myjit): + kernel32_CreateFileMapping(myjit, whoami(), get_str_unic) + + +def kernel32_MapViewOfFile(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + hfile, flprotect, dwfileoffsethigh, dwfileoffsetlow, length = args + + if not hfile in winobjs.handle_pool: + raise ValueError('unknown handle') + hmap = winobjs.handle_pool[hfile] + print hmap + if not hmap.info in winobjs.handle_pool: + raise ValueError('unknown file handle') + + hfile_o = winobjs.handle_pool[hmap.info] + print hfile_o + fd = hfile_o.info + fd.seek((dwfileoffsethigh << 32) | dwfileoffsetlow) + if length: + data = fd.read(length) + else: + data = fd.read() + length = len(data) + + print 'mapp total:', hex(len(data)) + access_dict = {0x0: 0, + 0x1: 0, + 0x2: PAGE_READ, + 0x4: PAGE_READ | PAGE_WRITE, + 0x10: PAGE_EXEC, + 0x20: PAGE_EXEC | PAGE_READ, + 0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE, + 0x100: 0 + } + access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()]) + + if not flprotect in access_dict: + raise ValueError('unknown access dw!') + + alloc_addr = alloc_mem(myjit, len(data)) + myjit.vm.vm_set_mem(alloc_addr, data) + + winobjs.handle_mapped[ + alloc_addr] = hfile_o, dwfileoffsethigh, dwfileoffsetlow, length + print 'return', hex(alloc_addr) + + myjit.func_ret_stdcall(ret_ad, alloc_addr) + + +def kernel32_UnmapViewOfFile(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + ad, = args + + if not ad in winobjs.handle_mapped: + raise NotImplementedError("Untested case") + """ + hfile_o, dwfileoffsethigh, dwfileoffsetlow, length = winobjs.handle_mapped[ad] + off = (dwfileoffsethigh<<32) | dwfileoffsetlow + s = myjit.vm.vm_get_mem(ad, length) + hfile_o.info.seek(off) + hfile_o.info.write(s) + hfile_o.info.close() + """ + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_GetDriveType(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(1) + pathname, = args + + print funcname, hex(pathname) + + p = get_str(myjit, pathname) + print repr(p) + p = p.upper() + + ret = 0 + if p[0] == "C": + ret = 3 + + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_GetDriveTypeA(myjit): + kernel32_GetDriveType(myjit, whoami(), get_str_ansi) + + +def kernel32_GetDriveTypeW(myjit): + kernel32_GetDriveType(myjit, whoami(), get_str_unic) + + +def kernel32_GetDiskFreeSpace(myjit, funcname, get_str): + ret_ad, args = myjit.func_args_stdcall(5) + (lprootpathname, lpsectorpercluster, lpbytespersector, + lpnumberoffreeclusters, lptotalnumberofclusters) = args + + if lprootpathname: + rootpath = get_str(myjit, lprootpathname) + else: + rootpath = "" + print repr(rootpath) + + myjit.vm.vm_set_mem(lpsectorpercluster, pck32(8)) + myjit.vm.vm_set_mem(lpbytespersector, pck32(0x200)) + myjit.vm.vm_set_mem(lpnumberoffreeclusters, pck32(0x222222)) + myjit.vm.vm_set_mem(lptotalnumberofclusters, pck32(0x333333)) + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_GetDiskFreeSpaceA(myjit): + kernel32_GetDiskFreeSpace(myjit, whoami(), get_str_ansi) + + +def kernel32_GetDiskFreeSpaceW(myjit): + kernel32_GetDiskFreeSpace(myjit, whoami(), get_str_unic) + + +def kernel32_VirtualQuery(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + ad, lpbuffer, dwl = args + + access_dict = {0x0: 0, + 0x1: 0, + 0x2: PAGE_READ, + 0x4: PAGE_READ | PAGE_WRITE, + 0x10: PAGE_EXEC, + 0x20: PAGE_EXEC | PAGE_READ, + 0x40: PAGE_EXEC | PAGE_READ | PAGE_WRITE, + 0x100: 0 + } + access_dict_inv = dict([(x[1], x[0]) for x in access_dict.items()]) + + all_mem = myjit.vm.vm_get_all_memory() + found = None + for basead, m in all_mem.items(): + if basead <= ad < basead + m['size']: + found = ad, m + break + if not found: + raise ValueError('cannot find mem', hex(ad)) + + if dwl != 0x1c: + raise ValueError('strange mem len', hex(dwl)) + s = struct.pack('IIIIIII', + ad, + basead, + access_dict_inv[m['access']], + m['size'], + 0x1000, + access_dict_inv[m['access']], + 0x01000000) + myjit.vm.vm_set_mem(lpbuffer, s) + + myjit.func_ret_stdcall(ret_ad, dwl) + + +def kernel32_GetProcessAffinityMask(myjit): + ret_ad, args = myjit.func_args_stdcall(3) + hprocess, procaffmask, systemaffmask = args + myjit.vm.vm_set_mem(procaffmask, pck32(1)) + myjit.vm.vm_set_mem(systemaffmask, pck32(1)) + + myjit.func_ret_stdcall(ret_ad, 1) + + +def msvcrt_rand(myjit): + ret_ad, args = myjit.func_args_cdecl(0) + myjit.func_ret_stdcall(ret_ad, 0x666) + + +def kernel32_SetFilePointer(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + hwnd, distance, p_distance_high, movemethod = args + + if hwnd == winobjs.module_cur_hwnd: + pass + elif hwnd in winobjs.handle_pool: + pass + else: + raise ValueError('unknown hwnd!') + + eax = 0xffffffff + data = None + if hwnd in winobjs.files_hwnd: + winobjs.files_hwnd[winobjs.module_cur_hwnd].seek(distance) + elif hwnd in winobjs.handle_pool: + wh = winobjs.handle_pool[hwnd] + data = wh.info.seek(distance) + else: + raise ValueError('unknown filename') + myjit.func_ret_stdcall(ret_ad, distance) + + +def kernel32_SetFilePointerEx(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + hwnd, distance_l, distance_h, pnewfileptr, movemethod = args + + distance = distance_l | (distance_h << 32) + if distance: + TODO_XXX + + if pnewfileptr: + TODO_XXX + if hwnd == winobjs.module_cur_hwnd: + pass + elif hwnd in winobjs.handle_pool: + pass + else: + raise ValueError('unknown hwnd!') + + eax = 0xffffffff + data = None + if hwnd in winobjs.files_hwnd: + winobjs.files_hwnd[winobjs.module_cur_hwnd].seek(distance) + elif hwnd in winobjs.handle_pool: + wh = winobjs.handle_pool[hwnd] + data = wh.info.seek(distance) + else: + raise ValueError('unknown filename') + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_SetEndOfFile(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + hwnd, = args + if hwnd in winobjs.handle_pool: + wh = winobjs.handle_pool[hwnd] + wh.info.seek(0, 2) + else: + raise ValueError('unknown filename') + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_FlushFileBuffers(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + hwnd, = args + if hwnd in winobjs.handle_pool: + pass + else: + raise ValueError('unknown filename') + myjit.func_ret_stdcall(ret_ad, 1) + + +def kernel32_WriteFile(myjit): + ret_ad, args = myjit.func_args_stdcall(5) + (hwnd, lpbuffer, nnumberofbytestowrite, + lpnumberofbyteswrite, lpoverlapped) = args + + data = myjit.vm.vm_get_mem(lpbuffer, nnumberofbytestowrite) + + if hwnd == winobjs.module_cur_hwnd: + pass + elif hwnd in winobjs.handle_pool: + pass + else: + raise ValueError('unknown hwnd!') + + eax = 0xffffffff + if hwnd in winobjs.files_hwnd: + winobjs.files_hwnd[winobjs.module_cur_hwnd].write(data) + elif hwnd in winobjs.handle_pool: + wh = winobjs.handle_pool[hwnd] + wh.info.write(data) + else: + raise ValueError('unknown filename') + + if (lpnumberofbyteswrite): + myjit.vm.vm_set_mem(lpnumberofbyteswrite, pck32(len(data))) + + myjit.func_ret_stdcall(ret_ad, 1) + + +def user32_IsCharUpperA(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + c, = args + + if c & 0x20: + ret = 0 + else: + ret = 1 + myjit.func_ret_stdcall(ret_ad, ret) + + +def user32_IsCharLowerA(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + c, = args + + if c & 0x20: + ret = 1 + else: + ret = 0 + + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_GetSystemDefaultLangID(myjit): + ret_ad, args = myjit.func_args_stdcall(0) + myjit.func_ret_stdcall(ret_ad, 0x409) # encglish + + +def msvcrt_malloc(myjit): + ret_ad, args = myjit.func_args_cdecl(1) + msize, = args + addr = alloc_mem(myjit, msize) + myjit.func_ret_cdecl(ret_ad, addr) + + +def msvcrt_free(myjit): + ret_ad, args = myjit.func_args_cdecl(1) + ptr, = args + myjit.func_ret_cdecl(ret_ad, 0) + + +def msvcrt_fopen(myjit): + ret_ad, args = myjit.func_args_cdecl(2) + fname, rw = args + + fname = get_str_ansi(myjit, fname) + rw = get_str_ansi(myjit, rw) + print fname, rw + if rw in ['rb', 'wb+']: + fname = fname.replace('\\', "/").lower() + f = os.path.join('file_sb', fname) + h = open(f, rw) + eax = winobjs.handle_pool.add(f, h) + alloc_addr = alloc_mem(myjit, 0x20) + myjit.vm.vm_set_mem(alloc_addr, pck32(0x11112222) + pck32( + 0) + pck32(0) + pck32(0) + pck32(eax)) # pck32(0x11112222) + else: + raise NotImplementedError("Untested case") + + myjit.func_ret_cdecl(ret_ad, alloc_addr) + + +def msvcrt_fseek(myjit): + ret_ad, args = myjit.func_args_cdecl(3) + stream, offset, orig = args + fd = upck32(myjit.vm.vm_get_mem(stream + 0x10, 4)) + print hex(fd) + + if not fd in winobjs.handle_pool: + raise NotImplementedError("Untested case") + o = winobjs.handle_pool[fd] + o.info.seek(offset, orig) + myjit.func_ret_cdecl(ret_ad, 0) + + +def msvcrt_ftell(myjit): + ret_ad, args = myjit.func_args_cdecl(1) + stream, = args + fd = upck32(myjit.vm.vm_get_mem(stream + 0x10, 4)) + print hex(fd) + + if not fd in winobjs.handle_pool: + raise NotImplementedError("Untested case") + o = winobjs.handle_pool[fd] + off = o.info.tell() + myjit.func_ret_cdecl(ret_ad, off) + + +def msvcrt_rewind(myjit): + ret_ad, args = myjit.func_args_cdecl(1) + stream, = args + fd = upck32(myjit.vm.vm_get_mem(stream + 0x10, 4)) + print hex(fd) + + if not fd in winobjs.handle_pool: + raise NotImplementedError("Untested case") + o = winobjs.handle_pool[fd] + off = o.info.seek(0, 0) + myjit.func_ret_cdecl(ret_ad, 0) + + +def msvcrt_fread(myjit): + ret_ad, args = myjit.func_args_cdecl(4) + buf, size, nmemb, stream = args + fd = upck32(myjit.vm.vm_get_mem(stream + 0x10, 4)) + print hex(fd) + if not fd in winobjs.handle_pool: + raise NotImplementedError("Untested case") + + data = winobjs.handle_pool[fd].info.read(size * nmemb) + myjit.vm.vm_set_mem(buf, data) + myjit.func_ret_cdecl(ret_ad, nmemb) + + +def msvcrt_fclose(myjit): + ret_ad, args = myjit.func_args_cdecl(1) + stream, = args + fd = upck32(myjit.vm.vm_get_mem(stream + 0x10, 4)) + print hex(fd) + + if not fd in winobjs.handle_pool: + raise NotImplementedError("Untested case") + o = winobjs.handle_pool[fd] + off = o.info.close() + myjit.func_ret_cdecl(ret_ad, 0) + + +def msvcrt_atexit(myjit): + ret_ad, args = myjit.func_args_cdecl(1) + func, = args + myjit.func_ret_cdecl(ret_ad, 0) + + +def user32_MessageBoxA(myjit): + ret_ad, args = myjit.func_args_stdcall(4) + hwnd, lptext, lpcaption, utype = args + + text = get_str_ansi(myjit, lptext) + caption = get_str_ansi(myjit, lpcaption) + + print 'Caption:', repr(caption), 'Text:', repr(text) + + myjit.func_ret_stdcall(ret_ad, 0) + + +def kernel32_myGetTempPath(myjit, func): + ret_ad, args = myjit.func_args_stdcall(2) + l, buf = args + + l = 'c:\\temp\\' + myjit.vm.vm_set_mem(buf, func(l + '\x00')) + myjit.func_ret_stdcall(ret_ad, len(l)) + + +def kernel32_GetTempPathA(myjit): + kernel32_myGetTempPath(myjit, set_str_ansi) + + +def kernel32_GetTempPathW(myjit): + kernel32_myGetTempPath(myjit, set_str_unic) + + +temp_num = 0 + + +def kernel32_GetTempFileNameA(myjit): + global temp_num + ret_ad, args = myjit.func_args_stdcall(4) + path, ext, unique, buf = args + + temp_num += 1 + if ext: + ext = get_str_ansi(myjit, ext) + else: + ext = 'tmp' + if path: + path = get_str_ansi(myjit, path) + else: + path = "xxx" + print ext, path + fname = path + "\\" + "temp%.4d" % temp_num + "." + ext + print fname + myjit.vm.vm_set_mem(buf, fname) + + myjit.func_ret_stdcall(ret_ad, 0) + + +class win32_find_data: + fileattrib = 0 + creationtime = 0 + lastaccesstime = 0 + lastwritetime = 0 + filesizehigh = 0 + filesizelow = 0 + dwreserved0 = 0 + dwreserved1 = 0x1337beef + cfilename = "" + alternamefilename = "" + + def __init__(self, **kargs): + for k, v in kargs.items(): + setattr(self, k, v) + + def toStruct(self): + s = struct.pack('=IQQQIIII', + self.fileattrib, + self.creationtime, + self.lastaccesstime, + self.lastwritetime, + self.filesizehigh, + self.filesizelow, + self.dwreserved0, + self.dwreserved1) + fname = self.cfilename + '\x00' * win_api_x86_32.MAX_PATH + fname = fname[:win_api_x86_32.MAX_PATH] + s += fname + fname = self.alternamefilename + '\x00' * 14 + fname = fname[:14] + s += fname + return s + + +class find_data_mngr: + + def __init__(self): + self.patterns = {} + self.flist = [] + # handle number -> (flist index, current index in list) + self.handles = {} + + def add_list(self, pattern, flist): + index = len(self.flist) + self.flist.append(flist) + + self.patterns[pattern] = index + + def findfirst(self, pattern): + assert(pattern in self.patterns) + findex = self.patterns[pattern] + h = len(self.handles) + 1 + self.handles[h] = [findex, 0] + return h + + def findnext(self, h): + assert(h in self.handles) + findex, index = self.handles[h] + if index >= len(self.flist[findex]): + return None + fname = self.flist[findex][index] + self.handles[h][1] += 1 + + return fname + + +def kernel32_FindFirstFileA(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + pfilepattern, pfindfiledata = args + + filepattern = get_str_ansi(myjit, pfilepattern) + print repr(filepattern) + h = winobjs.find_data.findfirst(filepattern) + + fname = winobjs.find_data.findnext(h) + fdata = win32_find_data(cfilename=fname) + + myjit.vm.vm_set_mem(pfindfiledata, fdata.toStruct()) + myjit.func_ret_stdcall(ret_ad, h) + + +def kernel32_FindNextFileA(myjit): + ret_ad, args = myjit.func_args_stdcall(2) + handle, pfindfiledata = args + + fname = winobjs.find_data.findnext(handle) + if fname is None: + ret = 0 + else: + ret = 1 + fdata = win32_find_data(cfilename=fname) + myjit.vm.vm_set_mem(pfindfiledata, fdata.toStruct()) + + myjit.func_ret_stdcall(ret_ad, ret) + + +def kernel32_GetNativeSystemInfo(myjit): + ret_ad, args = myjit.func_args_stdcall(1) + sys_ptr, = args + sysinfo = systeminfo() + myjit.vm.vm_set_mem(sys_ptr, sysinfo.pack()) + myjit.func_ret_stdcall(ret_ad, 0) + + +def raw2guid(r): + o = struct.unpack('IHHHBBBBBB', r) + return '{%.8X-%.4X-%.4X-%.4X-%.2X%.2X%.2X%.2X%.2X%.2X}' % o + + +digs = string.digits + string.lowercase + + +def int2base(x, base): + if x < 0: + sign = -1 + elif x == 0: + return '0' + else: + sign = 1 + x *= sign + digits = [] + while x: + digits.append(digs[x % base]) + x /= base + if sign < 0: + digits.append('-') + digits.reverse() + return ''.join(digits) + + +def msvcrt__ultow(myjit): + ret_ad, args = myjit.func_args_cdecl(3) + value, p, radix = args + + value &= 0xFFFFFFFF + if not radix in [10, 16, 20]: + TODO_TEST + s = int2base(value, radix) + myjit.vm.vm_set_mem(p, set_str_unic(s + "\x00")) + myjit.func_ret_cdecl(ret_ad, p) + + +def msvcrt_myfopen(myjit, func): + ret_ad, args = myjit.func_args_cdecl(2) + pfname, pmode = args + + + fname = func(myjit, pfname) + rw = func(myjit, pmode) + print repr(fname) + print repr(rw) + + if rw in ['r', 'rb', 'wb+']: + fname = fname.replace('\\', "/").lower() + f = os.path.join('file_sb', fname) + h = open(f, rw) + eax = winobjs.handle_pool.add(f, h) + dwsize = 0x20 + alloc_addr = alloc_mem(myjit, dwsize) + pp = pck32(0x11112222)+pck32(0)+pck32(0)+pck32(0)+pck32(eax)#pdw(0x11112222) + myjit.vm.vm_set_mem(alloc_addr, pp) + + + else: + raise ValueError('unknown access mode %s'%rw) + + myjit.func_ret_cdecl(ret_ad, alloc_addr) + +def msvcrt__wfopen(myjit): + msvcrt_myfopen(myjit, get_str_unic) + +def msvcrt_fopen(myjit): + msvcrt_myfopen(myjit, get_str_ansi) diff --git a/miasm2/jitter/os_dep/win_api_x86_32_seh.py b/miasm2/jitter/os_dep/win_api_x86_32_seh.py new file mode 100644 index 00000000..4136c592 --- /dev/null +++ b/miasm2/jitter/os_dep/win_api_x86_32_seh.py @@ -0,0 +1,896 @@ +#!/usr/bin/env python +#-*- coding:utf-8 -*- + +# +# 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. +# +import logging +from elfesteem import pe_init +from miasm2.jitter.vm_mngr import * +from miasm2.jitter.csts import * +from miasm2.core.utils import * +from miasm2.arch import x86 +import os + +# Constants Windows +EXCEPTION_BREAKPOINT = 0x80000003 +EXCEPTION_ACCESS_VIOLATION = 0xc0000005 +EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094 +EXCEPTION_PRIV_INSTRUCTION = 0xc0000096 +EXCEPTION_ILLEGAL_INSTRUCTION = 0xc000001d + + +log = logging.getLogger("seh_helper") +console_handler = logging.StreamHandler() +console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) +log.addHandler(console_handler) +log.setLevel(logging.WARN) + +FS_0_AD = 0x7ff70000 +PEB_AD = 0x7ffdf000 +LDR_AD = 0x340000 + +MAX_MODULES = 0x40 + +# fs:[0] Page (TIB) +tib_address = FS_0_AD +peb_address = PEB_AD +peb_ldr_data_offset = 0x1ea0 +peb_ldr_data_address = LDR_AD + peb_ldr_data_offset # PEB_AD + 0x1000 + + +modules_list_offset = 0x1f00 + +InInitializationOrderModuleList_offset = 0x1ee0 # 0x1f48 +InInitializationOrderModuleList_address = LDR_AD + \ + InInitializationOrderModuleList_offset # PEB_AD + 0x2000 + +InLoadOrderModuleList_offset = 0x1ee0 + \ + MAX_MODULES * 0x1000 # 0x1f48 + MAX_MODULES*0x1000 +InLoadOrderModuleList_address = LDR_AD + \ + InLoadOrderModuleList_offset # PEB_AD + 0x2000 + +# in_load_order_module_1 = LDR_AD + +# in_load_order_module_list_offset#PEB_AD + 0x3000 +default_seh = PEB_AD + 0x20000 + +process_environment_address = 0x10000 +process_parameters_address = 0x200000 + +context_address = 0x201000 +exception_record_address = context_address + 0x1000 +return_from_exception = 0x6eadbeef + +FAKE_SEH_B_AD = context_address + 0x2000 + +cur_seh_ad = FAKE_SEH_B_AD + +loaded_modules = ["ntdll.dll", "kernel32.dll"] +main_pe = None +main_pe_name = "c:\\xxx\\toto.exe" + + +def build_fake_teb(): + """ + +0x000 NtTib : _NT_TIB + +0x01c EnvironmentPointer : Ptr32 Void + +0x020 ClientId : _CLIENT_ID + +0x028 ActiveRpcHandle : Ptr32 Void + +0x02c ThreadLocalStoragePointer : Ptr32 Void + +0x030 ProcessEnvironmentBlock : Ptr32 _PEB + +0x034 LastErrorValue : Uint4B + ... + """ + o = "" + o += pck32(default_seh) + o += (0x18 - len(o)) * "\x00" + o += pck32(tib_address) + + o += (0x30 - len(o)) * "\x00" + o += pck32(peb_address) + o += pck32(0x11223344) + + return o + + +def build_fake_peb(): + """ + +0x000 InheritedAddressSpace : UChar + +0x001 ReadImageFileExecOptions : UChar + +0x002 BeingDebugged : UChar + +0x003 SpareBool : UChar + +0x004 Mutant : Ptr32 Void + +0x008 ImageBaseAddress : Ptr32 Void + +0x00c Ldr : Ptr32 _PEB_LDR_DATA + +0x010 processparameter + """ + + offset_serverdata = 0x100 + offset_data1 = 0x108 + offset_data2 = 0x110 + o = "" + o += "\x00" * 0x8 + if main_pe: + o += pck32(main_pe.NThdr.ImageBase) + else: + o += "AAAA" + o += pck32(peb_ldr_data_address) + o += pck32(process_parameters_address) + + o += (0x54 - len(o)) * "A" + o += pck32(peb_address + offset_serverdata) + o += (0x64 - len(o)) * "E" + o += pck32(1) # number of cpu + + o += (offset_serverdata - len(o)) * "B" + o += pck32(0x33333333) + o += pck32(peb_address + offset_data1) + o += (offset_data1 - len(o)) * "C" + o += pck32(0x44444444) + o += pck32(peb_address + offset_data2) + o += (offset_data2 - len(o)) * "D" + o += pck32(0x55555555) + o += pck32(0x0077007C) + return o + + +def build_fake_ldr_data(modules_info): + """ + +0x000 Length : Uint4B + +0x004 Initialized : UChar + +0x008 SsHandle : Ptr32 Void + +0x00c InLoadOrderModuleList : _LIST_ENTRY + +0x014 InMemoryOrderModuleList : _LIST_ENTRY + +0x01C InInitializationOrderModuleList : _LIST_ENTRY + """ + o = "" + # ldr offset pad + o += "\x00" * peb_ldr_data_offset + o += "\x00" * 0xc + # text XXX + + # get main pe info + m_e = None + for bname, (addr, e) in modules_info.items(): + if e == main_pe: + m_e = (e, bname, addr) + break + if not m_e: + log.warn('no main pe, ldr data will be unconsistant') + else: + print 'inloadorder first', hex(m_e[2]) + o += pck32(m_e[2]) + pck32(0) + + # get ntdll + ntdll_e = None + for bname, (addr, e) in modules_info.items(): + if bname[::2].lower() == "ntdll.dll": + ntdll_e = (e, bname, addr) + continue + if not ntdll_e: + log.warn('no ntdll, ldr data will be unconsistant') + else: + print 'ntdll', hex(ntdll_e[2]) + o += pck32(ntdll_e[2] + 0x8) + pck32(0) # XXX TODO + o += pck32(ntdll_e[2] + 0x10) + pck32(0) + + return o + +# def build_fake_InInitializationOrderModuleList(modules_name): +# """ +# +0x000 Flink : Ptr32 -+ This distance +# +0x004 Blink : Ptr32 | is eight bytes +# +0x018 DllBase : Ptr32 Void -+ DllBase +# +0x01c EntryPoint : Ptr32 Void +# +0x020 SizeOfImage : Uint4B +# +0x024 FullDllName : _UNICODE_STRING +# +0x02c BaseDllName : _UNICODE_STRING +# +0x034 Flags : Uint4B +# +0x038 LoadCount : Uint2B +# +0x03a TlsIndex : Uint2B +# +0x03c HashLinks : _LIST_ENTRY +# +0x03c SectionPointer : Ptr32 Void +# +0x040 CheckSum : Uint4B +# +0x044 TimeDateStamp : Uint4B +# +0x044 LoadedImports : Ptr32 Void +# +0x048 EntryPointActivationContext : Ptr32 Void +# +0x04c PatchInformation : Ptr32 Void +# """ +# +# o = "" +# offset_name = 0x700 +# for i, m in enumerate(modules_name): +# fname = os.path.join('win_dll', m) +# if isinstance(m, tuple): +# fname, e = m +# else: +# fname, e = m, None +# bname = os.path.split(fname)[1].lower() +# bname = "\x00".join(bname)+"\x00" +# print "add module", repr(bname) +# print hex(InInitializationOrderModuleList_address+i*0x1000) +# if e == None: +# e = pe_init.PE(open(fname, 'rb').read()) +# +# next_ad = InInitializationOrderModuleList_address + (i+1)*0x1000 +# if i == len(modules_name) -1: +# next_ad = InInitializationOrderModuleList_address +# m_o = "" +# m_o += pck32(next_ad ) +# m_o += pck32(InInitializationOrderModuleList_address + (i-1)*0x1000) +# m_o += pck32(next_ad + 8 ) +# m_o += pck32(InInitializationOrderModuleList_address +# + (i-1)*0x1000 + 8) +# m_o += pck32(next_ad + 0x10 ) +# m_o += pck32(InInitializationOrderModuleList_address +# + (i-1)*0x1000 + 0x10) +# m_o += pck32(e.NThdr.ImageBase) +# m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint)) +# m_o += pck32(e.NThdr.sizeofimage) +# +# m_o += (0x24 - len(m_o))*"A" +# print hex(len(bname)), repr(bname) +# m_o += struct.pack('HH', len(bname), len(bname)+2) +# m_o += pck32(InInitializationOrderModuleList_address +# + i*0x1000+offset_name) +# +# m_o += (0x2C - len(m_o))*"A" +# m_o += struct.pack('HH', len(bname), len(bname)+2) +# m_o += pck32(InInitializationOrderModuleList_address +# + i*0x1000+offset_name) +# +# m_o += (offset_name - len(m_o))*"B" +# m_o += bname +# m_o += "\x00"*3 +# +# +# m_o += (0x1000 - len(m_o))*"J" +# +# print "module", "%.8X"%e.NThdr.ImageBase, fname +# +# o += m_o +# return o +# +dummy_e = pe_init.PE() +dummy_e.NThdr.ImageBase = 0 +dummy_e.Opthdr.AddressOfEntryPoint = 0 +dummy_e.NThdr.sizeofimage = 0 + + +def create_modules_chain(myjit, modules_name): + modules_info = {} + base_addr = LDR_AD + modules_list_offset # XXXX + offset_name = 0x500 + offset_path = 0x600 + + out = "" + for i, m in enumerate([(main_pe_name, main_pe), + ("", dummy_e)] + modules_name): + addr = base_addr + i * 0x1000 + # fname = os.path.join('win_dll', m) + if isinstance(m, tuple): + fname, e = m + else: + fname, e = m, None + bpath = fname.replace('/', '\\') + bname = os.path.split(fname)[1].lower() + bname = "\x00".join(bname) + "\x00" + # print "add module", repr(bname), repr(bpath) + # print hex(InInitializationOrderModuleList_address+i*0x1000) + if e is None: + if i == 0: + full_name = fname + else: + full_name = os.path.join("win_dll", fname) + try: + e = pe_init.PE(open(full_name, 'rb').read()) + except IOError: + log.error('no main pe, ldr data will be unconsistant!!') + e = None + if e is None: + continue + print "add module", hex(e.NThdr.ImageBase), repr(bname) + + modules_info[bname] = addr, e + + m_o = "" + m_o += pck32(0) + m_o += pck32(0) + m_o += pck32(0) + m_o += pck32(0) + m_o += pck32(0) + m_o += pck32(0) + m_o += pck32(e.NThdr.ImageBase) + m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint)) + m_o += pck32(e.NThdr.sizeofimage) + + m_o += (0x24 - len(m_o)) * "A" + print hex(len(bname)), repr(bname) + m_o += struct.pack('HH', len(bname), len(bname) + 2) + m_o += pck32(addr + offset_path) + + m_o += (0x2C - len(m_o)) * "A" + m_o += struct.pack('HH', len(bname), len(bname) + 2) + m_o += pck32(addr + offset_name) + + m_o += (offset_name - len(m_o)) * "B" + m_o += bname + m_o += "\x00" * 3 + + m_o += (offset_path - len(m_o)) * "B" + m_o += "\x00".join(bpath) + "\x00" + m_o += "\x00" * 3 + # out += m_o + myjit.vm.vm_set_mem(addr, m_o) + return modules_info + + +def fix_InLoadOrderModuleList(myjit, module_info): + print "fix inloadorder" + # first binary is PE + # last is dumm_e + olist = [] + m_e = None + d_e = None + for m in [main_pe_name, ""] + loaded_modules: + + if isinstance(m, tuple): + fname, e = m + else: + fname, e = m, None + + if "/" in fname: + fname = fname[fname.rfind("/") + 1:] + bname = '\x00'.join(fname) + '\x00' + if not bname.lower() in module_info: + log.warn('module not found, ldr data will be unconsistant') + continue + + addr, e = module_info[bname.lower()] + # for bname, (addr, e) in module_info.items(): + print bname + if e == main_pe: + m_e = (e, bname, addr) + continue + elif e == dummy_e: + d_e = (e, bname, addr) + continue + olist.append((e, bname, addr)) + if not m_e or not d_e: + log.warn('no main pe, ldr data will be unconsistant') + else: + olist[0:0] = [m_e] + olist.append(d_e) + + last_addr = 0 + for i in xrange(len(olist)): + e, bname, addr = olist[i] + p_e, p_bname, p_addr = olist[(i - 1) % len(olist)] + n_e, n_bname, n_addr = olist[(i + 1) % len(olist)] + myjit.vm.vm_set_mem(addr + 0, pck32(n_addr) + pck32(p_addr)) + + +def fix_InMemoryOrderModuleList(myjit, module_info): + # first binary is PE + # last is dumm_e + olist = [] + m_e = None + d_e = None + for m in [main_pe_name, ""] + loaded_modules: + + if isinstance(m, tuple): + fname, e = m + else: + fname, e = m, None + + if "/" in fname: + fname = fname[fname.rfind("/") + 1:] + bname = '\x00'.join(fname) + '\x00' + if not bname.lower() in module_info: + log.warn('module not found, ldr data will be unconsistant') + continue + addr, e = module_info[bname.lower()] + # for bname, (addr, e) in module_info.items(): + print bname + if e == main_pe: + m_e = (e, bname, addr) + continue + elif e == dummy_e: + d_e = (e, bname, addr) + continue + olist.append((e, bname, addr)) + if not m_e or not d_e: + log.warn('no main pe, ldr data will be unconsistant') + else: + olist[0:0] = [m_e] + olist.append(d_e) + + last_addr = 0 + + for i in xrange(len(olist)): + e, bname, addr = olist[i] + p_e, p_bname, p_addr = olist[(i - 1) % len(olist)] + n_e, n_bname, n_addr = olist[(i + 1) % len(olist)] + myjit.vm.vm_set_mem( + addr + 0x8, pck32(n_addr + 0x8) + pck32(p_addr + 0x8)) + + +def fix_InInitializationOrderModuleList(myjit, module_info): + # first binary is ntdll + # second binary is kernel32 + olist = [] + ntdll_e = None + kernel_e = None + for bname, (addr, e) in module_info.items(): + if bname[::2].lower() == "ntdll.dll": + ntdll_e = (e, bname, addr) + continue + elif bname[::2].lower() == "kernel32.dll": + kernel_e = (e, bname, addr) + continue + elif e == dummy_e: + d_e = (e, bname, addr) + continue + elif e == main_pe: + continue + olist.append((e, bname, addr)) + if not ntdll_e or not kernel_e or not d_e: + log.warn('no kernel ntdll, ldr data will be unconsistant') + else: + olist[0:0] = [ntdll_e] + olist[1:1] = [kernel_e] + + olist.append(d_e) + + last_addr = 0 + for i in xrange(len(olist)): + e, bname, addr = olist[i] + p_e, p_bname, p_addr = olist[(i - 1) % len(olist)] + n_e, n_bname, n_addr = olist[(i + 1) % len(olist)] + myjit.vm.vm_set_mem( + addr + 0x10, pck32(n_addr + 0x10) + pck32(p_addr + 0x10)) + + +def add_process_env(myjit): + env_str = 'ALLUSEESPROFILE=C:\\Documents and Settings\\All Users\x00' + env_str = '\x00'.join(env_str) + env_str += "\x00" * 0x10 + myjit.vm.vm_add_memory_page(process_environment_address, + PAGE_READ | PAGE_WRITE, + env_str) + myjit.vm.vm_set_mem(process_environment_address, env_str) + + +def add_process_parameters(myjit): + o = "" + o += pck32(0x1000) # size + o += "E" * (0x48 - len(o)) + o += pck32(process_environment_address) + myjit.vm.vm_add_memory_page(process_parameters_address, + PAGE_READ | PAGE_WRITE, + o) + + +def build_fake_InLoadOrderModuleList(modules_name): + """ + +0x000 Flink : Ptr32 -+ This distance + +0x004 Blink : Ptr32 | is eight bytes + +0x018 DllBase : Ptr32 Void -+ DllBase -> _IMAGE_DOS_HEADER + +0x01c EntryPoint : Ptr32 Void + +0x020 SizeOfImage : Uint4B + +0x024 FullDllName : _UNICODE_STRING + +0x02c BaseDllName : _UNICODE_STRING + +0x034 Flags : Uint4B + +0x038 LoadCount : Uint2B + +0x03a TlsIndex : Uint2B + +0x03c HashLinks : _LIST_ENTRY + +0x03c SectionPointer : Ptr32 Void + +0x040 CheckSum : Uint4B + +0x044 TimeDateStamp : Uint4B + +0x044 LoadedImports : Ptr32 Void + +0x048 EntryPointActivationContext : Ptr32 Void + +0x04c PatchInformation : Ptr32 Void + """ + + o = "" + offset_name = 0x700 + first_name = "\x00".join(main_pe_name + "\x00\x00") + + o = "" + o += pck32(InLoadOrderModuleList_address) + o += pck32(InLoadOrderModuleList_address + + (len(modules_name) - 1) * 0x1000) + o += pck32(InLoadOrderModuleList_address + 8) + o += pck32(InLoadOrderModuleList_address + + (len(modules_name) - 1) * 0x1000 + 8) + o += pck32(InLoadOrderModuleList_address + 0x10) + o += pck32(InLoadOrderModuleList_address + + (len(modules_name) - 1) * 0x1000 + 0x10) + + if main_pe: + o += pck32(main_pe.NThdr.ImageBase) + o += pck32(main_pe.rva2virt(main_pe.Opthdr.AddressOfEntryPoint)) + else: + # no fixed values + pass + + o += (0x24 - len(o)) * "A" + o += struct.pack('HH', len(first_name), len(first_name)) + o += pck32(InLoadOrderModuleList_address + offset_name) + + o += (0x2C - len(o)) * "A" + o += struct.pack('HH', len(first_name), len(first_name)) + o += pck32(InLoadOrderModuleList_address + offset_name) + + o += (offset_name - len(o)) * "B" + o += first_name + o += (0x1000 - len(o)) * "C" + for i, m in enumerate(modules_name): + # fname = os.path.join('win_dll', m) + if isinstance(m, tuple): + fname, e = m + else: + fname, e = m, None + bname = os.path.split(fname)[1].lower() + bname = "\x00".join(bname) + "\x00" + print hex(InLoadOrderModuleList_address + i * 0x1000) + if e is None: + e = pe_init.PE(open(fname, 'rb').read()) + + print "add module", hex(e.NThdr.ImageBase), repr(bname) + + next_ad = InLoadOrderModuleList_address + (i + 1) * 0x1000 + if i == len(modules_name) - 1: + next_ad = InLoadOrderModuleList_address + m_o = "" + m_o += pck32(next_ad) + m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000) + m_o += pck32(next_ad + 8) + m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000 + 8) + m_o += pck32(next_ad + 0x10) + m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000 + 0x10) + m_o += pck32(e.NThdr.ImageBase) + m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint)) + m_o += pck32(e.NThdr.sizeofimage) + + m_o += (0x24 - len(m_o)) * "A" + print hex(len(bname)), repr(bname) + m_o += struct.pack('HH', len(bname), len(bname) + 2) + m_o += pck32(InLoadOrderModuleList_address + i * 0x1000 + offset_name) + + m_o += (0x2C - len(m_o)) * "A" + m_o += struct.pack('HH', len(bname), len(bname) + 2) + m_o += pck32(InLoadOrderModuleList_address + i * 0x1000 + offset_name) + + m_o += (offset_name - len(m_o)) * "B" + m_o += bname + m_o += "\x00" * 3 + + m_o += (0x1000 - len(m_o)) * "J" + + print "module", "%.8X" % e.NThdr.ImageBase, fname + + o += m_o + return o + + +all_seh_ad = dict([(x, None) + for x in xrange(FAKE_SEH_B_AD, FAKE_SEH_B_AD + 0x1000, 0x20)]) +# http://blog.fireeye.com/research/2010/08/download_exec_notes.html + + +def init_seh(myjit): + global seh_count + seh_count = 0 + # myjit.vm.vm_add_memory_page(tib_address, PAGE_READ | PAGE_WRITE, + # p(default_seh) + p(0) * 11 + p(peb_address)) + myjit.vm.vm_add_memory_page( + FS_0_AD, PAGE_READ | PAGE_WRITE, build_fake_teb()) + # myjit.vm.vm_add_memory_page(peb_address, PAGE_READ | PAGE_WRITE, p(0) * + # 3 + p(peb_ldr_data_address)) + myjit.vm.vm_add_memory_page( + peb_address, PAGE_READ | PAGE_WRITE, build_fake_peb()) + # myjit.vm.vm_add_memory_page(peb_ldr_data_address, PAGE_READ | + # PAGE_WRITE, p(0) * 3 + p(in_load_order_module_list_address) + p(0) * + # 0x20) + + """ + ldr_data += "\x00"*(InInitializationOrderModuleList_offset - len(ldr_data)) + ldr_data += build_fake_InInitializationOrderModuleList(loaded_modules) + ldr_data += "\x00"*(InLoadOrderModuleList_offset - len(ldr_data)) + ldr_data += build_fake_InLoadOrderModuleList(loaded_modules) + """ + myjit.vm.vm_add_memory_page( + LDR_AD, PAGE_READ | PAGE_WRITE, "\x00" * MAX_MODULES * 0x1000) + module_info = create_modules_chain(myjit, loaded_modules) + fix_InLoadOrderModuleList(myjit, module_info) + fix_InMemoryOrderModuleList(myjit, module_info) + fix_InInitializationOrderModuleList(myjit, module_info) + + ldr_data = build_fake_ldr_data(module_info) + myjit.vm.vm_set_mem(LDR_AD, ldr_data) + add_process_env(myjit) + add_process_parameters(myjit) + + # myjit.vm.vm_add_memory_page(in_load_order_module_list_address, + # PAGE_READ | PAGE_WRITE, p(0) * 40) + # myjit.vm.vm_add_memory_page(in_load_order_module_list_address, + # PAGE_READ | PAGE_WRITE, build_fake_inordermodule(loaded_modules)) + myjit.vm.vm_add_memory_page(default_seh, PAGE_READ | PAGE_WRITE, pck32( + 0xffffffff) + pck32(0x41414141) + pck32(0x42424242)) + + myjit.vm.vm_add_memory_page( + context_address, PAGE_READ | PAGE_WRITE, '\x00' * 0x2cc) + myjit.vm.vm_add_memory_page( + exception_record_address, PAGE_READ | PAGE_WRITE, '\x00' * 200) + + myjit.vm.vm_add_memory_page( + FAKE_SEH_B_AD, PAGE_READ | PAGE_WRITE, 0x10000 * "\x00") + +# http://www.codeproject.com/KB/system/inject2exe.aspx#RestorethefirstRegistersContext5_1 + + +def regs2ctxt(regs): + ctxt = "" + ctxt += '\x00\x00\x00\x00' # ContextFlags + ctxt += '\x00\x00\x00\x00' * 6 # drX + ctxt += '\x00' * 112 # float context + ctxt += '\x00\x00\x00\x00' + '\x3b\x00\x00\x00' + \ + '\x23\x00\x00\x00' + '\x23\x00\x00\x00' # segment selectors + ctxt += pck32(regs['EDI']) + pck32(regs['ESI']) + pck32(regs['EBX']) + \ + pck32(regs['EDX']) + pck32(regs['ECX']) + pck32(regs['EAX']) + \ + pck32(regs['EBP']) + pck32(regs['EIP']) # gpregs + ctxt += '\x23\x00\x00\x00' # cs + ctxt += '\x00\x00\x00\x00' # eflags + ctxt += pck32(regs['ESP']) # esp + ctxt += '\x23\x00\x00\x00' # ss segment selector + return ctxt + + +def ctxt2regs(ctxt): + ctxt = ctxt[:] + regs = {} + # regs['ctxtsflags'] = upck32(ctxt[:4]) + ctxt = ctxt[4:] + for i in xrange(8): + if i in [4, 5]: + continue + # regs['dr%d'%i] = upck32(ctxt[:4]) + ctxt = ctxt[4:] + + ctxt = ctxt[112:] # skip float + + # regs['seg_gs'] = upck32(ctxt[:4]) + ctxt = ctxt[4:] + # regs['seg_fs'] = upck32(ctxt[:4]) + ctxt = ctxt[4:] + # regs['seg_es'] = upck32(ctxt[:4]) + ctxt = ctxt[4:] + # regs['seg_ds'] = upck32(ctxt[:4]) + ctxt = ctxt[4:] + + regs['EDI'], regs['ESI'], regs['EBX'], regs['EDX'], regs['ECX'], regs[ + 'EAX'], regs['EBP'], regs['EIP'] = struct.unpack('I' * 8, ctxt[:4 * 8]) + ctxt = ctxt[4 * 8:] + + # regs['seg_cs'] = upck32(ctxt[:4]) + ctxt = ctxt[4:] + + # regs['eflag'] = upck32(ctxt[:4]) + ctxt = ctxt[4:] + + regs['ESP'] = upck32(ctxt[:4]) + ctxt = ctxt[4:] + + for a, b in regs.items(): + print a, hex(b) + # skip extended + return regs + + +def get_free_seh_place(): + global all_seh_ad + ads = all_seh_ad.keys() + ads.sort() + for ad in ads: + v = all_seh_ad[ad] + if v is None: + print 'TAKING SEH', hex(ad) + all_seh_ad[ad] = True + return ad + raise ValueError('too many stacked seh ') + + +def free_seh_place(ad): + print 'RELEASING SEH', hex(ad) + + if not ad in all_seh_ad: + raise ValueError('zarb seh ad!', hex(ad)) + if all_seh_ad[ad] is not True: + # @wisk typolol + raise ValueError('seh alreaedy remouvede?!!', hex(ad)) + all_seh_ad[ad] = None + + +def fake_seh_handler(myjit, except_code): + global seh_count + regs = myjit.cpu.vm_get_gpreg() + print '-> exception at', hex(myjit.cpu.EIP), seh_count + seh_count += 1 + + # Help lambda + p = lambda s: struct.pack('I', s) + + # dump_gpregs_py() + # jitarch.dump_gpregs() + # Forge a CONTEXT + ctxt = '\x00\x00\x00\x00' + '\x00\x00\x00\x00' * 6 + '\x00' * 112 + ctxt += '\x00\x00\x00\x00' + '\x3b\x00\x00\x00' + '\x23\x00\x00\x00' + ctxt += '\x23\x00\x00\x00' + ctxt += pck32(myjit.cpu.EDI) + pck32(myjit.cpu.ESI) + \ + pck32(myjit.cpu.EBX) + pck32(myjit.cpu.EDX) + \ + pck32(myjit.cpu.ECX) + pck32(myjit.cpu.EAX) + \ + pck32(myjit.cpu.EBP) + pck32(myjit.cpu.EIP) + ctxt += '\x23\x00\x00\x00' + '\x00\x00\x00\x00' + pck32(myjit.cpu.ESP) + ctxt += '\x23\x00\x00\x00' + # ctxt = regs2ctxt(regs) + + # Find a room for seh + # seh = (get_memory_page_max_address_py()+0x1000)&0xfffff000 + + # Get current seh (fs:[0]) + seh_ptr = upck32(myjit.vm.vm_get_mem(tib_address, 4)) + + # Retrieve seh fields + old_seh, eh, safe_place = struct.unpack( + 'III', myjit.vm.vm_get_mem(seh_ptr, 0xc)) + + print '-> seh_ptr', hex(seh_ptr), '-> { old_seh', + print hex(old_seh), 'eh', hex(eh), 'safe_place', hex(safe_place), '}' + # print '-> write SEH at', hex(seh&0xffffffff) + + # Write current seh + # myjit.vm.vm_add_memory_page(seh, PAGE_READ | PAGE_WRITE, p(old_seh) + + # p(eh) + p(safe_place) + p(0x99999999)) + + # Write context + myjit.vm.vm_set_mem(context_address, ctxt) + + # Write exception_record + + """ + #http://msdn.microsoft.com/en-us/library/aa363082(v=vs.85).aspx + + typedef struct _EXCEPTION_RECORD { + DWORD ExceptionCode; + DWORD ExceptionFlags; + struct _EXCEPTION_RECORD *ExceptionRecord; + PVOID ExceptionAddress; + DWORD NumberParameters; + ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; + } EXCEPTION_RECORD, *PEXCEPTION_RECORD; + """ + + myjit.vm.vm_set_mem(exception_record_address, pck32(except_code) + + pck32(0) + pck32(0) + pck32(myjit.cpu.EIP) + + pck32(0) + pck32(0)) + + # Prepare the stack + myjit.vm_push_uint32_t(context_address) # Context + myjit.vm_push_uint32_t(seh_ptr) # SEH + myjit.vm_push_uint32_t(exception_record_address) # ExceptRecords + myjit.vm_push_uint32_t(return_from_exception) # Ret address + + # Set fake new current seh for exception + fake_seh_ad = get_free_seh_place() + print hex(fake_seh_ad) + myjit.vm.vm_set_mem(fake_seh_ad, pck32(seh_ptr) + pck32( + 0xaaaaaaaa) + pck32(0xaaaaaabb) + pck32(0xaaaaaacc)) + myjit.vm.vm_set_mem(tib_address, pck32(fake_seh_ad)) + + dump_seh(myjit) + + print '-> jumping at', hex(eh) + myjit.vm.vm_set_exception(0) + myjit.cpu.vm_set_exception(0) + + # XXX set ebx to nul? + myjit.cpu.EBX = 0 + + return eh + +fake_seh_handler.base = FAKE_SEH_B_AD + + +def dump_seh(myjit): + print 'dump_seh:' + print '-> tib_address:', hex(tib_address) + cur_seh_ptr = upck32(myjit.vm.vm_get_mem(tib_address, 4)) + indent = 1 + loop = 0 + while True: + if loop > 5: + print "too many seh, quit" + return + prev_seh, eh = struct.unpack('II', myjit.vm.vm_get_mem(cur_seh_ptr, 8)) + print '\t' * indent + 'seh_ptr:', hex(cur_seh_ptr), + print ' -> { prev_seh:', hex(prev_seh), 'eh:', hex(eh), '}' + if prev_seh in [0xFFFFFFFF, 0]: + break + cur_seh_ptr = prev_seh + indent += 1 + loop += 1 + + +def set_win_fs_0(myjit, fs=4): + regs = myjit.cpu.vm_get_gpreg() + regs['FS'] = 0x4 + myjit.cpu.vm_set_gpreg(regs) + myjit.cpu.vm_set_segm_base(regs['FS'], FS_0_AD) + segm_to_do = set([x86.regs.FS]) + return segm_to_do + + +def add_modules_info(pe_in, pe_in_name="toto.exe", all_pe=None): + global main_pe, main_pe_name, loaded_modules + if all_pe is None: + all_pe = [] + main_pe = pe_in + main_pe_name = pe_in_name + loaded_modules = all_pe + + +def return_from_seh(myjit): + "Handle return after a call to fake seh handler" + + # Get current context + myjit.cpu.ESP = upck32(myjit.vm.vm_get_mem(context_address + 0xc4, 4)) + logging.info('-> new esp: %x' % myjit.cpu.ESP) + + # Rebuild SEH + old_seh = upck32(myjit.vm.vm_get_mem(tib_address, 4)) + new_seh = upck32(myjit.vm.vm_get_mem(old_seh, 4)) + logging.info('-> old seh: %x' % old_seh) + logging.info('-> new seh: %x' % new_seh) + myjit.vm.vm_set_mem(tib_address, pck32(new_seh)) + + dump_seh(myjit) + + # Release SEH + free_seh_place(old_seh) + + if myjit.cpu.EAX == 0x0: + # ExceptionContinueExecution + print '-> seh continues' + ctxt_ptr = context_address + print '-> context:', hex(ctxt_ptr) + + # Get registers changes + ctxt_str = myjit.vm.vm_get_mem(ctxt_ptr, 0x2cc) + regs = ctxt2regs(ctxt_str) + myjit.pc = regs["EIP"] + for reg_name, reg_value in regs.items(): + setattr(myjit.cpu, reg_name, reg_value) + + logging.info('-> context::Eip: %x' % myjit.pc) + + elif myjit.cpu.EAX == -1: + raise NotImplementedError("-> seh try to go to the next handler") + + elif myjit.cpu.EAX == 1: + # ExceptionContinueSearch + raise NotImplementedError("-> seh, gameover") diff --git a/miasm2/jitter/queue.h b/miasm2/jitter/queue.h new file mode 100644 index 00000000..0caf72fb --- /dev/null +++ b/miasm2/jitter/queue.h @@ -0,0 +1,553 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD$ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +//#include <sys/cdefs.h> + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * + */ +#define QUEUE_MACRO_DEBUG 0 +#if QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + char * lastfile; + int lastline; + char * prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = \ + SLIST_NEXT(SLIST_NEXT(curelm, field), field); \ + } \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *) \ + ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + if ((STAILQ_NEXT(curelm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((curelm), field);\ + } \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ + if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT((elm)->field.tqe_next); \ + TRASHIT((elm)->field.tqe_prev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + + +#ifdef _KERNEL + +/* + * XXX insque() and remque() are an old way of handling certain queues. + * They bogusly assumes that all queue heads look alike. + */ + +struct quehead { + struct quehead *qh_link; + struct quehead *qh_rlink; +}; + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) + +static __inline void +insque(void *a, void *b) +{ + struct quehead *element = (struct quehead *)a, + *head = (struct quehead *)b; + + element->qh_link = head->qh_link; + element->qh_rlink = head; + head->qh_link = element; + element->qh_link->qh_rlink = element; +} + +static __inline void +remque(void *a) +{ + struct quehead *element = (struct quehead *)a; + + element->qh_link->qh_rlink = element->qh_rlink; + element->qh_rlink->qh_link = element->qh_link; + element->qh_rlink = 0; +} + +#else /* !(__GNUC__ || __INTEL_COMPILER) */ + +void insque(void *a, void *b); +void remque(void *a); + +#endif /* __GNUC__ || __INTEL_COMPILER */ + +#endif /* _KERNEL */ + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c new file mode 100644 index 00000000..7d47fadc --- /dev/null +++ b/miasm2/jitter/vm_mngr.c @@ -0,0 +1,1640 @@ +/* +** 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 <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> + +#include <stdint.h> +#include <inttypes.h> +#include <math.h> + +#include "queue.h" +#include "vm_mngr.h" + + + + +/* +struct memory_page_list_head memory_page_pool; +struct code_bloc_list_head code_bloc_pool; + +struct memory_breakpoint_info_head memory_breakpoint_pool; +*/ + +/****************memory manager**************/ + + + + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + + +//#define DEBUG_MIASM_AUTOMOD_CODE + + + + + +void print_val(uint64_t base, uint64_t addr) +{ + uint64_t *ptr = (uint64_t *) addr; + fprintf(stderr, "addr 0x%"PRIX64" val 0x%"PRIX64"\n", addr-base, *ptr); +} + + +int is_mem_mapped(vm_mngr_t* vm_mngr, uint64_t ad) +{ + struct memory_page_node * mpn; + /* + mpn = memory_page_pool_tab[ad>>MEMORY_PAGE_POOL_MASK_BIT]; + if ( mpn && (mpn->ad <= ad) && (ad < mpn->ad + mpn->size)) + return 1; + */ + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + if ((mpn->ad <= ad) && (ad <mpn->ad + mpn->size)) + return 1; + } + + return 0; +} + + +/* return the address base of the memory page + containing addr +*/ +uint64_t get_mem_base_addr(vm_mngr_t* vm_mngr, uint64_t ad, uint64_t *addr_base) +{ + struct memory_page_node * mpn; + /* + mpn = memory_page_pool_tab[ad>>MEMORY_PAGE_POOL_MASK_BIT]; + if ( mpn && (mpn->ad <= ad) && (ad < mpn->ad + mpn->size)){ + *addr_base = mpn->ad; + return 1; + } + */ + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + if ((mpn->ad <= ad) && (ad <mpn->ad + mpn->size)) { + *addr_base = mpn->ad; + return 1; + } + } + return 0; +} + +struct memory_page_node * get_memory_page_from_address(vm_mngr_t* vm_mngr, uint64_t ad) +{ + struct memory_page_node * mpn; +#if 0 + mpn = memory_page_pool_tab[ad>>MEMORY_PAGE_POOL_MASK_BIT]; + if ( mpn && (mpn->ad <= ad) && (ad < mpn->ad + mpn->size)) + return mpn; + + fprintf(stderr, "WARNING: address 0x%"PRIX64" is not mapped in virtual memory:\n", ad); + //dump_memory_page_pool(); + //dump_gpregs(); + //exit(-1); + vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; + + return NULL; +#else + + //printf("search for page ad: %X\n", ad); + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + if ((mpn->ad <= ad) && (ad < mpn->ad + mpn->size)) + return mpn; + } + fprintf(stderr, "WARNING: address 0x%"PRIX64" is not mapped in virtual memory:\n", ad); + //dump_memory_page_pool(); + //dump_gpregs(); + //exit(-1); + vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; + return NULL; +#endif +} + + + + +static inline uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t ad) +{ + struct memory_page_node * mpn; + unsigned char * addr; + uint64_t ret = 0; + struct memory_breakpoint_info * b; + + + mpn = get_memory_page_from_address(vm_mngr, ad); + if (!mpn) + return 0; + + if ((mpn->access & PAGE_READ) == 0){ + fprintf(stderr, "access to non readable page!! %"PRIX64"\n", ad); + vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; + return 0; + } + + /* check read breakpoint*/ + LIST_FOREACH(b, &vm_mngr->memory_breakpoint_pool, next){ + if ((b->access & BREAKPOINT_READ) == 0) + continue; + if ((b->ad <= ad) && (ad < b->ad + b->size)) + vm_mngr->exception_flags |= EXCEPT_BREAKPOINT_INTERN; + } + + + addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad]; + + /* read fits in a page */ + if (ad - mpn->ad + my_size/8 <= mpn->size){ + switch(my_size){ + case 8: + ret = *((unsigned char*)addr)&0xFF; + break; + case 16: + ret = *((unsigned short*)addr)&0xFFFF; + ret = Endian16_Swap(ret); + break; + case 32: + ret = *((unsigned int*)addr)&0xFFFFFFFF; + ret = Endian32_Swap(ret); + break; + case 64: + ret = *((uint64_t*)addr)&0xFFFFFFFFFFFFFFFFULL; + ret = Endian64_Swap(ret); + break; + default: + exit(0); + break; + } + } + /* read is multiple page wide */ + else{ + unsigned int new_size = my_size; + int index = 0; + fprintf(stderr, "read multiple page! %"PRIX64" %d\n", ad, new_size); + dump_memory_page_pool(vm_mngr); + while (new_size){ + mpn = get_memory_page_from_address(vm_mngr, ad); + if (!mpn) + return 0; + addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad]; + ret |= (*((unsigned char*)addr)&0xFF)<<(index); + index +=8; + new_size -= 8; + ad ++; + } + switch(my_size){ + case 8: + ret = ret; + break; + case 16: + ret = Endian16_Swap(ret); + break; + case 32: + ret = Endian32_Swap(ret); + break; + case 64: + ret = Endian64_Swap(ret); + break; + default: + exit(0); + break; + } + } + return ret; +} + +static inline void memory_page_write(vm_mngr_t* vm_mngr, unsigned int my_size, + uint64_t ad, uint64_t src) +{ + struct memory_page_node * mpn; + unsigned char * addr; + struct memory_breakpoint_info * b; + + mpn = get_memory_page_from_address(vm_mngr, ad); + if (!mpn) + return; + + if ((mpn->access & PAGE_WRITE) == 0){ + fprintf(stderr, "access to non writable page!! %"PRIX64"\n", ad); + vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; + return ; + } + + /* check read breakpoint*/ + LIST_FOREACH(b, &vm_mngr->memory_breakpoint_pool, next){ + if ((b->access & BREAKPOINT_WRITE) == 0) + continue; + if ((b->ad <= ad) && (ad < b->ad + b->size)) + vm_mngr->exception_flags |= EXCEPT_BREAKPOINT_INTERN; + } + + addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad]; + + /* write fits in a page */ + if (ad - mpn->ad + my_size/8 <= mpn->size){ + switch(my_size){ + case 8: + *((unsigned char*)addr) = src&0xFF; + break; + case 16: + src = Endian16_Swap(src); + *((unsigned short*)addr) = src&0xFFFF; + break; + case 32: + src = Endian32_Swap(src); + *((unsigned int*)addr) = src&0xFFFFFFFF; + break; + case 64: + src = Endian64_Swap(src); + *((uint64_t*)addr) = src&0xFFFFFFFFFFFFFFFFULL; + break; + default: + exit(0); + break; + } + } + /* write is multiple page wide */ + else{ + fprintf(stderr, "write multiple page! %"PRIX64" %d\n", ad, my_size); + dump_memory_page_pool(vm_mngr); + switch(my_size){ + + case 8: + src = src; + break; + case 16: + src = Endian16_Swap(src); + break; + case 32: + src = Endian32_Swap(src); + break; + case 64: + src = Endian64_Swap(src); + break; + default: + exit(0); + break; + } + while (my_size){ + mpn = get_memory_page_from_address(vm_mngr, ad); + if (!mpn) + return; + + addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad]; + *((unsigned char*)addr) = src&0xFF; + my_size -= 8; + src >>=8; + ad ++; + } + } +} + +/* TODO: Those functions have to be moved to a common operations file, with + * parity, ... + */ + +inline uint16_t bcdadd_16(uint16_t a, uint16_t b) +{ + int carry = 0; + int i,j = 0; + uint16_t res = 0; + int nib_a, nib_b; + for (i = 0; i < 16; i += 4) { + nib_a = (a >> i) & (0xF); + nib_b = (b >> i) & (0xF); + + j = (carry + nib_a + nib_b); + if (j >= 10) { + carry = 1; + j -= 10; + j &=0xf; + } + else { + carry = 0; + } + res += j << i; + } + return res; +} + +inline uint16_t bcdadd_cf_16(uint16_t a, uint16_t b) +{ + int carry = 0; + int i,j = 0; + int nib_a, nib_b; + for (i = 0; i < 16; i += 4) { + nib_a = (a >> i) & (0xF); + nib_b = (b >> i) & (0xF); + + j = (carry + nib_a + nib_b); + if (j >= 10) { + carry = 1; + j -= 10; + j &=0xf; + } + else { + carry = 0; + } + } + return carry; +} +// ################## + +void dump_code_bloc(vm_mngr_t* vm_mngr) +{ + struct code_bloc_node * cbp; + LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ + fprintf(stderr, "%"PRIX64"%"PRIX64"\n", cbp->ad_start, cbp->ad_stop); + } + +} + +inline void check_write_code_bloc(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr) +{ + struct code_bloc_node * cbp; + vm_mngr->last_write_ad = addr; + vm_mngr->last_write_size = my_size; + + + + //if(vmmngr.my_tick> my_tick) + // printf("M_WRITE %2d %.8X %.8X\n", my_size, addr, src); + if (!(addr + my_size/8 <= vm_mngr->code_bloc_pool_ad_min || + addr >=vm_mngr->code_bloc_pool_ad_max)){ + LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ + if ((cbp->ad_start < addr + my_size/8) && + (addr < cbp->ad_stop)){ +#ifdef DEBUG_MIASM_AUTOMOD_CODE + fprintf(stderr, "**********************************\n"); + fprintf(stderr, "self modifying code %"PRIX64" %.8X\n", + addr, my_size); + fprintf(stderr, "**********************************\n"); + //dump_code_bloc(vm_mngr); +#endif + vm_mngr->exception_flags |= EXCEPT_CODE_AUTOMOD; + + break; + } + } + } +} + +PyObject* addr2BlocObj(vm_mngr_t* vm_mngr, uint64_t addr) +{ + PyObject* pyaddr; + PyObject* b; + + //printf("addr2blocobj %"PRIx64"\n", addr); + pyaddr = PyLong_FromUnsignedLongLong(addr); + /* + Py_INCREF(pyaddr); + return pyaddr; + */ + b = PyDict_GetItem(vm_mngr->addr2obj, pyaddr); + if (b == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + + //printf("addr2blocobj OBJ %p\n", b); + Py_INCREF(b); + return b; +} + +/* +PyObject* add_code_resolver(vm_mngr_t* vm_mngr, uint64_t addr) +{ + pyaddr = PyLong_FromUnsignedLongLong(addr); + + func_resolver* f = malloc(sizeof(func_resolver)); + f->func = addr2blocobj; + fsdfsd + return f; +} +*/ +/* +void MEM_WRITE(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr, unsigned int src) +{ + struct code_bloc_node * cbp; + + vm_mngr->last_write_ad = addr; + vm_mngr->last_write_size = my_size; + + //if(vmmngr.my_tick> my_tick) + // printf("M_WRITE %2d %.8X %.8X\n", my_size, addr, src); + if (!(addr + my_size/8 <= vm_mngr->code_bloc_pool_ad_min || + addr >= vm_mngr->code_bloc_pool_ad_max)){ + LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ + if ((cbp->ad_start <= addr + my_size/8) && + (addr < cbp->ad_stop)){ +#ifdef DEBUG_MIASM_AUTOMOD_CODE + fprintf(stderr, "self modifying code %"PRIX64" %.8X\n", + addr, my_size); +#endif + vm_mngr->exception_flags |= EXCEPT_CODE_AUTOMOD; + break; + } + } + } + + memory_page_write(vm_mngr, my_size, addr, src); +} +*/ +void MEM_WRITE_08(vm_mngr_t* vm_mngr, uint64_t addr, unsigned char src) +{ + check_write_code_bloc(vm_mngr, 8, addr); + memory_page_write(vm_mngr, 8, addr, src); +} + +void MEM_WRITE_16(vm_mngr_t* vm_mngr, uint64_t addr, unsigned short src) +{ + check_write_code_bloc(vm_mngr, 16, addr); + memory_page_write(vm_mngr, 16, addr, src); +} +void MEM_WRITE_32(vm_mngr_t* vm_mngr, uint64_t addr, unsigned int src) +{ + check_write_code_bloc(vm_mngr, 32, addr); + memory_page_write(vm_mngr, 32, addr, src); +} +void MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src) +{ + check_write_code_bloc(vm_mngr, 64, addr); + memory_page_write(vm_mngr, 64, addr, src); +} + +unsigned int MEM_LOOKUP(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr) +{ + unsigned int ret; + ret = memory_page_read(vm_mngr, my_size, addr); + return ret; +} + +unsigned char MEM_LOOKUP_08(vm_mngr_t* vm_mngr, uint64_t addr) +{ + unsigned char ret; + ret = memory_page_read(vm_mngr, 8, addr); + return ret; +} +unsigned short MEM_LOOKUP_16(vm_mngr_t* vm_mngr, uint64_t addr) +{ + unsigned short ret; + ret = memory_page_read(vm_mngr, 16, addr); + return ret; +} +unsigned int MEM_LOOKUP_32(vm_mngr_t* vm_mngr, uint64_t addr) +{ + unsigned int ret; + ret = memory_page_read(vm_mngr, 32, addr); + return ret; +} +uint64_t MEM_LOOKUP_64(vm_mngr_t* vm_mngr, uint64_t addr) +{ + uint64_t ret; + ret = memory_page_read(vm_mngr, 64, addr); + return ret; +} + +inline unsigned int parity(unsigned int a) +{ +#if defined(__builtin_parity) + return __builtin_parity(a); +#else + unsigned int tmp, cpt; + + tmp = a&0xFF; + cpt = 1; + while (tmp!=0){ + cpt^=tmp&1; + tmp>>=1; + } + return cpt; +#endif +} + + +int shift_right_arith(unsigned int size, int a, unsigned int b) +{ + int i32_a; + short i16_a; + char i8_a; + switch(size){ + case 8: + i8_a = a; + return (i8_a >> b)&0xff; + case 16: + i16_a = a; + return (i16_a >> b)&0xffff; + case 32: + i32_a = a; + return (i32_a >> b)&0xffffffff; + default: + fprintf(stderr, "inv size in shift %d\n", size); + exit(0); + } +} +/* +int shift_right_arith_08(int a, unsigned int b) +{ + char i8_a; + i8_a = a; + return (i8_a >> b)&0xff; +} + +int shift_right_arith_16(int a, unsigned int b) +{ + short i16_a; + i16_a = a; + return (i16_a >> b)&0xffff; +} + +int shift_right_arith_32(int a, unsigned int b) +{ + int i32_a; + i32_a = a; + return (i32_a >> b)&0xffffffff; +} +*/ +unsigned int shift_right_logic(unsigned int size, + unsigned int a, unsigned int b) +{ + unsigned int u32_a; + unsigned short u16_a; + unsigned char u8_a; + switch(size){ + case 8: + u8_a = a; + return (u8_a >> b)&0xff; + case 16: + u16_a = a; + return (u16_a >> b)&0xffff; + case 32: + u32_a = a; + return (u32_a >> b)&0xffffffff; + default: + fprintf(stderr, "inv size in shift %d\n", size); + exit(0); + } +} +/* +int shift_right_logic_08(unsigned int a, unsigned int b) +{ + unsigned char u8_a; + u8_a = a; + return (u8_a >> b)&0xff; +} + +int shift_right_logic_16(unsigned int a, unsigned int b) +{ + unsigned short u16_a; + u16_a = a; + return (u16_a >> b)&0xffff; +} + +int shift_right_logic_32(unsigned int a, unsigned int b) +{ + unsigned int u32_a; + u32_a = a; + return (u32_a >> b)&0xffffffff; +} +*/ +int shift_left_logic(unsigned int size, unsigned int a, unsigned int b) +{ + switch(size){ + case 8: + return (a<<b)&0xff; + case 16: + return (a<<b)&0xffff; + case 32: + return (a<<b)&0xffffffff; + default: + fprintf(stderr, "inv size in shift %d\n", size); + exit(0); + } +} +/* +int shift_left_logic_O8(unsigned int a, unsigned int b) +{ + return (a<<b)&0xff; +} + +int shift_left_logic_16(unsigned int a, unsigned int b) +{ + return (a<<b)&0xffff; +} + +int shift_left_logic_32(unsigned int a, unsigned int b) +{ + return (a<<b)&0xffffffff; +} +*/ + +unsigned int mul_lo_op(unsigned int size, unsigned int a, unsigned int b) +{ + unsigned int mask; + + switch (size) { + case 8: mask = 0xff; break; + case 16: mask = 0xffff; break; + case 32: mask = 0xffffffff; break; + default: fprintf(stderr, "inv size in mul %d\n", size); exit(0); + } + + a &= mask; + b &= mask; + return ((int64_t)a * (int64_t) b) & mask; +} + +unsigned int mul_hi_op(unsigned int size, unsigned int a, unsigned int b) +{ + uint64_t res = 0; + unsigned int mask; + + switch (size) { + case 8: mask = 0xff; break; + case 16: mask = 0xffff; break; + case 32: mask = 0xffffffff; break; + default: fprintf(stderr, "inv size in mul %d\n", size); exit(0); + } + + a &= mask; + b &= mask; + res = ((uint64_t)a * (uint64_t)b); + return (res >> 32) & mask; +} + + +unsigned int imul_lo_op_08(char a, char b) +{ + return a*b; +} + +unsigned int imul_lo_op_16(short a, short b) +{ + return a*b; +} + +unsigned int imul_lo_op_32(int a, int b) +{ + return a*b; +} + +int imul_hi_op_08(char a, char b) +{ + int64_t res = 0; + res = a*b; + return res>>8; +} + +int imul_hi_op_16(short a, short b) +{ + int64_t res = 0; + res = a*b; + return res>>16; +} + +int imul_hi_op_32(int a, int b) +{ + int64_t res = 0; + res = (int64_t)a*(int64_t)b; + //printf("%x %x dd %"PRIx64"\n", a, b, res); + return res>>32ULL; +} + +unsigned int umul16_lo(unsigned short a, unsigned short b) +{ + return (a*b) & 0xffff; +} + +unsigned int umul16_hi(unsigned short a, unsigned short b) +{ + uint32_t c; + c = a*b; + return (c>>16) & 0xffff; +} + + + + +unsigned int div_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c) +{ + int64_t num; + if (c == 0) + { + //vmmngr.exception_flags |= EXCEPT_INT_DIV_BY_ZERO; + return 0; + } + num = ((int64_t)a << size) + b; + num/=(int64_t)c; + return num; +} + + +unsigned int rem_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c) +{ + int64_t num; + + if (c == 0) + { + //vmmngr.exception_flags |= EXCEPT_INT_DIV_BY_ZERO; + return 0; + } + + num = ((int64_t)a << size) + b; + num = (int64_t)num-c*(num/c); + return num; +} + + +unsigned int rot_left(unsigned int size, unsigned int a, unsigned int b) +{ + unsigned int tmp; + + b = b&0x1F; + b %= size; + switch(size){ + case 8: + tmp = (a << b) | ((a&0xFF) >> (size-b)); + return tmp&0xff; + case 16: + tmp = (a << b) | ((a&0xFFFF) >> (size-b)); + return tmp&0xffff; + case 32: + tmp = (a << b) | ((a&0xFFFFFFFF) >> (size-b)); + return tmp&0xffffffff; + default: + fprintf(stderr, "inv size in rotleft %d\n", size); + exit(0); + } +} + +unsigned int rot_right(unsigned int size, unsigned int a, unsigned int b) +{ + unsigned int tmp; + + b = b&0x1F; + b %= size; + switch(size){ + case 8: + tmp = ((a&0xFF) >> b) | (a << (size-b)); + return tmp&0xff; + case 16: + tmp = ((a&0xFFFF) >> b) | (a << (size-b)); + return tmp&0xffff; + case 32: + tmp = ((a&0xFFFFFFFF) >> b) | (a << (size-b)); + return tmp&0xffffffff; + default: + fprintf(stderr, "inv size in rotleft %d\n", size); + exit(0); + } +} + + +int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf) +{ + uint64_t tmp; + + + size++; + b %= size; + + if (b == 0) { + switch(size){ + case 8+1: + return a&0xff; + case 16+1: + return a&0xffff; + case 32+1: + return a&0xffffffff; + default: + fprintf(stderr, "inv size in rclleft %d\n", size); + exit(0); + } + } + + tmp = (a<<1) | cf; + b -=1; + switch(size){ + case 8+1: + tmp = (tmp << b) | ((tmp&0x1FF) >> (size-b)); + return tmp&0xff; + case 16+1: + tmp = (tmp << b) | ((tmp&0x1FFFF) >> (size-b)); + return tmp&0xffff; + case 32+1: + tmp = (tmp << b) | ((tmp&0x1FFFFFFFFULL) >> (size-b)); + return tmp&0xffffffff; + default: + fprintf(stderr, "inv size in rclleft %d\n", size); + exit(0); + } +} + +int rcr_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf) +{ + return rcl_rez_op(size, a, size+1-b, cf); + +} + + +int rcl_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf) +{ + uint64_t tmp; + + tmp = (cf<< size) | a; + + size++; + b %= size; + + switch(size){ + case 8+1: + tmp = (tmp << b) | ((tmp&0x1FF) >> (size-b)); + return (tmp>>8)&1; + case 16+1: + tmp = (tmp << b) | ((tmp&0x1FFFF) >> (size-b)); + return (tmp>>16)&1; + case 32+1: + tmp = (tmp << b) | ((tmp&0x1FFFFFFFFULL) >> (size-b)); + return (tmp>>32)&1; + default: + fprintf(stderr, "inv size in rclleft %d\n", size); + exit(0); + } +} + +int rcr_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf) +{ + return rcl_cf_op(size, a, size+1-b, cf); +} +unsigned int my_bsr(unsigned int a, unsigned int b) +{ + int i; + + for (i=31; i>=0; i--){ + if (b & (1<<i)) + return i; + } + return a; +} + +unsigned int my_bsf(unsigned int a, unsigned int b) +{ + int i; + + for (i=0; i<32; i++){ + if (b & (1<<i)) + return i; + } + return a; +} + + +unsigned int my_imul08(unsigned int a, unsigned int b) +{ + char a08, b08; + short a16; + + a08 = a&0xFF; + b08 = b&0xFF; + a16 = a08*b08; + return (int)a16; +} + + + +unsigned int cpuid(unsigned int a, unsigned int reg_num) +{ + if (reg_num >3){ + fprintf(stderr, "not implemented cpuid reg %x\n", reg_num); + exit(-1); + } + + if (a == 0){ + switch(reg_num){ + case 0: + return 0xa; + case 1: + return 0x756E6547; + case 2: + return 0x6C65746E; + case 3: + return 0x49656E69; + } + } + + else if (a == 1){ + switch(reg_num){ + case 0: + //return 0x000006FB; + return 0x00020652; + case 1: + //return 0x02040800; + return 0x00000800; + case 2: + //return 0x0004E3BD; + return 0x00000209; + case 3: + //return 0xBFEBFBFF; + return 0x078bf9ff; + } + } + else{ + fprintf(stderr, "WARNING not implemented cpuid index %X!\n", a); + //exit(-1); + } + return 0; +} + +#define DEBUG_MIASM_DOUBLE + +void dump_float(void) +{ + /* + printf("%e\n", vmmngr.float_st0); + printf("%e\n", vmmngr.float_st1); + printf("%e\n", vmmngr.float_st2); + printf("%e\n", vmmngr.float_st3); + printf("%e\n", vmmngr.float_st4); + printf("%e\n", vmmngr.float_st5); + printf("%e\n", vmmngr.float_st6); + printf("%e\n", vmmngr.float_st7); + */ +} + +double mem_32_to_double(unsigned int m) +{ + float f; + double d; + + f = *((float*)&m); + d = f; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%d float %e\n", m, d); +#endif + return d; +} + + +double mem_64_to_double(uint64_t m) +{ + double d; + d = *((double*)&m); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%"PRId64" double %e\n", m, d); +#endif + return d; +} + +double int_16_to_double(unsigned int m) +{ + double d; + + d = (double)(m&0xffff); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%d double %e\n", m, d); +#endif + return d; +} + +double int_32_to_double(unsigned int m) +{ + double d; + + d = (double)m; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%d double %e\n", m, d); +#endif + return d; +} + +double int_64_to_double(uint64_t m) +{ + double d; + + d = (double)m; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%"PRId64" double %e\n", m, d); +#endif + return d; +} + +int32_t double_to_int_32(double d) +{ + int32_t i; + + i = (int32_t)d; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e int %d\n", d, i); +#endif + return i; +} + +int64_t double_to_int_64(double d) +{ + int64_t i; + + i = (int64_t)d; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e int %"PRId64"\n", d, i); +#endif + return i; +} + + +double fadd(double a, double b) +{ + double c; + c = a + b; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e + %e -> %e\n", a, b, c); +#endif + return c; +} + +double fsub(double a, double b) +{ + double c; + c = a - b; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e - %e -> %e\n", a, b, c); +#endif + return c; +} + +double fmul(double a, double b) +{ + double c; + c = a * b; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e * %e -> %e\n", a, b, c); +#endif + return c; +} + +double fdiv(double a, double b) +{ + double c; + c = a / b; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e / %e -> %e\n", a, b, c); +#endif + return c; +} + +double ftan(double a) +{ + double b; + b = tan(a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e tan %e\n", a, b); +#endif + return b; +} + +double frndint(double a) +{ + int64_t b; + double c; + b = (int64_t)a; + c = (double)b; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e double %e\n", a, c); +#endif + return c; +} + +double fsin(double a) +{ + double b; + b = sin(a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e sin %e\n", a, b); +#endif + return b; +} + +double fcos(double a) +{ + double b; + b = cos(a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e cos %e\n", a, b); +#endif + return b; +} + + +double fscale(double a, double b) +{ + double c; + c = a * exp2(trunc(b)); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e *exp2 %e -> %e\n", a, b, c); +#endif + return c; +} + +double f2xm1(double a) +{ + double b; + b = exp2(a)-1; +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e exp2 -1 %e\n", a, b); +#endif + return b; +} + +double fsqrt(double a) +{ + double b; + b = sqrt(a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e sqrt %e\n", a, b); +#endif + return b; +} + +double fabs(double a) +{ + double b; + b = abs(a); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%e abs %e\n", a, b); +#endif + return b; +} + + + +unsigned int fcom_c0(double a, double b) +{ + if (a>=b) + return 0; + return 1; +} +unsigned int fcom_c1(double a, double b) +{ + //XXX + return 0; +} +unsigned int fcom_c2(double a, double b) +{ + return 0; +} +unsigned int fcom_c3(double a, double b) +{ + if (a==b) + return 1; + return 0; +} + + +unsigned int double_to_mem_32(double d) +{ + unsigned int m; + float f; + f = d; + m = *((unsigned int*)&f); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%d %e\n", m, d); +#endif + return m; +} + +uint64_t double_to_mem_64(double d) +{ + uint64_t m; + m = *((uint64_t*)&d); +#ifdef DEBUG_MIASM_DOUBLE + dump_float(); + printf("%"PRId64" %e\n", m, d); +#endif + return m; +} + +struct memory_page_node * create_memory_page_node(uint64_t ad, unsigned int size, unsigned int access) +{ + struct memory_page_node * mpn; + void* p; + + mpn = malloc(sizeof(*mpn)); + if (!mpn){ + fprintf(stderr, "cannot alloc mpn\n"); + return NULL; + } + p = malloc(size); + if (!p){ + fprintf(stderr, "cannot alloc %d\n", size); + return NULL; + } + mpn->ad = ad; + mpn->size = size; + mpn->access = access; + mpn->ad_hp = p; + + return mpn; +} + + +struct code_bloc_node * create_code_bloc_node(uint64_t ad_start, uint64_t ad_stop) +{ + struct code_bloc_node * cbp; + + cbp = malloc(sizeof(*cbp)); + if (!cbp){ + fprintf(stderr, "cannot alloc cbp\n"); + exit(-1); + } + + cbp->ad_start = ad_start; + cbp->ad_stop = ad_stop; + + return cbp; +} + + +void add_code_bloc(vm_mngr_t* vm_mngr, struct code_bloc_node* cbp) +{ + LIST_INSERT_HEAD(&vm_mngr->code_bloc_pool, cbp, next); + if (vm_mngr->code_bloc_pool_ad_min> cbp->ad_start) + vm_mngr->code_bloc_pool_ad_min = cbp->ad_start; + if (vm_mngr->code_bloc_pool_ad_max< cbp->ad_stop) + vm_mngr->code_bloc_pool_ad_max = cbp->ad_stop; +} + +void dump_code_bloc_pool(vm_mngr_t* vm_mngr) +{ + struct code_bloc_node * cbp; + + LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ + printf("ad start %"PRIX64" ad_stop %"PRIX64"\n", + cbp->ad_start, + cbp->ad_stop); + } +} + + +void init_memory_page_pool(vm_mngr_t* vm_mngr) +{ + unsigned int i; + LIST_INIT(&vm_mngr->memory_page_pool); + for (i=0;i<MAX_MEMORY_PAGE_POOL_TAB; i++) + vm_mngr->memory_page_pool_tab[i] = NULL; +} + +void init_code_bloc_pool(vm_mngr_t* vm_mngr) +{ + LIST_INIT(&vm_mngr->code_bloc_pool); + vm_mngr->code_bloc_pool_ad_min = 0xffffffff; + vm_mngr->code_bloc_pool_ad_max = 0; +} + +void init_memory_breakpoint(vm_mngr_t* vm_mngr) +{ + LIST_INIT(&vm_mngr->memory_breakpoint_pool); +} + + +void reset_memory_page_pool(vm_mngr_t* vm_mngr) +{ + struct memory_page_node * mpn; + unsigned int i; + + while (!LIST_EMPTY(&vm_mngr->memory_page_pool)) { + mpn = LIST_FIRST(&vm_mngr->memory_page_pool); + LIST_REMOVE(mpn, next); + free(mpn->ad_hp); + free(mpn); + } + for (i=0;i<MAX_MEMORY_PAGE_POOL_TAB; i++) + vm_mngr->memory_page_pool_tab[i] = NULL; + +} + + +void reset_code_bloc_pool(vm_mngr_t* vm_mngr) +{ + struct code_bloc_node * cbp; + + + while (!LIST_EMPTY(&vm_mngr->code_bloc_pool)) { + cbp = LIST_FIRST(&vm_mngr->code_bloc_pool); + LIST_REMOVE(cbp, next); + free(cbp); + } + vm_mngr->code_bloc_pool_ad_min = 0xffffffff; + vm_mngr->code_bloc_pool_ad_max = 0; +} + + +void reset_memory_breakpoint(vm_mngr_t* vm_mngr) +{ + struct memory_breakpoint_info * mpn; + + while (!LIST_EMPTY(&vm_mngr->memory_breakpoint_pool)) { + mpn = LIST_FIRST(&vm_mngr->memory_breakpoint_pool); + LIST_REMOVE(mpn, next); + free(mpn); + } + +} + + +int is_mpn_in_tab(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a) +{ + struct memory_page_node * mpn; + + /* + for (i=mpn_a->ad >> MEMORY_PAGE_POOL_MASK_BIT; + i<(mpn_a->ad + mpn_a->size + PAGE_SIZE - 1)>>MEMORY_PAGE_POOL_MASK_BIT; + i++){ + if (memory_page_pool_tab[i] !=NULL){ + return 1; + } + } + */ + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + if (mpn->ad >= mpn_a->ad + mpn_a->size) + continue; + if (mpn->ad + mpn->size <= mpn_a->ad) + continue; + printf("is mpn in! %"PRIX64" %"PRIX64" \n", mpn_a->ad, mpn_a->size); + printf("known:! %"PRIX64" %"PRIX64" \n", mpn->ad, mpn->size); + + return 1; + } + + return 0; +} + +void insert_mpn_in_tab(struct memory_page_node* mpn_a) +{ + /* + for (i=mpn_a->ad >> MEMORY_PAGE_POOL_MASK_BIT; + i<(mpn_a->ad + mpn_a->size + PAGE_SIZE - 1)>>MEMORY_PAGE_POOL_MASK_BIT; + i++){ + if (memory_page_pool_tab[i] !=NULL){ + fprintf(stderr, "known page in tab\n"); + exit(1); + } + memory_page_pool_tab[i] = mpn_a; + } + */ + +} + +void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a) +{ + struct memory_page_node * mpn; + struct memory_page_node * lmpn; + + if (LIST_EMPTY(&vm_mngr->memory_page_pool)){ + LIST_INSERT_HEAD(&vm_mngr->memory_page_pool, mpn_a, next); + insert_mpn_in_tab(mpn_a); + return; + } + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + lmpn = mpn; + if (mpn->ad < mpn_a->ad) + continue; + LIST_INSERT_BEFORE(mpn, mpn_a, next); + insert_mpn_in_tab(mpn_a); + return; + } + LIST_INSERT_AFTER(lmpn, mpn_a, next); + insert_mpn_in_tab(mpn_a); + +} + +void dump_memory_page_pool(vm_mngr_t* vm_mngr) +{ + struct memory_page_node * mpn; + + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + printf("ad %"PRIX64" size %"PRIX64" %c%c%c hpad %p\n", + mpn->ad, + mpn->size, + mpn->access & PAGE_READ? 'R':'_', + mpn->access & PAGE_WRITE? 'W':'_', + mpn->access & PAGE_EXEC? 'X':'_', + mpn->ad_hp + ); + } +} + +void dump_memory_breakpoint_pool(vm_mngr_t* vm_mngr) +{ + struct memory_breakpoint_info * mpn; + + LIST_FOREACH(mpn, &vm_mngr->memory_breakpoint_pool, next){ + printf("ad %"PRIX64" size %"PRIX64" access %"PRIX64"\n", + mpn->ad, + mpn->size, + mpn->access + ); + } +} + + +void add_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, uint64_t size, unsigned int access) +{ + struct memory_breakpoint_info * mpn_a; + mpn_a = malloc(sizeof(*mpn_a)); + if (!mpn_a) { + printf("cannot alloc\n"); + exit(0); + } + mpn_a->ad = ad; + mpn_a->size = size; + mpn_a->access = access; + + LIST_INSERT_HEAD(&vm_mngr->memory_breakpoint_pool, mpn_a, next); + +} + +void remove_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, unsigned int access) +{ + struct memory_breakpoint_info * mpn; + + LIST_FOREACH(mpn, &vm_mngr->memory_breakpoint_pool, next){ + if (mpn->ad == ad && mpn->access == access) + LIST_REMOVE(mpn, next); + } + +} + + + + + + + +unsigned int get_memory_page_next(vm_mngr_t* vm_mngr, unsigned int n_ad) +{ + struct memory_page_node * mpn; + uint64_t ad = 0; + + LIST_FOREACH(mpn, &vm_mngr->memory_page_pool, next){ + if (mpn->ad < n_ad) + continue; + + if (ad == 0 || mpn->ad <ad) + ad = mpn->ad; + } + return ad; +} + + +#if 0 +unsigned int get_memory_page_from_min_ad(unsigned int size) +{ + struct memory_page_node * mpn; + unsigned int c_ad ; + unsigned int min_ad = min_page_ad; + int end = 0; + /* first, find free min ad */ + while (!end){ + end = 1; + LIST_FOREACH(mpn, &memory_page_pool, next){ + c_ad = (mpn->ad + mpn->size+0x1000)&0xfffff000; + if (c_ad <= min_ad) + continue; + if (mpn->ad <= min_ad){ + min_ad = c_ad; + end = 0; + break; + } + if (mpn->ad - min_ad < size){ + min_ad = c_ad; + end = 0; + break; + } + } + } + return min_ad; + } +#endif + + + +/********************************************/ + +void hexdump(char* m, unsigned int l) +{ + int i, j, last; + last = 0; + for (i=0;i<l;i++){ + if (!(i%0x10) && i){ + last = i; + printf(" "); + for (j=-0x10;j<0;j++){ + if (isprint(m[i+j])){ + printf("%c", m[i+j]); + } + else{ + printf("."); + } + } + printf("\n"); + } + printf("%.2X ", m[i]&0xFF); + } + l-=last; + if (l){ + for (j=i;j<last+0x10;j++) + printf(" "); + printf(" "); + for (j = 0;l;j++){ + if (isprint(m[last+j])){ + printf("%c", m[last+j]); + } + else{ + printf("."); + } + l--; + } + } + printf("\n"); + +} + + + + +unsigned int access_segment(unsigned int d) +{ + // XXX TODO + printf("access segment %X\n", d); + return 0; +} +unsigned int access_segment_ok(unsigned int d) +{ + // XXX TODO + printf("access segment ok %X\n", d); + return 0; +} + +unsigned int load_segment_limit(unsigned int d) +{ + // XXX TODO + printf("load segment limit %X\n", d); + return 0; +} +unsigned int load_segment_limit_ok(unsigned int d) +{ + // XXX TODO + printf("load segment limit ok %X\n", d); + return 0; +} + +unsigned int load_tr_segment_selector(unsigned int d) +{ + // XXX TODO + return 0; +} + +// Return vm_mngr's exception flag value +uint64_t get_exception_flag(vm_mngr_t* vm_mngr) +{ + return vm_mngr->exception_flags; +} diff --git a/miasm2/jitter/vm_mngr.h b/miasm2/jitter/vm_mngr.h new file mode 100644 index 00000000..1e032200 --- /dev/null +++ b/miasm2/jitter/vm_mngr.h @@ -0,0 +1,363 @@ +/* +** 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. +*/ +#ifndef CODENAT_H +#define CODENAT_H + + +#if __BYTE_ORDER == __BIG_ENDIAN +#define Endian16_Swap(value) \ + ((((uint16_t)((value) & 0x00FF)) << 8) | \ + (((uint16_t)((value) & 0xFF00)) >> 8)) + +#define Endian32_Swap(value) \ + ((((uint32_t)((value) & 0x000000FF)) << 24) | \ + (((uint32_t)((value) & 0x0000FF00)) << 8) | \ + (((uint32_t)((value) & 0x00FF0000)) >> 8) | \ + (((uint32_t)((value) & 0xFF000000)) >> 24)) + +#define Endian64_Swap(value) \ + (((((uint64_t)value)<<56) & 0xFF00000000000000ULL) | \ + ((((uint64_t)value)<<40) & 0x00FF000000000000ULL) | \ + ((((uint64_t)value)<<24) & 0x0000FF0000000000ULL) | \ + ((((uint64_t)value)<< 8) & 0x000000FF00000000ULL) | \ + ((((uint64_t)value)>> 8) & 0x00000000FF000000ULL) | \ + ((((uint64_t)value)>>24) & 0x0000000000FF0000ULL) | \ + ((((uint64_t)value)>>40) & 0x000000000000FF00ULL) | \ + ((((uint64_t)value)>>56) & 0x00000000000000FFULL)) +#else +#define Endian16_Swap(value) (value) + +#define Endian32_Swap(value) (value) + +#define Endian64_Swap(value) (value) +#endif + + + + +LIST_HEAD(memory_page_list_head, memory_page_node); +LIST_HEAD(code_bloc_list_head, code_bloc_node); +LIST_HEAD(memory_breakpoint_info_head, memory_breakpoint_info); + + +#define BREAKPOINT_READ 1 +#define BREAKPOINT_WRITE 2 + + + +#define MAX_MEMORY_PAGE_POOL_TAB 0x100000 +#define MEMORY_PAGE_POOL_MASK_BIT 12 +#define PAGE_SIZE (1<<MEMORY_PAGE_POOL_MASK_BIT) + +typedef struct { + + struct memory_page_list_head memory_page_pool; + struct code_bloc_list_head code_bloc_pool; + struct memory_breakpoint_info_head memory_breakpoint_pool; + + struct memory_page_node *memory_page_pool_tab[MAX_MEMORY_PAGE_POOL_TAB]; + + unsigned int *code_addr_tab; + unsigned int code_bloc_pool_ad_min; + unsigned int code_bloc_pool_ad_max; + + uint64_t exception_flags; + uint64_t exception_flags_new; + uint64_t last_write_ad; + uint64_t last_write_size ; + PyObject *cb_automod; + PyObject *addr2obj; +}vm_mngr_t; + + + +typedef struct { + PyObject *func; +}func_resolver; + + + + +//extern vm_mngr_t vmmngr; + +struct memory_page_node { + uint64_t ad; + uint64_t size; + uint64_t access; + void* ad_hp; + LIST_ENTRY(memory_page_node) next; +}; + + + +struct code_bloc_node { + uint64_t ad_start; + uint64_t ad_stop; + uint64_t ad_code; + LIST_ENTRY(code_bloc_node) next; +}; + + +struct memory_breakpoint_info { + uint64_t ad; + uint64_t size; + uint64_t access; + LIST_ENTRY(memory_breakpoint_info) next; +}; + + +#define PAGE_READ 1 +#define PAGE_WRITE 2 +#define PAGE_EXEC 4 + +#define EXCEPT_DO_NOT_UPDATE_PC (1<<25) + +// interrupt with eip update after instr +#define EXCEPT_CODE_AUTOMOD (1<<0) +#define EXCEPT_SOFT_BP (1<<1) +#define EXCEPT_INT_XX (1<<2) + +#define EXCEPT_BREAKPOINT_INTERN (1<<10) + +#define EXCEPT_NUM_UPDT_EIP (1<<11) +// interrupt with eip at instr +#define EXCEPT_UNK_MEM_AD ((1<<12) | EXCEPT_DO_NOT_UPDATE_PC) +#define EXCEPT_THROW_SEH ((1<<13) | EXCEPT_DO_NOT_UPDATE_PC) +#define EXCEPT_UNK_EIP ((1<<14) | EXCEPT_DO_NOT_UPDATE_PC) +#define EXCEPT_ACCESS_VIOL ((1<<14) | EXCEPT_DO_NOT_UPDATE_PC) +#define EXCEPT_INT_DIV_BY_ZERO ((1<<16) | EXCEPT_DO_NOT_UPDATE_PC) +#define EXCEPT_PRIV_INSN ((1<<17) | EXCEPT_DO_NOT_UPDATE_PC) +#define EXCEPT_ILLEGAL_INSN ((1<<18) | EXCEPT_DO_NOT_UPDATE_PC) +#define EXCEPT_UNK_MNEMO ((1<<19) | EXCEPT_DO_NOT_UPDATE_PC) + + +int is_mem_mapped(vm_mngr_t* vm_mngr, uint64_t ad); +uint64_t get_mem_base_addr(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t *addr_base); +void MEM_WRITE(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr, unsigned int src); +unsigned int MEM_LOOKUP(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr); + + +void MEM_WRITE_08(vm_mngr_t* vm_mngr, uint64_t addr, unsigned char src); +void MEM_WRITE_16(vm_mngr_t* vm_mngr, uint64_t addr, unsigned short src); +void MEM_WRITE_32(vm_mngr_t* vm_mngr, uint64_t addr, unsigned int src); +void MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src); + + +unsigned char MEM_LOOKUP_08(vm_mngr_t* vm_mngr, uint64_t addr); +unsigned short MEM_LOOKUP_16(vm_mngr_t* vm_mngr, uint64_t addr); +unsigned int MEM_LOOKUP_32(vm_mngr_t* vm_mngr, uint64_t addr); +uint64_t MEM_LOOKUP_64(vm_mngr_t* vm_mngr, uint64_t addr); + + +void MEM_WRITE_08_PASSTHROUGH(uint64_t addr, unsigned char src); +void MEM_WRITE_16_PASSTHROUGH(uint64_t addr, unsigned short src); +void MEM_WRITE_32_PASSTHROUGH(uint64_t addr, unsigned int src); +void MEM_WRITE_64_PASSTHROUGH(uint64_t addr, uint64_t src); +unsigned char MEM_LOOKUP_08_PASSTHROUGH(uint64_t addr); +unsigned short MEM_LOOKUP_16_PASSTHROUGH(uint64_t addr); +unsigned int MEM_LOOKUP_32_PASSTHROUGH(uint64_t addr); +uint64_t MEM_LOOKUP_64_PASSTHROUGH(uint64_t addr); + + +inline unsigned int parity(unsigned int a); +unsigned int my_imul08(unsigned int a, unsigned int b); + +void vm_throw(vm_mngr_t* vm_mngr, unsigned long flags); +int shift_right_arith(unsigned int size, int a, unsigned int b); +unsigned int shift_right_logic(unsigned int size, unsigned int a, unsigned int b); +int shift_left_logic(unsigned int size, unsigned int a, unsigned int b); +/* +int shift_left_logic_08(unsigned int a, unsigned int b); +int shift_left_logic_16(unsigned int a, unsigned int b); +int shift_left_logic_32(unsigned int a, unsigned int b); +*/ +unsigned int mul_lo_op(unsigned int size, unsigned int a, unsigned int b); +unsigned int mul_hi_op(unsigned int size, unsigned int a, unsigned int b); +unsigned int imul_lo_op_08(char a, char b); +unsigned int imul_lo_op_16(short a, short b); +unsigned int imul_lo_op_32(int a, int b); +int imul_hi_op_08(char a, char b); +int imul_hi_op_16(short a, short b); +int imul_hi_op_32(int a, int b); + + +unsigned int umul16_lo(unsigned short a, unsigned short b); +unsigned int umul16_hi(unsigned short a, unsigned short b); + + +unsigned int div_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c); +unsigned int rem_op(unsigned int size, unsigned int a, unsigned int b, unsigned int c); +unsigned int rot_left(unsigned int size, unsigned int a, unsigned int b); +unsigned int rot_right(unsigned int size, unsigned int a, unsigned int b); +int rcl_rez_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf); +int rcl_cf_op(unsigned int size, unsigned int a, unsigned int b, unsigned int cf); + +//PyObject* _vm_push_uint32_t(PyObject *item); +//PyObject* _vm_pop_uint32_t(void); +////PyObject* _vm_put_str(PyObject *item); +//PyObject* _vm_set_mem(PyObject *item, PyObject *item_str); +//PyObject* _vm_set_mem_access(PyObject *addr, PyObject *access); +//PyObject* _vm_get_str(PyObject *item, PyObject *item_len); +//PyObject* _vm_add_memory_page(PyObject *item, PyObject *access, PyObject *item_str); +//PyObject* _vm_add_code_bloc(PyObject *item1, PyObject *item2);//, PyObject *item3); +//PyObject* _call_pyfunc_from_globals(char* funcname); +//PyObject* _call_pyfunc_from_eip(void); +// +//PyObject* call_pyfunc_from_globals(char* funcname); +// +//PyObject* _vm_get_gpreg(void); + +void hexdump(char* m, unsigned int l); + +struct code_bloc_node * create_code_bloc_node(uint64_t ad_start, uint64_t ad_stop); +void add_code_bloc(vm_mngr_t* vm_mngr, struct code_bloc_node* cbp); + +struct memory_page_node * create_memory_page_node(uint64_t ad, unsigned int size, unsigned int access);//memory_page* mp); +void init_memory_page_pool(vm_mngr_t* vm_mngr); +void init_code_bloc_pool(vm_mngr_t* vm_mngr); +void reset_memory_page_pool(vm_mngr_t* vm_mngr); +void reset_code_bloc_pool(vm_mngr_t* vm_mngr); +void dump_code_bloc_pool(vm_mngr_t* vm_mngr); +void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a); + + +void init_memory_breakpoint(vm_mngr_t* vm_mngr); +void reset_memory_breakpoint(vm_mngr_t* vm_mngr); +void add_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, uint64_t size, unsigned int access); +void remove_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, unsigned int access); + +void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn); + +void dump_memory_page_pool(vm_mngr_t* vm_mngr); +void dump_memory_breakpoint_pool(vm_mngr_t* vm_mngr); +//PyObject* _vm_get_all_memory(void); +PyObject* addr2BlocObj(vm_mngr_t* vm_mngr, uint64_t addr); + + + + +/********************************************/ + +//PyObject* _vm_get_cpu_state(void); +//PyObject* _vm_set_cpu_state(PyObject * s_cpustate); + + +//void memory_page_write(unsigned int my_size, uint64_t ad, unsigned int src); +//unsigned int memory_page_read(unsigned int my_size, uint64_t ad); +unsigned int get_memory_page_max_address(void); +unsigned int get_memory_page_max_user_address(void); + + +int is_mpn_in_tab(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a); + + +void _func_free(void); +void _func_alloc(void); +unsigned int _get_memory_page_max_address_py(void); +unsigned int _get_memory_page_max_user_address_py(void); +unsigned int _get_memory_page_from_min_ad_py(unsigned int size); + +void _func_malloc_memory_page(void); +void _func_free_memory_page(void); +void _func_virtualalloc_memory_page(void); +void _func_virtualfree_memory_page(void); +void _func_loadlib_fake(void); +void _func_getproc_fake(void); + + +void func_free(void); +void func_alloc(void); +unsigned int get_memory_page_max_address_py(void); +unsigned int get_memory_page_max_user_address_py(void); +unsigned int get_memory_page_from_min_ad_py(unsigned int size); +struct memory_page_node * get_memory_page_from_address(vm_mngr_t*, uint64_t ad); +void func_malloc_memory_page(void); +void func_free_memory_page(void); +void func_virtualalloc_memory_page(void); +void func_virtualfree_memory_page(void); +void func_loadlib_fake(void); +void func_getproc_fake(void); + + +//PyObject* _vm_exec_bloc(PyObject* my_eip, PyObject* known_blocs); + +unsigned int cpuid(unsigned int a, unsigned int reg_num); +double int2double(unsigned int m); +//PyObject* _vm_exec_blocs(PyObject* my_eip); + +double fadd(double a, double b); +double fsub(double a, double b); +double fmul(double a, double b); +double fdiv(double a, double b); +double ftan(double a); +double frndint(double a); +double fsin(double a); +double fcos(double a); +double fscale(double a, double b); +double f2xm1(double a); +double fsqrt(double a); +double fabs(double a); +unsigned int fcom_c0(double a, double b); +unsigned int fcom_c1(double a, double b); +unsigned int fcom_c2(double a, double b); +unsigned int fcom_c3(double a, double b); + + + +double mem_32_to_double(unsigned int m); +double mem_64_to_double(uint64_t m); +double int_16_to_double(unsigned int m); +double int_32_to_double(unsigned int m); +double int_64_to_double(uint64_t m); +int32_t double_to_int_32(double d); +int64_t double_to_int_64(double d); +double fadd(double a, double b); +unsigned int double_to_mem_32(double d); +uint64_t double_to_mem_64(double d); + +unsigned int access_segment(unsigned int d); +unsigned int access_segment_ok(unsigned int d); + +unsigned int load_segment_limit(unsigned int d); +unsigned int load_segment_limit_ok(unsigned int d); + +unsigned int load_tr_segment_selector(unsigned int d); + +#define shift_right_arith_08(a, b)\ + ((((char)(a)) >> ((int)(b)&0x1f))&0xff) +#define shift_right_arith_16(a, b)\ + ((((short)(a)) >> ((int)(b)&0x1f))&0xffff) +#define shift_right_arith_32(a, b)\ + ((((int)(a)) >> ((int)(b)&0x1f))&0xffffffff) + + +#define shift_right_logic_08(a, b)\ + ((((unsigned char)(a)) >> ((unsigned int)(b)&0x1f))&0xff) +#define shift_right_logic_16(a, b)\ + ((((unsigned short)(a)) >> ((unsigned int)(b)&0x1f))&0xffff) +#define shift_right_logic_32(a, b)\ + ((((unsigned int)(a)) >> ((unsigned int)(b)&0x1f))&0xffffffff) + +#define shift_left_logic_08(a, b)\ + (((a)<<((b)&0x1f))&0xff) +#define shift_left_logic_16(a, b)\ + (((a)<<((b)&0x1f))&0xffff) +#define shift_left_logic_32(a, b)\ + (((a)<<((b)&0x1f))&0xffffffff) + +#endif diff --git a/miasm2/jitter/vm_mngr_py.c b/miasm2/jitter/vm_mngr_py.c new file mode 100644 index 00000000..a8085d92 --- /dev/null +++ b/miasm2/jitter/vm_mngr_py.c @@ -0,0 +1,939 @@ +/* +** 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 "queue.h" +#include "vm_mngr.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;} + + + +typedef struct { + PyObject_HEAD + PyObject *vmmngr; + vm_mngr_t vm_mngr; +} 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; +} + + +#define PyGetInt(item, value) \ + if (PyInt_Check(item)){ \ + value = (uint64_t)PyInt_AsLong(item); \ + } \ + else if (PyLong_Check(item)){ \ + value = (uint64_t)PyLong_AsUnsignedLongLong(item); \ + } \ + else{ \ + RAISE(PyExc_TypeError,"arg must be int"); \ + } \ + + +PyObject* vm_is_mem_mapped(VmMngr* self, PyObject* item) +{ + PyObject *addr; + uint64_t page_addr; + uint32_t ret; + if (!PyArg_ParseTuple(item, "O", &addr)) + return NULL; + + PyGetInt(addr, page_addr); + + ret = is_mem_mapped(&self->vm_mngr, page_addr); + return PyInt_FromLong((long)ret); +} + + + +PyObject* vm_get_mem_base_addr(VmMngr* self, PyObject* item) +{ + PyObject *addr; + + uint64_t page_addr; + uint64_t addr_base; + unsigned int ret; + + if (!PyArg_ParseTuple(item, "O", &addr)) + return NULL; + + PyGetInt(addr, page_addr); + + ret = get_mem_base_addr(&self->vm_mngr, page_addr, &addr_base); + if (ret == 0){ + Py_INCREF(Py_None); + return Py_None; + } + return PyLong_FromUnsignedLongLong((uint64_t)addr_base); +} + + +PyObject* vm_add_memory_page(VmMngr* self, PyObject* args) +{ + PyObject *addr; + PyObject *access; + PyObject *item_str; + uint64_t buf_size; + char* buf_data; + Py_ssize_t length; + uint64_t ret = 0x1337beef; + uint64_t page_addr; + uint64_t page_access; + + struct memory_page_node * mpn; + + if (!PyArg_ParseTuple(args, "OOO", &addr, &access, &item_str)) + return NULL; + + PyGetInt(addr, page_addr); + PyGetInt(access, page_access); + + if(!PyString_Check(item_str)) + RAISE(PyExc_TypeError,"arg must be str"); + + buf_size = PyString_Size(item_str); + PyString_AsStringAndSize(item_str, &buf_data, &length); + + fprintf(stderr, "add page %"PRIX64" %"PRIX64" %"PRIX64"\n", page_addr, buf_size, page_access); + mpn = create_memory_page_node(page_addr, buf_size, page_access); + if (mpn == NULL) + RAISE(PyExc_TypeError,"cannot create page"); + if (is_mpn_in_tab(&self->vm_mngr, mpn)) + RAISE(PyExc_TypeError,"known page in memory"); + + memcpy(mpn->ad_hp, buf_data, buf_size); + add_memory_page(&self->vm_mngr, mpn); + + return PyLong_FromUnsignedLongLong((uint64_t)ret); + +} + + + + +PyObject* vm_set_mem(VmMngr* self, PyObject* args) +{ + PyObject *addr; + PyObject *item_str; + + uint64_t buf_size; + char* buf_data; + Py_ssize_t length; + int ret = 0x1337; + uint64_t val; + uint64_t l; + + struct memory_page_node * mpn; + + if (!PyArg_ParseTuple(args, "OO", &addr, &item_str)) + return NULL; + + PyGetInt(addr, val); + + if(!PyString_Check(item_str)) + RAISE(PyExc_TypeError,"arg must be str"); + + buf_size = PyString_Size(item_str); + PyString_AsStringAndSize(item_str, &buf_data, &length); + + /* read is multiple page wide */ + while (buf_size){ + mpn = get_memory_page_from_address(&self->vm_mngr, val); + if (!mpn){ + PyErr_SetString(PyExc_RuntimeError, "cannot find address"); + return 0; + } + l = MIN(buf_size, mpn->size - (val-mpn->ad)); + memcpy(mpn->ad_hp + (val-mpn->ad), buf_data, l); + buf_data += l; + val += l; + buf_size -= l; + } + + return PyLong_FromUnsignedLongLong((uint64_t)ret); +} + +PyObject* vm_set_mem_access(VmMngr* self, PyObject* args) +{ + PyObject *addr; + PyObject *access; + + uint64_t ret = 0x1337beef; + uint64_t page_addr; + uint64_t page_access; + struct memory_page_node * mpn; + + if (!PyArg_ParseTuple(args, "OO", &addr, &access)) + return NULL; + + PyGetInt(addr, page_addr); + PyGetInt(access, page_access); + + mpn = get_memory_page_from_address(&self->vm_mngr, page_addr); + mpn->access = page_access; + return PyLong_FromUnsignedLongLong((uint64_t)ret); +} + + + + +PyObject* vm_get_mem(VmMngr* self, PyObject* args) +{ + PyObject *item; + PyObject *item_len; + + uint64_t buf_addr; + uint64_t buf_len; + PyObject *obj_out; + struct memory_page_node * mpn; + char * buf_out; + char * addr_tmp; + char * addr_out; + uint64_t off; + uint64_t l; + uint64_t my_size; + + if (!PyArg_ParseTuple(args, "OO", &item, &item_len)) + return NULL; + + PyGetInt(item, buf_addr); + PyGetInt(item_len, buf_len); + + my_size = buf_len; + buf_out = malloc(buf_len); + if (!buf_out){ + fprintf(stderr, "cannot alloc read\n"); + exit(-1); + } + + addr_out = buf_out; + + /* read is multiple page wide */ + while (my_size){ + mpn = get_memory_page_from_address(&self->vm_mngr, buf_addr); + if (!mpn){ + PyErr_SetString(PyExc_RuntimeError, "cannot find address"); + return 0; + } + + off = buf_addr - mpn->ad; + addr_tmp = &((char*)mpn->ad_hp)[off]; + + l = MIN(my_size, mpn->size - off); + memcpy(addr_out, addr_tmp, l); + my_size -= l; + addr_out +=l; + buf_addr +=l; + } + + obj_out = PyString_FromStringAndSize(buf_out, buf_len); + free(buf_out); + return obj_out; +} + +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)) + return NULL; + + PyGetInt(ad, b_ad); + PyGetInt(size, b_size); + PyGetInt(access, b_access); + + add_memory_breakpoint(&self->vm_mngr, b_ad, b_size, b_access); + 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)) + return NULL; + + PyGetInt(ad, b_ad); + PyGetInt(access, b_access); + remove_memory_breakpoint(&self->vm_mngr, b_ad, b_access); + + Py_INCREF(Py_None); + return Py_None; +} + + +PyObject* vm_get_last_write_ad(VmMngr* self, PyObject* args) +{ + return PyInt_FromLong((uint64_t)self->vm_mngr.last_write_ad); +} + +PyObject* vm_get_last_write_size(VmMngr* self, PyObject* args) +{ + return PyLong_FromUnsignedLongLong((uint64_t)self->vm_mngr.last_write_size); +} + +PyObject* vm_set_exception(VmMngr* self, PyObject* args) +{ + PyObject *item1; + uint64_t i; + + if (!PyArg_ParseTuple(args, "O", &item1)) + return NULL; + + PyGetInt(item1, i); + + self->vm_mngr.exception_flags = i; + 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_dump_memory_page_pool(VmMngr* self, PyObject* args) +{ + dump_memory_page_pool(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; +} + +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; + + + dict = PyDict_New(); + + LIST_FOREACH(mpn, &self->vm_mngr.memory_page_pool, next){ + + dict2 = PyDict_New(); + + o = PyString_FromStringAndSize(mpn->ad_hp, mpn->size); + PyDict_SetItemString(dict2, "data", o); + Py_DECREF(o); + + o = PyInt_FromLong((long)mpn->size); + PyDict_SetItemString(dict2, "size", o); + Py_DECREF(o); + + o = PyInt_FromLong((long)mpn->access); + PyDict_SetItemString(dict2, "access", o); + Py_DECREF(o); + + o = PyInt_FromLong((long)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_call_pyfunc_from_globals(VmMngr* self, PyObject* args) +{ + char* funcname; + PyObject *mod, *func, *rslt, *globals, *func_globals; + + + if (!PyArg_ParseTuple(args, "s", &funcname)) + return NULL; + + + fprintf(stderr, "getting pyfunc %s\n", funcname); + mod = PyEval_GetBuiltins(); + + if (!mod) { + fprintf(stderr, "cannot find module\n"); + exit(0); + } + + func_globals = PyDict_GetItemString(mod, "globals"); + if (!func_globals) { + fprintf(stderr, "cannot find function globals\n"); + exit(0); + } + + if (!PyCallable_Check (func_globals)) { + fprintf(stderr, "function not callable\n"); + exit(0); + } + + globals = PyObject_CallObject (func_globals, NULL); + if (!globals) { + fprintf(stderr, "cannot get globals\n"); + exit(0); + } + + func = PyDict_GetItemString (globals, funcname); + if (!func) { + fprintf(stderr, "cannot find function %s\n", funcname); + exit(0); + } + + if (!PyCallable_Check (func)) { + fprintf(stderr, "function not callable\n"); + exit(0); + } + + rslt = PyObject_CallObject (func, NULL); + return rslt; +} + +PyObject* vm_add_code_bloc(VmMngr *self, PyObject *args) +{ + PyObject *item1; + PyObject *item2; + uint64_t ret = 0x1337beef; + uint64_t ad_start, ad_stop, ad_code = 0; + + struct code_bloc_node * cbp; + + if (!PyArg_ParseTuple(args, "OO", &item1, &item2)) + return NULL; + + PyGetInt(item1, ad_start); + PyGetInt(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); + return PyLong_FromUnsignedLongLong((uint64_t)ret); +} + +PyObject* vm_dump_code_bloc_pool(VmMngr* self) +{ + dump_code_bloc_pool(&self->vm_mngr); + Py_INCREF(Py_None); + return Py_None; + +} + + +PyObject* vm_exec_blocs(VmMngr* self, PyObject* args) +{ + PyObject* my_eip; + PyObject* b; + PyObject* module; + PyObject* func; + PyObject* meip; + uint64_t tmp; + + PyObject* known_blocs; + PyObject* e; + + if (!PyArg_ParseTuple(args, "OO", &my_eip, &known_blocs)) + return NULL; + + if(!PyDict_Check(known_blocs)) + RAISE(PyExc_TypeError, "arg must be dict"); + + PyGetInt(my_eip, tmp); + meip = PyLong_FromUnsignedLongLong((uint64_t)tmp); + while (1){ + b = PyDict_GetItem(known_blocs, meip); + if (b == NULL) + return meip; + + module = PyObject_GetAttrString(b, "module_c"); + if (module == NULL){ + fprintf(stderr, "assert eip module_c in pyobject\n"); + exit(0); + } + func = PyObject_GetAttrString(module, "func"); + if (func == NULL){ + fprintf(stderr, "assert func module_c in pyobject\n"); + exit(0); + } + + Py_DECREF(module); + if (!PyCallable_Check (func)) { + fprintf(stderr, "function not callable\n"); + exit(0); + } + Py_DECREF(meip); + //printf("exec bloc %"PRIX64"\n", tmp); + meip = PyObject_CallObject (func, NULL); + + Py_DECREF(func); + e = PyErr_Occurred (); + if (e){ + fprintf(stderr, "exception\n"); + return meip; + } + + if (self->vm_mngr.exception_flags) + return meip; + + } +} + + + +PyObject* vm_exec_bloc(PyObject* self, PyObject* args) +{ + PyObject* b; + PyObject* module; + PyObject* func; + PyObject* meip; + uint64_t tmp; + + PyObject* my_eip; + PyObject* known_blocs; + PyObject* e; + + if (!PyArg_ParseTuple(args, "OO", &my_eip, &known_blocs)) + return NULL; + + + if (PyInt_Check(my_eip)){ + tmp = (uint64_t)PyInt_AsLong(my_eip); + } + else if (PyLong_Check(my_eip)){ + tmp = (uint64_t)PyLong_AsUnsignedLongLong(my_eip); + } + else{ + RAISE(PyExc_TypeError,"arg1 must be int"); + } + + meip = PyInt_FromLong((long)tmp); + b = PyDict_GetItem(known_blocs, my_eip); + if (b == NULL) + return meip; + module = PyObject_GetAttrString(b, "module_c"); + if (module == NULL) + return meip; + func = PyObject_GetAttrString(module, "func"); + if (func == NULL) + return meip; + Py_DECREF(module); + if (!PyCallable_Check (func)) { + fprintf(stderr, "function not callable\n"); + exit(0); + } + Py_DECREF(meip); + meip = PyObject_CallObject (func, NULL); + + Py_DECREF(func); + e = PyErr_Occurred (); + if (e){ + fprintf(stderr, "exception\n"); + return meip; + } + + return meip; +} + + +PyObject* vm_set_automod_cb(VmMngr* self, PyObject* args) +{ + PyObject* cb_automod; + + if (!PyArg_ParseTuple(args, "O", &cb_automod)) + return NULL; + + if (self->vm_mngr.cb_automod != NULL){ + Py_DECREF(self->vm_mngr.cb_automod); + } + + Py_INCREF(cb_automod); + self->vm_mngr.cb_automod = cb_automod; + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* vm_set_addr2obj(VmMngr* self, PyObject* args) +{ + PyObject* addr2obj; + + if (!PyArg_ParseTuple(args, "O", &addr2obj)) + return NULL; + + if (self->vm_mngr.addr2obj != NULL){ + Py_DECREF(self->vm_mngr.addr2obj); + } + + Py_INCREF(addr2obj); + self->vm_mngr.addr2obj = addr2obj; + Py_INCREF(Py_None); + return Py_None; +} + + + +/* +PyObject* add_jitbloc(VmMngr* self, PyObject* args) +{ + PyObject* jitobj; + + if (!PyArg_ParseTuple(args, "O", &addr2obj)) + return NULL; + + Py_INCREF(Py_None); + return Py_None; + +} +*/ + + + + +static void +VmMngr_dealloc(VmMngr* self) +{ + self->ob_type->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)&(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[] = { + {"vm_init_memory_page_pool", (PyCFunction)vm_init_memory_page_pool, METH_VARARGS, + "X"}, + {"vm_init_memory_breakpoint", (PyCFunction)vm_init_memory_breakpoint, METH_VARARGS, + "X"}, + {"vm_init_code_bloc_pool",(PyCFunction)vm_init_code_bloc_pool, METH_VARARGS, + "X"}, + {"vm_set_mem_access", (PyCFunction)vm_set_mem_access, METH_VARARGS, + "X"}, + {"vm_set_mem", (PyCFunction)vm_set_mem, METH_VARARGS, + "X"}, + {"vm_set_automod_cb", (PyCFunction)vm_set_automod_cb, METH_VARARGS, + "X"}, + {"vm_set_addr2obj", (PyCFunction)vm_set_addr2obj, METH_VARARGS, + "X"}, + {"vm_add_code_bloc",(PyCFunction)vm_add_code_bloc, METH_VARARGS, + "X"}, + {"vm_exec_bloc",(PyCFunction)vm_exec_bloc, METH_VARARGS, + "X"}, + {"vm_exec_blocs",(PyCFunction)vm_exec_blocs, METH_VARARGS, + "X"}, + {"vm_get_mem", (PyCFunction)vm_get_mem, METH_VARARGS, + "X"}, + {"vm_add_memory_page",(PyCFunction)vm_add_memory_page, METH_VARARGS, + "X"}, + {"vm_add_memory_breakpoint",(PyCFunction)vm_add_memory_breakpoint, METH_VARARGS, + "X"}, + {"vm_remove_memory_breakpoint",(PyCFunction)vm_remove_memory_breakpoint, METH_VARARGS, + "X"}, + {"vm_set_exception", (PyCFunction)vm_set_exception, METH_VARARGS, + "X"}, + {"vm_dump_memory_page_pool", (PyCFunction)vm_dump_memory_page_pool, METH_VARARGS, + "X"}, + {"vm_dump_memory_breakpoint", (PyCFunction)vm_dump_memory_breakpoint, METH_VARARGS, + "X"}, + {"vm_get_all_memory",(PyCFunction)vm_get_all_memory, METH_VARARGS, + "X"}, + {"vm_reset_memory_page_pool", (PyCFunction)vm_reset_memory_page_pool, METH_VARARGS, + "X"}, + {"vm_reset_memory_breakpoint", (PyCFunction)vm_reset_memory_breakpoint, METH_VARARGS, + "X"}, + {"vm_reset_code_bloc_pool", (PyCFunction)vm_reset_code_bloc_pool, METH_VARARGS, + "X"}, + {"vm_call_pyfunc_from_globals",(PyCFunction)vm_call_pyfunc_from_globals, METH_VARARGS, + "X"}, + + {"vm_get_exception",(PyCFunction)vm_get_exception, METH_VARARGS, + "X"}, + {"vm_get_exception",(PyCFunction)vm_get_exception, METH_VARARGS, + "X"}, + {"vm_get_last_write_ad", (PyCFunction)vm_get_last_write_ad, METH_VARARGS, + "X"}, + {"vm_get_last_write_size",(PyCFunction)vm_get_last_write_size, METH_VARARGS, + "X"}, + + {NULL} /* Sentinel */ +}; + +static int +VmMngr_init(VmMngr *self, PyObject *args, PyObject *kwds) +{ + + + fprintf(stderr, "ad cpu: %p\n", &(self->vm_mngr)); + memset(&(self->vm_mngr), 0, sizeof(self->vm_mngr)); + return 0; +} + +static PyGetSetDef VmMngr_getseters[] = { + {"vmmngr", + (getter)VmMngr_get_vmmngr, (setter)VmMngr_set_vmmngr, + "first name", + NULL}, + {NULL} /* Sentinel */ +}; + + +static PyTypeObject VmMngrType = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "JitCore_x86_32.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*/ + 0, /*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 objects", /* 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 PyObject *Vm_Mngr_Error; + + +static PyMethodDef Vm_Mngr_Methods[] = { + + {NULL, NULL, 0, NULL} /* Sentinel */ + +}; + + +PyMODINIT_FUNC +initvm_mngr(void) +{ + PyObject *m; + + if (PyType_Ready(&VmMngrType) < 0) + return; + + m = Py_InitModule("vm_mngr", Vm_Mngr_Methods); + if (m == NULL) + return; + + Vm_Mngr_Error = PyErr_NewException("vm_mngr_.error", NULL, NULL); + Py_INCREF(Vm_Mngr_Error); + PyModule_AddObject(m, "error", Vm_Mngr_Error); + + Py_INCREF(&VmMngrType); + PyModule_AddObject(m, "VmMngr", (PyObject *)&VmMngrType); + +} + |