# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. # # This software is provided under under a slightly modified version # of the Apache Software License. See the accompanying LICENSE file # for more information. # # Author: Alberto Solino (@agsolino) # # Description: # [MS-DRSR] Directory Replication Service (DRS) DRSUAPI Interface implementation # # Best way to learn how to use these calls is to grab the protocol standard # so you understand what the call does, and then read the test case located # at https://github.com/SecureAuthCorp/impacket/tree/master/tests/SMB_RPC # # Some calls have helper functions, which makes it even easier to use. # They are located at the end of this file. # Helper functions start with "h". # There are test cases for them too. # from __future__ import division from __future__ import print_function from builtins import bytes import hashlib from struct import pack import six from six import PY2 from impacket import LOG from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray, NDRUNION, NDR, NDRENUM from impacket.dcerpc.v5.dtypes import PUUID, DWORD, NULL, GUID, LPWSTR, BOOL, ULONG, UUID, LONGLONG, ULARGE_INTEGER, LARGE_INTEGER from impacket import hresult_errors, system_errors from impacket.structure import Structure from impacket.uuid import uuidtup_to_bin, string_to_bin from impacket.dcerpc.v5.enum import Enum from impacket.dcerpc.v5.rpcrt import DCERPCException from impacket.krb5 import crypto from pyasn1.type import univ from pyasn1.codec.ber import decoder from impacket.crypto import transformKey try: from Cryptodome.Cipher import ARC4, DES except Exception: LOG.critical("Warning: You don't have any crypto installed. You need pycryptodomex") LOG.critical("See https://pypi.org/project/pycryptodomex/") MSRPC_UUID_DRSUAPI = uuidtup_to_bin(('E3514235-4B06-11D1-AB04-00C04FC2DCD2','4.0')) class DCERPCSessionError(DCERPCException): def __init__(self, error_string=None, error_code=None, packet=None): DCERPCException.__init__(self, error_string, error_code, packet) def __str__( self ): key = self.error_code if key in hresult_errors.ERROR_MESSAGES: error_msg_short = hresult_errors.ERROR_MESSAGES[key][0] error_msg_verbose = hresult_errors.ERROR_MESSAGES[key][1] return 'DRSR SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) elif key & 0xffff in system_errors.ERROR_MESSAGES: error_msg_short = system_errors.ERROR_MESSAGES[key & 0xffff][0] error_msg_verbose = system_errors.ERROR_MESSAGES[key & 0xffff][1] return 'DRSR SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) else: return 'DRSR SessionError: unknown error code: 0x%x' % self.error_code ################################################################################ # CONSTANTS ################################################################################ # 4.1.10.2.17 EXOP_ERR Codes class EXOP_ERR(NDRENUM): align = 4 align64 = 4 structure = ( ('Data', '= 16384: # mark it so that it is known to not be the whole lastValue lowerWord += 32768 upperWord = pos attrTyp = ATTRTYP() attrTyp['Data'] = (upperWord << 16) + lowerWord return attrTyp def OidFromAttid(prefixTable, attr): # separate the ATTRTYP into two parts upperWord = attr // 65536 lowerWord = attr % 65536 # search in the prefix table to find the upperWord, if found, # construct the binary OID by appending lowerWord to the end of # found prefix. binaryOID = None for j, item in enumerate(prefixTable): if item['ndx'] == upperWord: binaryOID = item['prefix']['elements'][:item['prefix']['length']] if lowerWord < 128: binaryOID.append(pack('B',lowerWord)) else: if lowerWord >= 32768: lowerWord -= 32768 binaryOID.append(pack('B',(((lowerWord//128) % 128)+128))) binaryOID.append(pack('B',(lowerWord%128))) break if binaryOID is None: return None return str(decoder.decode(b'\x06' + pack('B',(len(binaryOID))) + b''.join(binaryOID), asn1Spec = univ.ObjectIdentifier())[0]) if __name__ == '__main__': prefixTable = [] oid0 = '1.2.840.113556.1.4.94' oid1 = '2.5.6.2' oid2 = '1.2.840.113556.1.2.1' oid3 = '1.2.840.113556.1.3.223' oid4 = '1.2.840.113556.1.5.7000.53' o0 = MakeAttid(prefixTable, oid0) print(hex(o0)) o1 = MakeAttid(prefixTable, oid1) print(hex(o1)) o2 = MakeAttid(prefixTable, oid2) print(hex(o2)) o3 = MakeAttid(prefixTable, oid3) print(hex(o3)) o4 = MakeAttid(prefixTable, oid4) print(hex(o4)) jj = OidFromAttid(prefixTable, o0) print(jj) jj = OidFromAttid(prefixTable, o1) print(jj) jj = OidFromAttid(prefixTable, o2) print(jj) jj = OidFromAttid(prefixTable, o3) print(jj) jj = OidFromAttid(prefixTable, o4) print(jj)