def writepmc(self, type_a, type_d, datano_s, datano_e, value):
# datano_s & datano_e = start & end number
length = 8 + (datano_e - datano_s + 1)
# c union datatype
class UnionC(ctypes.Union):
_fields_ = [
('cdata[N]', ctypes.c_char),
('idata[N]', ctypes.c_short),
('ldata[N]', ctypes.c_long),
('fdata[N]', ctypes.c_float),
('dfdata[N]', ctypes.c_double),
]
union = UnionC()
union.ldata[0] = value
class Iodbpmc(ctypes.Structure):
_fields_ = [("type_a", ctypes.c_short),
("type_d", ctypes.c_short),
("datano_s", ctypes.c_short),
("datano_e", ctypes.c_short),
("u", union)]
iodbpmc = Iodbpmc()
iodbpmc.type_a = type_a
iodbpmc.type_d = type_d
iodbpmc.datano_s = datano_s
iodbpmc.datano_e = datano_e
ret = focas.pmc_wrpmcrng(libh, length, ctypes.byref(iodbpmc))
self.wrpmc_errorcheck(ret)
return ret
I'm working on a Universal Robot and have to use Python 2.7. I am also using the CTypes lib. I keep getting the error in the title and am not sure what I'm doing wrong.
I don't have a lot of experience with CTypes or OOP in Python. Does anyone know what's causing the error?
I managed to solve the issue myself.
I wrote:
class UnionC(ctypes.Union):
_fields_ = [
('cdata', ctypes.c_char),
('idata', ctypes.c_short),
('ldata', ctypes.c_long),
('fdata', ctypes.c_float),
('dfdata', ctypes.c_double),
]
And I removed :
union = UnionC()
union.ldata[0] = value
These changes solved the problem for me. I'm pretty sure the line two lines above were causing the issue.
Related
I am calling a native c library using ctypes, passing in a specialiezed struct and getting back another struct. I get a seg fault when gc is called, can't find much details in gdb trace:
Thread 1 "python" received signal SIGSEGV, Segmentation fault.
0x00007ffff7a5ca44 in visit_decref (op=0xf5ee10, data=0x0) at Modules/gcmodule.c:374
374 Modules/gcmodule.c: No such file or directory.
gdb) where
#0 0x00007ffff7a5ca44 in visit_decref (op=0xf5ee10, data=0x0) at Modules/gcmodule.c:374
#1 0x00007ffff798bb0c in subtype_traverse (self=0x7fff7744fd90, visit=0x7ffff7a5ca40 <visit_decref>, arg=0x0) at Objects/typeobject.c:1011
#2 0x00007ffff7a5bd77 in subtract_refs (containers=<optimized out>) at Modules/gcmodule.c:399
#3 collect (generation=generation#entry=0, n_collected=n_collected#entry=0x7fffffffb708, n_uncollectable=n_uncollectable#entry=0x7fffffffb710, nofail=nofail#entry=0) at Modules/gcmodule.c:956
#4 0x00007ffff7a5c95d in collect_with_callback (generation=0) at Modules/gcmodule.c:1128
#5 0x00007ffff7a5d1eb in collect_generations () at Modules/gcmodule.c:1151
#6 _PyObject_GC_Alloc (basicsize=<optimized out>, use_calloc=0) at Modules/gcmodule.c:1726
#7 _PyObject_GC_Malloc (basicsize=<optimized out>) at Modules/gcmodule.c:1736
The code sample is this:
_C_DOUBLE_P = POINTER(c_double)
_C_INT_P = POINTER(c_int)
class _IN_DATA(Structure):
_fields_ = [('in_kps', _C_DOUBLE_P),
('in_desc', _C_DOUBLE_P)
]
def __init__(self):
t = c_int
self.test = ctypes.cast(t, POINTER(c_int))
class _OUT_DATA(Structure):
_fields_ = [
('num_out_kps', ctypes.c_int),
('out_kps', _C_DOUBLE_P),
('out_desc', _C_DOUBLE_P)
]
class _IN_DATA_LIST(ctypes.Structure):
_fields_ = [
('num_crops', c_int),
('crops', POINTER(_IN_DATA))
]
def __init__(self, crops_raw_kps: List[np.ndarray], crops_raw_descriptors: List[np.ndarray]):
num_crops = len(crops_raw_kps)
self.num_crops = num_crops
crops = (POINTER(_IN_DATA) * num_crops)()
self.crops = ctypes.cast(crops, POINTER(_IN_DATA))
for i in range(num_crops):
self.crops[i].in_kps = crops_raw_kps[i].ctypes.data_as(_C_DOUBLE_P)
self.crops[i].in_desc = crops_raw_descriptors[i].ctypes.data_as(_C_DOUBLE_P)
class _OUT_DATA_LIST(ctypes.Structure):
_fields_ = [
('crops_data', ctypes.POINTER(_OUT_DATA)),
('num_results', c_int)
]
class SPPostWrapper:
def __init__(self):
self._post_processor_lib = ctypes.cdll.LoadLibrary("multitracker/custom_features/build/ffme/libffme.so")
self._post_processor_lib.py_postprocess.restype = _OUT_DATA_LIST
self._post_processor_lib.py_postprocess.argtypes = [POINTER(_IN_DATA_LIST)]
def post_process_multi(self, crops_raw_kps: List[np.ndarray], crops_raw_descriptors: List[np.ndarray]):
num_crops = len(crops_raw_kps)
adjusted_kps = [np.asarray(np.squeeze(kp), np.double) for kp in crops_raw_kps]
adjusted_desc = [np.asarray(np.squeeze(desc), np.double) for desc in crops_raw_descriptors]
crops_struct = _IN_DATA_LIST(adjusted_kps, adjusted_desc)
out_result= self._post_processor_lib.py_postprocess(ctypes.byref(crops_struct))
I allocate the IN_DATA in python, and the OUT_DATA is allocated in the c code , I tried using cache in c (assuming python will not clean the memory) or allocating new memory for each call (assuming python does free the out_data memory) - both methods fail when gc of python is called.
Update:
To better isolate the problem I removed the usage of out_data, setting the method to void, and still the problem happens. I also tried keeping the in data as a member and i think this prevents the data from happening, until the process shutdown. So it must be something to do with the memory I allocated to input/input list.
Update 2:
I was able to verify that the problem only happens if I pass more than 1 item in the IN_DATA_LIST (more than 1 crop). This is very strange indeed...
After validating that the problem happens even if the c code does nothing and returns nothing, and not being able to solve it, I ended up using a more shallow input (and output) , this seems to run ok, without seg faults:
class _IN_DATA(Structure):
_fields_ = [
('num_crops', c_int),
('in_kps', _C_DOUBLE_P),
('in_desc', _C_DOUBLE_P)
]
def __init__(self, kps_flat, desc_falt, num_crops):
self.num_crops = num_crops
self.in_kps = kps_flat.ctypes.data_as(_C_DOUBLE_P)
self.in_desc = desc_falt.ctypes.data_as(_C_DOUBLE_P)
class _OUT_DATA(Structure):
_fields_ = [
('num_results', ctypes.c_int),
('results_per_crop', _C_INT_P),
('out_kps', _C_DOUBLE_P), # x,y, score
('out_desc', _C_DOUBLE_P)
]
I'm trying to find the base address of render.dll used in the process process.exe. I have modified the code in this question, and I'm able to get a result for the base address of render.dll.
from ctypes import *
from ctypes.wintypes import *
import psutil
class MODULEENTRY32(Structure):
_fields_ = [( 'dwSize', DWORD),
( 'th32ModuleID', DWORD),
( 'th32ProcessID', DWORD),
( 'GlblcntUsage', DWORD),
( 'ProccntUsage', DWORD),
( 'modBaseAddr', POINTER(BYTE)),
( 'modBaseSize', DWORD),
( 'hModule', HMODULE),
( 'szModule', c_char * 256),
( 'szExePath', c_char * 260)]
CreateToolhelp32Snapshot = windll.kernel32.CreateToolhelp32Snapshot
Module32First = windll.kernel32.Module32First
Module32Next = windll.kernel32.Module32Next
CloseHandle = windll.kernel32.CloseHandle
TH32CS_SNAPMODULE = 0x00000008
TH32CS_SNAPMODULE32 = 0x00000010
def getpid(processname):
for proc in psutil.process_iter():
if str(processname) in str(proc.name):
return proc.pid
def GetModuleByName(name):
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE32 | TH32CS_SNAPMODULE, getpid('process.exe'))
entry = MODULEENTRY32()
entry.dwSize = sizeof(MODULEENTRY32)
if Module32First(snapshot, pointer(entry)):
while Module32Next(snapshot, entry):
if entry.szModule == name:
CloseHandle(snapshot)
return entry.modBaseAddr
CloseHandle(snapshot)
return None
baseAddr = GetModuleByName('render.dll')
print baseAddr
Which results in <__main__.LP_c_byte object at 0x00000000023C9348>. I know this is to do with the result being a POINTER(BYTE) type, but I am not sure how to get from this type to a normal hex memory address that I can use to read the process memory at this location.
I found an answer here. Turns out I had the same misunderstanding as the other poster and that using ctypes.addressof(baseAddr.contents) returns the correct memory address for the .dll.
I followed the Grey Hat Python and made a debugger, but it can't work well.
I ran the calc.exe and find the PID. However, the debugger can't attach to the process. I copied the code from the book and also downloaded the code from the Internet. Both of them gave me the same result.Here is my code:
from ctypes import *
from my_debugger_defines import *
kernel32 = windll.kernel32
class debugger():
def __init__(self):
self.h_process = None
self.pid = None
self.debugger_active = False
def load(self, path_to_exe):
#dwCreation flag determines how to create the process
#set creation_flags = CREATE_NEW_CONSOLE if you want
#to see the calculator GUI
creation_flags = DEBUG_PROCESS
#instantiate the structs
startupinfo = STARTUPINFO()
process_information = PROCESS_INFORMATION()
#The following two options allow the started process
#to be shown as a separate window. This also illustrates
#how different settings in the STARTUPINFO struct can affect
#the debugger.
startupinfo.dwFlags =0x1
startupinfo.wShowWindow =0x0
#We then initialize the cb variable in the STARTUPINFO struct
#which is just the size of the struct itself
startupinfo.cb = sizeof(startupinfo)
if kernel32.CreateProcessA(path_to_exe,
None,
None,
None,
None,
creation_flags,
None,
None,
byref(startupinfo),
byref(process_information)):
print "[*] We have successfully launched the process!"
print "[*] PID: %d" % process_information.dwProcessId
#Obtain a valid handle to the newly created process
#and store it for future access
self.h_process = self.open_process(process_information.dwProcessId)
else:
print "[*] Error:0x%08x."%kernel32.GetLastError()
def open_process(self, pid):
h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
return h_process
def attach(self, pid):
self.h_process = self.open_process(pid)
#We attempt to attach to the process
#if this fails we exit the callable
if kernel32.DebugActiveProcess(pid):
self.debugger_active = True
self.pid = int(pid)
self.run()
else:
print "[*] Unable to attach to the process."
def run(self):
#Now we have to poll the debugger for debugging events
while self.debugger_active == True:
self.get_debug_event()
def get_debug_event(self):
debug_event = DEBUG_EVENT()
continue_status = DBG_CONTINUE
if kernel32.WaitForDebugEvent(byref(debug_event), INFINITE):
#We aren't going to build any event handlers just yet.
#Let's just resume the process for now.
raw_input("press a key to continue...")
self.debugger_active = False
kernel32.ContinueDebugEvent(\
debug_event.dwProcessId, \
debug_event.dwThreadId, \
continue_status )
def detach(self):
if kernel32.DebugActiveProcessStop(self.pid):
print "[*] Finished debugging. Exiting..."
return True
else:
print "There was an error"
return False
Everytime I run the program, it print "[*]Unable to attach to the process." and "There was an error".
Here is my test.py.
import my_debugger
debugger = my_debugger.debugger()
pid = raw_input("Enter the PID of the process to attach to: ")
debugger.attach(int(pid))
debugger.detach()
Why? Is it my computer system's problem? Can win8.1 use kernel32? How to fix it?
This code from the book works only on a 32-bit platform, so you can't attach to 64-bit process calc.exe.
Look at the answers to the question Python WaitForDebugEvent & ContinueDebugEvent (Gray Hat Python). May be they'll help you.
The content of "my_debugger_defines.py" file should be as follows ...
And It works on a 64-bit platform
from ctypes import *
BYTE = c_ubyte
WORD = c_ushort
DWORD = c_ulong
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
HANDLE = c_void_p
PVOID = c_void_p
LPVOID = c_void_p
UINT_PTR = c_ulong
DEBUG_PROCESS = 0x00000001
PROCESS_ALL_ACCESS = 0x001F0FFF
INFINITE = 0xFFFFFFFF
DBG_CONTINUE = 0x00010002
class STARTUPINFO(Structure):
_fields_ = [
("cb", DWORD),
("lpReserved", LPTSTR),
("lpDesktop", LPTSTR),
("lpTitle", LPTSTR),
("dwX", DWORD),
("dwY", DWORD),
("dwXSize", DWORD),
("dwYSize", DWORD),
("dwXCountChars", DWORD),
("dwYCountChars", DWORD),
("dwFillAttribute",DWORD),
("dwFlags", DWORD),
("wShowWindow", WORD),
("cbReserved2", WORD),
("lpReserved2", LPBYTE),
("hStdInput", HANDLE),
("hStdOutput", HANDLE),
("hStdError", HANDLE),
]
class PROCESS_INFORMATION(Structure):
_fields_ = [
("hProcess", HANDLE),
("hThread", HANDLE),
("dwProcessId", DWORD),
("dwThreadId", DWORD),
]
class EXCEPTION_RECORD(Structure):
pass
EXCEPTION_RECORD._fields_ = [
("ExceptionCode", DWORD),
("ExceptionFlags", DWORD),
("ExceptionRecord", POINTER(EXCEPTION_RECORD)),
("ExceptionAddress", PVOID),
("NumberParameters", DWORD),
("ExceptionInformation", UINT_PTR * 15),
]
class _EXCEPTION_RECORD(Structure):
_fields_ = [
("ExceptionCode", DWORD),
("ExceptionFlags", DWORD),
("ExceptionRecord", POINTER(EXCEPTION_RECORD)),
("ExceptionAddress", PVOID),
("NumberParameters", DWORD),
("ExceptionInformation", UINT_PTR * 15),
]
class EXCEPTION_DEBUG_INFO(Structure):
_fields_ = [
("ExceptionRecord", EXCEPTION_RECORD),
("dwFirstChance", DWORD),
]
class CREATE_PROCESS_DEBUG_INFO(Structure):
_fields_ = [
("hFile", HANDLE),
("hProcess", HANDLE),
("hThread", HANDLE),
("lpBaseOfImage", LPVOID),
("dwDebugInfoFileOffset",DWORD),
("nDebugInfoSize", DWORD),
("lpThreadLocalBase", LPVOID),
("lpStartAddress", HANDLE),
("lpImageName", LPVOID),
("fUnicode", WORD)
]
class CREATE_THREAD_DEBUG_INFO(Structure):
_fields_ = [
("hThread", HANDLE),
("lpThreadLocalBase", LPVOID),
("lpStartAddress", HANDLE)
]
class EXIT_THREAD_DEBUG_INFO(Structure):
_fields_ = [
("dwExitCode", DWORD)
]
class EXIT_PROCESS_DEBUG_INFO(Structure):
_fields_ = [
("dwExitCode", DWORD)
]
class LOAD_DLL_DEBUG_INFO(Structure):
_fields_ = [
("hFile", HANDLE),
("lpBaseOfDll", LPVOID),
("dwDebugInfoFileOffset", DWORD),
("nDebugInfoSize", DWORD),
("lpImageName", LPVOID),
("fUnicode", WORD)
]
class UNLOAD_DLL_DEBUG_INFO(Structure):
_fields_ = [
("lpBaseOfDll", LPVOID)
]
class OUTPUT_DEBUG_STRING_INFO(Structure):
_fields_ = [
("lpDebugStringData", LPTSTR),
("fUnicode", WORD),
("nDebugStringLength", WORD)
]
class RIP_INFO(Structure):
_fields_ = [
("dwError", DWORD),
("dwType", DWORD)
]
class DEBUG_EVENT_UNION(Union):
_fields_ = [
("Exception", EXCEPTION_DEBUG_INFO),
("CreateThread", CREATE_THREAD_DEBUG_INFO),
("CreateProcessInfo", CREATE_PROCESS_DEBUG_INFO),
("ExitThread", EXIT_THREAD_DEBUG_INFO),
("ExitProcess", EXIT_PROCESS_DEBUG_INFO),
("LoadDll", LOAD_DLL_DEBUG_INFO),
("UnloadDll", UNLOAD_DLL_DEBUG_INFO),
("DebugString", OUTPUT_DEBUG_STRING_INFO),
("RipInfo", RIP_INFO),
]
class DEBUG_EVENT(Structure):
_fields_ = [
("dwDebugEventCode", DWORD),
("dwProcessId", DWORD),
("dwThreadId", DWORD),
("u", DEBUG_EVENT_UNION),
]
several month ago,I wrote https://github.com/325862401/goagent/blob/master/local/ieproxysetting.cpp. that program can set internet proxy automatically.
Now I want to use ctypes.windll.Wininet to do the same thing.
But I donot know how to pass the argument to InternetQueryOptionW.
and I also don't find the class refer to the INTERNET_PER_CONN_OPTION_LIST structure.
is there any demo for the usage of InternetQueryOptionW or InternetSetOptionW in python.
this https://bitbucket.org/canassa/switch-proxy/src/685ac447783a7cb3ead6ce8369b66483790c26be/proxy.py?at=default maybe be helpful.
but I donot want to modify Registry.
just use the api.
Thanks a lot.
sorry for poor English.
Here is Python equivalent to your cpp code, pretty much straight forward conversation (I didn't test it that much):
#-*- coding: utf-8 -*-
#!python
from ctypes import *
from ctypes.wintypes import *
# stick to unicode version
LPWSTR = POINTER(WCHAR)
HINTERNET = LPVOID
INTERNET_PER_CONN_FLAGS = 1
INTERNET_PER_CONN_AUTOCONFIG_URL = 4
INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5
INTERNET_OPTION_REFRESH = 37
INTERNET_OPTION_SETTINGS_CHANGED = 39
INTERNET_OPTION_PER_CONNECTION_OPTION = 75
PROXY_TYPE_AUTO_PROXY_URL = 4
class INTERNET_PER_CONN_OPTION(Structure):
class Value(Union):
_fields_ = [
('dwValue', DWORD),
('pszValue', LPWSTR),
('ftValue', FILETIME),
]
_fields_ = [
('dwOption', DWORD),
('Value', Value),
]
class INTERNET_PER_CONN_OPTION_LIST(Structure):
_fields_ = [
('dwSize', DWORD),
('pszConnection', LPWSTR),
('dwOptionCount', DWORD),
('dwOptionError', DWORD),
('pOptions', POINTER(INTERNET_PER_CONN_OPTION)),
]
InternetSetOption = windll.wininet.InternetSetOptionW
InternetSetOption.argtypes = [HINTERNET, DWORD, LPVOID, DWORD]
InternetSetOption.restype = BOOL
if __name__ == '__main__':
proxy = create_unicode_buffer('http://127.0.0.1:8086/proxy.pac')
List = INTERNET_PER_CONN_OPTION_LIST()
Option = (INTERNET_PER_CONN_OPTION * 2)()
nSize = c_ulong(sizeof(INTERNET_PER_CONN_OPTION_LIST))
Option[0].dwOption = INTERNET_PER_CONN_AUTOCONFIG_URL
Option[0].Value.pszValue = proxy
Option[1].dwOption = INTERNET_PER_CONN_FLAGS
Option[1].Value.dwValue = PROXY_TYPE_AUTO_PROXY_URL
List.dwSize = sizeof(INTERNET_PER_CONN_OPTION_LIST)
List.pszConnection = None
List.dwOptionCount = 2
List.dwOptionError = 0
List.pOptions = Option
assert InternetSetOption(None, INTERNET_OPTION_PER_CONNECTION_OPTION, byref(List), nSize) == True
assert InternetSetOption(None, INTERNET_OPTION_SETTINGS_CHANGED, None, 0) == True
assert InternetSetOption(None, INTERNET_OPTION_REFRESH, None, 0) == True
You don't need MultiByteToWideChar, create_unicode_buffer and the unicode version of InternetSetOption should do the job.
I'm working on a captive portal projet on Windows. I've written this piece of code (similar to this) :
from ctypes import wintypes
import ctypes
WlanApi = ctypes.windll.wlanapi
hClientHandle = wintypes.HANDLE()
phClientHandle = ctypes.pointer(hClientHandle)
dwNegotiatedVersion = wintypes.DWORD()
pdwNegotiatedVersion = ctypes.pointer(dwNegotiatedVersion)
dwClientVersion = wintypes.DWORD()
dwClientVersion.value = 2L
rc = WlanApi.WlanOpenHandle(dwClientVersion, None, pdwNegotiatedVersion, phClientHandle)
print rc
class GUID(ctypes.Structure):
_fields_ = [("Data1", wintypes.DWORD),
("Data2", wintypes.WORD),
("Data3", wintypes.WORD),
("Data4", wintypes.BYTE * 8)]
class WLAN_INTERFACE_INFO (ctypes.Structure):
_fields_ = [('InterfaceGuid', GUID),
('strInterfaceDescription', wintypes.WCHAR * 256),
('isState', wintypes.????)]
class WLAN_INTERFACE_INFO_LIST(ctypes.Structure):
_fields_ = [('dwNumberOfItems', wintypes.DWORD),
('dwIndex', wintypes.DWORD),
('InterfaceInfo', WLAN_INTERFACE_INFO * 10)]
IfList = WLAN_INTERFACE_INFO_LIST()
pIfList = ctypes.pointer(IfList)
rc = WlanApi.WlanEnumInterfaces(hClientHandle, None, pIfList)
print rc
print "Num Entries: %s" % IfList.dwNumberOfItems
I can't find how to structure "WLAN_INTERFACE_STATE enumeration" and when I try with a WCHAR array or anything else, this script return my 6000000 wireless interfaces !!!
Can somebody help me?
It's just an integer, there is no structure 0 = Not ready, 1 = connected etc.
Hmm it starts to make sense,as most of these structs have a corresponding pointer.
According to the boys at PInvoke
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WLAN_INTERFACE_INFO
{
/// GUID->_GUID
public Guid InterfaceGuid;
/// WCHAR[256]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string strInterfaceDescription;
/// WLAN_INTERFACE_STATE->_WLAN_INTERFACE_STATE
public WLAN_INTERFACE_STATE isState;
}
Where WLAN_INTERFACE_STATE is
public enum WLAN_INTERFACE_STATE
{
wlan_interface_state_not_ready = 0,
...
// 1 to 6
...
wlan_interface_state_authenticating = 7,
}
PInvoke on WLAN...