Hello there!
In this blog post, I am sharing one of the steps from my SOAR project.
By completing this guide, you will be able to retrieve Windows logs using Python.
1}Understanding Windows Logs
Before retrieving logs using Python, you must understand where Windows stores logs and how they are structured.
Open Event Viewer → expand Windows Logs.
You will see:
Application
Security
Setup
System
Forwarded Events
Each category contains events stored in a structured format.
2}Windows Event Structure
Windows event has 5 parts.
Log Name : Application, Security, System, Setup.
Level : The level of security e.g, Info, warning, Critical, Verbose.
Data and Time : When event has occurred.
Source : The program, service or component that generated the event.
Event ID : A unique Identification of number.
Event Log Structure:
Every Windows event has 5 important parts.
- Event ID : You already saw this (e.g., 4624 = logon).
Level :
This tells how serious the event is:
Information
Warning
Error
Critical
Audit Success
Audit Failure
4624 = Audit Success
4625 = Audit FailureTime Created
The exact timestamp when the event happened.
This tells you when the action occurred.Provider (Source)
This tells you who created the event.
Examples:
Microsoft-Windows-Security-Auditing
Service Control Manager
Application ErrorEvent Details (Description / XML)
Scroll down to the bottom and you will see a section called “Details”.
Click Details → Select XML view.
This XML view is exactly what Python reads using libraries like pywin32 or win32evtlog.
2}Python Libraries for Windows Logs
There are three major options
-->Option 1: pywin32
Allows Python access to Windows APIs.
Offers win32evtlog and win32evtlogutil.
Learn:
Installing: pip install pywin32
Reading event logs using win32evtlog.OpenEventLog
Parsing event records
-->Option 2: win32com / WMI
Use WMI to query logs.
Learn:
Installing: pip install wmi
Basic WMI queries (e.g., SELECT * FROM Win32_NTLogEvent)
-->Option 3: subprocess + PowerShell
Run PowerShell command Get-WinEvent or Get-EventLog from Python and parse output.
Learn:
Using subprocess.run
Reading command output (stdout)
I choose option 3, here i use python(subprocess) and power shell.
Let's start with power shell basics, Basic level of power shell learning is necessary for this.
PowerShell : It is a cross-platform command-line shell and object-oriented scripting language used for system administration.
3} Power Shell Basics
-->Core Log Reading Commands
1}Get-WinEvent
2}Get-EventLog
3}wevtutil qe
4}Get-Wmiobject win32_NTLogEvent
5}Get-CimInstance Win32_NTLogEvent
-->Core Log Filtering Commands
1}Where-Object
2}Select-Object
3}Sort-Object
4}Group-Object
5}Measure-Object
6}Select-String
-->Log Exporting Commands
1}Out-File
2}Export-Csv
3}ConvertTo-Json
4}wevtutil epl
5}Out-GridView
-->Log Management Command
1}wevtutil cl
2}wevtutil gl
3}New-EventLog
4}Write-EventLog
5}Remove-EventLog
-->Log File / Folder Commands
1}Get-ChildItem
2}Set-Location
3}New-Item
4}Test-Path
5}Get-Content
6}Get-Content-Wait
7}Get-Content-Tail
-->System/Metadata Commands
1}Get-EventSubscriber
2}Get-Service
3}Get-Process
4}Get-WinEvent -ListLog *
5}Get-WinEvent -ListProvider *
-->PowerShell "Thinking Tools"
1}Get-Help
2}Get-Help -Examples
3}Get-Command
4}Get-Member
5}Get-Alias
Each commands accepts only certain parameter. view them by
Get-Help
Example :
Get help for Get-EventLog
->Get-Help Get-EventLog
I recommend learn it online and complete some tasks to get familiar with it like ask AI tools to assign some tasks for power shell commands and complete them.
But Not all commands will work for normal user in power shell you need to run it at Administrative level.
4}How Windows Admin Rights Actually Work
Windows does not allow any program to just become admin out of no where.
Instead :
Every program is launched with a security token.
That token is either:
-- A standard User.
-- Administrator.
If your script starts as a normal user, the only way to become Admin is:
Show a UAC popup.
Or run the script inside a session that is already elevated.
Or use a scheduled task that runs elevated.
Understanding the Admin Check Code:
ctypes : A python module that lets python call windows system DLLs
ctypes.windll.shell32 means:
Access the Windows system DLL shell32.dll
Code :
import ctypes
import sys
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
if not is_admin():
ctypes.windll.shell32.ShellExecuteW( None, "runas", sys.executable, " ".join(sys.argv),None, 1)
print("Running as admin!")
-->ctypes.windll.shell32.IsUserAnAdmin()
This line check whether user or admin
How Python Elevates Itself :
If Python is not already admin,
if not is_admin():
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, " ".join(sys.argv),None, 1)
sys.exit()
ShellExecuteW : A windows API function that can launch a new program.
The above mentioned parameters :
None --> No parent Window
runas --> Tells windows "Run As Administrator"
sys.executable -->Path to python.exe
" ".join(sys.argv) -->Arguments of your script and Because ShellExecuteW CANNOT accept a list.
sys.argv is a list.
So you cannot pass it directly.
Example:
['retrivelogs.py']
ShellExecuteW does not understand lists.
It only understands strings like:
"retrivelogs.py"
So we convert:
sys.argv → " ".join(sys.argv)
That is the ONLY reason.
We used " ".join(sys.argv)
because Windows API requires ONE STRING
not a Python list.
" ".join(sys.argv) = "retrivelogs.py"
None -->Working directory
1 -->Shows the windows
Now you can guess what are we trying to do,
We are just executing power shell commands but in python code.
Subprocess module makes our work even easier.
5}Subprocess Module
The subprocess module lets you run external commands, spawn new processes, interact with their input/output and retrieve results.
Python offers four main ways to run subprocesses but here we discuss main two:
1}subprocess.run() : Recommended High-Level Function.
This is the best way to run a command and collect the result.
Signature :
subprocess.run(args, *,
stdin=None,
input=None,
stdout=None,
stderr=None,
capture_output=False,
shell=False, cwd=None,
timeout=None,
check=False,
text=False, encoding=None, errors=None)
Example :
import subprocess
res = subprocess.run(["ls","-l"],
capture_output = True,
text = True,
check =True #raise error if command fails)
2}subprocess.Popen() :
This is the advanced, fully configurable way.
Signature :
subprocess.Popen(args,
bufsize=0,
executable=None,
stdin=None,
stdout=None, stderr=None,
preexec_fn=None,
close_fds=True, shell=False,
cwd=None, env=None,
universal_newlines=False, text=None,
startupinfo=None, creationflags=0,
pipesize=-1)
Example :
from subprocess import Popen, PIPE
p = Popen(["grep", "hello"],
stdin=PIPE,
stdout=PIPE,
text=True)
out = p.communicate("hello world")[0]
print(out)
2}Important Classes
Returned by run()
Attributes:
args
returncode
stdout
stderr
Returned by Popen()
Methods:
poll() — check if process ended
wait() — wait until finished
communicate() — send input & read output
terminate() — graceful stop (SIGTERM)
kill() — force kill (SIGKILL)
NOTE : Popen can stream real time output but run can't.
1) Stream real-time output
from subprocess import Popen, PIPE
p = Popen(["ping", "google.com"], stdout=PIPE, text=True)
for line in p.stdout:
print("LIVE:", line, end="")
run() cannot do this — it waits until the command finishes.
*Python Code *:
import subprocess
import json
import ctypes
import sys
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
if not is_admin():
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, " ".join(sys.argv),None, 1)
print("Running as admin!")
command = [
"powershell",
"-Command",#you can change the commands here
"Get-WinEvent -LogName System -MaxEvents 5 | "
"Select-Object Id, @{Name='TimeCreated';Expression={$_.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss')}} | "
"ConvertTo-Json -Depth 4"
]
result = subprocess.run(command, capture_output=True, text=True)
output = result.stdout
try:
events = json.loads(output)
except json.JSONDecodeError:
print("Error parsing JSON. Raw output:")
print(output)
exit()
//Ensure output is always a list
if isinstance(events, dict):
events = [events]
for event in events:
print(f"ID: {event['Id']} Time: {event['TimeCreated']}")
Top comments (0)