Modem Metamorphosis
Modem Metamorphosis
Platform: CUSTOM | Category: Forensics | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: pcap_triage, http_object_extraction, basic_auth_decoding, firmware_upload_analysis
Summary
Walkthrough of the CUSTOM Forensics Modem Metamorphosis. Task: analyze a PCAP containing a router web administration session and firmware upgrade. Solution: extract HTTP objects, recover the router UI pages and multipart upload, then combine the old Linksys
Description
Provided artifact:
morph.pcapFlag format:
DawgCTF{Manufacturer_Model_OldFirmwareVersion_NewFirmwareName_NewFirmwareVersion}
English summary: the challenge gives a packet capture of a router administration session. The goal is to identify the device, determine the old firmware version, recover the uploaded replacement firmware, and assemble the flag fields in the required order.
Analysis
Step 1: Initial PCAP triage
The first step was to confirm what protocols were present:
bash read-only • copy allowedtshark -r morph.pcap -q -z io,phs
Relevant result:
text read-only • copy allowedhttp frames:250 bytes:67977 mime_multipart frames:1 bytes:375
That immediately suggests a web-based workflow, and the single mime_multipart entry is a strong hint that a file upload happened inside HTTP.
Step 2: Identify router admin traffic
Listing HTTP requests showed a browser talking directly to 192.168.1.1 and visiting typical embedded router pages such as /Wireless_Basic.asp, /Management.asp, and /Upgrade.asp.
bash read-only • copy allowedtshark -r morph.pcap -Y "http.request" -T fields \ -e frame.number -e http.request.method -e http.host -e http.request.uri
Important requests included:
text read-only • copy allowed2748 GET 192.168.1.1 /Management.asp 3291 GET 192.168.1.1 /Upgrade.asp 13300 POST 192.168.1.1 /upgrade.cgi
The capture also contains repeated Basic Authentication headers:
bash read-only • copy allowedtshark -r morph.pcap -Y "http.authorization" -T fields \ -e frame.number -e ip.src -e ip.dst -e http.authorization
Example output:
text read-only • copy allowed69 192.168.1.101 192.168.1.1 Basic OmFkbWlu
Decoding the Base64 portion confirms the credentials:
bash read-only • copy allowedpython3 - <<'PY' import base64 print(base64.b64decode('OmFkbWlu').decode()) PY
Output:
text read-only • copy allowed:admin
The observed header decodes to :admin, showing that the capture uses the default admin password during HTTP Basic Auth. That was enough to explain why the browser could access the router interface in the capture.
Step 3: Extract HTTP objects from the PCAP
To inspect the router web interface offline, I exported all HTTP objects:
bash read-only • copy allowedmkdir http_objects tshark -r morph.pcap --export-objects http,http_objects
This recovered the router pages and the upload transaction artifacts, including:
http_objects/Upgrade.asphttp_objects/Management.asphttp_objects/upgrade.cgihttp_objects/upgrade(1).cgi
At this point the challenge becomes a straightforward reconstruction of what the administrator saw and uploaded.
Step 4: Recover the old firmware version from the web UI
Searching the recovered ASP pages for model and version strings:
bash read-only • copy allowedrg -n 'WRT610N|1\.00\.00|B18|WRT610NV1' http_objects/*.asp
The key evidence is in Upgrade.asp:
text read-only • copy allowedstyle="FONT-SIZE: 7pt" ... : 1.00.00 B18 style="FONT-SIZE: 8pt"><B>WRT610N</B>
That gives the visible router model WRT610N and old firmware version 1.00.00 B18.
Management.asp provides an additional detail that matters for the flag:
text read-only • copy allowedonclick=window.location.href="WRT610NV1_v1.00.00.cfg"
This backup filename is the strongest evidence for the hardware revision being v1. The main UI only displays WRT610N, but the configuration backup naming convention includes WRT610NV1, so the correct model field for the flag is WRT610N_v1.
Step 5: Extract and parse the firmware upload
The upload is the POST to /upgrade.cgi seen at frame 13300. After exporting objects, the multipart body is preserved in http_objects/upgrade.cgi.
The easiest way to recover the uploaded filename is:
bash read-only • copy allowedstrings http_objects/upgrade.cgi | rg 'filename=|openwrt|Content-Disposition'
Output:
text read-only • copy allowedContent-Disposition: form-data; name="file"; filename="openwrt-24.10.0-bcm47xx-generic-REDACTED-v1-squashfs.bin"
This single filename gives almost everything needed for the new firmware portion:
- manufacturer:
Linksys - model/revision:
WRT610N v1 - new firmware name:
OpenWrt - new firmware version:
24.10.0
I also verified that the extracted firmware image itself matches the same naming pattern:
bash read-only • copy allowedstrings openwrt-24.10.0-bcm47xx-generic-REDACTED-v1-squashfs.bin | \ rg 'OpenWrt|24\.10\.0|wrt610n|linksys'
The important point is that the router upload is not ambiguous: the multipart POST explicitly contains the OpenWrt image filename.
Solution
Assemble the flag fields in the required order:
- Manufacturer:
Linksys - Model:
WRT610N_v1WRT610Nis shown in the UIv1is justified byWRT610NV1_v1.00.00.cfginManagement.asp
- Old firmware version:
1.00.00_B18- from
Upgrade.asp
- from
- New firmware name:
OpenWrt- from uploaded firmware filename
- New firmware version:
24.10.0- from uploaded firmware filename
Final flag:
text read-only • copy allowedDawgCTF{REDACTED}
Minimal reconstruction commands:
python read-only • copy allowed#!/usr/bin/env python3 import base64 from pathlib import Path import re upgrade = Path("http_objects/Upgrade.asp").read_text(errors="ignore") management = Path("http_objects/Management.asp").read_text(errors="ignore") multipart = Path("http_objects/upgrade.cgi").read_text(errors="ignore") old_fw = re.search(r'1\.00\.00 B18', upgrade).group(0) model = re.search(r'WRT610N', upgrade).group(0) rev = 'v1' if 'WRT610NV1_v1.00.00.cfg' in management else 'unknown' filename = re.search(r'filename="([^"]+)"', multipart).group(1) assert base64.b64decode('OmFkbWlu').decode() == ':admin' assert filename == 'openwrt-24.10.0-bcm47xx-generic-REDACTED-v1-squashfs.bin' flag = f'DawgCTF{{Linksys_{model}_{rev}_{old_fw.replace(" ", "_")}REDACTED}}' print(flag)
Key Takeaways / Lessons
- Mastering pcap_triage, http_object_extraction, basic_auth_decoding, firmware_upload_analysis was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-04-07 • CUSTOM • Modem Metamorphosis • Difficulty: Easy