A router, an IP camera, an industrial controller: somewhere in that device's firmware there's a Linux kernel with modules, a handful of statically linked binaries, and a userspace built from a dozen open source components. You don't have the vendor's source tree. What you have is a .bin file, or after unpacking it, a pile of .ko , .o and stripped ELF binaries. The question you actually need answered is boring but important: is any of this running something with a known CVE? This comes up constantly in embedded and IoT work, and it's a different problem from auditing your own codebase. You're not hunting for a new bug, you're checking for old ones the vendor never patched. In practice that's the more common finding: not a novel zero-day, but a five-year-old OpenSSL or BusyBox build nobody was tracking. Unpack first, guess later binwalk is still the first move. Point it at the firmware image and let it scan for known magic bytes: SquashFS, CramFS, JFFS2, gzip streams, kernel headers. Most consumer and SOHO firmware is a bootloader plus a compressed filesystem, and binwalk's extraction mode gets you the actual filesystem tree instead of one opaque blob. Once you have that, you're auditing files, not guessing at a blob. Fingerprint by version string, not by hash Hash-matching binaries against known-vulnerable databases sounds appealing and mostly doesn't work here, because vendors relink, strip and sometimes patch without touching anything else. What works more often: grep the extracted binaries for version banners. strings on busybox , openssl , dropbear , lighttpd , zlib and similar userspace binaries usually still leaks a version string even when the binary is stripped of debug symbols, because those strings are compiled-in constants the program itself prints or logs, not debug metadata. strings | grep -iE "openssl|busybox|dropbear|zlib" is unglamorous and it's the single highest-signal step in this whole process. Cross-reference what you find Once you have component plus version, check it against a CVE feed. CVE-bin-tool automates exactly this: it ships a local mirror of NVD-sourced data and matches identified binaries and library strings against known-vulnerable version ranges, so you're not hand-searching each one. It's not perfect, a vendor can backport a fix without bumping the version string, but it turns "manually search five components" into "run one scan and review the hits." When there's no version string: .ko and .o files Kernel modules and object files are the annoying case, because they usually don't carry human-readable version banners the way userspace daemons do. Two things help. modinfo (or reading the .modinfo section directly with readelf if the module can't be loaded to inspect) can surface the vermagic string, which gives you the exact kernel version and config the module was built against, and that alone narrows which kernel-side CVEs are even in play. Past that, you're doing symbol and function-layout comparison: pull the module into Ghidra or radare2 and compare its exported symbols against a known-vulnerable version of the same driver or subsystem. Slower, but it's the real fallback once there's nothing left to fingerprint automatically. A version match is a lead, not a finding The step people skip most: confirming the vulnerable code path is actually compiled in and reachable, not just that a version number matched. Vendors backport security fixes without bumping the version string more often than you'd expect, and plenty of embedded builds compile out entire code paths, a protocol handler that's never enabled, to save flash space. Treat every version-based match as something to verify against the actual disassembly before you write it up, not something to report on its own. None of this is fast, and source-available auditing is genuinely an easier problem, worth being honest about instead of pretending firmware auditing is "run a scanner and done." But the fingerprint-then-verify workflow above is what actually closes the gap between "we shipped this device" and "we know what's running inside it."