CVE-2024-0244 – A heap buffer overflow in the Canon MF753Cdw printer
With Pwn2Own Ireland 2026 coming up, I wanted to share an unreleased blog post from my time as a P 2026-9-23 19:2:37 Author: www.thezdi.com(查看原文) 阅读量:9 收藏

With Pwn2Own Ireland 2026 coming up, I wanted to share an unreleased blog post from my time as a Pwn2Own contestant. This post covers the discovery and exploitation of CVE-2024-0244, which is an unauthenticated heap-based buffer overflow leading to an arbitrary free() in the Canon MF753Cdw printer featured in Pwn2Own Toronto 2023. This blog post gives an overview of the vulnerability and the exploitation techniques used.

Figure 1 - MF753Cdw printer

Previously, I had exploited the very similarly named MF743Cdw at Pwn2Own Toronto 2022 using a classic stack buffer overflow, so I had a solid baseline understanding of this family of printers and their quirks.

Starting Point

Over the years at Pwn2Own, the Canon family of printers has been exploited many times, which means that many researchers have combed through the firmware. Lots of the more obvious vulnerabilities have been exploited (especially against the proprietary cadm service), so I decided to start vulnerability research against something a bit more obscure that hadn’t been exploited before.

This led to me exploring Canon’s drivers that interact with lesser-used services. The MF753Cdw support page offered a handful of Windows drivers with one of these being for sending faxes. This seemed obscure enough and I therefore chose it as a research target.

Faxing

After installing the fax driver in a Windows virtual machine, the usual Windows print dialog box contained a new entry for sending faxes. Before sending a fax job to the printer, the fax destination information needs to be filled out.

Figure 2 - Required fax information

I then used Wireshark to capture the traffic once the fax job was submitted. Interestingly, the printer accepted the fax request even though no phone line was connected. Behind the scenes, the driver sends many SOAP messages to the printer to initiate the fax job before sending the actual fax payload. These SOAP messages are all sent to the /wsd/print HTTP endpoint.

Figure 3 - SOAP request to /wsd/print

After the fax job has been initiated, a SOAP message with a binary payload is sent to /wsd/print. This message stands out as it's the only SOAP message in the fax flow to contain binary data. Upon closer inspection, the binary payload contains:

• the information entered into the fax destination dialog
• the file and filename to fax
• the Windows username
• the Windows machine name
• a few hundred bytes of unknown data (not shown in the screenshot below)

Figure 4 - Fax job binary payload snippet

Taking a closer look at the binary payload showed that the byte before most of the strings held the length of the string. Perfect!

Figure 5 - String length and values highlighted

Vulnerability Tinkering around with the length fields didn’t initially highlight any issues until I tried a large length value (0xff) for the length of the destination fax number (shown as primarynumberhere in the above screenshot). This caused the fax task to crash and subsequently reboot the printer. Analysing the printer logs showed a few free() related log messages just before the crash as well as register values.

Whilst looking through the firmware, I found a free() function that includes logging. It prints out the address of the object to be freed via UART and then calls the actual free() function.

Figure 6 - free() with logging

By (ab)using the UART shell, I patched all of the relevant calls to free() with the address of dtdo_free_with_log() so they would all log the address of what was going to be freed. After manually sending a variety of malformed payloads, one log message stood out:

Figure 7 - Controlled free() pointer

The pointer passed to free() was fully controlled via a malformed binary fax payload that contained a large string length and lots of A’s as the destination fax number.

The actual root cause of the overflow was never identified, but it can be assumed there is a fax-related object allocated on the heap similar to this:

When the malformed fax job is parsed, the destination fax number is copied into the phone_number array using the provided length. As there are no length checks, the phone_number array overflows into other members of the object on the heap including a pointer (void *unknown). This unknown pointer is subsequently passed to free(), triggering an arbitrary free.

Exploitation

I explored quite a few exploitation avenues but eventually abandoned each one. One potential method involved freeing system-related objects that were allocated at boot at fairly consistent addresses. Subsequently, the attack would cause specific heap allocations to write controlled data in place of the freed system object. The printer would eventually use the system related object (and therefore the attacker controlled data), leading to code execution through a function pointer hijack or the like. Whilst this method did work, it was too unreliable, especially for the competition.

Other methods such as overwriting adjacent chunk metadata weren’t viable either, as the maximum overflow size was only large enough to overflow fields in the vulnerable object itself and not adjacent chunks.

As the competition deadline loomed, I needed to devise an alternative technique. As is no surprise to those familiar with Canon printer exploitation, the BJNP protocol came to the rescue. BJNP is a Canon proprietary protocol that handles device discovery and print jobs. The protocol has a few desirable properties that can aid exploitation:

  1. Any unauthenticated client can send BJNP requests
  2. Multiple requests can be sent, each of which is stored at a known fixed address
  3. Any bytes in the BJNP payload body are accepted (including null bytes)

The combination of the 3 makes for a great way to store shellcode on the printer at a known address, which can then be jumped to after the program flow is hijacked. This works since all dynamic memory on the Canon is RWX. Any address you jump to will execute as code. This presents an interesting opportunity to exploit the arbitrary free. The exploitation strategy was as follows:

  1. Send an initial BJNP request that contains a fake allocated heap chunk with valid metadata and a known size. This is stored at a known BJNP fixed address
  2. Send a second BJNP request that contains the shellcode to execute. This is stored at a different known BJNP fixed address At this point the printer memory looks like this:
  1. Trigger the fax arbitrary free and use the known address of the fake chunk in BJNP buffer 1 (from step 1) to free. This forces the heap manager to add the fake BJNP buffer 1 chunk to the free list.

BJNP buffer 1 is now part of the heap free list:

  1. Trigger a heap allocation that is of a similar size to the previously freed fake chunk so the heap manager will allocate BJNP buffer 1.

BJNP buffer 1 is used to service a heap memory allocation request:

  1. Close the BJNP session from step 1 and start a new session. Data sent by the client will be copied as usual to the fixed BJNP buffer 1 offset, but since BJNP buffer 1 has been allocated as a legitimate heap object, the BJNP client will directly overwrite that heap object.

BJNP buffer 1 contains a legitimate heap chunk, which can be overwritten by starting a new BJNP session:

  1. The BJNP data we supply in the previous step is chosen to overwrite a function pointer in the legitimate heap object so that it points to the shellcode in BJNP buffer 2 (from step 2).

Fortunately, as part of the fax handling process and after the fake BJNP buffer 1 chunk has been added to the free list, a memory allocation request is consistently made that will automatically be placed at the fake BJNP buffer 1 chunk address. This simplifies step 4 as no forced allocation is required. The automatically allocated chunk contains a function pointer that can be overwritten with the address of BJNP buffer 2 shellcode for code execution!

I prepared a few different shellcode payloads. The most interesting one connects back to the attacking machine, retrieves an image, and writes it directly to the printer's display framebuffer. I couldn’t resist showing DOOM on the display:

Figure 8 - Shellcode execution - Doomguy Approved

Conclusion

A lot of work went into finding and exploiting this vulnerability, which couldn’t be reasonably covered in a single blog post. Hopefully, this post gives enough of an overview to understand the vulnerability and the techniques used to exploit it. I hope it will inspire some research for Pwn2Own Ireland 2026, which includes the Canon imageFORCE 1643F Multifunction Copier as a target.

The state of Canon printer security has changed over the years, with the introduction a few security mitigations. Techniques covered in this post may not be directly applicable to newer devices.

You can find me on Twitter at @ByteInsight, and follow the team on Twitter, Mastodon, LinkedIn, or Bluesky for the latest in exploit techniques and security patches.


文章来源: https://www.thezdi.com/blog/2026/9/23/cve-2024-0244-a-heap-buffer-overflow-in-the-canon-mf753cdw-printer
如有侵权请联系:admin#unsafe.sh