Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
6.0 kB
1
Indexable
Never
import win32evtlog
import xml.etree.ElementTree as ET
import ctypes
import sys
import time
import paramiko
import datetime
import os


LOG_FILE_PATH = 'C:\Windows\System32\winevt\Logs\ForwardedEvents.evtx'
INDEX_FILE_PATH = 'last_timestamp.txt'
MAX_RECORDS_TO_READ = 500
OUTPUT_FILE_PATH='C:\\Users\\capeuser\\Python\\cape_event_log_integration\\Code\\event_log_output.txt'
OUTPUT_FILE_DIR='C:\\Users\\capeuser\\Python\\cape_event_log_integration\\Code\\'
MAX_EVENT_COUNT=5000
event_count=0

REMOTE_HOST = '192.168.100.21'
REMOTE_USER = 'TCSCAPEAGENT'
REMOTE_PASSWORD = 'C@peM@nitor'
REMOTE_PATH = '/var/log/EventLog/'


current_time = time.strftime("%Y-%m-%d-%H-%M-%S")
print(current_time)


def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False


def get_last_timestamp():
    try:
        with open(INDEX_FILE_PATH, 'r') as f:
            last_timestamp = f.readline().strip()
            return last_timestamp
    except:
        return None



def write_last_timestamp(timestamp):
    with open(INDEX_FILE_PATH, 'w') as f:
        f.write(str(timestamp))



if is_admin():
    last_timestamp = get_last_timestamp()
    if last_timestamp is not None:
        # convert the last timestamp to a datetime object
        last_dt = datetime.datetime.strptime(last_timestamp, '%Y-%m-%dT%H:%M:%S.%fZ')
        # format the last timestamp for the query
        last_query_timestamp = last_dt.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
        print(f'Resuming reading events after timestamp {last_timestamp}...')
    else:
        last_query_timestamp = None
        print('Starting to read events from the beginning...')

    # open event file
    query_handle = win32evtlog.EvtQuery(
    LOG_FILE_PATH,
    win32evtlog.EvtQueryFilePath,
    f'Event/System[TimeCreated[@SystemTime>"{last_query_timestamp}"]]' if last_query_timestamp is not None else None
    )

    # open output file for writing
    with open(OUTPUT_FILE_PATH, 'a') as f:
        stop = False
        transfer_success_flag=False
        while not stop:
            # wait for new events to arrive
            time.sleep(5)
            
            # read 1 record(s)
            events = win32evtlog.EvtNext(query_handle, MAX_RECORDS_TO_READ)

            # if there is no record break the loop
            if len(events) == 0:
                break

            for event in events:
                xml_content = win32evtlog.EvtRender(event, win32evtlog.EvtRenderEventXml)
                # parse xml content
                xml = ET.fromstring(xml_content)
                # xml namespace, root element has a xmlns definition, so we have to use the namespace
                ns = '{http://schemas.microsoft.com/win/2004/08/events/event}'
                
                try:
                    substatus = xml[1][9].text
                    message = xml.find(f'.//{ns}Message').text
                except IndexError:
                    #print('Substatus field not found in event.')
                    substatus = None
                    message = None

                event_id = xml.find(f'.//{ns}EventID').text
                computer = xml.find(f'.//{ns}Computer').text
                channel = xml.find(f'.//{ns}Channel').text
                execution = xml.find(f'.//{ns}Execution')
                time_created = xml.find(f'.//{ns}TimeCreated').get('SystemTime')
                level = xml.find(f'.//{ns}Level').text
                
                
                
                
                # write event data to output file
                event_data = f'Time: {time_created}, Computer: {computer}, Substatus: {substatus}, Event Id: {event_id},Message: {message},Level: {level},Channel: {channel}\n'
                f.write(event_data)
                event_count += 1
                #print(event_count)
                
                # update last timestamp
                last_timestamp = xml.find(f'.//{ns}TimeCreated').get('SystemTime')
                write_last_index(last_timestamp)

                # check if event count has exceeded the limit
                if event_count >= MAX_EVENT_COUNT:
                    stop = True
                    break
                    
                # check if stop flag is set
                if stop:
                    break
                    
    # close output file
    f.close()               
                    
                    
                    
    # check if output file is empty and delete it if it is
    if os.stat(OUTPUT_FILE_PATH).st_size == 0:
        os.remove(OUTPUT_FILE_PATH)
        print('Output file is empty and has been deleted.')
    else:
        # transfer file to remote agent
        import paramiko

        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(REMOTE_HOST, username=REMOTE_USER, password=REMOTE_PASSWORD)
        try:
            sftp = ssh.open_sftp()
            sftp.put(OUTPUT_FILE_PATH, REMOTE_PATH + 'Forwarded_Logs'+"-T" +str(current_time)+".log")
            sftp.close()
            print(f"File Transferred Successfully at {current_time}")
            transfer_success_flag= True
        
        except:
            print("File not Transferred")
        ssh.close()
        
        if transfer_success_flag:
            print("Renaming the File in our Local")
            # add a delay before renaming the file
            time.sleep(5)
            # rename the local file
            filename = OUTPUT_FILE_DIR+"sent_event_logs-T" + str(current_time)+".txt"
            print(filename)
            os.replace(OUTPUT_FILE_PATH, filename )
        
        

else:
    # Re-run the program with admin rights
    ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)