International Hack10 CTF 2026
Malware Or Not
International HACK@10 CTF 2026 hack10, forensics, reverse engineering writeup covering Malware Or Not with analysis, solution steps, and final recovery notes.
CTF: International HACK@10 CTF 2026
Category: Forensics / Malware Analysis
Points: 448
Flag Format: hack10{url}
Author: Wh1teB3ar
Challenge Overview
The challenge provides a document file named malware.doc. The goal is to analyze the document in a controlled environment and identify the suspicious URL acting as an Indicator of Compromise.
The final flag must be submitted as:
hack10{url}
Initial Analysis
The document appears simple when opened. The visible content is only:
Testing
Im hacker
However, malicious Office documents often hide behavior inside their internal XML structure instead of visible text.
Modern Word documents are usually OOXML files, which are ZIP archives containing XML files. Even if the extension is .doc, the file may still be ZIP-based.
Initial commands:
file malware.doc
strings malware.doc | grep -Ei "http|https|Target|External|oleObject"
unzip malware.doc -d extracted_doc
After extraction, the important location is:
word/_rels/document.xml.rels
This file stores document relationships, including external objects, links, and embedded references.
Vulnerability / Weakness Identification
The suspicious behavior comes from an external relationship inside the Word document.
The document contains an external OLE object reference:
Target="https://happy.divide.cloud/nowyouknow.html"
TargetMode="External"
This is suspicious because the document can reference a remote resource when opened. In malware analysis, such URLs are treated as IoCs because they may be used for tracking, beaconing, payload delivery, or command-and-control staging.
Exploitation Strategy
The simplest reliable method is static analysis.
Plan:
-
Treat the document as a ZIP archive.
-
Extract all internal files.
-
Search XML relationship files for URLs.
-
Identify relationships using
TargetMode="External". -
Extract the suspicious URL.
-
Wrap the URL using the required flag format.
No dynamic execution is needed.
Proof of Concept
Manual extraction:
mkdir extracted_doc
unzip malware.doc -d extracted_doc
cat extracted_doc/word/_rels/document.xml.rels
Search for URLs:
grep -RniE "https?://" extracted_doc
Expected suspicious result:
https://happy.divide.cloud/nowyouknow.html
Full Python Solver
#!/usr/bin/env python3
import zipfile
import re
import sys
from pathlib import Path
import xml.etree.ElementTree as ET
def extract_urls_from_docx_relationships(file_path):
"""
Extract suspicious external URLs from OOXML relationship files.
Works for .docx files and .doc files that are actually ZIP-based OOXML.
"""
path = Path(file_path)
if not path.exists():
print(f"[!] File not found: {file_path}")
sys.exit(1)
if not zipfile.is_zipfile(path):
print("[!] This file is not a ZIP-based OOXML document.")
print("[*] Falling back to raw string URL extraction...")
data = path.read_bytes()
urls = re.findall(rb"https?://[^\s\"'<>()]+", data)
return sorted(set(url.decode(errors="ignore") for url in urls))
found_urls = set()
with zipfile.ZipFile(path, "r") as z:
print("[*] OOXML ZIP document detected.")
print("[*] Searching relationship files...")
for name in z.namelist():
if name.endswith(".rels"):
content = z.read(name)
# Raw regex extraction as backup
urls = re.findall(rb"https?://[^\s\"'<>()]+", content)
for url in urls:
found_urls.add(url.decode(errors="ignore"))
# XML parsing for TargetMode="External"
try:
root = ET.fromstring(content)
for rel in root:
target = rel.attrib.get("Target", "")
mode = rel.attrib.get("TargetMode", "")
rel_type = rel.attrib.get("Type", "")
if mode.lower() == "external" and target.startswith(("http://", "https://")):
print(f"[+] External relationship found in: {name}")
print(f" Type : {rel_type}")
print(f" Target : {target}")
found_urls.add(target)
except ET.ParseError:
pass
return sorted(found_urls)
def main():
if len(sys.argv) != 2:
print(f"Usage: python3 {sys.argv[0]} <document>")
sys.exit(1)
file_path = sys.argv[1]
urls = extract_urls_from_docx_relationships(file_path)
if not urls:
print("[!] No URLs found.")
sys.exit(1)
print("\n[*] URLs found:")
for url in urls:
print(f" {url}")
# For this challenge, the suspicious IoC is the external URL.
ioc = urls[0]
print("\n[+] Flag:")
print(f"hack10{{{ioc}}}")
if __name__ == "__main__":
main()
Walkthrough
Save the script:
nano solve.py
Run it:
python3 solve.py malware.doc
Expected output:
[*] OOXML ZIP document detected.
[*] Searching relationship files...
[+] External relationship found in: word/_rels/document.xml.rels
Target : https://happy.divide.cloud/nowyouknow.html
[+] Flag:
hack10{https://happy.divide.cloud/nowyouknow.html}
Troubleshooting:
sudo apt install unzip python3
If unzip fails, use:
strings malware.doc | grep -Ei "https?://"
Flag
hack10{https://happy.divide.cloud/nowyouknow.html}
Conclusion
The root cause of the challenge is a hidden external relationship inside an OOXML Word document. The visible document content is only a decoy. The real IoC is stored inside word/_rels/document.xml.rels.
Key lesson: never trust only the visible content of an Office document. Always inspect internal OOXML relationship files for external URLs, embedded objects, and suspicious remote references.