Once PDFiD flags a suspicious PDF (as I covered in that article), pdf-parser is the tool I turn to next. Also written by Didier Stevens, it’s a proper object-level parser that lets me walk through every object in a PDF file, dump its raw or decompressed content, and extract embedded JavaScript or other suspicious payloads for manual review — all without ever rendering the document in a real PDF viewer.
What pdf-parser Does and How It Works
Unlike PDFiD’s shallow keyword counting, pdf-parser actually parses the PDF’s object structure: it identifies each numbered object, its dictionary entries, and any associated stream data. It can:
- List all objects and their types
- Search for objects containing specific keywords (
/JS,/JavaScript,/OpenAction, etc.) - Decompress and display stream content (many malicious payloads are hidden inside
FlateDecode-compressed streams) - Follow object references so you can trace, for example, which object an
/OpenActionpoints to and see exactly what code will run
Because it’s written in pure Python with no PDF-rendering engine involved, it can safely inspect a malicious PDF’s content without any risk of the document actually executing.
Installing pdf-parser
On Kali, it’s typically available directly:
which pdf-parser.py
If missing:
sudo apt update
sudo apt install -y pdf-parser
Or from source:
git clone https://github.com/DidierStevens/DidierStevensSuite.git
cd DidierStevensSuite
python3 pdf-parser.py --help
Basic Syntax
python3 pdf-parser.py [options] <file.pdf>
Options I use regularly:
python3 pdf-parser.py suspicious.pdf # list all objects
python3 pdf-parser.py -a suspicious.pdf # show statistics summary
python3 pdf-parser.py -o 12 suspicious.pdf # show a specific object number
python3 pdf-parser.py -s /JavaScript suspicious.pdf # search objects containing a keyword
python3 pdf-parser.py -o 12 -f suspicious.pdf # decompress/filter stream content of object 12
python3 pdf-parser.py --object 7 --raw suspicious.pdf # dump raw stream bytes
Real Example
Starting with a statistics overview:
$ python3 pdf-parser.py -a suspicious.pdf
PDF Comment '%PDF-1.7'
PDF Comment '%¥±ë'
Type Count
---- -----
obj 42
endobj 42
stream 5
endstream 5
xref 1
trailer 1
startxref 1
/Page 3
/JS 1
/JavaScript 1
/OpenAction 1
Following the OpenAction reference:
$ python3 pdf-parser.py -o 1 suspicious.pdf
obj 1 0
Type: /Catalog
Referencing: 2 0 R, 5 0 R
<<
/Type /Catalog
/Pages 2 0 R
/OpenAction 5 0 R
>>
Then dumping the actual JavaScript object it points to:
$ python3 pdf-parser.py -o 5 -f suspicious.pdf
obj 5 0
Type: /Action
<<
/Type /Action
/S /JavaScript
/JS (this.exportDataObject({cName:"payload.exe", nLaunch:2});)
>>
That output right there — an auto-triggered JavaScript action attempting to launch an embedded executable — is a textbook malicious PDF pattern, and I can read the full logic without any risk of it actually executing.
Real-World Use Cases
Malware analysis and reverse engineering — extracting and reading obfuscated JavaScript inside a malicious PDF to understand its payload delivery mechanism.
Phishing/incident response investigation — confirming exactly what an email attachment does before deciding on containment and remediation scope.
PDF exploit research (in an authorized lab) — studying how specific CVEs abuse PDF object structures by examining proof-of-concept files object by object.
Integration with Other Tools
- pdfid — I always run pdfid first for a fast triage pass, then escalate to pdf-parser for full object-level extraction.
- peepdf — an alternative/complementary parser with an interactive shell, useful for cross-verifying findings.
- CyberChef — I often paste extracted, obfuscated JavaScript strings into CyberChef for deobfuscation (base64 decode, string reverse, etc.) since pdf-parser itself doesn’t deobfuscate JS logic.
Performance and Troubleshooting
- Some malicious PDFs deliberately corrupt their cross-reference table to confuse parsers; use the
-f(force) style options or pdf-parser’s error-tolerant parsing mode to still extract objects despite structural damage. - If a stream doesn’t decompress cleanly with
-f, check the object’s/Filterentry — some PDFs stack multiple filters (e.g.,FlateDecodethenASCII85Decode) that need to be unwound in the correct order. - A mistake I’ve made: forgetting that object numbers can be reused/updated across incremental PDF revisions — always check the
/Prevtrailer entries for older object versions that might hide the real payload.
Best Practices
- Always work inside an isolated analysis VM with networking disabled when examining anything you suspect is malicious.
- Document every object you examine and its content directly in your case notes for reproducibility.
- Cross-reference suspicious JavaScript logic against known exploit kits or malware family signatures before concluding it’s a novel threat.
FAQ
Can pdf-parser execute the JavaScript it finds? No — it only extracts and displays the code as text; it never executes it.
Does it handle encrypted PDFs? It has support for decrypting PDFs when the password or standard security handler is known/empty; heavily protected PDFs may need additional tooling.
Is pdf-parser a replacement for a full PDF library like PyPDF2? No — it’s purpose-built for security analysis and forensic extraction, not for general-purpose PDF editing or rendering.
Summary
pdf-parser gives me the object-level x-ray view of a PDF file that PDFiD’s keyword scan can only hint at. Between the two tools, I can go from “this file looks suspicious” to “here is the exact malicious code it contains” in just a few commands, entirely without opening the file in a vulnerable reader.
References
- Official tool page: https://blog.didierstevens.com/programs/pdf-tools/
- GitHub repository (DidierStevensSuite): https://github.com/DidierStevens/DidierStevensSuite
