Coverage for /root/GitHubProjects/impacket/impacket/dcerpc/v5/dtypes.py: 87%

# Coverage for /root/GitHubProjects/impacket/impacket/dcerpc/v5/dtypes.py : 87%

## 264 statements

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

16 from __future__ import division

17 from __future__ import print_function

18 from struct import pack

19 from six import binary_type

20

21 from 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

25 DWORD = NDRULONG

26 BOOL = NDRULONG

27 UCHAR = NDRUSMALL

28 SHORT = NDRSHORT

29 NULL = NULL

30

31 class LPDWORD(NDRPOINTER):

32 referent = (

33 ('Data', DWORD),

34 )

35

36 class PSHORT(NDRPOINTER):

37 referent = (

38 ('Data', SHORT),

39 )

40

41 class PBOOL(NDRPOINTER):

42 referent = (

43 ('Data', BOOL),

44 )

45

46 class LPBYTE(NDRPOINTER):

47 referent = (

48 ('Data', NDRUniConformantArray),

49 )

50 PBYTE = LPBYTE

51

52# 2.2.4 BOOLEAN

53 BOOLEAN = NDRBOOLEAN

54

55# 2.2.6 BYTE

56 BYTE = NDRUSMALL

57

58# 2.2.7 CHAR

59 CHAR = NDRSMALL

60 class PCHAR(NDRPOINTER):

61 referent = (

62 ('Data', CHAR),

63 )

64

65 class 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

87 class 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

140 class LPSTR(NDRPOINTER):

141 referent = (

142 ('Data', STR),

143 )

144

145 class 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

190 class LPWSTR(NDRPOINTER):

191 referent = (

192 ('Data', WSTR),

193 )

194

195# 2.2.5 BSTR

196 BSTR = LPWSTR

197

198# 2.2.8 DOUBLE

199 DOUBLE = NDRDOUBLEFLOAT

200 class PDOUBLE(NDRPOINTER):

201 referent = (

202 ('Data', DOUBLE),

203 )

204

205# 2.2.15 FLOAT

206 FLOAT = NDRFLOAT

207 class PFLOAT(NDRPOINTER):

208 referent = (

209 ('Data', FLOAT),

210 )

211

212# 2.2.18 HRESULT

213 HRESULT = NDRLONG

214 class PHRESULT(NDRPOINTER):

215 referent = (

216 ('Data', HRESULT),

217 )

218

219# 2.2.19 INT

220 INT = NDRLONG

221 class PINT(NDRPOINTER):

222 referent = (

223 ('Data', INT),

224 )

225

226# 2.2.26 LMSTR

227 LMSTR = LPWSTR

228

229# 2.2.27 LONG

230 LONG = NDRLONG

231 class LPLONG(NDRPOINTER):

232 referent = (

233 ('Data', LONG),

234 )

235

236 PLONG = LPLONG

237

238# 2.2.28 LONGLONG

239 LONGLONG = NDRHYPER

240

241 class PLONGLONG(NDRPOINTER):

242 referent = (

243 ('Data', LONGLONG),

244 )

245

246# 2.2.31 LONG64

247 LONG64 = NDRUHYPER

248 class PLONG64(NDRPOINTER):

249 referent = (

250 ('Data', LONG64),

251 )

252

253# 2.2.32 LPCSTR

254 LPCSTR = LPSTR

255

256# 2.2.36 NET_API_STATUS

257 NET_API_STATUS = DWORD

258

259# 2.2.52 ULONG_PTR

260 ULONG_PTR = NDRULONG

261# 2.2.10 DWORD_PTR

262 DWORD_PTR = ULONG_PTR

263

264# 2.3.2 GUID and UUID

265 class GUID(NDRSTRUCT):

266 structure = (

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

268 )

269

270 def getAlignment(self):

271 return 4

272

273 class PGUID(NDRPOINTER):

274 referent = (

275 ('Data', GUID),

276 )

277

278 UUID = GUID

279 PUUID = PGUID

280

281# 2.2.37 NTSTATUS

282 NTSTATUS = DWORD

283

284# 2.2.45 UINT

285 UINT = NDRULONG

286 class PUINT(NDRPOINTER):

287 referent = (

288 ('Data', UINT),

289 )

290

291# 2.2.50 ULONG

292 ULONG = NDRULONG

293 class PULONG(NDRPOINTER):

294 referent = (

295 ('Data', ULONG),

296 )

297

298 LPULONG = PULONG

299

300# 2.2.54 ULONGLONG

301 ULONGLONG = NDRUHYPER

302 class PULONGLONG(NDRPOINTER):

303 referent = (

304 ('Data', ULONGLONG),

305 )

306

307# 2.2.57 USHORT

308 USHORT = NDRUSHORT

309 class PUSHORT(NDRPOINTER):

310 referent = (

311 ('Data', USHORT),

312 )

313

314# 2.2.59 WCHAR

315 WCHAR = WSTR

316 PWCHAR = LPWSTR

317

318# 2.2.61 WORD

319 WORD = NDRUSHORT

320 class PWORD(NDRPOINTER):

321 referent = (

322 ('Data', WORD),

323 )

324 LPWORD = PWORD

325

326# 2.3.1 FILETIME

327 class FILETIME(NDRSTRUCT):

328 structure = (

329 ('dwLowDateTime', DWORD),

330 ('dwHighDateTime', LONG),

331 )

332

333 class PFILETIME(NDRPOINTER):

334 referent = (

335 ('Data', FILETIME),

336 )

337

338# 2.3.3 LARGE_INTEGER

339 LARGE_INTEGER = NDRHYPER

340 class PLARGE_INTEGER(NDRPOINTER):

341 referent = (

342 ('Data', LARGE_INTEGER),

343 )

344

345# 2.3.5 LUID

346 class LUID(NDRSTRUCT):

347 structure = (

348 ('LowPart', DWORD),

349 ('HighPart', LONG),

350 )

351

352# 2.3.8 RPC_UNICODE_STRING

353 class 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

398 class PRPC_UNICODE_STRING(NDRPOINTER):

399 referent = (

400 ('Data', RPC_UNICODE_STRING ),

401 )

402

403# 2.3.9 OBJECT_TYPE_LIST

404 ACCESS_MASK = DWORD

405 class OBJECT_TYPE_LIST(NDRSTRUCT):

406 structure = (

407 ('Level', WORD),

408 ('Remaining',ACCESS_MASK),

409 ('ObjectType',PGUID),

410 )

411

412 class POBJECT_TYPE_LIST(NDRPOINTER):

413 referent = (

414 ('Data', OBJECT_TYPE_LIST ),

415 )

416

417# 2.3.13 SYSTEMTIME

418 class 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

430 class PSYSTEMTIME(NDRPOINTER):

431 referent = (

432 ('Data', SYSTEMTIME ),

433 )

434

435# 2.3.15 ULARGE_INTEGER

436 class ULARGE_INTEGER(NDRSTRUCT):

437 structure = (

438 ('QuadPart', LONG64),

439 )

440

441 class PULARGE_INTEGER(NDRPOINTER):

442 referent = (

443 ('Data', ULARGE_INTEGER),

444 )

445

446# 2.4.2.3 RPC_SID

447 class DWORD_ARRAY(NDRUniConformantArray):

448 item = '<L'

449

450 class RPC_SID_IDENTIFIER_AUTHORITY(NDRUniFixedArray):

451 align = 1

452 align64 = 1

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

454 return 6

455

456 class 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

481 class PRPC_SID(NDRPOINTER):

482 referent = (

483 ('Data', RPC_SID),

484 )

485

486 PSID = PRPC_SID

487

488# 2.4.3 ACCESS_MASK

489 GENERIC_READ = 0x80000000

490 GENERIC_WRITE = 0x40000000

491 GENERIC_EXECUTE = 0x20000000

492 GENERIC_ALL = 0x10000000

493 MAXIMUM_ALLOWED = 0x02000000

494 ACCESS_SYSTEM_SECURITY = 0x01000000

495 SYNCHRONIZE = 0x00100000

496 WRITE_OWNER = 0x00080000

497 WRITE_DACL = 0x00040000

498 READ_CONTROL = 0x00020000

499 DELETE = 0x00010000

500

501# 2.4.5.1 ACL--RPC Representation

502 class ACL(NDRSTRUCT):

503 structure = (

504 ('AclRevision',NDRSMALL),

505 ('Sbz1',NDRSMALL),

506 ('AclSize',NDRSHORT),

507 ('AceCount',NDRSHORT),

508 ('Sbz2',NDRSHORT),

509 )

510

511 class PACL(NDRPOINTER):

512 referent = (

513 ('Data', ACL),

514 )

515

516# 2.4.6.1 SECURITY_DESCRIPTOR--RPC Representation

517 class 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

529 OWNER_SECURITY_INFORMATION = 0x00000001

530 GROUP_SECURITY_INFORMATION = 0x00000002

531 DACL_SECURITY_INFORMATION = 0x00000004

532 SACL_SECURITY_INFORMATION = 0x00000008

533 LABEL_SECURITY_INFORMATION = 0x00000010

534 UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000

535 UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000

536 PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000

537 PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000

538 ATTRIBUTE_SECURITY_INFORMATION = 0x00000020

539 SCOPE_SECURITY_INFORMATION = 0x00000040

540 BACKUP_SECURITY_INFORMATION = 0x00010000

541

542 SECURITY_INFORMATION = DWORD

543 class PSECURITY_INFORMATION(NDRPOINTER):

544 referent = (

545 ('Data', SECURITY_INFORMATION),

546 )