ByteScope

Firmware Inspector

The first pass over an unknown image: which parts are compressed, what is embedded in it, and what it says about itself.

The image is read in this tab and analysed in a Web Worker — nothing is uploaded.

Firmware image

Drop a .bin, a flash dump, a .img — whatever you want the first pass over. The whole analysis runs in a Web Worker inside this tab.

Drop a firmware image here

or click to browse — up to 64 MiB, read straight off disk

The file never leaves this tab. It is read with the File API, transferred to a Web Worker and dropped when you close the page — there is no upload endpoint behind this page to send it to.

About this tool

The first ten minutes with an unknown image

You have a .bin pulled off a router, a camera or a dev board, and no documentation. The first questions are always the same four: how big is it, which parts of it are compressed, which known formats are embedded in it, and does it say anything about itself in plain text. That is one binwalk run and a couple of strings | grep invocations, and it is what this page does — in a Web Worker, in your own browser, on a file that never moves. What it deliberately does not do is unpack: this tool identifies and slices, so you leave with offsets and lengths rather than a directory of extracted files.

The entropy map, and the one thing it cannot tell you

Entropy is a single number per block: how evenly the 256 possible byte values are spread across it, from 0 for a block that is one repeated byte to 8 for a block where every value appears equally often. Erased flash sits at zero, a bootloader's code and tables land in the middle, and a compressed payload pins the top of the chart and stays there — which is why the boundary between two sections is usually a visible step rather than a number you had to look for. The block size is yours: 4096 bytes shows the shape of the whole image, 256 finds the exact edge once you know roughly where it is. The four bands are padding, structured, mixed and compressed, and the last one is not called “encrypted” on purpose. A byte histogram cannot separate a compressed blob from an encrypted one; a tool that labels it for you is reporting something it does not know.

Signatures, regions, and the gaps between them

The scan walks the image once and reports every offset where a known magic sits: squashfs in four byte orders, JFFS2, CramFS, UBI and UBIFS, uImage, TRX, DfuSe, the DFU trailer, Android boot images, device tree blobs, Netgear CHK, PEM and SSH key markers — plus the whole shared format catalog this site already uses for file-type detection. Overlapping hits are all reported, because a squashfs magic inside a gzip blob is a real fact about the file rather than a mistake to tidy up. Each hit then starts a region that ends at the next hit, or at the length the header itself declared where there was one, which in practice is uImage and TRX and nothing else. When a declared length is shorter than the distance to the next hit, the map is left with a gap — and the gap is drawn, because bytes that no signature claimed are a finding, and stretching a region over them would be a guess wearing a border.

Strings, headers, and a guess that is allowed to say no

Printable runs are extracted in ASCII and UTF-16LE and tagged by shape: url, ip, email, path, version, private-key, ssh-key, certificate, credential, busybox, linux-version, u-boot. A tag is a shape and not a claim — 1.2.3.4 carries both ip and version because it honestly is both, and showing you what a string could be beats picking one for you. Where a header parses you get its fields with the format's own names on them: the uImage load address, entry point and CRCs; the ESP segment table with each segment's load address and length; the TRX offsets; the Android boot page size and kernel command line; the DFU suffix read from the end of the file. And where the architecture follows from one of those, or from a Linux version string that names its target, you get it with the evidence printed beside it. Where it does not follow from anything, you get unknown — never a default, and never the most popular answer.

Nothing is uploaded, which matters more here than on most pages

The files people bring to a firmware inspector are the ones they are least free to send anywhere: an image pulled off a customer's device, a build that has not shipped, a dump from a box that belongs to someone else. This page is a static file with no API behind it. The image is read with the File API, transferred into a Web Worker, analysed there and dropped when the tab closes, and you can confirm it the direct way: leave DevTools open on the Network tab and watch it stay empty while a 64 MB image is analysed.

Frequently asked questions

Is this binwalk in a browser?

It is the first half of one. The entropy profile, the signature scan, the string extraction and the header parsers are the part of a binwalk run that tells you what you are holding, and they are here in full. Extraction is not: nothing is decompressed, no squashfs is mounted and no gzip member is inflated, so you get the offset and the length of the payload rather than its contents. That is a deliberate boundary rather than an unfinished feature — carve the region out with dd and hand it to the real tool, and you have lost nothing except the wait.

Why does it say unknown for the architecture?

Because nothing in your image said otherwise. The guess has exactly three sources and they are tried in order: a uImage header whose arch field is a value U-Boot actually defines, an ESP image header, or a string tagged linux-version that names a target such as mips, armv7l or x86_64. If none of the three fires there is no fourth rule and no fallback, so the page prints unknown and lists which rules were tried. An architecture that nothing in the file supports would look exactly like one that something did, which is the whole reason the honest answer is worth more.

A block is at 7.99 bits per byte. Is it encrypted?

Entropy cannot answer that, and neither can any other tool that only looks at the byte distribution. Compressed data and encrypted data are both close to uniform by design — that is what compression is for and what encryption requires — so 7.99 is consistent with gzip, LZMA, a JPEG, and AES alike. What can separate them is structure at the edges: a compression format almost always leaves a header, a magic or a length field somewhere near the start of the region, and the signature scan will find it. A high-entropy region with no format signature anywhere in or before it is the shape that is worth being suspicious about — but that is an observation to follow up, not a verdict this page will print for you.

The scan found ten thousand hits. Which ones are real?

Start with the confidence column and the table it came from. Confidence is mechanical: eight bytes of magic or more, or four with an alignment constraint, is high; four to seven bytes free-scanned is medium; anything shorter is low. The flood is almost always esp-image, whose magic is the single byte 0xe9 and therefore matches by chance roughly once every 256 bytes — real information when it lands at offset 0 of an ESP flash dump, noise everywhere else, which is why the header panel only offers it at 4 KiB boundaries. Set the minimum confidence to high and the list usually collapses to the handful of hits that describe the actual layout.

How large a file will it take, and what happens at the limits?

Up to 64 MiB, and every limit is reported rather than applied silently. The signature scan stops at 10,000 hits and string extraction stops at 200,000 strings; both caps keep the earliest entries by offset, so what is missing is the tail of the file — and the page says so instead of letting a truncated list read as a complete one. Stop cancels an analysis in flight and shows nothing partial, because a scan interrupted halfway has not seen the rest of the image and its results are indistinguishable on screen from a finished run.