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) 2020 SecureAuth Corporation. All rights reserved. 

4# 

5# This software is provided under a slightly modified version 

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

7# for more information. 

8# 

9# Description: 

10# [MS-DTYP] Interface mini implementation 

11# 

12# Author: 

13# Alberto Solino (@agsolino) 

14# 

15 

16from __future__ import division 

17from __future__ import print_function 

18from struct import pack 

19from six import binary_type 

20 

21from impacket.dcerpc.v5.ndr import NDRULONG, NDRUHYPER, NDRSHORT, NDRLONG, NDRPOINTER, NDRUniConformantArray, \ 

22 NDRUniFixedArray, NDR, NDRHYPER, NDRSMALL, NDRPOINTERNULL, NDRSTRUCT, \ 

23 NDRUSMALL, NDRBOOLEAN, NDRUSHORT, NDRFLOAT, NDRDOUBLEFLOAT, NULL 

24 

25DWORD = NDRULONG 

26BOOL = NDRULONG 

27UCHAR = NDRUSMALL 

28SHORT = NDRSHORT 

29NULL = NULL 

30 

31class LPDWORD(NDRPOINTER): 

32 referent = ( 

33 ('Data', DWORD), 

34 ) 

35 

36class PSHORT(NDRPOINTER): 

37 referent = ( 

38 ('Data', SHORT), 

39 ) 

40 

41class PBOOL(NDRPOINTER): 

42 referent = ( 

43 ('Data', BOOL), 

44 ) 

45 

46class LPBYTE(NDRPOINTER): 

47 referent = ( 

48 ('Data', NDRUniConformantArray), 

49 ) 

50PBYTE = LPBYTE 

51 

52# 2.2.4 BOOLEAN 

53BOOLEAN = NDRBOOLEAN 

54 

55# 2.2.6 BYTE 

56BYTE = NDRUSMALL 

57 

58# 2.2.7 CHAR 

59CHAR = NDRSMALL 

60class PCHAR(NDRPOINTER): 

61 referent = ( 

62 ('Data', CHAR), 

63 ) 

64 

65class WIDESTR(NDRUniFixedArray): 

66 def getDataLen(self, data, offset=0): 

67 return data.find(b'\x00\x00\x00', offset)+3-offset 

68 

69 def __setitem__(self, key, value): 

70 if key == 'Data': 70 ↛ 79line 70 didn't jump to line 79, because the condition on line 70 was never false

71 try: 

72 self.fields[key] = value.encode('utf-16le') 

73 except UnicodeDecodeError: 

74 import sys 

75 self.fields[key] = value.decode(sys.getfilesystemencoding()).encode('utf-16le') 

76 

77 self.data = None # force recompute 

78 else: 

79 return NDR.__setitem__(self, key, value) 

80 

81 def __getitem__(self, key): 

82 if key == 'Data': 82 ↛ 85line 82 didn't jump to line 85, because the condition on line 82 was never false

83 return self.fields[key].decode('utf-16le') 

84 else: 

85 return NDR.__getitem__(self,key) 

86 

87class STR(NDRSTRUCT): 

88 commonHdr = ( 

89 ('MaximumCount', '<L=len(Data)'), 

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

91 ('ActualCount','<L=len(Data)'), 

92 ) 

93 commonHdr64 = ( 

94 ('MaximumCount', '<Q=len(Data)'), 

95 ('Offset','<Q=0'), 

96 ('ActualCount','<Q=len(Data)'), 

97 ) 

98 structure = ( 

99 ('Data',':'), 

100 ) 

101 

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

103 if msg is None: 

104 msg = self.__class__.__name__ 

105 if msg != '': 

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

107 # Here just print the data 

108 print(" %r" % (self['Data']), end=' ') 

109 

110 def __setitem__(self, key, value): 

111 if key == 'Data': 111 ↛ 125line 111 didn't jump to line 125, because the condition on line 111 was never false

112 try: 

113 if not isinstance(value, binary_type): 113 ↛ 117line 113 didn't jump to line 117, because the condition on line 113 was never false

114 self.fields[key] = value.encode('utf-8') 

115 else: 

116 # if it is a binary type (str in Python 2, bytes in Python 3), then we assume it is a raw buffer 

117 self.fields[key] = value 

118 except UnicodeDecodeError: 

119 import sys 

120 self.fields[key] = value.decode(sys.getfilesystemencoding()).encode('utf-8') 

121 self.fields['MaximumCount'] = None 

122 self.fields['ActualCount'] = None 

123 self.data = None # force recompute 

124 else: 

125 return NDR.__setitem__(self, key, value) 

126 

127 def __getitem__(self, key): 

128 if key == 'Data': 

129 try: 

130 return self.fields[key].decode('utf-8') 

131 except UnicodeDecodeError: 

132 # if we could't decode it, we assume it is a raw buffer 

133 return self.fields[key] 

134 else: 

135 return NDR.__getitem__(self,key) 

136 

137 def getDataLen(self, data, offset=0): 

138 return self["ActualCount"] 

139 

140class LPSTR(NDRPOINTER): 

141 referent = ( 

142 ('Data', STR), 

143 ) 

144 

145class WSTR(NDRSTRUCT): 

146 commonHdr = ( 

147 ('MaximumCount', '<L=len(Data)//2'), 

148 ('Offset','<L=0'), 

149 ('ActualCount','<L=len(Data)//2'), 

150 ) 

151 commonHdr64 = ( 

152 ('MaximumCount', '<Q=len(Data)//2'), 

153 ('Offset','<Q=0'), 

154 ('ActualCount','<Q=len(Data)//2'), 

155 ) 

156 structure = ( 

157 ('Data',':'), 

158 ) 

159 

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

161 if msg is None: 161 ↛ 162line 161 didn't jump to line 162, because the condition on line 161 was never true

162 msg = self.__class__.__name__ 

163 if msg != '': 

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

165 # Here just print the data 

166 print(" %r" % (self['Data']), end=' ') 

167 

168 def getDataLen(self, data, offset=0): 

169 return self["ActualCount"]*2 

170 

171 def __setitem__(self, key, value): 

172 if key == 'Data': 172 ↛ 182line 172 didn't jump to line 182, because the condition on line 172 was never false

173 try: 

174 self.fields[key] = value.encode('utf-16le') 

175 except UnicodeDecodeError: 

176 import sys 

177 self.fields[key] = value.decode(sys.getfilesystemencoding()).encode('utf-16le') 

178 self.fields['MaximumCount'] = None 

179 self.fields['ActualCount'] = None 

180 self.data = None # force recompute 

181 else: 

182 return NDR.__setitem__(self, key, value) 

183 

184 def __getitem__(self, key): 

185 if key == 'Data': 

186 return self.fields[key].decode('utf-16le') 

187 else: 

188 return NDR.__getitem__(self,key) 

189 

190class LPWSTR(NDRPOINTER): 

191 referent = ( 

192 ('Data', WSTR), 

193 ) 

194 

195# 2.2.5 BSTR 

196BSTR = LPWSTR 

197 

198# 2.2.8 DOUBLE 

199DOUBLE = NDRDOUBLEFLOAT 

200class PDOUBLE(NDRPOINTER): 

201 referent = ( 

202 ('Data', DOUBLE), 

203 ) 

204 

205# 2.2.15 FLOAT 

206FLOAT = NDRFLOAT 

207class PFLOAT(NDRPOINTER): 

208 referent = ( 

209 ('Data', FLOAT), 

210 ) 

211 

212# 2.2.18 HRESULT 

213HRESULT = NDRLONG 

214class PHRESULT(NDRPOINTER): 

215 referent = ( 

216 ('Data', HRESULT), 

217 ) 

218 

219# 2.2.19 INT 

220INT = NDRLONG 

221class PINT(NDRPOINTER): 

222 referent = ( 

223 ('Data', INT), 

224 ) 

225 

226# 2.2.26 LMSTR 

227LMSTR = LPWSTR 

228 

229# 2.2.27 LONG 

230LONG = NDRLONG 

231class LPLONG(NDRPOINTER): 

232 referent = ( 

233 ('Data', LONG), 

234 ) 

235 

236PLONG = LPLONG 

237 

238# 2.2.28 LONGLONG 

239LONGLONG = NDRHYPER 

240 

241class PLONGLONG(NDRPOINTER): 

242 referent = ( 

243 ('Data', LONGLONG), 

244 ) 

245 

246# 2.2.31 LONG64 

247LONG64 = NDRUHYPER 

248class PLONG64(NDRPOINTER): 

249 referent = ( 

250 ('Data', LONG64), 

251 ) 

252 

253# 2.2.32 LPCSTR 

254LPCSTR = LPSTR 

255 

256# 2.2.36 NET_API_STATUS 

257NET_API_STATUS = DWORD 

258 

259# 2.2.52 ULONG_PTR 

260ULONG_PTR = NDRULONG 

261# 2.2.10 DWORD_PTR 

262DWORD_PTR = ULONG_PTR 

263 

264# 2.3.2 GUID and UUID 

265class GUID(NDRSTRUCT): 

266 structure = ( 

267 ('Data','16s=b""'), 

268 ) 

269 

270 def getAlignment(self): 

271 return 4 

272 

273class PGUID(NDRPOINTER): 

274 referent = ( 

275 ('Data', GUID), 

276 ) 

277 

278UUID = GUID 

279PUUID = PGUID 

280 

281# 2.2.37 NTSTATUS 

282NTSTATUS = DWORD 

283 

284# 2.2.45 UINT 

285UINT = NDRULONG 

286class PUINT(NDRPOINTER): 

287 referent = ( 

288 ('Data', UINT), 

289 ) 

290 

291# 2.2.50 ULONG 

292ULONG = NDRULONG 

293class PULONG(NDRPOINTER): 

294 referent = ( 

295 ('Data', ULONG), 

296 ) 

297 

298LPULONG = PULONG 

299 

300# 2.2.54 ULONGLONG 

301ULONGLONG = NDRUHYPER 

302class PULONGLONG(NDRPOINTER): 

303 referent = ( 

304 ('Data', ULONGLONG), 

305 ) 

306 

307# 2.2.57 USHORT 

308USHORT = NDRUSHORT 

309class PUSHORT(NDRPOINTER): 

310 referent = ( 

311 ('Data', USHORT), 

312 ) 

313 

314# 2.2.59 WCHAR 

315WCHAR = WSTR 

316PWCHAR = LPWSTR 

317 

318# 2.2.61 WORD 

319WORD = NDRUSHORT 

320class PWORD(NDRPOINTER): 

321 referent = ( 

322 ('Data', WORD), 

323 ) 

324LPWORD = PWORD 

325 

326# 2.3.1 FILETIME 

327class FILETIME(NDRSTRUCT): 

328 structure = ( 

329 ('dwLowDateTime', DWORD), 

330 ('dwHighDateTime', LONG), 

331 ) 

332 

333class PFILETIME(NDRPOINTER): 

334 referent = ( 

335 ('Data', FILETIME), 

336 ) 

337 

338# 2.3.3 LARGE_INTEGER 

339LARGE_INTEGER = NDRHYPER 

340class PLARGE_INTEGER(NDRPOINTER): 

341 referent = ( 

342 ('Data', LARGE_INTEGER), 

343 ) 

344 

345# 2.3.5 LUID 

346class LUID(NDRSTRUCT): 

347 structure = ( 

348 ('LowPart', DWORD), 

349 ('HighPart', LONG), 

350 ) 

351 

352# 2.3.8 RPC_UNICODE_STRING 

353class RPC_UNICODE_STRING(NDRSTRUCT): 

354 # Here we're doing some tricks to make this data type 

355 # easier to use. It's exactly the same as defined. I changed the 

356 # Buffer name for Data, so users can write directly to the datatype 

357 # instead of writing to datatype['Buffer']. 

358 # The drawback is you cannot directly access the Length and  

359 # MaximumLength fields.  

360 # If you really need it, you will need to do it this way: 

361 # class TT(NDRCALL): 

362 # structure = ( 

363 # ('str1', RPC_UNICODE_STRING), 

364 # ) 

365 #  

366 # nn = TT() 

367 # nn.fields['str1'].fields['MaximumLength'] = 30 

368 structure = ( 

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

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

371 ('Data',LPWSTR), 

372 ) 

373 

374 def __setitem__(self, key, value): 

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

376 try: 

377 value.encode('utf-16le') 

378 except UnicodeDecodeError: 

379 import sys 

380 value = value.decode(sys.getfilesystemencoding()) 

381 self['Length'] = len(value)*2 

382 self['MaximumLength'] = len(value)*2 

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

384 

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

386 if msg is None: 386 ↛ 387line 386 didn't jump to line 387, because the condition on line 386 was never true

387 msg = self.__class__.__name__ 

388 if msg != '': 

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

390 

391 if isinstance(self.fields['Data'] , NDRPOINTERNULL): 391 ↛ 392line 391 didn't jump to line 392, because the condition on line 391 was never true

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

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

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

395 else: 

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

397 

398class PRPC_UNICODE_STRING(NDRPOINTER): 

399 referent = ( 

400 ('Data', RPC_UNICODE_STRING ), 

401 ) 

402 

403# 2.3.9 OBJECT_TYPE_LIST 

404ACCESS_MASK = DWORD 

405class OBJECT_TYPE_LIST(NDRSTRUCT): 

406 structure = ( 

407 ('Level', WORD), 

408 ('Remaining',ACCESS_MASK), 

409 ('ObjectType',PGUID), 

410 ) 

411 

412class POBJECT_TYPE_LIST(NDRPOINTER): 

413 referent = ( 

414 ('Data', OBJECT_TYPE_LIST ), 

415 ) 

416 

417# 2.3.13 SYSTEMTIME 

418class SYSTEMTIME(NDRSTRUCT): 

419 structure = ( 

420 ('wYear', WORD), 

421 ('wMonth', WORD), 

422 ('wDayOfWeek', WORD), 

423 ('wDay', WORD), 

424 ('wHour', WORD), 

425 ('wMinute', WORD), 

426 ('wSecond', WORD), 

427 ('wMilliseconds', WORD), 

428 ) 

429 

430class PSYSTEMTIME(NDRPOINTER): 

431 referent = ( 

432 ('Data', SYSTEMTIME ), 

433 ) 

434 

435# 2.3.15 ULARGE_INTEGER 

436class ULARGE_INTEGER(NDRSTRUCT): 

437 structure = ( 

438 ('QuadPart', LONG64), 

439 ) 

440 

441class PULARGE_INTEGER(NDRPOINTER): 

442 referent = ( 

443 ('Data', ULARGE_INTEGER), 

444 ) 

445 

446# 2.4.2.3 RPC_SID 

447class DWORD_ARRAY(NDRUniConformantArray): 

448 item = '<L' 

449 

450class RPC_SID_IDENTIFIER_AUTHORITY(NDRUniFixedArray): 

451 align = 1 

452 align64 = 1 

453 def getDataLen(self, data, offset=0): 

454 return 6 

455 

456class RPC_SID(NDRSTRUCT): 

457 structure = ( 

458 ('Revision',NDRSMALL), 

459 ('SubAuthorityCount',NDRSMALL), 

460 ('IdentifierAuthority',RPC_SID_IDENTIFIER_AUTHORITY), 

461 ('SubAuthority',DWORD_ARRAY), 

462 ) 

463 def getData(self, soFar = 0): 

464 self['SubAuthorityCount'] = len(self['SubAuthority']) 

465 return NDRSTRUCT.getData(self, soFar) 

466 

467 def fromCanonical(self, canonical): 

468 items = canonical.split('-') 

469 self['Revision'] = int(items[1]) 

470 self['IdentifierAuthority'] = b'\x00\x00\x00\x00\x00' + pack('B',int(items[2])) 

471 self['SubAuthorityCount'] = len(items) - 3 

472 for i in range(self['SubAuthorityCount']): 

473 self['SubAuthority'].append(int(items[i+3])) 

474 

475 def formatCanonical(self): 

476 ans = 'S-%d-%d' % (self['Revision'], ord(self['IdentifierAuthority'][5:6])) 

477 for i in range(self['SubAuthorityCount']): 

478 ans += '-%d' % self['SubAuthority'][i] 

479 return ans 

480 

481class PRPC_SID(NDRPOINTER): 

482 referent = ( 

483 ('Data', RPC_SID), 

484 ) 

485 

486PSID = PRPC_SID 

487 

488# 2.4.3 ACCESS_MASK 

489GENERIC_READ = 0x80000000 

490GENERIC_WRITE = 0x40000000 

491GENERIC_EXECUTE = 0x20000000 

492GENERIC_ALL = 0x10000000 

493MAXIMUM_ALLOWED = 0x02000000 

494ACCESS_SYSTEM_SECURITY = 0x01000000 

495SYNCHRONIZE = 0x00100000 

496WRITE_OWNER = 0x00080000 

497WRITE_DACL = 0x00040000 

498READ_CONTROL = 0x00020000 

499DELETE = 0x00010000 

500 

501# 2.4.5.1 ACL--RPC Representation 

502class ACL(NDRSTRUCT): 

503 structure = ( 

504 ('AclRevision',NDRSMALL), 

505 ('Sbz1',NDRSMALL), 

506 ('AclSize',NDRSHORT), 

507 ('AceCount',NDRSHORT), 

508 ('Sbz2',NDRSHORT), 

509 ) 

510 

511class PACL(NDRPOINTER): 

512 referent = ( 

513 ('Data', ACL), 

514 ) 

515 

516# 2.4.6.1 SECURITY_DESCRIPTOR--RPC Representation 

517class SECURITY_DESCRIPTOR(NDRSTRUCT): 

518 structure = ( 

519 ('Revision',UCHAR), 

520 ('Sbz1',UCHAR), 

521 ('Control',USHORT), 

522 ('Owner',PSID), 

523 ('Group',PSID), 

524 ('Sacl',PACL), 

525 ('Dacl',PACL), 

526 ) 

527 

528# 2.4.7 SECURITY_INFORMATION 

529OWNER_SECURITY_INFORMATION = 0x00000001 

530GROUP_SECURITY_INFORMATION = 0x00000002 

531DACL_SECURITY_INFORMATION = 0x00000004 

532SACL_SECURITY_INFORMATION = 0x00000008 

533LABEL_SECURITY_INFORMATION = 0x00000010 

534UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000 

535UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000 

536PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000 

537PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000 

538ATTRIBUTE_SECURITY_INFORMATION = 0x00000020 

539SCOPE_SECURITY_INFORMATION = 0x00000040 

540BACKUP_SECURITY_INFORMATION = 0x00010000 

541 

542SECURITY_INFORMATION = DWORD 

543class PSECURITY_INFORMATION(NDRPOINTER): 

544 referent = ( 

545 ('Data', SECURITY_INFORMATION), 

546 )