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# 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#

9# Description:

10# [MS-DTYP] Interface mini implementation

11#

12 from __future__ import division

13 from __future__ import print_function

14 from struct import pack

15 from six import binary_type

16

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

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

19 NDRUSMALL, NDRBOOLEAN, NDRUSHORT, NDRFLOAT, NDRDOUBLEFLOAT, NULL

20

21 DWORD = NDRULONG

22 BOOL = NDRULONG

23 UCHAR = NDRUSMALL

24 SHORT = NDRSHORT

25 NULL = NULL

26

27 class LPDWORD(NDRPOINTER):

28 referent = (

29 ('Data', DWORD),

30 )

31

32 class PSHORT(NDRPOINTER):

33 referent = (

34 ('Data', SHORT),

35 )

36

37 class PBOOL(NDRPOINTER):

38 referent = (

39 ('Data', BOOL),

40 )

41

42 class LPBYTE(NDRPOINTER):

43 referent = (

44 ('Data', NDRUniConformantArray),

45 )

46 PBYTE = LPBYTE

47

48# 2.2.4 BOOLEAN

49 BOOLEAN = NDRBOOLEAN

50

51# 2.2.6 BYTE

52 BYTE = NDRUSMALL

53

54# 2.2.7 CHAR

55 CHAR = NDRSMALL

56 class PCHAR(NDRPOINTER):

57 referent = (

58 ('Data', CHAR),

59 )

60

61 class WIDESTR(NDRUniFixedArray):

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

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

64

65 def __setitem__(self, key, value):

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

67 try:

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

69 except UnicodeDecodeError:

70 import sys

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

72

73 self.data = None # force recompute

74 else:

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

76

77 def __getitem__(self, key):

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

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

80 else:

81 return NDR.__getitem__(self,key)

82

83 class STR(NDRSTRUCT):

84 commonHdr = (

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

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

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

88 )

89 commonHdr64 = (

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

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

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

93 )

94 structure = (

95 ('Data',':'),

96 )

97

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

99 if msg is None:

100 msg = self.__class__.__name__

101 if msg != '':

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

103 # Here just print the data

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

105

106 def __setitem__(self, key, value):

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

108 try:

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

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

111 else:

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

113 self.fields[key] = value

114 except UnicodeDecodeError:

115 import sys

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

117 self.fields['MaximumCount'] = None

118 self.fields['ActualCount'] = None

119 self.data = None # force recompute

120 else:

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

122

123 def __getitem__(self, key):

124 if key == 'Data':

125 try:

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

127 except UnicodeDecodeError:

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

129 return self.fields[key]

130 else:

131 return NDR.__getitem__(self,key)

132

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

134 return self["ActualCount"]

135

136 class LPSTR(NDRPOINTER):

137 referent = (

138 ('Data', STR),

139 )

140

141 class WSTR(NDRSTRUCT):

142 commonHdr = (

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

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

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

146 )

147 commonHdr64 = (

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

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

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

151 )

152 structure = (

153 ('Data',':'),

154 )

155

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

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

158 msg = self.__class__.__name__

159 if msg != '':

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

161 # Here just print the data

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

163

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

165 return self["ActualCount"]*2

166

167 def __setitem__(self, key, value):

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

169 try:

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

171 except UnicodeDecodeError:

172 import sys

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

174 self.fields['MaximumCount'] = None

175 self.fields['ActualCount'] = None

176 self.data = None # force recompute

177 else:

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

179

180 def __getitem__(self, key):

181 if key == 'Data':

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

183 else:

184 return NDR.__getitem__(self,key)

185

186 class LPWSTR(NDRPOINTER):

187 referent = (

188 ('Data', WSTR),

189 )

190

191# 2.2.5 BSTR

192 BSTR = LPWSTR

193

194# 2.2.8 DOUBLE

195 DOUBLE = NDRDOUBLEFLOAT

196 class PDOUBLE(NDRPOINTER):

197 referent = (

198 ('Data', DOUBLE),

199 )

200

201# 2.2.15 FLOAT

202 FLOAT = NDRFLOAT

203 class PFLOAT(NDRPOINTER):

204 referent = (

205 ('Data', FLOAT),

206 )

207

208# 2.2.18 HRESULT

209 HRESULT = NDRLONG

210 class PHRESULT(NDRPOINTER):

211 referent = (

212 ('Data', HRESULT),

213 )

214

215# 2.2.19 INT

216 INT = NDRLONG

217 class PINT(NDRPOINTER):

218 referent = (

219 ('Data', INT),

220 )

221

222# 2.2.26 LMSTR

223 LMSTR = LPWSTR

224

225# 2.2.27 LONG

226 LONG = NDRLONG

227 class LPLONG(NDRPOINTER):

228 referent = (

229 ('Data', LONG),

230 )

231

232 PLONG = LPLONG

233

234# 2.2.28 LONGLONG

235 LONGLONG = NDRHYPER

236

237 class PLONGLONG(NDRPOINTER):

238 referent = (

239 ('Data', LONGLONG),

240 )

241

242# 2.2.31 LONG64

243 LONG64 = NDRUHYPER

244 class PLONG64(NDRPOINTER):

245 referent = (

246 ('Data', LONG64),

247 )

248

249# 2.2.32 LPCSTR

250 LPCSTR = LPSTR

251

252# 2.2.36 NET_API_STATUS

253 NET_API_STATUS = DWORD

254

255# 2.2.52 ULONG_PTR

256 ULONG_PTR = NDRULONG

257# 2.2.10 DWORD_PTR

258 DWORD_PTR = ULONG_PTR

259

260# 2.3.2 GUID and UUID

261 class GUID(NDRSTRUCT):

262 structure = (

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

264 )

265

266 def getAlignment(self):

267 return 4

268

269 class PGUID(NDRPOINTER):

270 referent = (

271 ('Data', GUID),

272 )

273

274 UUID = GUID

275 PUUID = PGUID

276

277# 2.2.37 NTSTATUS

278 NTSTATUS = DWORD

279

280# 2.2.45 UINT

281 UINT = NDRULONG

282 class PUINT(NDRPOINTER):

283 referent = (

284 ('Data', UINT),

285 )

286

287# 2.2.50 ULONG

288 ULONG = NDRULONG

289 class PULONG(NDRPOINTER):

290 referent = (

291 ('Data', ULONG),

292 )

293

294 LPULONG = PULONG

295

296# 2.2.54 ULONGLONG

297 ULONGLONG = NDRUHYPER

298 class PULONGLONG(NDRPOINTER):

299 referent = (

300 ('Data', ULONGLONG),

301 )

302

303# 2.2.57 USHORT

304 USHORT = NDRUSHORT

305 class PUSHORT(NDRPOINTER):

306 referent = (

307 ('Data', USHORT),

308 )

309

310# 2.2.59 WCHAR

311 WCHAR = WSTR

312 PWCHAR = LPWSTR

313

314# 2.2.61 WORD

315 WORD = NDRUSHORT

316 class PWORD(NDRPOINTER):

317 referent = (

318 ('Data', WORD),

319 )

320 LPWORD = PWORD

321

322# 2.3.1 FILETIME

323 class FILETIME(NDRSTRUCT):

324 structure = (

325 ('dwLowDateTime', DWORD),

326 ('dwHighDateTime', LONG),

327 )

328

329 class PFILETIME(NDRPOINTER):

330 referent = (

331 ('Data', FILETIME),

332 )

333

334# 2.3.3 LARGE_INTEGER

335 LARGE_INTEGER = NDRHYPER

336 class PLARGE_INTEGER(NDRPOINTER):

337 referent = (

338 ('Data', LARGE_INTEGER),

339 )

340

341# 2.3.5 LUID

342 class LUID(NDRSTRUCT):

343 structure = (

344 ('LowPart', DWORD),

345 ('HighPart', LONG),

346 )

347

348# 2.3.8 RPC_UNICODE_STRING

349 class RPC_UNICODE_STRING(NDRSTRUCT):

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

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

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

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

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

355 # MaximumLength fields.

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

357 # class TT(NDRCALL):

358 # structure = (

359 # ('str1', RPC_UNICODE_STRING),

360 # )

361 #

362 # nn = TT()

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

364 structure = (

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

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

367 ('Data',LPWSTR),

368 )

369

370 def __setitem__(self, key, value):

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

372 try:

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

374 except UnicodeDecodeError:

375 import sys

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

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

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

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

380

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

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

383 msg = self.__class__.__name__

384 if msg != '':

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

386

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

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

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

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

391 else:

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

393

394 class PRPC_UNICODE_STRING(NDRPOINTER):

395 referent = (

396 ('Data', RPC_UNICODE_STRING ),

397 )

398

399# 2.3.9 OBJECT_TYPE_LIST

400 ACCESS_MASK = DWORD

401 class OBJECT_TYPE_LIST(NDRSTRUCT):

402 structure = (

403 ('Level', WORD),

404 ('Remaining',ACCESS_MASK),

405 ('ObjectType',PGUID),

406 )

407

408 class POBJECT_TYPE_LIST(NDRPOINTER):

409 referent = (

410 ('Data', OBJECT_TYPE_LIST ),

411 )

412

413# 2.3.13 SYSTEMTIME

414 class SYSTEMTIME(NDRSTRUCT):

415 structure = (

416 ('wYear', WORD),

417 ('wMonth', WORD),

418 ('wDayOfWeek', WORD),

419 ('wDay', WORD),

420 ('wHour', WORD),

421 ('wMinute', WORD),

422 ('wSecond', WORD),

423 ('wMilliseconds', WORD),

424 )

425

426 class PSYSTEMTIME(NDRPOINTER):

427 referent = (

428 ('Data', SYSTEMTIME ),

429 )

430

431# 2.3.15 ULARGE_INTEGER

432 class ULARGE_INTEGER(NDRSTRUCT):

433 structure = (

434 ('QuadPart', LONG64),

435 )

436

437 class PULARGE_INTEGER(NDRPOINTER):

438 referent = (

439 ('Data', ULARGE_INTEGER),

440 )

441

442# 2.4.2.3 RPC_SID

443 class DWORD_ARRAY(NDRUniConformantArray):

444 item = '<L'

445

446 class RPC_SID_IDENTIFIER_AUTHORITY(NDRUniFixedArray):

447 align = 1

448 align64 = 1

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

450 return 6

451

452 class RPC_SID(NDRSTRUCT):

453 structure = (

454 ('Revision',NDRSMALL),

455 ('SubAuthorityCount',NDRSMALL),

456 ('IdentifierAuthority',RPC_SID_IDENTIFIER_AUTHORITY),

457 ('SubAuthority',DWORD_ARRAY),

458 )

459 def getData(self, soFar = 0):

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

461 return NDRSTRUCT.getData(self, soFar)

462

463 def fromCanonical(self, canonical):

464 items = canonical.split('-')

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

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

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

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

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

470

471 def formatCanonical(self):

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

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

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

475 return ans

476

477 class PRPC_SID(NDRPOINTER):

478 referent = (

479 ('Data', RPC_SID),

480 )

481

482 PSID = PRPC_SID

483

484# 2.4.3 ACCESS_MASK

485 GENERIC_READ = 0x80000000

486 GENERIC_WRITE = 0x40000000

487 GENERIC_EXECUTE = 0x20000000

488 GENERIC_ALL = 0x10000000

489 MAXIMUM_ALLOWED = 0x02000000

490 ACCESS_SYSTEM_SECURITY = 0x01000000

491 SYNCHRONIZE = 0x00100000

492 WRITE_OWNER = 0x00080000

493 WRITE_DACL = 0x00040000

494 READ_CONTROL = 0x00020000

495 DELETE = 0x00010000

496

497# 2.4.5.1 ACL--RPC Representation

498 class ACL(NDRSTRUCT):

499 structure = (

500 ('AclRevision',NDRSMALL),

501 ('Sbz1',NDRSMALL),

502 ('AclSize',NDRSHORT),

503 ('AceCount',NDRSHORT),

504 ('Sbz2',NDRSHORT),

505 )

506

507 class PACL(NDRPOINTER):

508 referent = (

509 ('Data', ACL),

510 )

511

512# 2.4.6.1 SECURITY_DESCRIPTOR--RPC Representation

513 class SECURITY_DESCRIPTOR(NDRSTRUCT):

514 structure = (

515 ('Revision',UCHAR),

516 ('Sbz1',UCHAR),

517 ('Control',USHORT),

518 ('Owner',PSID),

519 ('Group',PSID),

520 ('Sacl',PACL),

521 ('Dacl',PACL),

522 )

523

524# 2.4.7 SECURITY_INFORMATION

525 OWNER_SECURITY_INFORMATION = 0x00000001

526 GROUP_SECURITY_INFORMATION = 0x00000002

527 DACL_SECURITY_INFORMATION = 0x00000004

528 SACL_SECURITY_INFORMATION = 0x00000008

529 LABEL_SECURITY_INFORMATION = 0x00000010

530 UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000

531 UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000

532 PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000

533 PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000

534 ATTRIBUTE_SECURITY_INFORMATION = 0x00000020

535 SCOPE_SECURITY_INFORMATION = 0x00000040

536 BACKUP_SECURITY_INFORMATION = 0x00010000

537

538 SECURITY_INFORMATION = DWORD

539 class PSECURITY_INFORMATION(NDRPOINTER):

540 referent = (

541 ('Data', SECURITY_INFORMATION),

542 )