Skip to content

Commit a183e46

Browse files
committed
fix dbgprint to use hardcoded dict + improve rpc client forge_call + new ndr varying string
1 parent bd5976d commit a183e46

9 files changed

Lines changed: 62 additions & 9 deletions

File tree

TODO

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
TODO:
2-
- Documentation
3-
- thread.set_context in a sample
42

53
- Better WMI interface
6-
- Bug in VARIANT_TYPE == BOOL (see Win32_OperatingSystem->Debug)
4+
75

86
- DBG
97
- Verif multiple bp at same place..
108
- Verif multiple pending at same place
119
- Test !! (bp, BP_HX, bp on only on process, bp_hx on only one thread..)
1210
- test breakpoint with specific target
1311

14-
1512
- Rethink/adapt Debugger._explicit_single_step
1613
- Does not handle case where EEFlags.TF was by the debugge before trigering the exception
1714
- Should set the flag explicitly in single_step ? and not just use EEFlags.TF ?
@@ -24,11 +21,11 @@ TODO:
2421
- j'attends a avoir un thread/process mais je fait des check sur TID/PID..
2522
- Ecrire un test et fix..
2623

24+
2725
- windows.alpc | windows.rpc
2826
- Clean + doc + samples
2927

3028

31-
3229
- remotectypes
3330
- pretty sur I can get rid of PointerToStruct64/PointerToStruct32
3431

ctypes_generation/definitions/windef.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,10 @@
924924
#define ALPC_MSGFLG_WAIT_ALERTABLE 0x200000
925925
#define ALPC_MSGFLG_WOW64_CALL 0x80000000
926926

927+
#define ALPC_PORFLG_ALLOW_LPC_REQUESTS 0x20000
928+
#define ALPC_PORFLG_WAITABLE_PORT 0x40000
929+
#define ALPC_PORFLG_SYSTEM_PROCESS 0x100000
930+
927931
#define ALPC_CANCELFLG_TRY_CANCEL 0x1
928932
#define ALPC_CANCELFLG_NO_CONTEXT_CHECK 0x8
929933
#define ALPC_CANCELFLGP_FLUSH 0x10000

docs/source/windef_generated.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,9 @@ Windef
796796
.. autodata:: ALPC_MSGFLG_WAIT_USER_MODE
797797
.. autodata:: ALPC_MSGFLG_WAIT_ALERTABLE
798798
.. autodata:: ALPC_MSGFLG_WOW64_CALL
799+
.. autodata:: ALPC_PORFLG_ALLOW_LPC_REQUESTS
800+
.. autodata:: ALPC_PORFLG_WAITABLE_PORT
801+
.. autodata:: ALPC_PORFLG_SYSTEM_PROCESS
799802
.. autodata:: ALPC_CANCELFLG_TRY_CANCEL
800803
.. autodata:: ALPC_CANCELFLG_NO_CONTEXT_CHECK
801804
.. autodata:: ALPC_CANCELFLGP_FLUSH

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@
2121
'windows.winobject',
2222
'windows.debug',
2323
'windows.crypto',
24+
'windows.rpc',
2425
'windows.test'],
2526
)

tests/test_rpc.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import sys
12
import pytest
23
import os.path
34

@@ -58,7 +59,7 @@ def test_rpc_uac_call():
5859
client = windows.rpc.find_alpc_endpoint_and_connect(UAC_UIID)
5960
iid = client.bind(UAC_UIID)
6061

61-
python_path = 'C:\\Python27\\python.exe'
62+
python_path = sys.executable
6263
python_name = os.path.basename(python_path)
6364

6465
# Marshalling parameters.
@@ -98,5 +99,6 @@ def test_rpc_uac_call():
9899
windows.winproxy.CloseHandle(th) # NoLeak
99100
proc = windows.WinProcess(handle=ph)
100101
assert proc.name == python_name
102+
assert proc.pid == pid
101103
proc.exit(0)
102104

windows/dbgprint.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import inspect
55

66
options = {'active': False, 'cats': None}
7+
# options = {'active': True, 'cats': ["HANDLE"]}
78

89

910
def get_stack_func_name(lvl):
@@ -40,6 +41,10 @@ def parse_option(s):
4041
dbgprint = do_dbgprint
4142
option_str = [opt for opt in sys.argv if opt.startswith("--DBGPRINT")][0]
4243
parse_option(option_str[len('--DBGPRINT'):])
44+
elif options["active"]:
45+
formt = 'DBG|%(name)s|%(message)s'
46+
logging.basicConfig(format=formt, level=logging.DEBUG)
47+
dbgprint = do_dbgprint
4348
else:
4449
dbgprint = do_nothing
4550
except Exception as e:

windows/generated_def/windef.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,9 @@ def make_flag(name, value):
847847
ALPC_MSGFLG_WAIT_USER_MODE = make_flag("ALPC_MSGFLG_WAIT_USER_MODE", 0x100000)
848848
ALPC_MSGFLG_WAIT_ALERTABLE = make_flag("ALPC_MSGFLG_WAIT_ALERTABLE", 0x200000)
849849
ALPC_MSGFLG_WOW64_CALL = make_flag("ALPC_MSGFLG_WOW64_CALL", 0x80000000)
850+
ALPC_PORFLG_ALLOW_LPC_REQUESTS = make_flag("ALPC_PORFLG_ALLOW_LPC_REQUESTS", 0x20000)
851+
ALPC_PORFLG_WAITABLE_PORT = make_flag("ALPC_PORFLG_WAITABLE_PORT", 0x40000)
852+
ALPC_PORFLG_SYSTEM_PROCESS = make_flag("ALPC_PORFLG_SYSTEM_PROCESS", 0x100000)
850853
ALPC_CANCELFLG_TRY_CANCEL = make_flag("ALPC_CANCELFLG_TRY_CANCEL", 0x1)
851854
ALPC_CANCELFLG_NO_CONTEXT_CHECK = make_flag("ALPC_CANCELFLG_NO_CONTEXT_CHECK", 0x8)
852855
ALPC_CANCELFLGP_FLUSH = make_flag("ALPC_CANCELFLGP_FLUSH", 0x10000)

windows/rpc/client.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,26 @@ class ALPC_RPC_BIND(ctypes.Structure):
4444
("UNK9", gdef.DWORD),
4545
]
4646

47+
class ALPC_RPC_CALL(ctypes.Structure):
48+
_pack_ = 1
49+
_fields_ = [
50+
("request_type", gdef.DWORD),
51+
("UNK1", gdef.DWORD),
52+
("flags",gdef.DWORD),
53+
("request_id", gdef.DWORD),
54+
("if_nb", gdef.DWORD),
55+
("method_offset", gdef.DWORD),
56+
("UNK2", gdef.DWORD),
57+
("UNK3", gdef.DWORD),
58+
("UNK4", gdef.DWORD),
59+
("UNK5", gdef.DWORD),
60+
("UNK6", gdef.DWORD),
61+
("UNK7", gdef.DWORD),
62+
("UNK8", gdef.DWORD),
63+
("UNK9", gdef.DWORD),
64+
("UNK10", gdef.DWORD),
65+
("UNK11", gdef.DWORD),
66+
]
4767

4868
class RPCClient(object):
4969
"""A client for RPC-over-ALPC able to bind to interface and perform calls using NDR32 marshalling"""
@@ -99,18 +119,26 @@ def _send_request(self, request):
99119
def _forge_call_request(self, interface_nb, method_offset, params):
100120
# TODO: differents REQUEST_IDENTIFIER for each req ?
101121
# TODO: what is this '0' ? (1 is also accepted) (flags ?)
102-
request = struct.pack("<16I", gdef.RPC_REQUEST_TYPE_CALL, NOT_USED, 1, self.REQUEST_IDENTIFIER, interface_nb, method_offset, *[NOT_USED] * 10)
103-
request += params
104-
return request
122+
# request = struct.pack("<16I", gdef.RPC_REQUEST_TYPE_CALL, NOT_USED, 1, self.REQUEST_IDENTIFIER, interface_nb, method_offset, *[NOT_USED] * 10)
123+
req = ALPC_RPC_CALL()
124+
req.request_type = gdef.RPC_REQUEST_TYPE_CALL
125+
req.flags = 0
126+
req.request_id = self.REQUEST_IDENTIFIER
127+
req.if_nb = interface_nb
128+
req.method_offset = method_offset
129+
130+
return buffer(req)[:] + params
105131

106132
def _forge_bind_request(self, uuid, syntaxversion, requested_if_nb):
107133
version_major, version_minor = syntaxversion
108134
req = ALPC_RPC_BIND()
109135
req.request_type = gdef.RPC_REQUEST_TYPE_BIND
110136
req.target = gdef.RPC_IF_ID(uuid, *syntaxversion)
111137
req.flags = gdef.BIND_IF_SYNTAX_NDR32
138+
# req.flags = gdef.BIND_IF_SYNTAX_NDR64
112139
req.if_nb_ndr32 = requested_if_nb
113140
req.if_nb_ndr64 = 0
141+
req.if_nb_ndr64 = requested_if_nb
114142
req.if_nb_unkn = 0
115143
req.register_multiple_syntax = False
116144
req.some_context_id = 0xB00B00B

windows/rpc/ndr.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,16 @@ def unpack(cls, stream):
9797
subcount = NdrLong.unpack(stream)
9898
return stream.read(8 + (subcount * 4))
9999

100+
class NdrVaryingCString(object):
101+
@classmethod
102+
def pack(cls, data):
103+
if data is None:
104+
return None
105+
l = len(data)
106+
result = struct.pack("<2I", 0, l)
107+
result += data
108+
return dword_pad(result)
109+
100110
class NdrWString(object):
101111
@classmethod
102112
def pack(cls, data):

0 commit comments

Comments
 (0)