如何阻止Cython编译生成的pyd模块被代码检查
Cython编译pyd后阻断dir()模块探查的实现方案
提前说明:不存在100%无法破解的二进制防护,以下方法可以直接阻断常规dir()的探查路径,把普通用户随手扒接口的路径堵死,满足一般场景下的黑盒分发需求:
- 重写模块级
__dir__方法,仅暴露许可的公开接口
在你的Cython源码(.pyx)全局作用域直接定义__dir__函数,返回值只包含你允许对外展示的接口名称,内部实现的名称全部不返回,即可让常规dir(your_module)调用拿不到内部结构:
注意不要把# 示例:仅对外暴露public_api一个接口 def __dir__(): return ["public_api"]__dir__本身加入返回列表,避免暴露重写逻辑。 - 关闭Cython的属性绑定开关,减少属性暴露
在.pyx文件头部添加Cython编译指令,关闭Python层属性绑定,避免内部C实现自动注册到模块属性表被dir()扫到:
上述指令同时会关闭代码注释生成、文档字符串导出,避免额外信息泄露。# cython: binding=False, emit_code_comments=False, docstrings=False - 编译时剥离所有符号信息
用GCC编译时添加-s参数,编译完成后对生成的.pyd/.so文件执行strip操作,彻底移除二进制里的函数名、类名等调试符号,从根源上减少可被探查的属性条目。Windows平台编译注意不要生成.pdb调试文件,避免符号泄露。 - 内部实现全部使用Cython原生语法定义,不暴露到Python层
所有不需要对外调用的函数、类全部用cdef关键字定义,不要用def/cpdef:纯cdef定义的逻辑是C层级实现,不会注册到Python模块的属性字典,dir()完全无法枚举到。对外暴露的必要接口才用def定义,且统一通过__getattr__做访问拦截:
上述逻辑可以拦截所有对非公开属性的直接访问,哪怕他人猜测内部属性名也无法获取对应对象。cdef dict _public_interface = {"public_api": public_api} def __getattr__(str name): if name in _public_interface: return _public_interface[name] raise AttributeError(f"module has no attribute '{name}'")
注意:以上方案仅能防范普通用户通过Python控制台常规手段的探查,无法对抗专业逆向人员使用IDA、Ghidra等二进制分析工具的逆向行为,属于提高逆向成本的防护手段,无法实现绝对的代码隐藏。
内容的提问来源于stack exchange,提问作者Tommaso Bendinelli
相关产品推荐
相关产品推荐

