1# Copyright (c) 2003-2016 CORE Security Technologies 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-VDS]: Virtual Disk Service (VDS) Protocol 11# This was used as a way to test the DCOM runtime. Further 12# testing is needed to verify it is working as expected 13# 14# Best way to learn how to use these calls is to grab the protocol standard 15# so you understand what the call does, and then read the test case located 16# at https://github.com/CoreSecurity/impacket/tree/master/impacket/testcases/SMB_RPC 17# 18# Since DCOM is like an OO RPC, instead of helper functions you will see the 19# classes described in the standards developed. 20# There are test cases for them too. 21# 22from impacket.dcerpc.v5.ndr import NDRSTRUCT, NDRUniConformantVaryingArray, NDRENUM 23from impacket.dcerpc.v5.dcomrt import DCOMCALL, DCOMANSWER, IRemUnknown2, PMInterfacePointer, INTERFACE 24from impacket.dcerpc.v5.dtypes import LPWSTR, ULONG, DWORD, SHORT, GUID 25from impacket.dcerpc.v5.rpcrt import DCERPCException 26from impacket.dcerpc.v5.enum import Enum 27from impacket import hresult_errors 28from impacket.uuid import string_to_bin 29 30class DCERPCSessionError(DCERPCException): 31 def __init__(self, error_string=None, error_code=None, packet=None): 32 DCERPCException.__init__(self, error_string, error_code, packet) 33 34 def __str__( self ): 35 if hresult_errors.ERROR_MESSAGES.has_key(self.error_code): 36 error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0] 37 error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1] 38 return 'VDS SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) 39 else: 40 return 'VDS SessionError: unknown error code: 0x%x' % (self.error_code) 41 42################################################################################ 43# CONSTANTS 44################################################################################ 45# 1.9 Standards Assignments 46CLSID_VirtualDiskService = string_to_bin('7D1933CB-86F6-4A98-8628-01BE94C9A575') 47IID_IEnumVdsObject = string_to_bin('118610B7-8D94-4030-B5B8-500889788E4E') 48IID_IVdsAdviseSink = string_to_bin('8326CD1D-CF59-4936-B786-5EFC08798E25') 49IID_IVdsAsync = string_to_bin('D5D23B6D-5A55-4492-9889-397A3C2D2DBC') 50IID_IVdsServiceInitialization = string_to_bin('4AFC3636-DB01-4052-80C3-03BBCB8D3C69') 51IID_IVdsService = string_to_bin('0818A8EF-9BA9-40D8-A6F9-E22833CC771E') 52IID_IVdsSwProvider = string_to_bin('9AA58360-CE33-4F92-B658-ED24B14425B8') 53IID_IVdsProvider = string_to_bin('10C5E575-7984-4E81-A56B-431F5F92AE42') 54 55error_status_t = ULONG 56 57# 2.2.1.1.3 VDS_OBJECT_ID 58VDS_OBJECT_ID = GUID 59 60################################################################################ 61# STRUCTURES 62################################################################################ 63# 2.2.2.1.3.1 VDS_SERVICE_PROP 64class VDS_SERVICE_PROP(NDRSTRUCT): 65 structure = ( 66 ('pwszVersion',LPWSTR), 67 ('ulFlags',ULONG), 68 ) 69 70class OBJECT_ARRAY(NDRUniConformantVaryingArray): 71 item = PMInterfacePointer 72 73# 2.2.2.7.1.1 VDS_PROVIDER_TYPE 74class VDS_PROVIDER_TYPE(NDRENUM): 75 class enumItems(Enum): 76 VDS_PT_UNKNOWN = 0 77 VDS_PT_SOFTWARE = 1 78 VDS_PT_HARDWARE = 2 79 VDS_PT_VIRTUALDISK = 3 80 VDS_PT_MAX = 4 81 82# 2.2.2.7.2.1 VDS_PROVIDER_PROP 83class VDS_PROVIDER_PROP(NDRSTRUCT): 84 structure = ( 85 ('id',VDS_OBJECT_ID), 86 ('pwszName',LPWSTR), 87 ('guidVersionId',GUID), 88 ('pwszVersion',LPWSTR), 89 ('type',VDS_PROVIDER_TYPE), 90 ('ulFlags',ULONG), 91 ('ulStripeSizeFlags',ULONG), 92 ('sRebuildPriority',SHORT), 93 ) 94 95################################################################################ 96# RPC CALLS 97################################################################################ 98 99# 3.4.5.2.5.1 IVdsServiceInitialization::Initialize (Opnum 3) 100class IVdsServiceInitialization_Initialize(DCOMCALL): 101 opnum = 3 102 structure = ( 103 ('pwszMachineName', LPWSTR), 104 ) 105 106class IVdsServiceInitialization_InitializeResponse(DCOMANSWER): 107 structure = ( 108 ('ErrorCode', error_status_t), 109 ) 110 111# 3.4.5.2.4.1 IVdsService::IsServiceReady (Opnum 3) 112class IVdsService_IsServiceReady(DCOMCALL): 113 opnum = 3 114 structure = ( 115 ) 116 117class IVdsService_IsServiceReadyResponse(DCOMANSWER): 118 structure = ( 119 ('ErrorCode', error_status_t), 120 ) 121 122# 3.4.5.2.4.2 IVdsService::WaitForServiceReady (Opnum 4) 123class IVdsService_WaitForServiceReady(DCOMCALL): 124 opnum = 4 125 structure = ( 126 ) 127 128class IVdsService_WaitForServiceReadyResponse(DCOMANSWER): 129 structure = ( 130 ('ErrorCode', error_status_t), 131 ) 132 133# 3.4.5.2.4.3 IVdsService::GetProperties (Opnum 5) 134class IVdsService_GetProperties(DCOMCALL): 135 opnum = 5 136 structure = ( 137 ) 138 139class IVdsService_GetPropertiesResponse(DCOMANSWER): 140 structure = ( 141 ('pServiceProp', VDS_SERVICE_PROP), 142 ('ErrorCode', error_status_t), 143 ) 144 145# 3.4.5.2.4.4 IVdsService::QueryProviders (Opnum 6) 146class IVdsService_QueryProviders(DCOMCALL): 147 opnum = 6 148 structure = ( 149 ('masks', DWORD), 150 ) 151 152class IVdsService_QueryProvidersResponse(DCOMANSWER): 153 structure = ( 154 ('ppEnum', PMInterfacePointer), 155 ('ErrorCode', error_status_t), 156 ) 157 158# 3.1.1.1 IEnumVdsObject Interface 159# 3.4.5.2.1.1 IEnumVdsObject::Next (Opnum 3) 160class IEnumVdsObject_Next(DCOMCALL): 161 opnum = 3 162 structure = ( 163 ('celt', ULONG), 164 ) 165 166class IEnumVdsObject_NextResponse(DCOMANSWER): 167 structure = ( 168 ('ppObjectArray', OBJECT_ARRAY), 169 ('pcFetched', ULONG), 170 ('ErrorCode', error_status_t), 171 ) 172# 3.4.5.2.14.1 IVdsProvider::GetProperties (Opnum 3) 173class IVdsProvider_GetProperties(DCOMCALL): 174 opnum = 3 175 structure = ( 176 ) 177 178class IVdsProvider_GetPropertiesResponse(DCOMANSWER): 179 structure = ( 180 ('pProviderProp', VDS_PROVIDER_PROP), 181 ('ErrorCode', error_status_t), 182 ) 183 184################################################################################ 185# OPNUMs and their corresponding structures 186################################################################################ 187OPNUMS = { 188} 189 190################################################################################ 191# HELPER FUNCTIONS AND INTERFACES 192################################################################################ 193class IEnumVdsObject(IRemUnknown2): 194 def Next(self, celt=0xffff): 195 request = IEnumVdsObject_Next() 196 request['ORPCthis'] = self.get_cinstance().get_ORPCthis() 197 request['ORPCthis']['flags'] = 0 198 request['celt'] = celt 199 try: 200 resp = self.request(request, uuid = self.get_iPid()) 201 except Exception, e: 202 resp = e.get_packet() 203 # If it is S_FALSE(1) means less items were returned 204 if resp['ErrorCode'] != 1: 205 raise 206 interfaces = list() 207 for interface in resp['ppObjectArray']: 208 interfaces.append(IRemUnknown2(INTERFACE(self.get_cinstance(), ''.join(interface['abData']), self.get_ipidRemUnknown(), target = self.get_target()))) 209 return interfaces 210 211class IVdsProvider(IRemUnknown2): 212 def GetProperties(self): 213 request = IVdsProvider_GetProperties() 214 request['ORPCthis'] = self.get_cinstance().get_ORPCthis() 215 request['ORPCthis']['flags'] = 0 216 resp = self.request(request, uuid = self.get_iPid()) 217 return resp 218 219class IVdsServiceInitialization(IRemUnknown2): 220 def __init__(self, interface): 221 IRemUnknown2.__init__(self, interface) 222 223 def Initialize(self): 224 request = IVdsServiceInitialization_Initialize() 225 request['ORPCthis'] = self.get_cinstance().get_ORPCthis() 226 request['ORPCthis']['flags'] = 0 227 request['pwszMachineName'] = '\x00' 228 resp = self.request(request, uuid = self.get_iPid()) 229 return resp 230 231class IVdsService(IRemUnknown2): 232 def __init__(self, interface): 233 IRemUnknown2.__init__(self, interface) 234 235 def IsServiceReady(self): 236 request = IVdsService_IsServiceReady() 237 request['ORPCthis'] = self.get_cinstance().get_ORPCthis() 238 request['ORPCthis']['flags'] = 0 239 try: 240 resp = self.request(request, uuid = self.get_iPid()) 241 except Exception, e: 242 resp = e.get_packet() 243 return resp 244 245 def WaitForServiceReady(self): 246 request = IVdsService_WaitForServiceReady() 247 request['ORPCthis'] = self.get_cinstance().get_ORPCthis() 248 request['ORPCthis']['flags'] = 0 249 resp = self.request(request, uuid = self.get_iPid()) 250 return resp 251 252 def GetProperties(self): 253 request = IVdsService_GetProperties() 254 request['ORPCthis'] = self.get_cinstance().get_ORPCthis() 255 request['ORPCthis']['flags'] = 0 256 resp = self.request(request, uuid = self.get_iPid()) 257 return resp 258 259 def QueryProviders(self, masks): 260 request = IVdsService_QueryProviders() 261 request['ORPCthis'] = self.get_cinstance().get_ORPCthis() 262 request['ORPCthis']['flags'] = 0 263 request['masks'] = masks 264 resp = self.request(request, uuid = self.get_iPid()) 265 return IEnumVdsObject(INTERFACE(self.get_cinstance(), ''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) 266 267 268 269 270