<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged networkforensics</title>
<link>https://coderlegion.com/tag/networkforensics</link>
<description>Powered by Question2Answer</description>
<item>
<title>Ursnif Malware — Reconstructing a 6-Stage Infection Chain from a PCAP</title>
<link>https://coderlegion.com/14178/ursnif-malware-reconstructing-a-6-stage-infection-chain-from-a-pcap</link>
<description>&lt;p&gt;date: 2026-03-20&lt;br&gt;
description: A walkthrough of my first real malware PCAP investigation — how Ursnif used .avi file extensions to disguise DLL payloads, TLS C2 beaconing, and how I mapped the full attack to MITRE ATT&amp;amp;CK with Splunk detection rules.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;One of the most powerful skills a SOC analyst can develop is the ability to look at a packet capture and reconstruct exactly what an attacker did — step by step, packet by packet.&lt;/p&gt;
&lt;p&gt;This write-up walks through my first real PCAP investigation using a controlled Ursnif/Gozi banking trojan dataset from &lt;a rel=&quot;nofollow&quot; href=&quot;https://malware-traffic-analysis.net&quot;&gt;malware-traffic-analysis.net&lt;/a&gt; — a site widely used in the security community for analyst training.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; 6-stage infection chain reconstructed · 10 IOCs extracted · 5 Splunk detection rules written — from 2,180 packets.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-is-ursnif-&quot;&gt;What is Ursnif?&lt;/h3&gt;
&lt;p&gt;Ursnif (also known as Gozi or ISFB) is one of the oldest banking trojans documented in the wild. Key characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delivered via malicious Office document macros&lt;/li&gt;
&lt;li&gt;Multi-stage payload delivery using disguised file extensions&lt;/li&gt;
&lt;li&gt;Encrypted C2 communication over TLS&lt;/li&gt;
&lt;li&gt;Modular credential theft and web injection&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;tools-used&quot;&gt;Tools Used&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Wireshark 4.x&lt;/strong&gt; — packet analysis&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VirusTotal&lt;/strong&gt; — hash and domain reputation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MITRE ATT&amp;amp;CK Navigator&lt;/strong&gt; — TTP mapping&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Splunk SPL&lt;/strong&gt; — detection rule development&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-1-getting-bearings&quot;&gt;Step 1 — Getting Bearings&lt;/h3&gt;
&lt;p&gt;Before any filters, I start with Statistics.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Statistics → Conversations → TCP&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ozq7sc5q5247m1qqzhpl.png&quot; alt=&quot;Image description&quot;&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;External IP &lt;/th&gt;&lt;th&gt;Packets &lt;/th&gt;&lt;th&gt;Role (discovered later)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;46.102.153.16 &lt;/td&gt;&lt;td&gt;906 &lt;/td&gt;&lt;td&gt;Payload server&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;68.168.123.78 &lt;/td&gt;&lt;td&gt;18 &lt;/td&gt;&lt;td&gt;C2 server&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;217.138.205.170 &lt;/td&gt;&lt;td&gt;8 &lt;/td&gt;&lt;td&gt;Initial C2&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Statistics → Protocol Hierarchy:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TCP: 97.9%&lt;/li&gt;
&lt;li&gt;TLS: 8.2% — encrypted C2 and payload retrieval&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/la9o2n4z9xkipmwpchm5.png&quot; alt=&quot;Image description&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-2-identifying-the-victim&quot;&gt;Step 2 — Identifying the Victim&lt;/h3&gt;
&lt;p&gt;Filter: &lt;code&gt;dhcp&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4jws3ry52tbycx68z0eq.png&quot; alt=&quot;Image description&quot;&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Field &lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;IP Address &lt;/td&gt;&lt;td&gt;10.2.24.101&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;MAC Address &lt;/td&gt;&lt;td&gt;00:08:02:1c:47:ae&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-3-the-full-infection-chain&quot;&gt;Step 3 — The Full Infection Chain&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gjt2rrbgntmovsxi3q3i.jpeg&quot; alt=&quot;Image description&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;stage-1-initial-compromise&quot;&gt;Stage 1 — Initial Compromise&lt;/h4&gt;
&lt;p&gt;Consistent with Ursnif's delivery: malicious Excel file with embedded VBA macro. Not captured in PCAP.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MITRE:&lt;/strong&gt; &lt;code&gt;T1566.001&lt;/code&gt; &lt;code&gt;T1059.005&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;stage-2-first-tls-contact-packet-10-&quot;&gt;Stage 2 — First TLS Contact (Packet 10)&lt;/h4&gt;
&lt;p&gt;Filter: &lt;code&gt;ssl.handshake.type==1&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;Source:      10.2.24.101
Destination: 217.138.205.170
SNI:         fatturapagamentodi.pw
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzxy982ld5i6bny563dd.png&quot; alt=&quot;Image description&quot;&gt;&lt;/p&gt;
&lt;p&gt;The SNI field in a TLS Client Hello is &lt;strong&gt;plaintext&lt;/strong&gt; — even without decrypting traffic, we can see exactly which domain the malware contacted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MITRE:&lt;/strong&gt; &lt;code&gt;T1071.003&lt;/code&gt; &lt;code&gt;T1573.001&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;stage-3-payload-download-packets-218-1116-&quot;&gt;Stage 3 — Payload Download (Packets 218–1116)&lt;/h4&gt;
&lt;p&gt;Filter: &lt;code&gt;http.request.method == &quot;GET&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ykmt9gt8xgixbcrccqq.png&quot; alt=&quot;Image description&quot;&gt;&lt;/p&gt;
&lt;p&gt;906 packets to 46.102.153.16. Files had &lt;code&gt;.avi&lt;/code&gt; extensions — but were Ursnif DLL segments reassembled in memory. The &lt;code&gt;.avi&lt;/code&gt; extension bypasses firewalls that block &lt;code&gt;.exe&lt;/code&gt; and &lt;code&gt;.dll&lt;/code&gt; downloads.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MITRE:&lt;/strong&gt; &lt;code&gt;T1105&lt;/code&gt; &lt;code&gt;T1027&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;stage-4-secondary-payload-packets-1299-1563-&quot;&gt;Stage 4 — Secondary Payload (Packets 1299, 1563)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;GET /grabb32.rar  →  37.10.71.149
GET /grabb64.rar  →  37.10.71.149
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both 32-bit and 64-bit binaries from a separate server.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;stage-5-c2-beaconing-packets-1215-2167-&quot;&gt;Stage 5 — C2 Beaconing (Packets 1215–2167)&lt;/h4&gt;
&lt;p&gt;Filter: &lt;code&gt;ssl.handshake.type==1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/on32qknfcp1bpyxty8z2.png&quot; alt=&quot;Image description&quot;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;Destination: 68.168.123.78
SNI:         asistenzaonline.xyz
Interval:    ~5–10 minutes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Human browsing is random and bursty. &lt;strong&gt;Malware is a clock.&lt;/strong&gt; The consistent interval between TLS handshakes is machine behavior — your detection signal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MITRE:&lt;/strong&gt; &lt;code&gt;T1071.001&lt;/code&gt; &lt;code&gt;T1573.001&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;stage-6-persistence-inferred-&quot;&gt;Stage 6 — Persistence (Inferred)&lt;/h4&gt;
&lt;p&gt;Registry injection under &lt;code&gt;HKCU\Software\[random key]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MITRE:&lt;/strong&gt; &lt;code&gt;T1547.001&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;indicators-of-compromise&quot;&gt;Indicators of Compromise&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Type &lt;/th&gt;&lt;th&gt;Value &lt;/th&gt;&lt;th&gt;Role&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;IP &lt;/td&gt;&lt;td&gt;217.138.205.170 &lt;/td&gt;&lt;td&gt;Initial C2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;IP &lt;/td&gt;&lt;td&gt;46.102.153.16 &lt;/td&gt;&lt;td&gt;Payload server&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;IP &lt;/td&gt;&lt;td&gt;37.10.71.149 &lt;/td&gt;&lt;td&gt;Secondary payload&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;IP &lt;/td&gt;&lt;td&gt;68.168.123.78 &lt;/td&gt;&lt;td&gt;Primary C2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Domain &lt;/td&gt;&lt;td&gt;fatturapagamentodi.pw &lt;/td&gt;&lt;td&gt;Stage 2 C2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Domain &lt;/td&gt;&lt;td&gt;asistenzaonline.xyz &lt;/td&gt;&lt;td&gt;Persistent C2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Domain &lt;/td&gt;&lt;td&gt;pizdelko.xyz &lt;/td&gt;&lt;td&gt;Fallback C2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;URL &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://46.102.153.16/*.avi&quot;&gt;http://46.102.153.16/*.avi&lt;/a&gt; &lt;/td&gt;&lt;td&gt;DLL delivery&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;File &lt;/td&gt;&lt;td&gt;grabb32.rar &lt;/td&gt;&lt;td&gt;32-bit binary&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;File &lt;/td&gt;&lt;td&gt;grabb64.rar &lt;/td&gt;&lt;td&gt;64-bit binary&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3 id=&quot;mitre-att-amp-ck-map&quot;&gt;MITRE ATT&amp;amp;CK Map&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;ID &lt;/th&gt;&lt;th&gt;Technique&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;T1566.001 &lt;/td&gt;&lt;td&gt;Phishing: Spearphishing Attachment&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;T1059.005 &lt;/td&gt;&lt;td&gt;Command and Scripting Interpreter: VBA&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;T1105 &lt;/td&gt;&lt;td&gt;Ingress Tool Transfer&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;T1071.001 &lt;/td&gt;&lt;td&gt;Application Layer Protocol: Web Protocols&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;T1071.003 &lt;/td&gt;&lt;td&gt;Application Layer Protocol: Mail Protocols&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;T1547.001 &lt;/td&gt;&lt;td&gt;Boot/Logon Autostart: Registry Run Keys&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;T1027 &lt;/td&gt;&lt;td&gt;Obfuscated Files or Information&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;T1573.001 &lt;/td&gt;&lt;td&gt;Encrypted Channel: Symmetric Cryptography&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3 id=&quot;detection-rules-splunk-spl-&quot;&gt;Detection Rules (Splunk SPL)&lt;/h3&gt;
&lt;h4 id=&quot;rule-1-tls-to-suspicious-sni&quot;&gt;Rule 1 — TLS to suspicious SNI&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-splunk&quot;&gt;index=network ssl.handshake.type=1
| stats count by src_ip, ssl.handshake.extensions_server_name
| where NOT ssl.handshake.extensions_server_name LIKE &quot;%.google.com&quot;
  AND NOT ssl.handshake.extensions_server_name LIKE &quot;%.microsoft.com&quot;
  AND NOT ssl.handshake.extensions_server_name LIKE &quot;%.cloudflare.com&quot;
| sort -count
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;rule-2-c2-beaconing-via-tls-regularity&quot;&gt;Rule 2 — C2 beaconing via TLS regularity&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-splunk&quot;&gt;index=network ssl.handshake.type=1
| bucket _time span=10m
| stats count by src_ip, dest_ip, _time
| streamstats window=6 current=t stdev(count) as regularity by src_ip, dest_ip
| where regularity &amp;lt; 1.5
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;rule-3-media-file-extension-from-non-cdn-ip&quot;&gt;Rule 3 — Media file extension from non-CDN IP&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-splunk&quot;&gt;index=network http.request.method=GET
| rex field=uri &quot;(?&amp;lt;ext&amp;gt;\.[a-z0-9]{2,4})$&quot;
| where ext IN (&quot;.avi&quot;,&quot;.mp4&quot;,&quot;.mp3&quot;)
| eval dest_is_cdn=if(match(dest_ip,&quot;^(151\.101|104\.16|172\.67)&quot;),1,0)
| where dest_is_cdn=0
| stats count by src_ip, dest_ip, uri, ext
| where count &amp;gt; 3
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;rule-4-chunked-download-from-single-external-ip&quot;&gt;Rule 4 — Chunked download from single external IP&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-splunk&quot;&gt;index=network http.request.method=GET
| stats dc(uri) as unique_files, count as total_requests by src_ip, dest_ip
| where unique_files &amp;gt; 3
| eval internal=if(match(dest_ip,&quot;^(10\.|192\.168\.)&quot;),1,0)
| where internal=0
| sort -total_requests
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;rule-5-suspicious-archive-by-name-pattern&quot;&gt;Rule 5 — Suspicious archive by name pattern&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-splunk&quot;&gt;index=network http.request.method=GET
  (uri=&quot;*.rar&quot; OR uri=&quot;*.zip&quot;)
| where NOT dest_ip LIKE &quot;192.168.%&quot; AND NOT dest_ip LIKE &quot;10.%&quot;
| eval suspicious=if(match(uri,&quot;(grabb|drop|stage|payload|inject)&quot;),1,0)
| where suspicious=1
| stats count by src_ip, dest_ip, uri
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;three-key-lessons&quot;&gt;Three Key Lessons&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; The &lt;code&gt;.avi&lt;/code&gt; trick works because defenders trust file extensions. Fix: inspect file content, not just extension.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Beaconing regularity is your strongest behavioral detection signal. Low standard deviation in connection intervals = machine, not human.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Multi-stage infrastructure creates more IOCs, not fewer. Four servers = four things to block and hunt for.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;immediate-response-actions&quot;&gt;Immediate Response Actions&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Isolate 10.2.24.101&lt;/li&gt;
&lt;li&gt;Block all 4 attacker IPs&lt;/li&gt;
&lt;li&gt;Sinkhole 3 C2 domains at DNS&lt;/li&gt;
&lt;li&gt;Hunt for &lt;code&gt;.avi&lt;/code&gt; GETs from non-CDN IPs in 30 days of proxy logs&lt;/li&gt;
&lt;li&gt;Deploy rules 1–5 to SIEM&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;full-report-on-github&quot;&gt;Full Report on GitHub&lt;/h3&gt;
&lt;p&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/himanshumodi3108/cybersec-portfolio&quot;&gt;github.com/himanshumodi3108/cybersec-portfolio&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;This analysis was performed on a controlled training dataset from malware-traffic-analysis.net for educational purposes.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Himanshu Kumar Modi · Associate at PwC India · SOC Analyst in Training&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.linkedin.com/in/himanshu-kumar-modi-063b88239&quot;&gt;LinkedIn&lt;/a&gt; · &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/himanshumodi3108/cybersec-portfolio&quot;&gt;Cybersecurity Portfolio&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/14178/ursnif-malware-reconstructing-a-6-stage-infection-chain-from-a-pcap</guid>
<pubDate>Tue, 07 Apr 2026 17:43:08 +0000</pubDate>
</item>
</channel>
</rss>