Recorded run · OpenWrt · AArch64

From two firmware images to one changed routine.

OpenWrt 24.10.3 and 24.10.4 for the same router contain 176 regular ELFs each. Exact comparison removes 106 unchanged common paths. Full analysis and targeted decompilation carry the changed ubusd binary to the empty-pattern guard added upstream.

2 official images176 ELFs each3 changed common paths0 model callstarget not run
Result

The run reaches the event-registration routine at 0x00104a3c in 24.10.3 and 0x001049a0 in 24.10.4. The newer binary checks the pattern length before reading its final byte. Upstream source names the routine and confirms why the guard was added.

THE EVIDENCE PATH

Inspect any step.

RECORDED EVIDENCE

Click a node to inspect it

10 nodes · 10 links
SELECTED05
OPEN

Changed common userland ELFs

Path and SHA-256 comparison leaves three common userland binaries. This narrows the work; it is not a vulnerability verdict.

EVIDENCEbin/busybox · sbin/ubusd · usr/sbin/odhcpd

Counts compare regular ELF files at paths present in both root filesystems. Versioned kernel-module and library paths remain outside the 109-path comparison. Default brief --extract is 64 MiB / 200 files / depth 2; the 176-ELF inventory used sandboxed unsquashfs with a higher file cap. Device nodes still need root.

01 · REDUCE THE CORPUS

Most common binaries did not change.

The two extracted root filesystems each contain 176 regular ELFs. There are 109 paths in common: 106 have the same SHA-256, while busybox, ubusd, and odhcpd changed. busybox and odhcpd were not followed. Sixty-seven paths exist only on each side, mostly under the release-specific kernel-module directories or versioned library names.

109 common ELF paths
├── 106 unchanged
└── 3 changed
    ├── bin/busybox    (not followed)
    ├── sbin/ubusd
    └── usr/sbin/odhcpd (not followed)

Default brief --extract caps at 64 MiB / 200 files / depth 2 and does not keep every rootfs ELF. The 176-ELF table used sandboxed unsquashfs with a higher file cap. An unchanged control matters here: uhttpd has SHA-256 4c2dd929…d480e2 in both releases, so the release-delta question stops there. Follow-up briefs of the other two changed ELFs: busybox is an eight-byte banner timestamp (rebuild noise); odhcpd import maps differ (strcpy 3→1) and were not followed to a patched routine.

02 · TURN A PIVOT INTO ADDRESSES

Three callers, not “strcpy is dangerous.”

The brief records strcpy in a memory/path region. That import alone says nothing about reachability or data flow. r2b verify recovers three dynamic call sites and gives the decompiler a bounded job.

strcpy  dynamic
0x00004b50  fcn.000033c4
0x00004b6c  function unresolved
0x00004ba8  fcn.00004a3c

The third lead sits in the event register/send handler. Source names are added only after checking the pinned upstream code.

03 · COMPARE ONE ROUTINE

The guard is visible in the binaries.

24.10.3 · 0x00104a3c
len = strlen(pattern);
last = pattern[len - 1];

if (pattern[0] == '\0' || acl_ok) {
    strcpy(destination, pattern);
}
24.10.4 · 0x001049a0
len = strlen(pattern);
if (0 < len) {
    last = pattern[len - 1];
    if (acl_ok) {
        strcpy(destination, pattern);
    }
}

The decompiler output is evidence of the changed control flow. The upstream patch ↗ supplies the name ubusd_alloc_event_pattern and explicitly rejects an empty pattern before pattern[len - 1]. The OpenWrt advisory ↗ supplies the security classification.

04 · FULL RUN COVERAGE

See what ran, what was thin, and what stayed off.

radare2completed

63 functions · 71 imports

Ghidracompleted

130 functions

angrcompleted

300 stored nodes · 381 edges

Capstonepartial

instructions only

DWARFchecked

no debug info

Frida / GEFnot run

runtime stays explicit

THE HONEST CLAIM

r2b did not discover the CVE. It made the path to the relevant routine short and reviewable.

Hash comparison supplied the release delta. Named-import verify supplied the caller list. r2b kept the firmware-child relationship, static-tool coverage, caller leads, selected function addresses, review overlay, and next commands. Upstream source supplied names and ground truth.

Kali aarch64 replay on 2026-09-02: same 176 ELFs / 3 changed paths / three 24.10.3 strcpy callers. Extract used bubblewrap. Device nodes still fail without root; that is not macOS-only. Default extract is 64 MiB / 200 files / depth 2; the 176-ELF inventory used a higher file cap.

Download the .r2brDownload case JSON