# The Printer Goes BRRRRR!!!

Heap overflow in Canon CADM checkUserPassword2 handler lets attacker corrupt allocator freelist and hijack a function pointer to run shellcode on the printer.

- Payout: $20,000
- Severity: high
- Program: HP, Lexmark, Canon
- Credited: Mehdi Talbi, Rémi Jullian, Thomas Jeunet
- Disclosed: 2022-05-25
- Write-up quality: 9/10
- Original: https://www.synacktiv.com/en/publications/the-printer-goes-brrrrr.html
- Library page: https://bugbountylibrary.com/r/blog%3Asynacktiv-com-en-publications-the-printer-goes-brrrrr-html
- Tags: domain:iot domain:network impact:rce kind:bounty platform:blog sev:high tech:linux technique:reverse-engineering technique:source-review vuln:memory-corruption vuln:rce

**Target:** Canon printer CADM service (TCP 47545/47547/9013)
**Root cause:** pjcc_dec_ope_checkUserPassword2 allocates a 428-byte struct and copies attacker-controlled salt/hash buffers using 1-byte length fields without bounds checks, overflowing adjacent heap chunks.
**Steps:**
1. Dump flash via SOP8 clip/CH341A, extract NCFW firmware from update tool, load in IDA with custom loader
2. Identify CADM handler table at 0x44557b58; opcode 0x83 maps to pjcc_act_checkUserPassword2 (0x4198ecf0)
3. Fragment heap by requesting UI over HTTPS so vulnerable object is served from a large chunk
4. Send CADM packet with opcode 0x83 and oversized salt_len/hash_len to overflow into next chunk's `next` pointer, set to 0x44557b14
5. Send large CADM echo packet to allocate fake chunk overlapping CADM handler table, overwrite pjcc_act_echo with shellcode address embedded in payload
6. Shellcode executes on next echo request, opens TCP socket and paints framebuffer at 0x40900000
**How found:** Reverse-engineered bootloader and firmware, identified DryOS and CADM protocol via nmap and task mapping, then audited CADM decode handlers and spotted unchecked 1-byte length fields copied into fixed inline buffers.
**Exploitation:** Attacker sends crafted CADM checkUserPassword2 packet to overflow heap chunk metadata, corrupts freelist next pointer to a fake chunk at 0x44557b14 (chosen for large size field and NULL next), then a large echo allocation returns the fake chunk overlapping CADM structures; handler pointer overwritten with shellcode address, executed on subsequent echo.
**Escalation:** Overlaps entire CADM handler/state structures to redirect function pointer while preserving state machine integrity, achieving arbitrary code execution from a single heap overflow.
**Insight:** When auditing proprietary binary protocols, map opcode handler tables and focus on decode functions that copy length-prefixed fields into fixed-size inline struct buffers; a 1-byte length is still enough to overflow. Also, a best-fit allocator with no chunk magic checks lets you forge freelist entries at addresses whose +4 field is a large size and +8 is NULL.
