Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 

2# Copyright (c) 2017 @MrAnde7son 

3# 

4# This software is provided under under a slightly modified version 

5# of the Apache Software License. See the accompanying LICENSE file 

6# for more information. 

7# 

8# Author: Itamar (@MrAnde7son) 

9# 

10# Description: 

11# Initial [MS-EVEN6] Interface implementation 

12# 

13# Best way to learn how to use these calls is to grab the protocol standard 

14# so you understand what the call does, and then read the test case located 

15# at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC 

16# 

17# Some calls have helper functions, which makes it even easier to use. 

18# They are located at the end of this file. 

19# Helper functions start with "h"<name of the call>. 

20# There are test cases for them too. 

21# 

22from impacket import system_errors 

23from impacket.dcerpc.v5.dtypes import WSTR, DWORD, LPWSTR, ULONG, LARGE_INTEGER, WORD, BYTE 

24from impacket.dcerpc.v5.ndr import NDRCALL, NDRPOINTER, NDRUniConformantArray, NDRUniVaryingArray, NDRSTRUCT 

25from impacket.dcerpc.v5.rpcrt import DCERPCException 

26from impacket.uuid import uuidtup_to_bin 

27 

28MSRPC_UUID_EVEN6 = uuidtup_to_bin(('F6BEAFF7-1E19-4FBB-9F8F-B89E2018337C', '1.0')) 

29 

30class DCERPCSessionError(DCERPCException): 

31 def __init__(self, error_string=None, error_code=None, packet=None): 

32 DCERPCException.__init__(self, error_string, error_code, packet) 

33 

34 def __str__(self): 

35 key = self.error_code 

36 if key in system_errors.ERROR_MESSAGES: 

37 error_msg_short = system_errors.ERROR_MESSAGES[key][0] 

38 error_msg_verbose = system_errors.ERROR_MESSAGES[key][1] 

39 return 'EVEN6 SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) 

40 else: 

41 return 'EVEN6 SessionError: unknown error code: 0x%x' % self.error_code 

42 

43################################################################################ 

44# CONSTANTS 

45################################################################################ 

46 

47# Evt Path Flags 

48EvtQueryChannelName = 0x00000001 

49EvtQueryFilePath = 0x00000002 

50EvtReadOldestToNewest = 0x00000100 

51EvtReadNewestToOldest = 0x00000200 

52 

53################################################################################ 

54# STRUCTURES 

55################################################################################ 

56 

57class CONTEXT_HANDLE_LOG_HANDLE(NDRSTRUCT): 

58 align = 1 

59 structure = ( 

60 ('Data', '20s=""'), 

61 ) 

62 

63class PCONTEXT_HANDLE_LOG_HANDLE(NDRPOINTER): 

64 referent = ( 

65 ('Data', CONTEXT_HANDLE_LOG_HANDLE), 

66 ) 

67 

68class CONTEXT_HANDLE_LOG_QUERY(NDRSTRUCT): 

69 align = 1 

70 structure = ( 

71 ('Data', '20s=""'), 

72 ) 

73 

74class PCONTEXT_HANDLE_LOG_QUERY(NDRPOINTER): 

75 referent = ( 

76 ('Data', CONTEXT_HANDLE_LOG_QUERY), 

77 ) 

78 

79class LPPCONTEXT_HANDLE_LOG_QUERY(NDRPOINTER): 

80 referent = ( 

81 ('Data', PCONTEXT_HANDLE_LOG_QUERY), 

82 ) 

83 

84class CONTEXT_HANDLE_OPERATION_CONTROL(NDRSTRUCT): 

85 align = 1 

86 structure = ( 

87 ('Data', '20s=""'), 

88 ) 

89 

90class PCONTEXT_HANDLE_OPERATION_CONTROL(NDRPOINTER): 

91 referent = ( 

92 ('Data', CONTEXT_HANDLE_OPERATION_CONTROL), 

93 ) 

94 

95# 2.2.11 EvtRpcQueryChannelInfo 

96class EvtRpcQueryChannelInfo(NDRSTRUCT): 

97 structure = ( 

98 ('Name', LPWSTR), 

99 ('Status', DWORD), 

100 ) 

101 

102class EvtRpcQueryChannelInfoArray(NDRUniVaryingArray): 

103 item = EvtRpcQueryChannelInfo 

104 

105class LPEvtRpcQueryChannelInfoArray(NDRPOINTER): 

106 referent = ( 

107 ('Data', EvtRpcQueryChannelInfoArray) 

108 ) 

109 

110class RPC_INFO(NDRSTRUCT): 

111 structure = ( 

112 ('Error', DWORD), 

113 ('SubError', DWORD), 

114 ('SubErrorParam', DWORD), 

115 ) 

116 

117class PRPC_INFO(NDRPOINTER): 

118 referent = ( 

119 ('Data', RPC_INFO) 

120 ) 

121 

122class WSTR_ARRAY(NDRUniVaryingArray): 

123 item = WSTR 

124 

125class DWORD_ARRAY(NDRUniVaryingArray): 

126 item = DWORD 

127 

128class LPDWORD_ARRAY(NDRPOINTER): 

129 referent = ( 

130 ('Data', DWORD_ARRAY) 

131 ) 

132 

133class BYTE_ARRAY(NDRUniVaryingArray): 

134 item = 'c' 

135 

136class CBYTE_ARRAY(NDRUniVaryingArray): 

137 item = BYTE 

138 

139class CDWORD_ARRAY(NDRUniConformantArray): 

140 item = DWORD 

141 

142class LPBYTE_ARRAY(NDRPOINTER): 

143 referent = ( 

144 ('Data', CBYTE_ARRAY) 

145 ) 

146 

147class ULONG_ARRAY(NDRUniVaryingArray): 

148 item = ULONG 

149 

150# 2.3.1 EVENT_DESCRIPTOR 

151class EVENT_DESCRIPTOR(NDRSTRUCT): 

152 structure = ( 

153 ('Id', WORD), 

154 ('Version', BYTE), 

155 ('Channel', BYTE), 

156 ('LevelSeverity', BYTE), 

157 ('Opcode', BYTE), 

158 ('Task', WORD), 

159 ('Keyword', ULONG), 

160 ) 

161 

162class BOOKMARK(NDRSTRUCT): 

163 structure = ( 

164 ('BookmarkSize', DWORD), 

165 ('HeaderSize', '<L=0x18'), 

166 ('ChannelSize', DWORD), 

167 ('CurrentChannel', DWORD), 

168 ('ReadDirection', DWORD), 

169 ('RecordIdsOffset', DWORD), 

170 ('LogRecordNumbers', ULONG_ARRAY), 

171 ) 

172 

173 

174#2.2.17 RESULT_SET 

175class RESULT_SET(NDRSTRUCT): 

176 structure = ( 

177 ('TotalSize', DWORD), 

178 ('HeaderSize', DWORD), 

179 ('EventOffset', DWORD), 

180 ('BookmarkOffset', DWORD), 

181 ('BinXmlSize', DWORD), 

182 ('EventData', BYTE_ARRAY), 

183 #('NumberOfSubqueryIDs', '<L=0'), 

184 #('SubqueryIDs', BYTE_ARRAY), 

185 #('BookMarkData', BOOKMARK), 

186 ) 

187 

188################################################################################ 

189# RPC CALLS 

190################################################################################ 

191 

192class EvtRpcRegisterLogQuery(NDRCALL): 

193 opnum = 5 

194 structure = ( 

195 ('Path', LPWSTR), 

196 ('Query', WSTR), 

197 ('Flags', DWORD), 

198 ) 

199 

200class EvtRpcRegisterLogQueryResponse(NDRCALL): 

201 structure = ( 

202 ('Handle', CONTEXT_HANDLE_LOG_QUERY), 

203 ('OpControl', CONTEXT_HANDLE_OPERATION_CONTROL), 

204 ('QueryChannelInfoSize', DWORD), 

205 ('QueryChannelInfo', EvtRpcQueryChannelInfoArray), 

206 ('Error', RPC_INFO), 

207 ) 

208 

209class EvtRpcQueryNext(NDRCALL): 

210 opnum = 11 

211 structure = ( 

212 ('LogQuery', CONTEXT_HANDLE_LOG_QUERY), 

213 ('NumRequestedRecords', DWORD), 

214 ('TimeOutEnd', DWORD), 

215 ('Flags', DWORD), 

216 ) 

217 

218class EvtRpcQueryNextResponse(NDRCALL): 

219 structure = ( 

220 ('NumActualRecords', DWORD), 

221 ('EventDataIndices', DWORD_ARRAY), 

222 ('EventDataSizes', DWORD_ARRAY), 

223 ('ResultBufferSize', DWORD), 

224 ('ResultBuffer', BYTE_ARRAY), 

225 ('ErrorCode', ULONG), 

226 ) 

227 

228class EvtRpcQuerySeek(NDRCALL): 

229 opnum = 12 

230 structure = ( 

231 ('LogQuery', CONTEXT_HANDLE_LOG_QUERY), 

232 ('Pos', LARGE_INTEGER), 

233 ('BookmarkXML', LPWSTR), 

234 ('Flags', DWORD), 

235 ) 

236 

237class EvtRpcQuerySeekResponse(NDRCALL): 

238 structure = ( 

239 ('Error', RPC_INFO), 

240 ) 

241 

242class EvtRpcClose(NDRCALL): 

243 opnum = 13 

244 structure = ( 

245 ("Handle", CONTEXT_HANDLE_LOG_HANDLE), 

246 ) 

247 

248class EvtRpcCloseResponse(NDRCALL): 

249 structure = ( 

250 ("Handle", PCONTEXT_HANDLE_LOG_HANDLE), 

251 ('ErrorCode', ULONG), 

252 ) 

253 

254class EvtRpcOpenLogHandle(NDRCALL): 

255 opnum = 17 

256 structure = ( 

257 ('Channel', WSTR), 

258 ('Flags', DWORD), 

259 ) 

260 

261class EvtRpcOpenLogHandleResponse(NDRCALL): 

262 structure = ( 

263 ('Handle', PCONTEXT_HANDLE_LOG_HANDLE), 

264 ('Error', RPC_INFO), 

265 ) 

266 

267class EvtRpcGetChannelList(NDRCALL): 

268 opnum = 19 

269 structure = ( 

270 ('Flags', DWORD), 

271 ) 

272 

273class EvtRpcGetChannelListResponse(NDRCALL): 

274 structure = ( 

275 ('NumChannelPaths', DWORD), 

276 ('ChannelPaths', WSTR_ARRAY), 

277 ('ErrorCode', ULONG), 

278 ) 

279 

280################################################################################ 

281# OPNUMs and their corresponding structures 

282################################################################################ 

283 

284OPNUMS = { 

285 5 : (EvtRpcRegisterLogQuery, EvtRpcRegisterLogQueryResponse), 

286 11 : (EvtRpcQueryNext, EvtRpcQueryNextResponse), 

287 12 : (EvtRpcQuerySeek, EvtRpcQuerySeekResponse), 

288 13 : (EvtRpcClose, EvtRpcCloseResponse), 

289 17 : (EvtRpcOpenLogHandle, EvtRpcOpenLogHandle), 

290 19 : (EvtRpcGetChannelList, EvtRpcGetChannelListResponse), 

291} 

292 

293################################################################################ 

294# HELPER FUNCTIONS 

295################################################################################ 

296 

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

298 request = EvtRpcRegisterLogQuery() 

299 

300 request['Path'] = path 

301 request['Query'] = query 

302 request['Flags'] = flags 

303 resp = dce.request(request) 

304 return resp 

305 

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

307 request = EvtRpcQueryNext() 

308 

309 request['LogQuery'] = handle 

310 request['NumRequestedRecords'] = numRequestedRecords 

311 request['TimeOutEnd'] = timeOutEnd 

312 request['Flags'] = 0 

313 status = system_errors.ERROR_MORE_DATA 

314 resp = dce.request(request) 

315 while status == system_errors.ERROR_MORE_DATA: 

316 try: 

317 resp = dce.request(request) 

318 except DCERPCException as e: 

319 if str(e).find('ERROR_NO_MORE_ITEMS') < 0: 

320 raise 

321 elif str(e).find('ERROR_TIMEOUT') < 0: 

322 raise 

323 resp = e.get_packet() 

324 return resp 

325 

326def hEvtRpcClose(dce, handle): 

327 request = EvtRpcClose() 

328 request['Handle'] = handle 

329 resp = dce.request(request) 

330 return resp 

331 

332def hEvtRpcOpenLogHandle(dce, channel, flags): 

333 request = EvtRpcOpenLogHandle() 

334 

335 request['Channel'] = channel 

336 request['Flags'] = flags 

337 return dce.request(request) 

338 

339def hEvtRpcGetChannelList(dce): 

340 request = EvtRpcGetChannelList() 

341 

342 request['Flags'] = 0 

343 resp = dce.request(request) 

344 return resp