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) 2018 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-SCMP]: Shadow Copy Management Protocol Interface implementation 

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/SecureAuthCorp/impacket/tree/master/tests/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# 

22# Author: 

23# Alberto Solino (@agsolino) 

24# 

25from __future__ import division 

26from __future__ import print_function 

27from impacket.dcerpc.v5.ndr import NDRENUM, NDRSTRUCT, NDRUNION 

28from impacket.dcerpc.v5.dcomrt import PMInterfacePointer, INTERFACE, DCOMCALL, DCOMANSWER, IRemUnknown2 

29from impacket.dcerpc.v5.dtypes import LONG, LONGLONG, ULONG, WSTR 

30from impacket.dcerpc.v5.enum import Enum 

31from impacket.dcerpc.v5.rpcrt import DCERPCException 

32from impacket import hresult_errors 

33from impacket.uuid import string_to_bin 

34 

35class DCERPCSessionError(DCERPCException): 

36 def __init__(self, error_string=None, error_code=None, packet=None): 

37 DCERPCException.__init__(self, error_string, error_code, packet) 

38 

39 def __str__( self ): 

40 if self.error_code in hresult_errors.ERROR_MESSAGES: 

41 error_msg_short = hresult_errors.ERROR_MESSAGES[self.error_code][0] 

42 error_msg_verbose = hresult_errors.ERROR_MESSAGES[self.error_code][1] 

43 return 'SCMP SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) 

44 else: 

45 return 'SCMP SessionError: unknown error code: 0x%x' % self.error_code 

46 

47################################################################################ 

48# CONSTANTS 

49################################################################################ 

50# 1.9 Standards Assignments 

51CLSID_ShadowCopyProvider = string_to_bin('0b5a2c52-3eb9-470a-96e2-6c6d4570e40f') 

52IID_IVssSnapshotMgmt = string_to_bin('FA7DF749-66E7-4986-A27F-E2F04AE53772') 

53IID_IVssEnumObject = string_to_bin('AE1C7110-2F60-11d3-8A39-00C04F72D8E3') 

54IID_IVssDifferentialSoftwareSnapshotMgmt = string_to_bin('214A0F28-B737-4026-B847-4F9E37D79529') 

55IID_IVssEnumMgmtObject = string_to_bin('01954E6B-9254-4e6e-808C-C9E05D007696') 

56IID_ShadowCopyProvider = string_to_bin('B5946137-7B9F-4925-AF80-51ABD60B20D5') 

57 

58# 2.2.1.1 VSS_ID 

59class VSS_ID(NDRSTRUCT): 

60 structure = ( 

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

62 ) 

63 

64 def getAlignment(self): 

65 return 2 

66 

67#2.2.1.2 VSS_PWSZ 

68VSS_PWSZ = WSTR 

69 

70# 2.2.1.3 VSS_TIMESTAMP 

71VSS_TIMESTAMP = LONGLONG 

72 

73error_status_t = LONG 

74################################################################################ 

75# STRUCTURES 

76################################################################################ 

77# 2.2.2.1 VSS_OBJECT_TYPE Enumeration 

78class VSS_OBJECT_TYPE(NDRENUM): 

79 class enumItems(Enum): 

80 VSS_OBJECT_UNKNOWN = 0 

81 VSS_OBJECT_NONE = 1 

82 VSS_OBJECT_SNAPSHOT_SET = 2 

83 VSS_OBJECT_SNAPSHOT = 3 

84 VSS_OBJECT_PROVIDER = 4 

85 VSS_OBJECT_TYPE_COUNT = 5 

86 

87# 2.2.2.2 VSS_MGMT_OBJECT_TYPE Enumeration 

88class VSS_MGMT_OBJECT_TYPE(NDRENUM): 

89 class enumItems(Enum): 

90 VSS_MGMT_OBJECT_UNKNOWN = 0 

91 VSS_MGMT_OBJECT_VOLUME = 1 

92 VSS_MGMT_OBJECT_DIFF_VOLUME = 2 

93 VSS_MGMT_OBJECT_DIFF_AREA = 3 

94 

95# 2.2.2.3 VSS_VOLUME_SNAPSHOT_ATTRIBUTES Enumeration 

96class VSS_VOLUME_SNAPSHOT_ATTRIBUTES(NDRENUM): 

97 class enumItems(Enum): 

98 VSS_VOLSNAP_ATTR_PERSISTENT = 0x01 

99 VSS_VOLSNAP_ATTR_NO_AUTORECOVERY = 0x02 

100 VSS_VOLSNAP_ATTR_CLIENT_ACCESSIBLE = 0x04 

101 VSS_VOLSNAP_ATTR_NO_AUTO_RELEASE = 0x08 

102 VSS_VOLSNAP_ATTR_NO_WRITERS = 0x10 

103 

104# 2.2.2.4 VSS_SNAPSHOT_STATE Enumeration 

105class VSS_SNAPSHOT_STATE(NDRENUM): 

106 class enumItems(Enum): 

107 VSS_SS_UNKNOWN = 0x01 

108 VSS_SS_CREATED = 0x0c 

109 

110# 2.2.2.5 VSS_PROVIDER_TYPE Enumeration 

111class VSS_PROVIDER_TYPE(NDRENUM): 

112 class enumItems(Enum): 

113 VSS_PROV_UNKNOWN = 0 

114 

115# 2.2.3.7 VSS_VOLUME_PROP Structure 

116class VSS_VOLUME_PROP(NDRSTRUCT): 

117 structure = ( 

118 ('m_pwszVolumeName', VSS_PWSZ), 

119 ('m_pwszVolumeDisplayName', VSS_PWSZ), 

120 ) 

121 

122# 2.2.3.5 VSS_MGMT_OBJECT_UNION Union 

123class VSS_MGMT_OBJECT_UNION(NDRUNION): 

124 commonHdr = ( 

125 ('tag', ULONG), 

126 ) 

127 union = { 

128 VSS_MGMT_OBJECT_TYPE.VSS_MGMT_OBJECT_VOLUME: ('Vol', VSS_VOLUME_PROP), 

129 #VSS_MGMT_OBJECT_DIFF_VOLUME: ('DiffVol', VSS_DIFF_VOLUME_PROP), 

130 #VSS_MGMT_OBJECT_DIFF_AREA: ('DiffArea', VSS_DIFF_AREA_PROP), 

131 } 

132 

133# 2.2.3.6 VSS_MGMT_OBJECT_PROP Structure 

134class VSS_MGMT_OBJECT_PROP(NDRSTRUCT): 

135 structure = ( 

136 ('Type', VSS_MGMT_OBJECT_TYPE), 

137 ('Obj', VSS_MGMT_OBJECT_UNION), 

138 ) 

139 

140################################################################################ 

141# RPC CALLS 

142################################################################################ 

143# 3.1.3 IVssEnumMgmtObject Details 

144 

145# 3.1.3.1 Next (Opnum 3) 

146class IVssEnumMgmtObject_Next(DCOMCALL): 

147 opnum = 3 

148 structure = ( 

149 ('celt', ULONG), 

150 ) 

151 

152class IVssEnumMgmtObject_NextResponse(DCOMANSWER): 

153 structure = ( 

154 ('rgelt', VSS_MGMT_OBJECT_PROP), 

155 ('pceltFetched', ULONG), 

156 ('ErrorCode', error_status_t), 

157 ) 

158 

159# 3.1.2.1 Next (Opnum 3) 

160class IVssEnumObject_Next(DCOMCALL): 

161 opnum = 3 

162 structure = ( 

163 ('celt', ULONG), 

164 ) 

165 

166class IVssEnumObject_NextResponse(DCOMANSWER): 

167 structure = ( 

168 ('rgelt', VSS_MGMT_OBJECT_PROP), 

169 ('pceltFetched', ULONG), 

170 ('ErrorCode', error_status_t), 

171 ) 

172 

173class GetProviderMgmtInterface(DCOMCALL): 

174 opnum = 3 

175 structure = ( 

176 ('ProviderId', VSS_ID), 

177 ('InterfaceId', VSS_ID), 

178 ) 

179 

180class GetProviderMgmtInterfaceResponse(DCOMANSWER): 

181 structure = ( 

182 ('ppItf', PMInterfacePointer), 

183 ('ErrorCode', error_status_t), 

184 ) 

185 

186class QueryVolumesSupportedForSnapshots(DCOMCALL): 

187 opnum = 4 

188 structure = ( 

189 ('ProviderId', VSS_ID), 

190 ('IContext', LONG), 

191 ) 

192 

193class QueryVolumesSupportedForSnapshotsResponse(DCOMANSWER): 

194 structure = ( 

195 ('ppEnum', PMInterfacePointer), 

196 ('ErrorCode', error_status_t), 

197 ) 

198 

199class QuerySnapshotsByVolume(DCOMCALL): 

200 opnum = 5 

201 structure = ( 

202 ('pwszVolumeName', VSS_PWSZ), 

203 ('ProviderId', VSS_ID), 

204 ) 

205 

206class QuerySnapshotsByVolumeResponse(DCOMANSWER): 

207 structure = ( 

208 ('ppEnum', PMInterfacePointer), 

209 ('ErrorCode', error_status_t), 

210 ) 

211 

212# 3.1.4.4.5 QueryDiffAreasForVolume (Opnum 6) 

213class QueryDiffAreasForVolume(DCOMCALL): 

214 opnum = 6 

215 structure = ( 

216 ('pwszVolumeName', VSS_PWSZ), 

217 ) 

218 

219class QueryDiffAreasForVolumeResponse(DCOMANSWER): 

220 structure = ( 

221 ('ppEnum', PMInterfacePointer), 

222 ('ErrorCode', error_status_t), 

223 ) 

224 

225# 3.1.4.4.6 QueryDiffAreasOnVolume (Opnum 7) 

226class QueryDiffAreasOnVolume(DCOMCALL): 

227 opnum = 7 

228 structure = ( 

229 ('pwszVolumeName', VSS_PWSZ), 

230 ) 

231 

232class QueryDiffAreasOnVolumeResponse(DCOMANSWER): 

233 structure = ( 

234 ('ppEnum', PMInterfacePointer), 

235 ('ErrorCode', error_status_t), 

236 ) 

237 

238 

239################################################################################ 

240# OPNUMs and their corresponding structures 

241################################################################################ 

242OPNUMS = { 

243} 

244 

245################################################################################ 

246# HELPER FUNCTIONS AND INTERFACES 

247################################################################################ 

248class IVssEnumMgmtObject(IRemUnknown2): 

249 def __init__(self, interface): 

250 IRemUnknown2.__init__(self, interface) 

251 self._iid = IID_IVssEnumMgmtObject 

252 

253 def Next(self, celt): 

254 request = IVssEnumMgmtObject_Next() 

255 request['ORPCthis'] = self.get_cinstance().get_ORPCthis() 

256 request['ORPCthis']['flags'] = 0 

257 request['celt'] = celt 

258 resp = self.request(request, self._iid, uuid = self.get_iPid()) 

259 return resp 

260 

261class IVssEnumObject(IRemUnknown2): 

262 def __init__(self, interface): 

263 IRemUnknown2.__init__(self, interface) 

264 self._iid = IID_IVssEnumObject 

265 

266 def Next(self, celt): 

267 request = IVssEnumObject_Next() 

268 request['ORPCthis'] = self.get_cinstance().get_ORPCthis() 

269 request['ORPCthis']['flags'] = 0 

270 request['celt'] = celt 

271 dce = self.connect() 

272 resp = dce.request(request, self._iid, uuid = self.get_iPid()) 

273 return resp 

274 

275class IVssSnapshotMgmt(IRemUnknown2): 

276 def __init__(self, interface): 

277 IRemUnknown2.__init__(self, interface) 

278 self._iid = IID_IVssSnapshotMgmt 

279 

280 def GetProviderMgmtInterface(self, providerId = IID_ShadowCopyProvider, interfaceId = IID_IVssDifferentialSoftwareSnapshotMgmt): 

281 req = GetProviderMgmtInterface() 

282 classInstance = self.get_cinstance() 

283 req['ORPCthis'] = classInstance.get_ORPCthis() 

284 req['ORPCthis']['flags'] = 0 

285 req['ProviderId'] = providerId 

286 req['InterfaceId'] = interfaceId 

287 resp = self.request(req, self._iid, uuid = self.get_iPid()) 

288 return IVssDifferentialSoftwareSnapshotMgmt(INTERFACE(classInstance, ''.join(resp['ppItf']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) 

289 

290 def QueryVolumesSupportedForSnapshots(self, providerId, iContext): 

291 req = QueryVolumesSupportedForSnapshots() 

292 classInstance = self.get_cinstance() 

293 req['ORPCthis'] = classInstance.get_ORPCthis() 

294 req['ORPCthis']['flags'] = 0 

295 req['ProviderId'] = providerId 

296 req['IContext'] = iContext 

297 resp = self.request(req, self._iid, uuid = self.get_iPid()) 

298 return IVssEnumMgmtObject(INTERFACE(self.get_cinstance(), ''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(),target = self.get_target())) 

299 

300 def QuerySnapshotsByVolume(self, volumeName, providerId = IID_ShadowCopyProvider): 

301 req = QuerySnapshotsByVolume() 

302 classInstance = self.get_cinstance() 

303 req['ORPCthis'] = classInstance.get_ORPCthis() 

304 req['ORPCthis']['flags'] = 0 

305 req['pwszVolumeName'] = volumeName 

306 req['ProviderId'] = providerId 

307 try: 

308 resp = self.request(req, self._iid, uuid = self.get_iPid()) 

309 except DCERPCException as e: 

310 print(e) 

311 from impacket.winregistry import hexdump 

312 data = e.get_packet() 

313 hexdump(data) 

314 kk = QuerySnapshotsByVolumeResponse(data) 

315 kk.dump() 

316 #resp.dump() 

317 return IVssEnumObject(INTERFACE(self.get_cinstance(), ''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) 

318 

319class IVssDifferentialSoftwareSnapshotMgmt(IRemUnknown2): 

320 def __init__(self, interface): 

321 IRemUnknown2.__init__(self, interface) 

322 self._iid = IID_IVssDifferentialSoftwareSnapshotMgmt 

323 

324 def QueryDiffAreasOnVolume(self, pwszVolumeName): 

325 req = QueryDiffAreasOnVolume() 

326 classInstance = self.get_cinstance() 

327 req['ORPCthis'] = classInstance.get_ORPCthis() 

328 req['ORPCthis']['flags'] = 0 

329 req['pwszVolumeName'] = pwszVolumeName 

330 resp = self.request(req, self._iid, uuid = self.get_iPid()) 

331 return IVssEnumMgmtObject(INTERFACE(self.get_cinstance(), ''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), target = self.get_target())) 

332 

333 def QueryDiffAreasForVolume(self, pwszVolumeName): 

334 req = QueryDiffAreasForVolume() 

335 classInstance = self.get_cinstance() 

336 req['ORPCthis'] = classInstance.get_ORPCthis() 

337 req['ORPCthis']['flags'] = 0 

338 req['pwszVolumeName'] = pwszVolumeName 

339 resp = self.request(req, self._iid, uuid = self.get_iPid()) 

340 return IVssEnumMgmtObject(INTERFACE(self.get_cinstance(), ''.join(resp['ppEnum']['abData']), self.get_ipidRemUnknown(), target = self.get_target()))