標籤:函數 工作 類型轉換 attrs module 結果 rewrite void content
近期在做一個漏洞展示平台,攻擊實現部分使用python實現。c語言實現部分使用libcli庫做一個類似telnet的東東,回呼函數run的時候調用python模組。
針對c調用python,做個了小demo
python模組:demo.py
def print_arg(str): print strdef add(a,b): print 'a=', a print 'b=', b return a + bclass Class_A: def __init__(self): print "init" def fun(self, str): print 'hello', str return strclass dedecms_get_webshell: def __init__(self): ''' ''' self._run = True #must rewrite function def check(self,site,port): ''' ''' print "Exploiting Host:%s,Port:(%d)......" % (site,port) flag = 1 if flag: content={"flag":1,"content":"POST http://www.baidu.com/shell.php (cmd)"} else: content={"flag":0,"content":"POST http://www.baidu.com/shell.php (cmd)"} return contentif __name__=="__main__": site="www.baidu.com" port=80 obj = dedecms_get_webshell() ret=obj.check(site,port)print ret
分析:
1. print_arg定義了一個傳參的函數
2. add 定義了一個傳如多個參數。且有返回值的函數
3. Class_A定義了一個類及類的一個方法fun(傳參數。有返回值)
4. dedecms_get_webshell定一個了類及類的一個方法check(傳多個參數,返回值是個元組)
以下使用c語言調用demo.py檔案裡的函數。
測試函數:
#include <Python.h>int main(int argc, char* argv[]){ test(); test1(); test2(); test3(); test4(); return 0;}
逐個分析:
//匯出當前環境變數
void getcurrent(){ PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('./')"); return;}
1. 一個最主要的調用方式
void test(){ Py_Initialize();//初始化python PyRun_SimpleString("print 'hello python'");//直接執行python代碼 Py_Finalize(); //釋放python return;}
分析:直接執行python 代碼,在調用的時候必須先做初始化操作(Py_Initialize),調用完後做清理工作(Py_Finalize)
2. 調用模組中的一個普通函數
void test1(){ Py_Initialize();//初始化python getcurrent(); PyObject *pModule = NULL, *pFunc = NULL, *pArg = NULL; pModule = PyImport_ImportModule("demo");//引入模組 pFunc = PyObject_GetAttrString(pModule, "print_arg");//直接擷取模組中的函數 pArg = Py_BuildValue("(s)", "hello_python"); //參數類型轉換,傳遞一個字串。將c/c++類型的字串轉換為python類型。元組中的python類型查看python文檔 PyEval_CallObject(pFunc, pArg); //調用直接獲得的函數。並傳遞參數 Py_Finalize(); //釋放python return;}
分析:先引用模組(PyImport_ImportModule)。然後擷取模組中的函數(PyObject_GetAttrString)。對c傳入python 的參數做類型轉換(Py_BuildValue("(s)","hello_python"))。最後直接調用函數並傳遞參數(PyEval_CallObject)。
3. 調用模組中的一個函數(多參數,帶返回值)
void test2(){ Py_Initialize(); getcurrent(); PyObject *pModule = NULL, *pDict = NULL, *pFunc = NULL, *pArg = NULL, *result = NULL; pModule = PyImport_ImportModule("demo"); //引入模組 pDict = PyModule_GetDict(pModule); //擷取模組字典屬性 //相當於Python模組對象的__dict__ 屬性,得到模組名稱空間下的字典對象 pFunc = PyDict_GetItemString(pDict, "add"); //從字典屬性中擷取函數 pArg = Py_BuildValue("(i, i)", 1, 2); //參數類型轉換,傳遞兩個整型參數 result = PyEval_CallObject(pFunc, pArg); //調用函數。並得到python類型的傳回值 int sum; PyArg_Parse(result, "i", &sum); //將python類型的傳回值轉換為c/c++類型 printf("sum=%d\n", sum); Py_Finalize();}
4. 調用模組中簡單的一個類(單個返回值)
void test3(){ Py_Initialize(); getcurrent(); PyObject *pModule = NULL, *pDict = NULL, *pClass = NULL, *pInstance = NULL, *result = NULL; pModule = PyImport_ImportModule("demo"); //引入模組 pDict = PyModule_GetDict(pModule); //擷取模組字典屬性 pClass = PyDict_GetItemString(pDict, "Class_A"); //通過字典屬性擷取模組中的類 pInstance = PyInstance_New(pClass, NULL, NULL);//執行個體化擷取的類 result = PyObject_CallMethod(pInstance, "fun", "(s)", "python_000"); //調用類的方法 char* name=NULL; PyArg_Parse(result, "s", &name); //將python類型的傳回值轉換為c/c++類型 printf("%s\n", name); Py_Finalize();}
5. 調用模組中一個簡單的類(返回值是個元組)
void test4()
{
Py_Initialize();
getcurrent();
PyObject *pModule = NULL, *pDict = NULL,*pClass = NULL, *pInstance = NULL, *result = NULL;
pModule =PyImport_ImportModule("demo"); //引入模組
pDict = PyModule_GetDict(pModule); //擷取模組字典屬性
pClass = PyDict_GetItemString(pDict,"dedecms_get_webshell"); //通過字典屬性擷取模組中的類
pInstance = PyInstance_New(pClass, NULL,NULL);
result = PyObject_CallMethod(pInstance,"check", "(s,i)", "www.baidu.com", 80);
int flag;
char*content = NULL;
PyObject *obj_content =PyDict_GetItemString(result, "content");
content = PyString_AsString(obj_content);
PyObject *obj_flag =PyDict_GetItemString(result, "flag");
flag = PyInt_AsLong(obj_flag);
printf("content: %s, flag: %d\n",content, flag);
Py_Finalize();
}
Makefile書寫:
all: testtest: pytest.o gcc -L/usr/lib/python2.7/ -lpython2.7 -ldl pytest.o -o testpytest.o: pytest.c gcc -g -std=gnu99 -Wall -c pytest.c -I/usr/include/python2.7/ clean: @rm -rf *.o *.pyc test
針對python不同的版本號碼。使用2.5,2.6等,庫的路徑參照安裝的路徑。
本打算展開多寫些東西,結果草草完事。
使用c語言調用python小結