134 lines
3.6 KiB
C
134 lines
3.6 KiB
C
#define PY_SSIZE_T_CLEAN
|
|
#define Py_CPYTHON_FRAMEOBJECT_H
|
|
#include "Python.h"
|
|
#include "marshal.h"
|
|
// #include "internal/pycore_frame.h"
|
|
#include "cpython/frameobject.h"
|
|
|
|
#define ARGTYPE 1
|
|
#include "libtomcrypt/headers/tomcrypt.h"
|
|
|
|
static const int MAJOR_VERSION = PY_MAJOR_VERSION;
|
|
static const int MINOR_VERSION = PY_MINOR_VERSION;
|
|
|
|
const unsigned char *aes_key = "WAIT_TO_BE_FILLED";
|
|
|
|
// PyObject *CodeObject;
|
|
|
|
PyObject* PyHumorRuntime_HumorEnter(PyObject* self, PyObject* args) {
|
|
PyFrameObject *frame = PyEval_GetFrame();
|
|
PyCodeObject *f_code = frame->f_code;
|
|
// PyCodeObject *f_code = PyFrame_GetCode(PyEval_GetFrame());
|
|
PyObject *codearray = f_code->co_code;
|
|
|
|
Py_ssize_t size;
|
|
unsigned char *data;
|
|
PyBytes_AsStringAndSize(codearray, &data, &size);
|
|
if (data == NULL) {
|
|
return NULL;
|
|
}
|
|
if (size < 8 || size > 8192) {
|
|
return NULL;
|
|
}
|
|
int use_size = (size - 8) - (size - 8) % 16;
|
|
|
|
symmetric_key skey;
|
|
int err;
|
|
if ((err = aes_setup(aes_key + 1, 16, 0, &skey)) != CRYPT_OK) {
|
|
return NULL;
|
|
}
|
|
for (int i = 0; i < use_size; i += 16) {
|
|
if ((err = aes_ecb_decrypt(data + i + 8, data + i + 8, &skey)) != CRYPT_OK) {
|
|
return NULL;
|
|
}
|
|
}
|
|
aes_done(&skey);
|
|
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* PyHumorRuntime_RunCode(PyObject* self, PyObject* args) {
|
|
PyObject* name;
|
|
PyObject* file;
|
|
char* bytecode;
|
|
Py_ssize_t bytecodeSize;
|
|
if (!PyArg_ParseTuple(args, "OOy#", &name, &file, &bytecode, &bytecodeSize)) {
|
|
return NULL;
|
|
}
|
|
|
|
// Parse the code meta
|
|
if (bytecodeSize < 16) {
|
|
return NULL;
|
|
}
|
|
if (bytecode[9] != MAJOR_VERSION || bytecode[10] != MINOR_VERSION) {
|
|
return NULL;
|
|
}
|
|
if (*(int*)(bytecode + 12) != bytecodeSize - 16) {
|
|
return NULL;
|
|
}
|
|
|
|
// Decrypt the bytecode
|
|
symmetric_key skey;
|
|
unsigned char *plaintext = malloc(bytecodeSize - 16);
|
|
int err;
|
|
if ((err = aes_setup(aes_key, 16, 0, &skey)) != CRYPT_OK) {
|
|
return NULL;
|
|
}
|
|
for (int i = 0; i * 16 < bytecodeSize - 16; i++) {
|
|
if ((err = aes_ecb_decrypt(bytecode + 16 + i * 16, plaintext + i * 16, &skey)) != CRYPT_OK) {
|
|
return NULL;
|
|
}
|
|
}
|
|
aes_done(&skey);
|
|
|
|
// Load the code object
|
|
PyObject *codeObject = PyMarshal_ReadObjectFromString(plaintext, bytecodeSize - 16);
|
|
free(plaintext);
|
|
if (codeObject == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
// Add __humor_enter__ function to the globals
|
|
PyMethodDef humorEnterMethodDef =
|
|
{"__humor_enter__", PyHumorRuntime_HumorEnter, METH_VARARGS, NULL};
|
|
|
|
PyObject* humorEnterFunc = PyCFunction_New(&humorEnterMethodDef, NULL);
|
|
if (humorEnterFunc == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
PyObject* globals = PyEval_GetGlobals();
|
|
if (globals == NULL || PyDict_SetItemString(globals, "__humor_enter__", humorEnterFunc) < 0) {
|
|
Py_DECREF(humorEnterFunc);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(humorEnterFunc); // Decrease reference count since it's now in the globals
|
|
|
|
// Run the code
|
|
PyObject* result = PyImport_ExecCodeModuleObject(name, codeObject, file, NULL);
|
|
Py_DECREF(codeObject);
|
|
|
|
// Remove __humor_enter__ function from the globals
|
|
PyDict_DelItemString(globals, "__humor_enter__");
|
|
|
|
return result;
|
|
}
|
|
|
|
static PyMethodDef PyHumorRuntime_Methods[] = {
|
|
{"__pyhumor__", PyHumorRuntime_RunCode, METH_VARARGS, NULL},
|
|
{NULL, NULL, 0, NULL}
|
|
};
|
|
|
|
static struct PyModuleDef PyHumorRuntime_Module = {
|
|
PyModuleDef_HEAD_INIT,
|
|
"pyhumor_runtime",
|
|
NULL,
|
|
-1,
|
|
PyHumorRuntime_Methods
|
|
};
|
|
|
|
PyMODINIT_FUNC PyInit_pyhumor_runtime(void) {
|
|
return PyModule_Create(&PyHumorRuntime_Module);
|
|
}
|