-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmach.c
95 lines (86 loc) · 3.09 KB
/
mach.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <Python.h>
#include <sys/types.h>
#include <mach/mach_init.h>
#include <mach/mach_traps.h>
#include <mach/mach_types.h>
#include <mach/mach_vm.h>
static PyObject *MachError;
static PyObject *mach_error(kern_return_t ret) {
return PyErr_Format(MachError, "kernel return code %d", (int)ret);
}
static PyObject *pymach_task_self(PyObject *self, PyObject *args) {
return Py_BuildValue("i", mach_task_self());
}
static PyObject *pymach_task_for_pid(PyObject *self, PyObject *args) {
int pid;
task_t task;
kern_return_t ret;
if (!PyArg_ParseTuple(args, "i", &pid)) return NULL;
ret = task_for_pid(mach_task_self(), pid, &task);
if (ret) return mach_error(ret);
return Py_BuildValue("i", task);
}
static PyObject *pymach_vm_protect(PyObject *self, PyObject *args) {
task_t task;
mach_vm_address_t address;
mach_vm_size_t size;
int prot;
kern_return_t ret;
if (!PyArg_ParseTuple(args, "iKLi", &task, &address, &size,
&prot)) return NULL;
ret = mach_vm_protect(task, address, size, 0, prot);
if (ret) return mach_error(ret);
Py_RETURN_NONE;
}
static PyObject *pymach_vm_read(PyObject *self, PyObject *args) {
task_t task;
mach_vm_address_t address;
mach_vm_size_t size;
vm_offset_t data;
mach_msg_type_number_t dataCnt;
kern_return_t ret;
if (!PyArg_ParseTuple(args, "iKL", &task, &address, &size)) return NULL;
ret = mach_vm_read(task, address, size, &data, &dataCnt);
if (ret) return mach_error(ret);
PyObject *val = Py_BuildValue("s#", data, dataCnt);
mach_vm_deallocate(mach_task_self(), data, dataCnt);
return val;
}
static PyObject *pymach_vm_write(PyObject *self, PyObject *args) {
task_t task;
mach_vm_address_t address;
char *buf;
int len;
kern_return_t ret;
if (!PyArg_ParseTuple(args, "iKt#", &task, &address,
&buf, &len)) return NULL;
ret = mach_vm_write(task, address, (vm_offset_t)buf, len);
if (ret) return mach_error(ret);
Py_RETURN_NONE;
}
static PyMethodDef MachMethods[] = {
{"task_self", pymach_task_self, METH_VARARGS,
"Get a Mach port for the current task"},
{"task_for_pid", pymach_task_for_pid, METH_VARARGS,
"Get a Mach port for the task corresponding to a pid"},
{"vm_protect", pymach_vm_protect, METH_VARARGS,
"Change memory protection in another task"},
{"vm_read", pymach_vm_read, METH_VARARGS,
"Read memory from another task"},
{"vm_write", pymach_vm_write, METH_VARARGS,
"Write memory to another task"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initmach(void) {
PyObject *m = Py_InitModule("mach", MachMethods);
if (!m) return;
MachError = PyErr_NewException("mach.MachError", NULL, NULL);
Py_INCREF(MachError);
PyModule_AddObject(m, "MachError", MachError);
PyModule_AddObject(m, "VM_PROT_NONE", PyInt_FromLong(VM_PROT_NONE));
PyModule_AddObject(m, "VM_PROT_READ", PyInt_FromLong(VM_PROT_READ));
PyModule_AddObject(m, "VM_PROT_WRITE", PyInt_FromLong(VM_PROT_WRITE));
PyModule_AddObject(m, "VM_PROT_EXECUTE", PyInt_FromLong(VM_PROT_EXECUTE));
PyModule_AddObject(m, "VM_PROT_DEFAULT", PyInt_FromLong(VM_PROT_DEFAULT));
PyModule_AddObject(m, "VM_PROT_ALL", PyInt_FromLong(VM_PROT_ALL));
}