Windows WlanApi and Python Ctypes - python

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...

Related

AttributeError: UnionC object has no attribute

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.

Convert memory address from POINTER(BYTE) type to hex

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.

Error using GetExtendedTcpTable in python

I've got some troubles with using "GetExtendedTcpTable". When I tried to run my script, i've got message like this:
AssertionError: [Error 0] The operation completed successfully
Rarely script working normally, I dont understand this message, Operation completed, what`s wrong?
This is code, i tried to execute:
from ctypes import *
from ctypes.wintypes import *
from socket import inet_aton, inet_ntoa, htons
AF_INET = 2
TCP_TABLE_BASIC_LISTENER = 0
TCP_TABLE_BASIC_CONNECTIONS = 1
TCP_TABLE_BASIC_ALL = 2
TCP_TABLE_OWNER_PID_LISTENER = 3
TCP_TABLE_OWNER_PID_CONNECTIONS = 4
TCP_TABLE_OWNER_PID_ALL = 5
TCP_TABLE_OWNER_MODULE_LISTENER = 6
TCP_TABLE_OWNER_MODULE_CONNECTIONS = 7
TCP_TABLE_OWNER_MODULE_ALL = 8
# for storing socket info python style.
class socket_info:
State = None
LocalAddr = None
LocalPort = None
RemoteAddr = None
RemotePort = None
def __init__ (self, **kwargs):
for key, word in kwargs.items():
setattr(self, key, word)
def formatip (ip):
ip = inet_aton (str(ip))
return inet_ntoa (ip[::-1])
states = {
1 : "TCP_STATE_CLOSED",
2 : "TCP_STATE_LISTEN",
3 : "TCP_STATE_SYN_SENT",
4 : "TCP_STATE_SYN_RCVD",
5 : "TCP_STATE_ESTAB",
6 : "TCP_STATE_FIN_WAIT",
7 : "TCP_STATE_FIN_WAIT2",
8 : "TCP_STATE_CLOSE_WAIT",
9 : "TCP_STATE_CLOSING",
10 : "TCP_STATE_LAST_ACK",
11 : "TCP_STATE_TIME_WAIT",
12 : "TCP_STATE_DELETE_TCB",
"TCP_STATE_CLOSED" : 1,
"TCP_STATE_LISTEN" : 2,
"TCP_STATE_SYN_SENT" : 3,
"TCP_STATE_SYN_RCVD" : 4,
"TCP_STATE_ESTAB" : 5,
"TCP_STATE_FIN_WAIT" : 6,
"TCP_STATE_FIN_WAIT2" : 7,
"TCP_STATE_CLOSE_WAIT" : 8,
"TCP_STATE_CLOSING" : 9,
"TCP_STATE_LAST_ACK" :10,
"TCP_STATE_TIME_WAIT" : 11,
"TCP_STATE_DELETE_TCB" : 12 }
class MIB_TCPROW_OWNER_PID(Structure):
_fields_ = [
("dwState", DWORD),
("dwLocalAddr", DWORD),
("dwLocalPort", DWORD),
("dwRemoteAddr", DWORD),
("dwRemotePort", DWORD),
("dwOwningPid", DWORD)
]
class MIB_TCPTABLE_OWNER_PID(Structure):
_fields_ = [
("dwNumEntries", DWORD),
("MIB_TCPROW_OWNER_PID", MIB_TCPROW_OWNER_PID * 100)
]
def GetExtendedTcpTable (vip=AF_INET):
table = MIB_TCPTABLE_OWNER_PID ()
so = sizeof (table)
size = DWORD (so)
order = c_int(1)
failure= windll.iphlpapi.GetExtendedTcpTable (
byref (table),
addressof (size),
order,
vip,
TCP_TABLE_OWNER_PID_ALL,
0 )
assert not failure, WinError (GetLastError ())
pytables = []
tables = table.MIB_TCPROW_OWNER_PID
for index in range(table.dwNumEntries):
table = tables [index]
pytables.append (
socket_info (
State=states.get (table.dwState, "UNKNOWN_STATE_%s" %(str(table.dwState))),
LocalAddr=formatip (table.dwLocalAddr),
LocalPort=htons(table.dwLocalPort),
RemoteAddr=formatip (table.dwRemoteAddr),
RemotePort=htons(table.dwRemotePort),
OwningPid = int (table.dwOwningPid)
)
)
return pytables
def GetTcpTableForPid (pid):
tables = GetExtendedTcpTable ()
for table in tables:
if table.OwningPid == pid: return table
raise "Cannot find tcp table for pid %s" %pid
dict_process = {}
pid_set =set()
pid_list = []
tcp_info_list = []
tcp_info = GetExtendedTcpTable()
for item in tcp_info:
LocalAddr = item.LocalAddr
LocalPort = item.LocalPort
RemoteAddr = item.RemoteAddr
RemotePort = item.RemotePort
OwningPid = item.OwningPid
print('local Addr: '+ LocalAddr,'local port: '+ str(LocalPort),'remote Addr: ' + RemoteAddr, 'Remote Port: ' + str(RemotePort), OwningPid)
The script is run from time to time. It can run for 5 minutes and then don't work about an hour with this stupid mistake. How to get around it?
I really dont know, what's with it. Please, help me, what i do wrong?
I use python 3.2 on Win7 SP1 x64
Thank you a lot!
You shouldn't use addressof(size). That returns a Python integer which will be cast as a 32-bit C int. Use byref(size) to create a pointer, which will be a 64-bit value if you're using 64-bit Python.
GetExtendedTcpTable doesn't call SetLastError. It returns a DWORD with one of the following codes:
NO_ERROR = 0
ERROR_INVALID_PARAMETER = 87
ERROR_INSUFFICIENT_BUFFER = 122
The pdwSize argument has the required size if the buffer was too small. One option here is to start with a length 0 array; then resize the struct; and finally cast the array to the correct size:
class MIB_TCPTABLE_OWNER_PID(Structure):
_fields_ = [
("dwNumEntries", DWORD),
("MIB_TCPROW_OWNER_PID", MIB_TCPROW_OWNER_PID * 0),
]
_GetExtendedTcpTable = windll.iphlpapi.GetExtendedTcpTable
def GetExtendedTcpTable(vip=AF_INET):
table = MIB_TCPTABLE_OWNER_PID()
size = DWORD()
order = 1
failure = _GetExtendedTcpTable(
byref(table),
byref(size),
order,
vip,
TCP_TABLE_OWNER_PID_ALL,
0)
if failure == ERROR_INSUFFICIENT_BUFFER:
resize(table, size.value)
memset(byref(table), 0, sizeof(table))
failure = _GetExtendedTcpTable(
byref(table),
byref(size),
order,
vip,
TCP_TABLE_OWNER_PID_ALL,
0)
if failure:
raise WinError(failure)
ptr_type = POINTER(MIB_TCPROW_OWNER_PID * table.dwNumEntries)
tables = cast(table.MIB_TCPROW_OWNER_PID, ptr_type)[0]
pytables = []
for table in tables:
# rest unchanged
Regarding the Win32 LastError value, in general you shouldn't rely on GetLastError in Python. You don't know if you're seeing an old error code from a previous call or if an intervening call modified the LastError value. If you're checking a single API call that uses LastError, then it should be OK to check GetLastError immediately afterward if the call failed. But more generally you may need to load the DLL with use_last_error=True:
iphlpapi = WinDLL('iphlpapi', use_last_error=True)
Function pointers created from this WinDLL instance will save LastError to thread local storage immediately after the call returns. Calling get_last_error returns the saved error code. Beforehand you can call set_last_error(0) to have 0 swapped in to LastError before the function is called.

How to use ctypes.windll.Wininet.InternetQueryOptionW in python

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.

Passing a structure pointer to a function in ctypes

I'm trying to redo the Misaka module in ctypes, but when I try to use bufputs I get an error (see end of 2nd code sample). When I pass the pointer to the function I use pointer(b). That doesn't work and byref(b) doesn't work either.
This is the function signature:
/* bufputs • appends a NUL-terminated string to a buffer */
void
bufputs(struct buf *, const char*);
This is my code:
>>> from ctypes import *
>>> sundown = cdll.LoadLibrary('./libsundown.so.1')
>>> sundown
<CDLL './libsundown.so.1', handle 1e2f190 at 1bea0d0>
>>> # OUT: <CDLL './libsundown.so.1', handle 2840d80 at 2797290>
>>> class buf(Structure):
... _fields_ = [
... ('data', c_char_p),
... ('size', c_size_t),
... ('asize', c_size_t),
... ('unit', c_size_t),
... ('ref', c_int)]
...
>>> sundown.bufnew.argtypes = [c_size_t]
>>> sundown.bufnew.restype = buf
>>> b = sundown.bufnew(c_size_t(1024))
>>> sundown.bufputs.argtypes = [POINTER(buf), c_char_p]
>>> s = c_char_p('this is a test')
>>> sundown.bufputs(pointer(b), s)
python2: malloc.c:3574: mremap_chunk: Assertion `((size + offset) & (mp_.pagesize-1)) == 0' failed.
Aborted
I can't figure out what I did wrong.
The OP's solution, originally posted in the question
class buf(Structure):
_fields_ = [
('data', c_char_p),
('size', c_size_t),
('asize', c_size_t),
('unit', c_size_t),
('ref', c_int)
]
buf_p = POINTER(buf)
sundown.bufnew.argtypes = [c_size_t]
sundown.bufnew.restype = buf_p
sundown.bufgrow.argtypes = [buf_p, c_size_t]
sundown.bufputs.argtypes = [buf_p, c_char_p]
ib = buf()
# ctypes does this internally:
# memset(byref(ib), 0x0, sizeof(buf))
text = 'this is some text'
ib.data = text
ib.size = len(text)
ob = sundown.bufnew(128)
sundown.bufgrow(ob, int(math.ceil(ib.size * 1.4)))
sundown.bufputs(ob, 'test')

Categories

Resources