What is a .pyd file? A .pyd file is only a .dll (renamed in .pyd) that contains the necessary information to use it as a python module.
PS. The "main" function of this lib "_mydaemon" is "init_mydaemon", if you want to change the name to (es.) "smthelse" the relative "main" function should be "initsmthelse".
There are 2 ways to build a .pyd on windows:
- distutils (there are more issues with python22, vc++6 and another distutils's settings on recent windows OSes and current compilers=bad way)
- using directly a compiler such as vc++ (tested on vs2010)
The relative ways
I said there are 2 ways, no?
- The first way is the worst but if you don't care about this, here how to do it:
-Create a .bat with this inside: (if you want to use another compiler other than vc++6 you have to edit the relative details inside python22\lib\distutils\msvccompiler.py; NB. you can also use mingw! NB2. for this .bat I'm using vs100!)
Code:call "%vs100comntools%vsvars32.bat" python .\_mydaemon\setup.py build -cmsvc --force pause
Code:import distutils from distutils.core import setup, Extension setup(name = '_mydaemon', version = '1.8', author = 'martysama0134', description = 'MyDaemon Package', url = 'http://docs.python.org/extending/building', ext_modules = [Extension('_mydaemon', sources = [r'c:\Users\blablabla\_mydaemon\_mydaemon.cpp'],)] )
(you'll find the source of _mydaemon.cpp below) - Second way (tested on vs2010)
Create a project with this 2 files:
Code:// _mydaemon.h #pragma once //# pyd required BEGIN #include <Python.h>//<stdio.h>, <string.h>, <errno.h>, <stdlib.h> //# pyd required END //c++module #include <iostream>//std::cin/cout #include <windows.h> #include <tlhelp32.h>//module32 funcs #include <tchar.h>//unicode set //#include <stdio.h>
Code:// _mydaemon.cpp #include "_mydaemon.h" static PyObject* MyDaemonError; /*START CODE*/ static PyObject* MyDaemon_DllView2(PyObject *self, PyObject *args) { DWORD dwPID; if(!PyArg_ParseTuple(args, "i", &dwPID)) return NULL; HANDLE hModuleSnap = INVALID_HANDLE_VALUE; MODULEENTRY32 me32; // Take a snapshot of all modules in the specified process. hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID); if(hModuleSnap == INVALID_HANDLE_VALUE) { return Py_BuildValue("i", 0); // CreateToolhelp32Snapshot (of modules) } // Set the size of the structure before using it. me32.dwSize = sizeof(MODULEENTRY32); // Retrieve information about the first module, // and exit if unsuccessful if(!Module32First(hModuleSnap, &me32)) { CloseHandle(hModuleSnap); return Py_BuildValue("i", 0);//Module32First } // Now walk the module list of the process, // and display information about each module int tuplemain_index = 0; do{tuplemain_index++;}while(Module32Next(hModuleSnap, &me32)); PyObject *DllTupleMain = PyTuple_New(tuplemain_index); PyObject *DllTupleChild; Module32First(hModuleSnap, &me32); tuplemain_index = 0; do { DllTupleChild = Py_BuildValue("(uuii)", me32.szModule, me32.szExePath, (DWORD) me32.modBaseAddr, me32.modBaseSize); PyTuple_SetItem(DllTupleMain, tuplemain_index, DllTupleChild); tuplemain_index++; }while(Module32Next(hModuleSnap, &me32)); CloseHandle(hModuleSnap); return DllTupleMain; } static PyObject* MyDaemon_System(PyObject *self, PyObject *args) { //ps. os.popen is better char* command; int sts; if(!PyArg_ParseTuple(args, "s", &command)) return NULL; sts = system(command); return Py_BuildValue("i", sts); } static PyObject* MyDaemon_LoadLib(PyObject *self, PyObject *args) { char* libname; if(!PyArg_ParseTuple(args, "s", &libname)) return NULL; //std::cout << libname << std::endl; HINSTANCE myH = LoadLibraryA(libname); return Py_BuildValue("i", myH != NULL); } static PyObject* MyDaemon_TaskList(PyObject *self, PyObject *args) { HANDLE hProcessSnap; HANDLE hProcess; PROCESSENTRY32 pe32; DWORD dwPriorityClass; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hProcessSnap == INVALID_HANDLE_VALUE) { return Py_BuildValue("i", 0); // CreateToolhelp32Snapshot (of processes) } // Set the size of the structure before using it. pe32.dwSize = sizeof(PROCESSENTRY32); // Retrieve information about the first process, // and exit if unsuccessful if(!Process32First(hProcessSnap, &pe32)) { CloseHandle(hProcessSnap);// clean the snapshot object return Py_BuildValue("i", 0); // Process32First } int tuplemain_index = 0; do{tuplemain_index++;}while(Process32Next(hProcessSnap, &pe32)); PyObject *DllTupleMain = PyTuple_New(tuplemain_index); PyObject *DllTupleChild; Process32First(hProcessSnap, &pe32); tuplemain_index = 0; do { dwPriorityClass = 0; // Retrieve the priority class. hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); //if(hProcess == NULL){} //else if(hProcess != NULL) { dwPriorityClass = GetPriorityClass(hProcess); CloseHandle(hProcess); } DllTupleChild = Py_BuildValue("(uiiiii)", pe32.szExeFile, pe32.th32ProcessID, pe32.cntThreads, pe32.th32ParentProcessID, pe32.pcPriClassBase, dwPriorityClass); PyTuple_SetItem(DllTupleMain, tuplemain_index, DllTupleChild); tuplemain_index++; } while(Process32Next(hProcessSnap, &pe32)); CloseHandle(hProcessSnap); return DllTupleMain; } /*METHODS_LIST*/ static PyMethodDef MyDaemonMethods[] = { {"dllview2", MyDaemon_DllView2, METH_VARARGS, "DllView in tuple return."}, {"loadlib", MyDaemon_LoadLib, METH_VARARGS, "Load a dll in memory."}, {"system", MyDaemon_System, METH_VARARGS, "Execute a shell command."}, {"tasklist", MyDaemon_TaskList, METH_VARARGS, "Show all active pc-process."}, {NULL, NULL, 0, NULL} }; /*INIT*/ DL_EXPORT(void) init_mydaemon(void) { PyObject *m, *d; m = Py_InitModule("_mydaemon", MyDaemonMethods); MyDaemonError = PyErr_NewException("_mydaemon.error", NULL, NULL); d = PyModule_GetDict(m); PyDict_SetItemString(d, "error", MyDaemonError); }
Now, you have to add this inside the (Project) Properties -> Configuration Properties -> Linker -> Command Line -> Additional Options:
Code:/export:init_mydaemon
Don't forget to add the python22 include path here:
(Project) Properties -> Configuration Properties -> C/C++ -> General -> Additional Include Directories
(you must install python22 on your os or, just download the python2.2.3 sources and compile them with vc++6 for the relative .lib files to include)
Now, build the project and you'll get the pyd!
Rename your .dll to .pyd and move it into the client\lib path (info )
To use this "new module" in python you just need to write something like this:
Code:
import _mydaemon #you can also do this: import _mydaemon as myd #show me my module namespaces! ##print dir(myd) #now it's time to test my defs! _mydaemon.loadlib("mylib.dll")#load this library in memory # import os dllloadedinmyclientbin=_mydaemon.dllview(os.get_pid())#tuple return ##for dllsnap in dllloadedinmyclientbin: ## print ", ".join([str(i) for i in dllsnap]) # tasklist=_mydaemon.tasklist() # _mydaemon.system(r"echo this >> %userprofile%\desktop\this.txt")
- _mydaemon.dllview2(pid) // it returns a tuple of all the dll injected into the pid process
- _mydaemon.loadlib(libname) // it loads libname in memory
- _mydaemon.tasklist() // it returns a tuple containing all the active processes on your computer
- _mydaemon.system(cmd) // it invokes the shell to execute cmd
Other
- I used this example to make dllview&tasklist defs:
- You can read the relative python documentation (this looks even better: )
- You should remember that this is only an example code, if you want to load a library or to show dlls/processes in another way it's your choice