views:

443

answers:

2

Hello! This may seem like a weird question, but I would like to know how I can run a function in a .dll from a memory 'signature'. I don't understand much about how it actually works, but I needed it badly. Its a way of running unexported functions from within a .dll, if you know the memory signature and adress of it. For example, I have these:

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

And using some pretty nifty C++ code you can use this to run functions from within a .dll.

Here is a well explained article on it: http://wiki.alliedmods.net/Signature_Scanning

So, is it possible using Ctypes or any other way to do this inside python?

+1  A: 

If you can already run them using C++ then you can try using SWIG to generate python wrappers for the C++ code you've written making it callable from python.

http://www.swig.org/

Some caveats that I've found using SWIG:

Swig looks up types based on a string value. For example an integer type in Python (int) will look to make sure that the cpp type is "int" otherwise swig will complain about type mismatches. There is no automatic conversion.

Swig copies source code verbatim therefore even objects in the same namespace will need to be fully qualified so that the cxx file will compile properly.

Hope that helps.

mabbit
A: 

You said you were trying to call a function that was not exported; as far as I know, that's not possible from Python. However, your problem seems to be merely that the name is mangled.

You can invoke an arbitrary export using ctypes. Since the name is mangled, and isn't a valid Python identifier, you can use getattr().

Another approach if you have the right information is to find the export by ordinal, which you'd have to do if there was no name exported at all. One way to get the ordinal would be using dumpbin.exe, included in many Windows compiled languages. It's actually a front-end to the linker, so if you have the MS LinK.exe, you can also use that with appropriate commandline switches.

To get the function reference (which is a "function-pointer" object bound to the address of it), you can use something like:

import ctypes func = getattr(ctypes.windll.msvcrt, "@@myfunc") retval = func(None)

Naturally, you'd replace the 'msvcrt' with the dll you specifically want to call.

What I don't show here is how to unmangle the name to derive the calling signature, and thus the arguments necessary. Doing that would require a demangler, and those are very specific to the brand AND VERSION of C++ compiler used to create the DLL.

There is a certain amount of error checking if the function is stdcall, so you can sometimes fiddle with things till you get them right. But if the function is cdecl, then there's no way to automatically check. Likewise you have to remember to include the extra this parameter if appropriate.