Skip to content

Commit 900ba3b

Browse files
committed
First prototype
1 parent 048e466 commit 900ba3b

File tree

3 files changed

+113
-0
lines changed

3 files changed

+113
-0
lines changed

mach.c

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

setup.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from distutils.core import setup, Extension
2+
3+
mach = Extension('mach',
4+
sources = ['mach.c']
5+
)
6+
7+
setup(name = 'mach',
8+
version = '1.0',
9+
description = 'Wrap some low-level Mach stuff',
10+
ext_modules = [mach]
11+
)

test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env python
2+
3+
import mach
4+
import sys
5+
6+
for arg in sys.argv[1:]:
7+
print arg, mach.task_for_pid(int(arg))

0 commit comments

Comments
 (0)