Bruteforce
Scenario
Can you analyze logs from an attempted RDP brute-force attack?
A system administrator identified a high volume of Audit Failure events in Windows Security logs. The goal is to validate attack scale, identify the targeted account, extract source infrastructure indicators, and summarize attacker behavior.
Investigation
Step 1: Convert CSV evidence to JSON for structured parsing
import pandas as pd
df = pd.read_csv("BTLO_Bruteforce_Challenge.csv")
df.to_json("challenge.json", orient="records", indent=4)
Purpose: prepare evidence for deterministic field extraction.
Logic:jqworks reliably on JSON; converting once avoids repeated manual parsing.
What this proves: source dataset is now queryable for repeatable forensic pivots.
Next: profile event IDs.
Step 2: Count event IDs in the dataset
jq -r '.[] | .Source' challenge.json | sort -n | uniq -c
4 4624
3103 4625
4 4672
18 5379
Purpose: identify dominant authentication outcome in logs.
Logic: Event ID distribution shows where attacker activity is concentrated.
What this proves:4625(failed logon) dominates with 3103 events.
Next: extract which account is being targeted.
Step 3: Identify targeted local account
jq -r '.[]
| select(.Source==4625)
| ."Task Category"
| capture("Account For Which Logon Failed:\\r\\n\\tSecurity ID:\\t\\tNULL SID\\r\\n\\tAccount Name:\\t\\t(?<u>[^\\r\\n]+)")
| .u' challenge.json | sort | uniq -c | sort -nr | head -1
3103 administrator
Purpose: determine which account is under brute-force pressure.
Logic: parse4625message body and count failed-account occurrences.
What this proves: the targeted local username is administrator.
Next: confirm the failure reason text.
Step 4: Extract failure reason
jq -r '.[] | select(.Source==4625) | ."Task Category"
| capture("Failure Reason:\\t\\t(?<r>[^\\r\\n]+)") | .r' challenge.json \
| sort | uniq -c | sort -nr | head -1
3103 Unknown user name or bad password.
Purpose: capture authentication failure semantics from event body.
Logic: exact reason text validates this is password/credential brute-force behavior.
What this proves: primary failure reason is Unknown user name or bad password.
Next: isolate source IP driving these failures.
Step 5: Identify attacker source IP
jq -r '.[] | select(.Source==4625) | ."Task Category"
| capture("Source Network Address:\\t(?<ip>[0-9.]+)") | .ip' challenge.json \
| sort | uniq -c | sort -nr | head -1
3103 113.161.192.227
Purpose: attribute brute-force activity to an originating host.
Logic: parse network address field from failed-logon records and rank by count.
What this proves: attack source IP is 113.161.192.227.
Next: enrich IP with geo attribution.
Step 6: Geo-attribute source IP
curl ipinfo.io/113.161.192.227
{
"ip": "113.161.192.227",
"hostname": "static.vnpt.vn",
"city": "Phan Thiết",
"region": "Lam Dong",
"country": "VN",
"loc": "10.9289,108.1021",
"org": "AS45899 VNPT Corp"
}
Purpose: enrich network IOC for reporting context.
Logic: external enrichment maps IP to country and provider.
What this proves: source country is VN (Vietnam).
Next: determine attacker source-port behavior.
Step 7: Compute attacker source-port range
jq -r '.[]
| select(.Source==4625)
| ."Task Category"
| capture("Source Port:\\t\\t(?<p>[0-9]+)")
| .p' challenge.json \
| sort -n | awk 'NR==1{min=$1} {max=$1} END{print min "-" max}'
49162-65534
Purpose: characterize source-port spread for brute-force traffic profile.
Logic: minimum and maximum observed ports summarize attacker connection behavior.
What this proves: source port range is 49162-65534.
Timeline
T0: Dataset converted from CSV to JSON for queryable analysis.T1: Event distribution shows 3103 failed logons (4625).T2: Failed logons targetadministratorwith consistent bad-credential reason.T3: Source IP113.161.192.227identified across failures.T4: Geo enrichment maps source toVN.T5: Source port spread calculated as49162-65534.
Final Answers (for submission)
3103administratorUnknown user name or bad password.4625113.161.192.227Vietnam49162-65534
Tool Significance
Python (pandas):- Converts raw CSV evidence into structured JSON for repeatable parsing.
jq:- Primary extraction tool for event IDs, account names, reasons, source IP, and source ports.
curl(ipinfo):- Fast IOC enrichment for country/provider attribution.
- Optional validation tool:
whoiscan support ownership context, but was not required to answer challenge fields.