Skip to content

Commit 1573271

Browse files
authored
Merge pull request #79 from hakril/fix_rpc_view
Bug in `RPCClient._get_response_effective_data` for 32b process
2 parents a5b5c06 + df8a63e commit 1573271

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

tests/test_rpc.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,46 @@ def test_rpc_uac_call():
114114
assert proc.pid == pid
115115
proc.exit(0)
116116

117+
118+
class DbgRpcClient(windows.rpc.RPCClient):
119+
def __init__(self, *args, **kwargs):
120+
super(DbgRpcClient, self).__init__(*args, **kwargs)
121+
self.last_response_was_view = False
122+
123+
def _get_response_effective_data(self, response):
124+
self.last_response_was_view = response.view_is_valid
125+
return super(DbgRpcClient, self)._get_response_effective_data(response)
126+
127+
128+
FIREWALL_RPC_IID = "2fb92682-6599-42dc-ae13-bd2ca89bd11c"
129+
130+
Proc0_RPC_FWOpenPolicyStore = 0
131+
Proc9_RPC_FWEnumFirewallRules = 9
132+
133+
def test_rpc_response_as_view():
134+
"""Check that parsing response as view in RPC Client works. Testing after a bug in 32b RPCCLient"""
135+
# We test what by using a RPC endpoint that returns a lot of info : forcing a response in a view
136+
# In this case we use the Firewall RPC and we list all Firerules.
137+
# We use a custom RPCClient subclasse to track if last response was a view
138+
client = windows.rpc.find_alpc_endpoint_and_connect(FIREWALL_RPC_IID, sid=gdef.WinLocalSid)
139+
client.__class__ = DbgRpcClient
140+
iid = client.bind(FIREWALL_RPC_IID)
141+
142+
# https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fasp/230d1ae7-b42e-4d9c-b997-b1463aaa0ded
143+
# !\x02\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00
144+
# Binaryversion : 0x022f
145+
# FW_STORE_TYPE_LOCAL
146+
# FW_POLICY_ACCESS_RIGHT_READ
147+
# Flags = 0
148+
resp1 = client.call(iid, Proc0_RPC_FWOpenPolicyStore, params=b"!\x02\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00")
149+
rawpolstore = resp1[:20]
150+
assert not client.last_response_was_view
151+
152+
# Proc9_RPC_FWEnumFirewallRules
153+
# \x00\x00\x03\x00\xff\xff\xff\x7f\x07\x00
154+
# https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fasp/36cddff4-c427-4863-a58d-3d913a12b221
155+
# FW_PROFILE_TYPE_ALL : 0x7FFFFFFF
156+
# FW_RULE_STATUS_CLASS_OK + FW_RULE_STATUS_PARTIALLY_IGNORED = 0x00010000 + 0x00020000
157+
# Flags = 7 ?
158+
resp2 = client.call(iid, Proc9_RPC_FWEnumFirewallRules, params=rawpolstore + b"\x00\x00\x03\x00\xff\xff\xff\x7f\x07\x00")
159+
assert client.last_response_was_view

windows/rpc/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ def _get_response_effective_data(self, response):
220220
data = response.data[ctypes.sizeof(ALPC_RPC_RESPONSE):]
221221
else:
222222
# Response in view M extract size from PORT_MESSAGE & read data from view
223-
assert response.port_message.u1.s1.TotalLength >= 0x48 # At least 0x20 of data
223+
assert response.port_message.u1.s1.DataLength >= ctypes.sizeof(ALPC_RPC_RESPONSE) # 0x20
224224
rpcdatasize = struct.unpack("<I", response.data[0x18:0x1c])[0] # ctypes.sizeof(ALPC_RPC_RESPONSE)
225225
viewattr = response.view_attribute
226226
assert viewattr.ViewSize >= rpcdatasize

0 commit comments

Comments
 (0)