Skip to content

Commit c4d3cd2

Browse files
authored
Merge pull request #87 from hakril/update_version_name
Add version name for 25H2 & 26H1
2 parents f920ff5 + b1ffdc8 commit c4d3cd2

2 files changed

Lines changed: 68 additions & 24 deletions

File tree

tests/test_rpc.py

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import sys
2-
import pytest
2+
import struct
33
import os.path
44
import time
55

@@ -125,37 +125,79 @@ def _get_response_effective_data(self, response):
125125
return super(DbgRpcClient, self)._get_response_effective_data(response)
126126

127127

128-
FIREWALL_RPC_IID = "2fb92682-6599-42dc-ae13-bd2ca89bd11c"
129-
130-
Proc0_RPC_FWOpenPolicyStore = 0
131-
Proc9_RPC_FWEnumFirewallRules = 9
128+
EVTX_RPC_IID = "82273FDC-E32A-18C3-3F78-827929DC23EA"
129+
130+
Proc7_ElfRpc_s_OpenELW = 7
131+
Proc10_ElfRpc_s_ReadELW = 10
132+
133+
class NdrCustomSizedString(object):
134+
@classmethod
135+
def pack(cls, data):
136+
"""Pack string ``data``. append ``\\x00`` if not present at the end of the string"""
137+
if not data:
138+
return None
139+
result = struct.pack("<3I", data[0], 0, data[1])
140+
result += data[2]
141+
return ndr.dword_pad(result)
142+
143+
@classmethod
144+
def get_alignment(self):
145+
# Not sure, but size is on 4 bytes so...
146+
return 4
147+
148+
class RPC_UNICODE_STRING(ndr.NdrStructure):
149+
MEMBERS = [
150+
ndr.NdrShort, # Length (in bytes)
151+
ndr.NdrShort, # MaximumLength (in bytes)
152+
ndr.NdrUniquePTR(NdrCustomSizedString) # Pointer to actual wide string character buffer
153+
]
154+
155+
class ElfrOpenELWPayload(ndr.NdrParameters):
156+
MEMBERS = [
157+
ndr.NdrUniquePTR(ndr.NdrWString), # UNCServerName (Pass None for local execution)
158+
RPC_UNICODE_STRING, # ModuleName (The target Log Name)
159+
RPC_UNICODE_STRING, # RegModuleName (Must be an empty string)
160+
ndr.NdrLong, # MajorVersion
161+
ndr.NdrLong # MinorVersion
162+
]
163+
164+
class ElfrReadELWPayload(ndr.NdrParameters):
165+
MEMBERS = [
166+
ndr.NdrContextHandle,
167+
ndr.NdrLong, # Flags
168+
ndr.NdrLong, # RecordOffset
169+
ndr.NdrLong, # NumberOfBytesToRead
170+
]
132171

133172
def test_rpc_response_as_view():
134173
"""Check that parsing response as view in RPC Client works. Testing after a bug in 32b RPCCLient"""
135174
# 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.
175+
# In this case we use the EVTX RPC & read method that allow us to ask for a sized return buffer
137176
# 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)
177+
client = windows.rpc.RPCClient(r"\RPC Control\eventlog")
139178
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]
179+
iid = client.bind(EVTX_RPC_IID, (0, 0))
180+
181+
# https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-even/1898e85b-10a1-43b9-a27e-92fc833cebea
182+
183+
184+
target_evtx = "Application"
185+
tsize = len(target_evtx)
186+
params = ElfrOpenELWPayload.pack([
187+
None, # UNCServerName (None resolves to a NULL pointer / Local)
188+
(tsize * 2, (tsize + 1) * 2, (tsize + 1, tsize, target_evtx.encode("utf-16-le") + b"\x00")), # ModuleName
189+
(0, 0, ""), # RegModuleName
190+
1, # MajorVersion
191+
1 # MinorVersion
192+
])
193+
194+
resp1 = client.call(iid, Proc7_ElfRpc_s_OpenELW, params=params)
195+
stream = ndr.NdrStream(resp1)
196+
handle = ndr.NdrContextHandle.unpack(stream)
150197
assert not client.last_response_was_view
151198

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")
199+
payload = ElfrReadELWPayload.pack([handle, 1 + 8, 0, 5000]) # Ask for a buffer of 5000 bytes -> response is view
200+
res = client.call(iid, Proc10_ElfRpc_s_ReadELW, payload)
159201
assert client.last_response_was_view
160202

161203
# This cannot work as is: as juste calling NtAlpcDeleteSectionView does not works.

windows/winobject/system.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ def version(self):
283283
(22621, True): u"Windows 11 Version 22H2",
284284
(22631, True): u"Windows 11 Version 23H2",
285285
(26100, True): u"Windows 11 Version 24H2",
286+
(26200, True): u"Windows 11 Version 25H2",
287+
(28000, True): u"Windows 11 Version 26H1",
286288

287289
(14393, False): u"Windows Server 2016",
288290
# 16299 : Windows Server, version 1709 ?

0 commit comments

Comments
 (0)