本周在开发一个python业务系统时,涉及到解密过程,解密是通过调用c的so文件实现的。开发过程中,踩进了一个不大不小的坑,差点腿都没拔出来,仅以此谨记不再踩ctypes坑。

1.首先我们要有一个so库,有一个待调用的方法,c语言部分实现如下:

int c_dec(unsigned char* c,
unsigned char* m,
unsigned long long b,
const unsigned char* n,
const unsigned char* k)
{
int cReturn = in_dec(c,m,b,n,k);
return cReturn;
}

2.编译c文件,生成so文件

sudo g++ -c -fPIC c_dec.c -o c_dec.o

sudo g++ -shared -Wl,-soname,c_dec.so -o c_dec.so c_dec.o

3.python调用so库,并使用该方法解密

import ctypes
##导入so库文件
lib = ctypes.cdll.LoadLibrary(Dec_Log_Path[sys.argv[1]])
##参数准备,注意部分数据需要指针类型
dec_n = ctypes.c_char_p(Dec_N)
dec_k = ctypes.c_char_p(Dec_K)
enc_len = ctypes.c_longlong(len(before_data))
encs = ctypes.create_string_buffer(before_data,len(before_data)+5)
decs = ctypes.create_string_buffer('',len(before_data)+5)
##方法调用,解密后的日志返回给decs
lib.c_logs_dec(decs,encs, enc_len, dec_n, dec_k)
##注意!!!!!!!decs传入的时候是一个指针,返回后是一个数组,我就是在这里一直踩坑。所以对于decs需要string转换。
tmp_dec=''
for dec_log in decLogs:
tmp_dec += dec_log

4.最后说一下怎么爬出这个坑的。

(1).首先确认的是so库方法收到的数据和解密后的数据是不是正确的,可以将数据打印到文本中查看。

(2).确认一下python接收到的数据的正确性,我曾使用到的方法如下:

print decs
print decs.value  ##c_char_p指针获取数据
print decs.contents.value  ##pointer,POINTER,byref 指针获取数据

最后爬坑用到的方法是,python的raw string,我用原始字符串才发现decs的数据已经是正确了的,以此为依据才找到正确获取回传数据的方式为数组。

print repr(decs.raw)

附1.ctypes类型参照表