Search code examples
pythondllctypesreverse-engineering

Retrieving data via old DLL in python


I try to use an old DLL from 2001 in Python and there is almost no documentation left. After some work I could get some function running. But I cannot receive data. My knowledge of DLL and pointers is relatively limited. Heres the problem:

The function TwixGetMainEntry expects three parameters

  • ID of record to retrieve
  • value. Pointer to string: This variable will be overwritten with the result. Thats what I am aiming for
  • Length of buffer

I do get results, but I cannot decode it properly. The data is probably not UTF-8. And I had to use a 32Bit-version of python.

import ctypes
twix = ctypes.WinDLL("twx.dll")

# Some initialization stuff first
# ...

# Get data
value = ctypes.c_wchar_p("")
twix.TwixGetMainEntry(2, ctypes.byref(value), 1024)

value.value.encode('utf-8') # Returns things like: \xe3\xb9\xb0\xdf\x98\xe3\x90...

Tried it with c_char_p as well, didn got a result.

Here are some definition of the function in other languages

# VB.net
Public Declare Function TwixGetMainEntry Lib "twx.dll" (ByVal nr As Integer, ByVal value As String, ByVal k As Integer) As Integer
# C
int (*TwixGetMainEntry)(int, char*, int);

Any ideas what I could try?

Many thanks!


Solution

  • Here's an example. Note that c_char_p is correct for C char* and create_string_buffer allocates a writable array of char. Use c_wchar_p and create_unicode_buffer if dealing with wchar_t*.

    import ctypes as ct
    
    # C - default calling convention is __cdecl
    # int (*TwixGetMainEntry)(int, char*, int);
    
    twix = ct.CDLL('./twx.dll')      # for __cdecl calling convention
    # twix = ct.WinDLL('./twx.dll')  # for __stdcall calling convention
    
    # Declaring argument types and result type helps ctypes check parameters.
    # Make sure to match the C prototype.
    twix.TwixGetMainEntry.argtypes = ct.c_int, ct.c_char_p, ct.c_int
    twix.TwixGetMainEntry.restype = ct.c_int
    
    value = ct.create_string_buffer(1024)  # Need to allocate an array, not just a pointer.
    result = twix.TwixGetMainEntry(2, value, ct.sizeof(value))
    print(value.raw)   # To view the whole buffer
    print(value.value) # to see the null-terminated value of the buffer