使用python运行未导出的.dll函数

时间:2009-01-07 17:30:22

标签: python memory ctypes

这可能看起来像一个奇怪的问题,但我想知道如何从内存'签名'在.dll中运行一个函数。我不太了解它实际上是如何工作的,但我非常需要它。它是一种在.dll中运行未导出函数的方法,如果你知道它的内存签名和地址。 例如,我有这些:

respawn_f "_ZN9CCSPlayer12RoundRespawnEv"
respawn_sig "568BF18B06FF90B80400008B86E80D00"
respawn_mask "xxxxx?xxx??xxxx?"

使用一些漂亮的C ++代码,您可以使用它来运行.dll中的函数。

这是一篇很好解释的文章: http://wiki.alliedmods.net/Signature_Scanning

那么,是否有可能在Cthon中使用Ctypes或任何其他方式来实现这一点?

2 个答案:

答案 0 :(得分:2)

如果您已经可以使用C ++运行它们,那么您可以尝试使用SWIG为您编写的C ++代码生成python包装器,使其可以从python中调用。

http://www.swig.org/

我使用SWIG找到了一些警告:

Swig根据字符串值查找类型。例如 Python(int)中的整数类型将确保 cpp类型是“int”否则swig会抱怨 关于类型不匹配。没有自动转换。

Swig逐字复制源代码,因此即使是同一命名空间中的对象也是如此 将需要完全限定,以便cxx文件可以正确编译。

希望有所帮助。

答案 1 :(得分:0)

你说你试图调用一个没有导出的函数;据我所知,这不可能来自Python。但是,你的问题似乎只是名称被破坏了。

您可以使用ctypes调用任意导出。由于名称被破坏,并且不是有效的Python标识符,因此可以使用getattr()。

如果您有正确的信息,另一种方法是按顺序查找导出,如果根本没有导出名称,则必须执行此操作。获取序数的一种方法是使用dumpbin.exe,包含在许多Windows编译语言中。它实际上是链接器的前端,所以如果你有MS LinK.exe,你也可以使用适当的命令行开关。

要获取函数引用(这是一个绑定到它的地址的“函数指针”对象),你可以使用类似的东西:

导入ctypes func = getattr(ctypes.windll.msvcrt,“@@ myfunc”) retval = func(无)

当然,你要用你特别想要调用的dll替换'msvcrt'。

我在这里没有展示的是如何解除名称以导出调用签名,从而得到必要的参数。这样做需要一个demangler,而且这些非常特定于用于创建DLL的C ++编译器的品牌 AND VERSION

如果函数是stdcall,则会进行一定数量的错误检查,因此有时你可以弄清楚它们是否正确。但如果函数是cdecl,那么就无法自动检查。同样,如果合适,您必须记住包含额外的此参数。