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# Impacket - Collection of Python classes for working with network protocols. 

2# 

3# SECUREAUTH LABS. Copyright (C) 2018 SecureAuth Corporation. All rights reserved. 

4# Copyright (c) 2017 @MrAnde7son 

5# 

6# This software is provided under a slightly modified version 

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

8# for more information. 

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# 

22# Author: 

23# Itamar (@MrAnde7son) 

24# 

25from impacket import system_errors 

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

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

28from impacket.dcerpc.v5.rpcrt import DCERPCException 

29from impacket.uuid import uuidtup_to_bin 

30 

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

32 

33class DCERPCSessionError(DCERPCException): 

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

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

36 

37 def __str__(self): 

38 key = self.error_code 

39 if key in system_errors.ERROR_MESSAGES: 

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

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

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

43 else: 

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

45 

46################################################################################ 

47# CONSTANTS 

48################################################################################ 

49 

50# Evt Path Flags 

51EvtQueryChannelName = 0x00000001 

52EvtQueryFilePath = 0x00000002 

53EvtReadOldestToNewest = 0x00000100 

54EvtReadNewestToOldest = 0x00000200 

55 

56################################################################################ 

57# STRUCTURES 

58################################################################################ 

59 

60class CONTEXT_HANDLE_LOG_HANDLE(NDRSTRUCT): 

61 align = 1 

62 structure = ( 

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

64 ) 

65 

66class PCONTEXT_HANDLE_LOG_HANDLE(NDRPOINTER): 

67 referent = ( 

68 ('Data', CONTEXT_HANDLE_LOG_HANDLE), 

69 ) 

70 

71class CONTEXT_HANDLE_LOG_QUERY(NDRSTRUCT): 

72 align = 1 

73 structure = ( 

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

75 ) 

76 

77class PCONTEXT_HANDLE_LOG_QUERY(NDRPOINTER): 

78 referent = ( 

79 ('Data', CONTEXT_HANDLE_LOG_QUERY), 

80 ) 

81 

82class LPPCONTEXT_HANDLE_LOG_QUERY(NDRPOINTER): 

83 referent = ( 

84 ('Data', PCONTEXT_HANDLE_LOG_QUERY), 

85 ) 

86 

87class CONTEXT_HANDLE_OPERATION_CONTROL(NDRSTRUCT): 

88 align = 1 

89 structure = ( 

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

91 ) 

92 

93class PCONTEXT_HANDLE_OPERATION_CONTROL(NDRPOINTER): 

94 referent = ( 

95 ('Data', CONTEXT_HANDLE_OPERATION_CONTROL), 

96 ) 

97 

98# 2.2.11 EvtRpcQueryChannelInfo 

99class EvtRpcQueryChannelInfo(NDRSTRUCT): 

100 structure = ( 

101 ('Name', LPWSTR), 

102 ('Status', DWORD), 

103 ) 

104 

105class EvtRpcQueryChannelInfoArray(NDRUniVaryingArray): 

106 item = EvtRpcQueryChannelInfo 

107 

108class LPEvtRpcQueryChannelInfoArray(NDRPOINTER): 

109 referent = ( 

110 ('Data', EvtRpcQueryChannelInfoArray) 

111 ) 

112 

113class RPC_INFO(NDRSTRUCT): 

114 structure = ( 

115 ('Error', DWORD), 

116 ('SubError', DWORD), 

117 ('SubErrorParam', DWORD), 

118 ) 

119 

120class PRPC_INFO(NDRPOINTER): 

121 referent = ( 

122 ('Data', RPC_INFO) 

123 ) 

124 

125class WSTR_ARRAY(NDRUniVaryingArray): 

126 item = WSTR 

127 

128class DWORD_ARRAY(NDRUniVaryingArray): 

129 item = DWORD 

130 

131class LPDWORD_ARRAY(NDRPOINTER): 

132 referent = ( 

133 ('Data', DWORD_ARRAY) 

134 ) 

135 

136class BYTE_ARRAY(NDRUniVaryingArray): 

137 item = 'c' 

138 

139class CBYTE_ARRAY(NDRUniVaryingArray): 

140 item = BYTE 

141 

142class CDWORD_ARRAY(NDRUniConformantArray): 

143 item = DWORD 

144 

145class LPBYTE_ARRAY(NDRPOINTER): 

146 referent = ( 

147 ('Data', CBYTE_ARRAY) 

148 ) 

149 

150class ULONG_ARRAY(NDRUniVaryingArray): 

151 item = ULONG 

152 

153# 2.3.1 EVENT_DESCRIPTOR 

154class EVENT_DESCRIPTOR(NDRSTRUCT): 

155 structure = ( 

156 ('Id', WORD), 

157 ('Version', BYTE), 

158 ('Channel', BYTE), 

159 ('LevelSeverity', BYTE), 

160 ('Opcode', BYTE), 

161 ('Task', WORD), 

162 ('Keyword', ULONG), 

163 ) 

164 

165class BOOKMARK(NDRSTRUCT): 

166 structure = ( 

167 ('BookmarkSize', DWORD), 

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

169 ('ChannelSize', DWORD), 

170 ('CurrentChannel', DWORD), 

171 ('ReadDirection', DWORD), 

172 ('RecordIdsOffset', DWORD), 

173 ('LogRecordNumbers', ULONG_ARRAY), 

174 ) 

175 

176 

177#2.2.17 RESULT_SET 

178class RESULT_SET(NDRSTRUCT): 

179 structure = ( 

180 ('TotalSize', DWORD), 

181 ('HeaderSize', DWORD), 

182 ('EventOffset', DWORD), 

183 ('BookmarkOffset', DWORD), 

184 ('BinXmlSize', DWORD), 

185 ('EventData', BYTE_ARRAY), 

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

187 #('SubqueryIDs', BYTE_ARRAY), 

188 #('BookMarkData', BOOKMARK), 

189 ) 

190 

191################################################################################ 

192# RPC CALLS 

193################################################################################ 

194 

195class EvtRpcRegisterLogQuery(NDRCALL): 

196 opnum = 5 

197 structure = ( 

198 ('Path', LPWSTR), 

199 ('Query', WSTR), 

200 ('Flags', DWORD), 

201 ) 

202 

203class EvtRpcRegisterLogQueryResponse(NDRCALL): 

204 structure = ( 

205 ('Handle', CONTEXT_HANDLE_LOG_QUERY), 

206 ('OpControl', CONTEXT_HANDLE_OPERATION_CONTROL), 

207 ('QueryChannelInfoSize', DWORD), 

208 ('QueryChannelInfo', EvtRpcQueryChannelInfoArray), 

209 ('Error', RPC_INFO), 

210 ) 

211 

212class EvtRpcQueryNext(NDRCALL): 

213 opnum = 11 

214 structure = ( 

215 ('LogQuery', CONTEXT_HANDLE_LOG_QUERY), 

216 ('NumRequestedRecords', DWORD), 

217 ('TimeOutEnd', DWORD), 

218 ('Flags', DWORD), 

219 ) 

220 

221class EvtRpcQueryNextResponse(NDRCALL): 

222 structure = ( 

223 ('NumActualRecords', DWORD), 

224 ('EventDataIndices', DWORD_ARRAY), 

225 ('EventDataSizes', DWORD_ARRAY), 

226 ('ResultBufferSize', DWORD), 

227 ('ResultBuffer', BYTE_ARRAY), 

228 ('ErrorCode', ULONG), 

229 ) 

230 

231class EvtRpcQuerySeek(NDRCALL): 

232 opnum = 12 

233 structure = ( 

234 ('LogQuery', CONTEXT_HANDLE_LOG_QUERY), 

235 ('Pos', LARGE_INTEGER), 

236 ('BookmarkXML', LPWSTR), 

237 ('Flags', DWORD), 

238 ) 

239 

240class EvtRpcQuerySeekResponse(NDRCALL): 

241 structure = ( 

242 ('Error', RPC_INFO), 

243 ) 

244 

245class EvtRpcClose(NDRCALL): 

246 opnum = 13 

247 structure = ( 

248 ("Handle", CONTEXT_HANDLE_LOG_HANDLE), 

249 ) 

250 

251class EvtRpcCloseResponse(NDRCALL): 

252 structure = ( 

253 ("Handle", PCONTEXT_HANDLE_LOG_HANDLE), 

254 ('ErrorCode', ULONG), 

255 ) 

256 

257class EvtRpcOpenLogHandle(NDRCALL): 

258 opnum = 17 

259 structure = ( 

260 ('Channel', WSTR), 

261 ('Flags', DWORD), 

262 ) 

263 

264class EvtRpcOpenLogHandleResponse(NDRCALL): 

265 structure = ( 

266 ('Handle', PCONTEXT_HANDLE_LOG_HANDLE), 

267 ('Error', RPC_INFO), 

268 ) 

269 

270class EvtRpcGetChannelList(NDRCALL): 

271 opnum = 19 

272 structure = ( 

273 ('Flags', DWORD), 

274 ) 

275 

276class EvtRpcGetChannelListResponse(NDRCALL): 

277 structure = ( 

278 ('NumChannelPaths', DWORD), 

279 ('ChannelPaths', WSTR_ARRAY), 

280 ('ErrorCode', ULONG), 

281 ) 

282 

283################################################################################ 

284# OPNUMs and their corresponding structures 

285################################################################################ 

286 

287OPNUMS = { 

288 5 : (EvtRpcRegisterLogQuery, EvtRpcRegisterLogQueryResponse), 

289 11 : (EvtRpcQueryNext, EvtRpcQueryNextResponse), 

290 12 : (EvtRpcQuerySeek, EvtRpcQuerySeekResponse), 

291 13 : (EvtRpcClose, EvtRpcCloseResponse), 

292 17 : (EvtRpcOpenLogHandle, EvtRpcOpenLogHandle), 

293 19 : (EvtRpcGetChannelList, EvtRpcGetChannelListResponse), 

294} 

295 

296################################################################################ 

297# HELPER FUNCTIONS 

298################################################################################ 

299 

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

301 request = EvtRpcRegisterLogQuery() 

302 

303 request['Path'] = path 

304 request['Query'] = query 

305 request['Flags'] = flags 

306 resp = dce.request(request) 

307 return resp 

308 

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

310 request = EvtRpcQueryNext() 

311 

312 request['LogQuery'] = handle 

313 request['NumRequestedRecords'] = numRequestedRecords 

314 request['TimeOutEnd'] = timeOutEnd 

315 request['Flags'] = 0 

316 status = system_errors.ERROR_MORE_DATA 

317 resp = dce.request(request) 

318 while status == system_errors.ERROR_MORE_DATA: 

319 try: 

320 resp = dce.request(request) 

321 except DCERPCException as e: 

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

323 raise 

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

325 raise 

326 resp = e.get_packet() 

327 return resp 

328 

329def hEvtRpcClose(dce, handle): 

330 request = EvtRpcClose() 

331 request['Handle'] = handle 

332 resp = dce.request(request) 

333 return resp 

334 

335def hEvtRpcOpenLogHandle(dce, channel, flags): 

336 request = EvtRpcOpenLogHandle() 

337 

338 request['Channel'] = channel 

339 request['Flags'] = flags 

340 return dce.request(request) 

341 

342def hEvtRpcGetChannelList(dce): 

343 request = EvtRpcGetChannelList() 

344 

345 request['Flags'] = 0 

346 resp = dce.request(request) 

347 return resp