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-TSCH] ATSVC Interface implementation 11# 12# Best way to learn how to use these calls is to grab the protocol standard 13# so you understand what the call does, and then read the test case located 14# at https://github.com/CoreSecurity/impacket/tree/master/impacket/testcases/SMB_RPC 15# 16# Some calls have helper functions, which makes it even easier to use. 17# They are located at the end of this file. 18# Helper functions start with "h"<name of the call>. 19# There are test cases for them too. 20# 21from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT, NDRPOINTER, NDRUniConformantArray 22from impacket.dcerpc.v5.dtypes import DWORD, LPWSTR, UCHAR, ULONG, LPDWORD, NULL 23from impacket import hresult_errors 24from impacket.uuid import uuidtup_to_bin 25from impacket.dcerpc.v5.rpcrt import DCERPCException 26 27MSRPC_UUID_ATSVC = uuidtup_to_bin(('1FF70682-0A51-30E8-076D-740BE8CEE98B','1.0')) 28 29class DCERPCSessionError(DCERPCException): 30 def __init__(self, error_string=None, error_code=None, packet=None): 31 DCERPCException.__init__(self, error_string, error_code, packet) 32 33 def __str__( self ): 34 key = self.error_code 35 if hresult_errors.ERROR_MESSAGES.has_key(key): 36 error_msg_short = hresult_errors.ERROR_MESSAGES[key][0] 37 error_msg_verbose = hresult_errors.ERROR_MESSAGES[key][1] 38 return 'TSCH SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose) 39 else: 40 return 'TSCH SessionError: unknown error code: 0x%x' % self.error_code 41 42################################################################################ 43# CONSTANTS 44################################################################################ 45ATSVC_HANDLE = LPWSTR 46# 2.3.1 Constant Values 47CNLEN = 15 48DNLEN = CNLEN 49UNLEN = 256 50MAX_BUFFER_SIZE = (DNLEN+UNLEN+1+1) 51 52# 2.3.7 Flags 53TASK_FLAG_INTERACTIVE = 0x1 54TASK_FLAG_DELETE_WHEN_DONE = 0x2 55TASK_FLAG_DISABLED = 0x4 56TASK_FLAG_START_ONLY_IF_IDLE = 0x10 57TASK_FLAG_KILL_ON_IDLE_END = 0x20 58TASK_FLAG_DONT_START_IF_ON_BATTERIES = 0x40 59TASK_FLAG_KILL_IF_GOING_ON_BATTERIES = 0x80 60TASK_FLAG_RUN_ONLY_IF_DOCKED = 0x100 61TASK_FLAG_HIDDEN = 0x200 62TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET = 0x400 63TASK_FLAG_RESTART_ON_IDLE_RESUME = 0x800 64TASK_FLAG_SYSTEM_REQUIRED = 0x1000 65TASK_FLAG_RUN_ONLY_IF_LOGGED_ON = 0x2000 66 67################################################################################ 68# STRUCTURES 69################################################################################ 70# 2.3.4 AT_INFO 71class AT_INFO(NDRSTRUCT): 72 structure = ( 73 ('JobTime',DWORD), 74 ('DaysOfMonth',DWORD), 75 ('DaysOfWeek',UCHAR), 76 ('Flags',UCHAR), 77 ('Command',LPWSTR), 78 ) 79 80class LPAT_INFO(NDRPOINTER): 81 referent = ( 82 ('Data',AT_INFO), 83 ) 84 85# 2.3.6 AT_ENUM 86class AT_ENUM(NDRSTRUCT): 87 structure = ( 88 ('JobId',DWORD), 89 ('JobTime',DWORD), 90 ('DaysOfMonth',DWORD), 91 ('DaysOfWeek',UCHAR), 92 ('Flags',UCHAR), 93 ('Command',LPWSTR), 94 ) 95 96class AT_ENUM_ARRAY(NDRUniConformantArray): 97 item = AT_ENUM 98 99class LPAT_ENUM_ARRAY(NDRPOINTER): 100 referent = ( 101 ('Data',AT_ENUM_ARRAY), 102 ) 103 104# 2.3.5 AT_ENUM_CONTAINER 105class AT_ENUM_CONTAINER(NDRSTRUCT): 106 structure = ( 107 ('EntriesRead',DWORD), 108 ('Buffer',LPAT_ENUM_ARRAY), 109 ) 110 111################################################################################ 112# RPC CALLS 113################################################################################ 114# 3.2.5.2.1 NetrJobAdd (Opnum 0) 115class NetrJobAdd(NDRCALL): 116 opnum = 0 117 structure = ( 118 ('ServerName',ATSVC_HANDLE), 119 ('pAtInfo', AT_INFO), 120 ) 121 122class NetrJobAddResponse(NDRCALL): 123 structure = ( 124 ('pJobId',DWORD), 125 ('ErrorCode',ULONG), 126 ) 127 128# 3.2.5.2.2 NetrJobDel (Opnum 1) 129class NetrJobDel(NDRCALL): 130 opnum = 1 131 structure = ( 132 ('ServerName',ATSVC_HANDLE), 133 ('MinJobId', DWORD), 134 ('MaxJobId', DWORD), 135 ) 136 137class NetrJobDelResponse(NDRCALL): 138 structure = ( 139 ('ErrorCode',ULONG), 140 ) 141 142# 3.2.5.2.3 NetrJobEnum (Opnum 2) 143class NetrJobEnum(NDRCALL): 144 opnum = 2 145 structure = ( 146 ('ServerName',ATSVC_HANDLE), 147 ('pEnumContainer', AT_ENUM_CONTAINER), 148 ('PreferedMaximumLength', DWORD), 149 ('pResumeHandle', DWORD), 150 ) 151 152class NetrJobEnumResponse(NDRCALL): 153 structure = ( 154 ('pEnumContainer', AT_ENUM_CONTAINER), 155 ('pTotalEntries', DWORD), 156 ('pResumeHandle',LPDWORD), 157 ('ErrorCode',ULONG), 158 ) 159 160# 3.2.5.2.4 NetrJobGetInfo (Opnum 3) 161class NetrJobGetInfo(NDRCALL): 162 opnum = 3 163 structure = ( 164 ('ServerName',ATSVC_HANDLE), 165 ('JobId', DWORD), 166 ) 167 168class NetrJobGetInfoResponse(NDRCALL): 169 structure = ( 170 ('ppAtInfo', LPAT_INFO), 171 ('ErrorCode',ULONG), 172 ) 173 174################################################################################ 175# OPNUMs and their corresponding structures 176################################################################################ 177OPNUMS = { 178 0 : (NetrJobAdd,NetrJobAddResponse ), 179 1 : (NetrJobDel,NetrJobDelResponse ), 180 2 : (NetrJobEnum,NetrJobEnumResponse ), 181 3 : (NetrJobGetInfo,NetrJobGetInfoResponse ), 182} 183 184################################################################################ 185# HELPER FUNCTIONS 186################################################################################ 187def hNetrJobAdd(dce, serverName = NULL, atInfo = NULL): 188 netrJobAdd = NetrJobAdd() 189 netrJobAdd['ServerName'] = serverName 190 netrJobAdd['pAtInfo'] = atInfo 191 return dce.request(netrJobAdd) 192 193def hNetrJobDel(dce, serverName = NULL, minJobId = 0, maxJobId = 0): 194 netrJobDel = NetrJobDel() 195 netrJobDel['ServerName'] = serverName 196 netrJobDel['MinJobId'] = minJobId 197 netrJobDel['MaxJobId'] = maxJobId 198 return dce.request(netrJobDel) 199 200def hNetrJobEnum(dce, serverName = NULL, pEnumContainer = NULL, preferedMaximumLength = 0xffffffff): 201 netrJobEnum = NetrJobEnum() 202 netrJobEnum['ServerName'] = serverName 203 netrJobEnum['pEnumContainer']['Buffer'] = pEnumContainer 204 netrJobEnum['PreferedMaximumLength'] = preferedMaximumLength 205 return dce.request(netrJobEnum) 206 207def hNetrJobGetInfo(dce, serverName = NULL, jobId = 0): 208 netrJobGetInfo = NetrJobGetInfo() 209 netrJobGetInfo['ServerName'] = serverName 210 netrJobGetInfo['JobId'] = jobId 211 return dce.request(netrJobGetInfo)