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# 

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

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

5# for more information. 

6# 

7# Author: Alberto Solino (@agsolino) 

8# Itamar Mizrahi (@MrAnde7son) 

9# 

10# Description: 

11# [MS-EVEN] 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 __future__ import division 

23from __future__ import print_function 

24from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDR, NDRPOINTERNULL, NDRUniConformantArray 

25from impacket.dcerpc.v5.dtypes import ULONG, LPWSTR, RPC_UNICODE_STRING, LPSTR, NTSTATUS, NULL, PRPC_UNICODE_STRING, PULONG, USHORT, PRPC_SID, LPBYTE 

26from impacket.dcerpc.v5.lsad import PRPC_UNICODE_STRING_ARRAY 

27from impacket.structure import Structure 

28from impacket import nt_errors 

29from impacket.uuid import uuidtup_to_bin 

30from impacket.dcerpc.v5.rpcrt import DCERPCException 

31 

32MSRPC_UUID_EVEN = uuidtup_to_bin(('82273FDC-E32A-18C3-3F78-827929DC23EA','0.0')) 

33 

34class DCERPCSessionError(DCERPCException): 

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

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

37 

38 def __str__( self ): 

39 key = self.error_code 

40 if key in nt_errors.ERROR_MESSAGES: 

41 error_msg_short = nt_errors.ERROR_MESSAGES[key][0] 

42 error_msg_verbose = nt_errors.ERROR_MESSAGES[key][1] 

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

44 else: 

45 return 'EVEN SessionError: unknown error code: 0x%x' % self.error_code 

46 

47################################################################################ 

48# CONSTANTS 

49################################################################################ 

50# 2.2.2 EventType 

51EVENTLOG_SUCCESS = 0x0000 

52EVENTLOG_ERROR_TYPE = 0x0001 

53EVENTLOG_WARNING_TYPE = 0x0002 

54EVENTLOG_INFORMATION_TYPE = 0x0004 

55EVENTLOG_AUDIT_SUCCESS = 0x0008 

56EVENTLOG_AUDIT_FAILURE = 0x0010 

57 

58# 2.2.7 EVENTLOG_HANDLE_A and EVENTLOG_HANDLE_W 

59#EVENTLOG_HANDLE_A 

60EVENTLOG_HANDLE_W = LPWSTR 

61 

62# 2.2.9 Constants Used in Method Definitions 

63MAX_STRINGS = 0x00000100 

64MAX_SINGLE_EVENT = 0x0003FFFF 

65MAX_BATCH_BUFF = 0x0007FFFF 

66 

67# 3.1.4.7 ElfrReadELW (Opnum 10) 

68EVENTLOG_SEQUENTIAL_READ = 0x00000001 

69EVENTLOG_SEEK_READ = 0x00000002 

70 

71EVENTLOG_FORWARDS_READ = 0x00000004 

72EVENTLOG_BACKWARDS_READ = 0x00000008 

73 

74################################################################################ 

75# STRUCTURES 

76################################################################################ 

77 

78class IELF_HANDLE(NDRSTRUCT): 

79 structure = ( 

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

81 ) 

82 def getAlignment(self): 

83 return 1 

84 

85# 2.2.3 EVENTLOGRECORD 

86class EVENTLOGRECORD(Structure): 

87 structure = ( 

88 ('Length','<L=0'), 

89 ('Reserved','<L=0'), 

90 ('RecordNumber','<L=0'), 

91 ('TimeGenerated','<L=0'), 

92 ('TimeWritten','<L=0'), 

93 ('EventID','<L=0'), 

94 ('EventType','<H=0'), 

95 ('NumStrings','<H=0'), 

96 ('EventCategory','<H=0'), 

97 ('ReservedFlags','<H=0'), 

98 ('ClosingRecordNumber','<L=0'), 

99 ('StringOffset','<L=0'), 

100 ('UserSidLength','<L=0'), 

101 ('UserSidOffset','<L=0'), 

102 ('DataLength','<L=0'), 

103 ('DataOffset','<L=0'), 

104 ('SourceName','z'), 

105 ('Computername','z'), 

106 ('UserSidPadding',':'), 

107 ('_UserSid','_-UserSid', 'self["UserSidLength"]'), 

108 ('UserSid',':'), 

109 ('Strings',':'), 

110 ('_Data','_-Data', 'self["DataLength"]'), 

111 ('Data',':'), 

112 ('Padding',':'), 

113 ('Length2','<L=0'), 

114 ) 

115 

116# 2.2.4 EVENTLOG_FULL_INFORMATION 

117class EVENTLOG_FULL_INFORMATION(NDRSTRUCT): 

118 structure = ( 

119 ('dwFull', ULONG), 

120 ) 

121 

122# 2.2.8 RPC_CLIENT_ID 

123class RPC_CLIENT_ID(NDRSTRUCT): 

124 structure = ( 

125 ('UniqueProcess', ULONG), 

126 ('UniqueThread', ULONG), 

127 ) 

128 

129# 2.2.12 RPC_STRING 

130class RPC_STRING(NDRSTRUCT): 

131 structure = ( 

132 ('Length','<H=0'), 

133 ('MaximumLength','<H=0'), 

134 ('Data',LPSTR), 

135 ) 

136 

137 def __setitem__(self, key, value): 

138 if key == 'Data' and isinstance(value, NDR) is False: 

139 self['Length'] = len(value) 

140 self['MaximumLength'] = len(value) 

141 return NDRSTRUCT.__setitem__(self, key, value) 

142 

143 def dump(self, msg = None, indent = 0): 

144 if msg is None: msg = self.__class__.__name__ 

145 if msg != '': 

146 print("%s" % msg, end=' ') 

147 

148 if isinstance(self.fields['Data'] , NDRPOINTERNULL): 

149 print(" NULL", end=' ') 

150 elif self.fields['Data']['ReferentID'] == 0: 

151 print(" NULL", end=' ') 

152 else: 

153 return self.fields['Data'].dump('',indent) 

154 

155################################################################################ 

156# RPC CALLS 

157################################################################################ 

158# 3.1.4.9 ElfrClearELFW (Opnum 0) 

159class ElfrClearELFW(NDRCALL): 

160 opnum = 0 

161 structure = ( 

162 ('LogHandle', IELF_HANDLE), 

163 ('BackupFileName', PRPC_UNICODE_STRING), 

164 ) 

165 

166class ElfrClearELFWResponse(NDRCALL): 

167 structure = ( 

168 ('ErrorCode', NTSTATUS), 

169 ) 

170 

171# 3.1.4.11 ElfrBackupELFW (Opnum 1) 

172class ElfrBackupELFW(NDRCALL): 

173 opnum = 1 

174 structure = ( 

175 ('LogHandle', IELF_HANDLE), 

176 ('BackupFileName', RPC_UNICODE_STRING), 

177 ) 

178 

179class ElfrBackupELFWResponse(NDRCALL): 

180 structure = ( 

181 ('ErrorCode', NTSTATUS), 

182 ) 

183 

184# 3.1.4.21 ElfrCloseEL (Opnum 2) 

185class ElfrCloseEL(NDRCALL): 

186 opnum = 2 

187 structure = ( 

188 ('LogHandle', IELF_HANDLE), 

189 ) 

190 

191class ElfrCloseELResponse(NDRCALL): 

192 structure = ( 

193 ('LogHandle', IELF_HANDLE), 

194 ('ErrorCode', NTSTATUS), 

195 ) 

196 

197# 3.1.4.18 ElfrNumberOfRecords (Opnum 4) 

198class ElfrNumberOfRecords(NDRCALL): 

199 opnum = 4 

200 structure = ( 

201 ('LogHandle', IELF_HANDLE), 

202 ) 

203 

204class ElfrNumberOfRecordsResponse(NDRCALL): 

205 structure = ( 

206 ('NumberOfRecords', ULONG), 

207 ('ErrorCode', NTSTATUS), 

208 ) 

209 

210# 3.1.4.19 ElfrOldestRecord (Opnum 5) 

211class ElfrOldestRecord(NDRCALL): 

212 opnum = 5 

213 structure = ( 

214 ('LogHandle', IELF_HANDLE), 

215 ) 

216 

217class ElfrOldestRecordResponse(NDRCALL): 

218 structure = ( 

219 ('OldestRecordNumber', ULONG), 

220 ('ErrorCode', NTSTATUS), 

221 ) 

222 

223# 3.1.4.3 ElfrOpenELW (Opnum 7) 

224class ElfrOpenELW(NDRCALL): 

225 opnum = 7 

226 structure = ( 

227 ('UNCServerName', EVENTLOG_HANDLE_W), 

228 ('ModuleName', RPC_UNICODE_STRING), 

229 ('RegModuleName', RPC_UNICODE_STRING), 

230 ('MajorVersion', ULONG), 

231 ('MinorVersion', ULONG), 

232 ) 

233 

234class ElfrOpenELWResponse(NDRCALL): 

235 structure = ( 

236 ('LogHandle', IELF_HANDLE), 

237 ('ErrorCode', NTSTATUS), 

238 ) 

239 

240# 3.1.4.5 ElfrRegisterEventSourceW (Opnum 8) 

241class ElfrRegisterEventSourceW(NDRCALL): 

242 opnum = 8 

243 structure = ( 

244 ('UNCServerName', EVENTLOG_HANDLE_W), 

245 ('ModuleName', RPC_UNICODE_STRING), 

246 ('RegModuleName', RPC_UNICODE_STRING), 

247 ('MajorVersion', ULONG), 

248 ('MinorVersion', ULONG), 

249 ) 

250 

251class ElfrRegisterEventSourceWResponse(NDRCALL): 

252 structure = ( 

253 ('LogHandle', IELF_HANDLE), 

254 ('ErrorCode', NTSTATUS), 

255 ) 

256 

257# 3.1.4.1 ElfrOpenBELW (Opnum 9) 

258class ElfrOpenBELW(NDRCALL): 

259 opnum = 9 

260 structure = ( 

261 ('UNCServerName', EVENTLOG_HANDLE_W), 

262 ('BackupFileName', RPC_UNICODE_STRING), 

263 ('MajorVersion', ULONG), 

264 ('MinorVersion', ULONG), 

265 ) 

266 

267class ElfrOpenBELWResponse(NDRCALL): 

268 structure = ( 

269 ('LogHandle', IELF_HANDLE), 

270 ('ErrorCode', NTSTATUS), 

271 ) 

272 

273# 3.1.4.7 ElfrReadELW (Opnum 10) 

274class ElfrReadELW(NDRCALL): 

275 opnum = 10 

276 structure = ( 

277 ('LogHandle', IELF_HANDLE), 

278 ('ReadFlags', ULONG), 

279 ('RecordOffset', ULONG), 

280 ('NumberOfBytesToRead', ULONG), 

281 ) 

282 

283class ElfrReadELWResponse(NDRCALL): 

284 structure = ( 

285 ('Buffer', NDRUniConformantArray), 

286 ('NumberOfBytesRead', ULONG), 

287 ('MinNumberOfBytesNeeded', ULONG), 

288 ('ErrorCode', NTSTATUS), 

289 ) 

290 

291# 3.1.4.13 ElfrReportEventW (Opnum 11) 

292class ElfrReportEventW(NDRCALL): 

293 opnum = 11 

294 structure = ( 

295 ('LogHandle', IELF_HANDLE), 

296 ('Time', ULONG), 

297 ('EventType', USHORT), 

298 ('EventCategory', USHORT), 

299 ('EventID', ULONG), 

300 ('NumStrings', USHORT), 

301 ('DataSize', ULONG), 

302 ('ComputerName', RPC_UNICODE_STRING), 

303 ('UserSID', PRPC_SID), 

304 ('Strings', PRPC_UNICODE_STRING_ARRAY), 

305 ('Data', LPBYTE), 

306 ('Flags', USHORT), 

307 ('RecordNumber', PULONG), 

308 ('TimeWritten', PULONG), 

309 ) 

310 

311class ElfrReportEventWResponse(NDRCALL): 

312 structure = ( 

313 ('RecordNumber', PULONG), 

314 ('TimeWritten', PULONG), 

315 ('ErrorCode', NTSTATUS), 

316 ) 

317 

318################################################################################ 

319# OPNUMs and their corresponding structures 

320################################################################################ 

321OPNUMS = { 

322 0 : (ElfrClearELFW, ElfrClearELFWResponse), 

323 1 : (ElfrBackupELFW, ElfrBackupELFWResponse), 

324 2 : (ElfrCloseEL, ElfrCloseELResponse), 

325 4 : (ElfrNumberOfRecords, ElfrNumberOfRecordsResponse), 

326 5 : (ElfrOldestRecord, ElfrOldestRecordResponse), 

327 7 : (ElfrOpenELW, ElfrOpenELWResponse), 

328 8 : (ElfrRegisterEventSourceW, ElfrRegisterEventSourceWResponse), 

329 9 : (ElfrOpenBELW, ElfrOpenBELWResponse), 

330 10 : (ElfrReadELW, ElfrReadELWResponse), 

331 11 : (ElfrReportEventW, ElfrReportEventWResponse), 

332} 

333 

334################################################################################ 

335# HELPER FUNCTIONS 

336################################################################################ 

337def hElfrOpenBELW(dce, backupFileName = NULL): 

338 request = ElfrOpenBELW() 

339 request['UNCServerName'] = NULL 

340 request['BackupFileName'] = backupFileName 

341 request['MajorVersion'] = 1 

342 request['MinorVersion'] = 1 

343 return dce.request(request) 

344 

345def hElfrOpenELW(dce, moduleName = NULL, regModuleName = NULL): 

346 request = ElfrOpenELW() 

347 request['UNCServerName'] = NULL 

348 request['ModuleName'] = moduleName 

349 request['RegModuleName'] = regModuleName 

350 request['MajorVersion'] = 1 

351 request['MinorVersion'] = 1 

352 return dce.request(request) 

353 

354def hElfrCloseEL(dce, logHandle): 

355 request = ElfrCloseEL() 

356 request['LogHandle'] = logHandle 

357 resp = dce.request(request) 

358 return resp 

359 

360def hElfrRegisterEventSourceW(dce, moduleName = NULL, regModuleName = NULL): 

361 request = ElfrRegisterEventSourceW() 

362 request['UNCServerName'] = NULL 

363 request['ModuleName'] = moduleName 

364 request['RegModuleName'] = regModuleName 

365 request['MajorVersion'] = 1 

366 request['MinorVersion'] = 1 

367 return dce.request(request) 

368 

369def hElfrReadELW(dce, logHandle = '', readFlags = EVENTLOG_SEEK_READ|EVENTLOG_FORWARDS_READ, 

370 recordOffset = 0, numberOfBytesToRead = MAX_BATCH_BUFF): 

371 request = ElfrReadELW() 

372 request['LogHandle'] = logHandle 

373 request['ReadFlags'] = readFlags 

374 request['RecordOffset'] = recordOffset 

375 request['NumberOfBytesToRead'] = numberOfBytesToRead 

376 return dce.request(request) 

377 

378def hElfrClearELFW(dce, logHandle = '', backupFileName = NULL): 

379 request = ElfrClearELFW() 

380 request['LogHandle'] = logHandle 

381 request['BackupFileName'] = backupFileName 

382 return dce.request(request) 

383 

384def hElfrBackupELFW(dce, logHandle = '', backupFileName = NULL): 

385 request = ElfrBackupELFW() 

386 request['LogHandle'] = logHandle 

387 request['BackupFileName'] = backupFileName 

388 return dce.request(request) 

389 

390def hElfrNumberOfRecords(dce, logHandle): 

391 request = ElfrNumberOfRecords() 

392 request['LogHandle'] = logHandle 

393 resp = dce.request(request) 

394 return resp 

395 

396def hElfrOldestRecordNumber(dce, logHandle): 

397 request = ElfrOldestRecord() 

398 request['LogHandle'] = logHandle 

399 resp = dce.request(request) 

400 return resp