Skip to content

Commit

Permalink
add more requests to even6 protocol (#1798)
Browse files Browse the repository at this point in the history
* add EvtRpcRegisterControllableOperation and EvtRpcClearLog to even6 protocol

* add EvtRpcExportLog request to even6

* add tests for even6 EvtRpcClearLog and EvtRpcExportLog requests

* minor changes in even6
  • Loading branch information
NtAlexio2 authored Jan 23, 2025
1 parent 664e025 commit ea242af
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 23 deletions.
127 changes: 104 additions & 23 deletions impacket/dcerpc/v5/even6.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
# Itamar (@MrAnde7son)
#
from impacket import system_errors
from impacket.dcerpc.v5.dtypes import WSTR, DWORD, LPWSTR, ULONG, LARGE_INTEGER, WORD, BYTE
from impacket.dcerpc.v5.ndr import NDRCALL, NDRPOINTER, NDRUniConformantArray, NDRUniVaryingArray, NDRSTRUCT
from impacket.dcerpc.v5.dtypes import WSTR, DWORD, LPWSTR, ULONG, LARGE_INTEGER, WORD, BYTE, UUID
from impacket.dcerpc.v5.ndr import NDRCALL, NDRPOINTER, NDRUniConformantArray, NDRUniVaryingArray, NDRSTRUCT, NULL
from impacket.dcerpc.v5.rpcrt import DCERPCException
from impacket.uuid import uuidtup_to_bin

Expand All @@ -46,36 +46,57 @@ def __str__(self):
else:
return 'EVEN6 SessionError: unknown error code: 0x%x' % self.error_code

def checkNullString(string):
if string == NULL:
return string

if string[-1:] != '\x00':
return string + '\x00'
else:
return string

################################################################################
# CONSTANTS
################################################################################

# Evt Path Flags
EvtQueryChannelName = 0x00000001
EvtQueryFilePath = 0x00000002
EvtQueryChannelName = 0x00000001
EvtQueryFilePath = 0x00000002

# EvtRpcExportLog
EvtQueryTolerateQueryErrors = 0x00001000

# EvtRpcRegisterLogQuery
EvtReadOldestToNewest = 0x00000100
EvtReadNewestToOldest = 0x00000200


################################################################################
# STRUCTURES
################################################################################

class CONTEXT_HANDLE_LOG_HANDLE(NDRSTRUCT):
align = 1
class handle_t(NDRSTRUCT):
structure = (
('Data', '20s=""'),
('context_handle_attributes',ULONG),
('context_handle_uuid',UUID),
)

def __init__(self, data=None, isNDR64=False):
NDRSTRUCT.__init__(self, data, isNDR64)
self['context_handle_uuid'] = b'\x00'*16

def isNull(self):
return self['context_handle_uuid'] == b'\x00'*16


CONTEXT_HANDLE_LOG_HANDLE = handle_t

class PCONTEXT_HANDLE_LOG_HANDLE(NDRPOINTER):
referent = (
('Data', CONTEXT_HANDLE_LOG_HANDLE),
)

class CONTEXT_HANDLE_LOG_QUERY(NDRSTRUCT):
align = 1
structure = (
('Data', '20s=""'),
)
CONTEXT_HANDLE_LOG_QUERY = handle_t

class PCONTEXT_HANDLE_LOG_QUERY(NDRPOINTER):
referent = (
Expand All @@ -87,11 +108,7 @@ class LPPCONTEXT_HANDLE_LOG_QUERY(NDRPOINTER):
('Data', PCONTEXT_HANDLE_LOG_QUERY),
)

class CONTEXT_HANDLE_OPERATION_CONTROL(NDRSTRUCT):
align = 1
structure = (
('Data', '20s=""'),
)
CONTEXT_HANDLE_OPERATION_CONTROL = handle_t

class PCONTEXT_HANDLE_OPERATION_CONTROL(NDRPOINTER):
referent = (
Expand Down Expand Up @@ -195,6 +212,16 @@ class RESULT_SET(NDRSTRUCT):
# RPC CALLS
################################################################################

class EvtRpcRegisterControllableOperation(NDRCALL):
opnum = 4
structure = ()

class EvtRpcRegisterControllableOperationResponse(NDRCALL):
structure = (
('Handle', CONTEXT_HANDLE_OPERATION_CONTROL),
('Error', DWORD),
)

class EvtRpcRegisterLogQuery(NDRCALL):
opnum = 5
structure = (
Expand All @@ -210,7 +237,36 @@ class EvtRpcRegisterLogQueryResponse(NDRCALL):
('QueryChannelInfoSize', DWORD),
('QueryChannelInfo', EvtRpcQueryChannelInfoArray),
('Error', RPC_INFO),
)
)

class EvtRpcClearLog(NDRCALL):
opnum = 6
structure = (
('Handle', CONTEXT_HANDLE_OPERATION_CONTROL),
('ChannelPath', WSTR),
('BackupPath', WSTR),
('Flags', DWORD),
)

class EvtRpcClearLogResponse(NDRCALL):
structure = (
('Error', RPC_INFO),
)

class EvtRpcExportLog(NDRCALL):
opnum = 7
structure = (
('Handle', CONTEXT_HANDLE_OPERATION_CONTROL),
('ChannelPath', WSTR),
('Query', WSTR),
('BackupPath', WSTR),
('Flags', DWORD),
)

class EvtRpcExportLogResponse(NDRCALL):
structure = (
('Error', RPC_INFO),
)

class EvtRpcQueryNext(NDRCALL):
opnum = 11
Expand Down Expand Up @@ -288,7 +344,10 @@ class EvtRpcGetChannelListResponse(NDRCALL):
################################################################################

OPNUMS = {
4 : (EvtRpcRegisterControllableOperation, EvtRpcRegisterControllableOperationResponse),
5 : (EvtRpcRegisterLogQuery, EvtRpcRegisterLogQueryResponse),
6 : (EvtRpcClearLog, EvtRpcClearLogResponse),
7 : (EvtRpcExportLog, EvtRpcExportLogResponse),
11 : (EvtRpcQueryNext, EvtRpcQueryNextResponse),
12 : (EvtRpcQuerySeek, EvtRpcQuerySeekResponse),
13 : (EvtRpcClose, EvtRpcCloseResponse),
Expand All @@ -300,15 +359,38 @@ class EvtRpcGetChannelListResponse(NDRCALL):
# HELPER FUNCTIONS
################################################################################

def hEvtRpcRegisterControllableOperation(dce):
request = EvtRpcRegisterControllableOperation()
resp = dce.request(request)
return resp

def hEvtRpcRegisterLogQuery(dce, path, flags, query='*\x00'):
request = EvtRpcRegisterLogQuery()

request['Path'] = path
request['Query'] = query
request['Path'] = checkNullString(path)
request['Query'] = checkNullString(query)
request['Flags'] = flags
resp = dce.request(request)
return resp

def hEvtRpcClearLog(dce, handle, path, backupPath=NULL):
request = EvtRpcClearLog()
request['Handle'] = handle
request['ChannelPath'] = checkNullString(path)
request['BackupPath'] = checkNullString(backupPath)
request['Flags'] = 0
resp = dce.request(request)
return resp

def hEvtRpcExportLog(dce, handle, channelPath, query, backupPath):
request = EvtRpcExportLog()
request['Handle'] = handle
request['ChannelPath'] = checkNullString(channelPath)
request['Query'] = checkNullString(query)
request['BackupPath'] = checkNullString(backupPath)
request['Flags'] = 0
resp = dce.request(request)
return resp

def hEvtRpcQueryNext(dce, handle, numRequestedRecords, timeOutEnd=1000):
request = EvtRpcQueryNext()

Expand Down Expand Up @@ -337,8 +419,7 @@ def hEvtRpcClose(dce, handle):

def hEvtRpcOpenLogHandle(dce, channel, flags):
request = EvtRpcOpenLogHandle()

request['Channel'] = channel
request['Channel'] = checkNullString(channel)
request['Flags'] = flags
return dce.request(request)

Expand Down
28 changes: 28 additions & 0 deletions tests/dcerpc/test_even6.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,34 @@ class EVEN6Tests(DCERPCTests):
authn = True
authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY

def test_hEvtRpcClearLog(self):
dce, rpctransport = self.connect()

resp = even6.hEvtRpcRegisterControllableOperation(dce)
resp.dump()

control_handle = resp['Handle']

resp = even6.hEvtRpcClearLog(dce, control_handle, 'Security\x00')
resp.dump()

resp = even6.hEvtRpcClose(dce, control_handle)
resp.dump()

def test_hEvtRpcExportLog(self):
dce, rpctransport = self.connect()

resp = even6.hEvtRpcRegisterControllableOperation(dce)
resp.dump()

control_handle = resp['Handle']

resp = even6.hEvtRpcExportLog(dce, control_handle, 'Security\x00', '*\x00', 'C:\\Security_Log_Exported.evtx\x00')
resp.dump()

resp = even6.hEvtRpcClose(dce, control_handle)
resp.dump()

def test_EvtRpcRegisterLogQuery_EvtRpcQueryNext(self):
dce, rpctransport = self.connect()

Expand Down

0 comments on commit ea242af

Please sign in to comment.