Skip to content

Fix TS_ALL_PROCESSES_INFO parsing for RpcWinStationGetAllProcesses#2155

Open
alexisbalbachan wants to merge 1 commit intofortra:masterfrom
alexisbalbachan:tstool_parser_fix
Open

Fix TS_ALL_PROCESSES_INFO parsing for RpcWinStationGetAllProcesses#2155
alexisbalbachan wants to merge 1 commit intofortra:masterfrom
alexisbalbachan:tstool_parser_fix

Conversation

@alexisbalbachan
Copy link
Copy Markdown
Collaborator

This PR fixes #1816 by replacing the heuristic parsing of RpcWinStationGetAllProcesses with a proper NDR structure implementation based on the protocol spec. Since the response is now modeled according to the actual
TS_ALL_PROCESSES_INFO layout, the example code was also updated to use the corrected process and SID fields.

@anadrianmanrique anadrianmanrique self-assigned this Mar 19, 2026
@anadrianmanrique anadrianmanrique added the bug Unexpected problem or unintended behavior label Mar 19, 2026
return self.fields['pTsProcessInfo'].fields['Data']

def getSid(self):
rawSid = self.fields['pSid']['Data'] if self.fields['pSid'].fields['ReferentID'] else b''
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rawSid it's returned for those cases where it's populated by the target, as a UCHAR_ARRAY, which is not expected by code client, as they expect to be a buffer. change line 1380 for rawSid = b''.join( self.fields['pSid']['Data'] ) if self.fields['pSid'].fields['ReferentID'] else b''

rawSid = self.fields['pSid']['Data'] if self.fields['pSid'].fields['ReferentID'] else b''
if not rawSid:
return ''
return SID().known_sid(format_sid(rawSid))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not use ldap3 helpers, as we're moving away from ldap3 depdency

@anadrianmanrique
Copy link
Copy Markdown
Collaborator

anadrianmanrique commented Mar 27, 2026

regarding getSid issue, on my tests, pSid has never been populated by the target. not clear to me when this condition changes. This code on the other hand is able to trigger the bug:

from impacket.dcerpc.v5 import tsts

resp = tsts.RpcWinStationGetAllProcessesResponse()
resp['pResult'] = 0
resp['pNumberOfProcesses'] = 1

arr = resp.fields['ppTsAllProcessesInfo'].fields['Data']
entry = tsts.TS_ALL_PROCESSES_INFO()

entry.fields['pTsProcessInfo'].fields['Data']['UniqueProcessId'] = 123
entry.fields['pTsProcessInfo'].fields['Data']['SessionId'] = 1

### Non-null SID pointer with valid SID bytes for SYSTEM (S-1-5-18) ###
entry['SizeOfSid'] = 12
entry.fields['pSid'].fields['Data']['Data'] = bytes([1,1,0,0,0,0,0,5,18,0,0,0])

arr['Data'] = [entry]
resp['ErrorCode'] = 1

parsed = tsts.RpcWinStationGetAllProcessesResponse(resp.getData())
print(parsed['ppTsAllProcessesInfo'][0].getSid())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Unexpected problem or unintended behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TStool.py with low priv user on DC crashes

2 participants