BusyBox
One binary that provides several hundred Unix utilities. It is the entire userland on most embedded Linux devices, and the reason those devices behave subtly differently from a desktop.
BusyBox v1.35.0 (Debian 1:1.35.0-4+b7) multi-call binary. BusyBox is copyrighted by many authors between 1998-2015. Licensed under GPLv2. See source distribution for detailed copyright notices. Usage: busybox [function [arguments]...] or: busybox --list[-full] or: busybox --show SCRIPT or: busybox --install [-s] [DIR] or: function [arguments]... BusyBox is a multi-call binary that combines many common Unix utilities into a single executable. Most people will create a link to busybox for each function they wish to use and BusyBox will act like whatever it was invoked as. Currently defined functions: [, [[, acpid, adjtimex, ar, arch, arp, arping, ascii, ash, awk, base64, basename, bc, blkdiscard, blkid, blockdev, brctl, bunzip2, bzcat, bzip2, cal, cat, chgrp, chmod, chown, chroot, chvt, clear, cmp, cp,
BusyBox packs several hundred common Unix utilities into a single executable of roughly one megabyte. It calls itself the Swiss Army knife of embedded Linux, and on the majority of routers, cameras and gateways it is not one tool among many: it is the whole userland.
The multi-call design
There is one binary. Every utility is a symlink to it, and BusyBox decides which applet to run by looking at argv[0]:
/bin/ls -> /bin/busybox
/bin/cat -> /bin/busybox
/bin/sh -> /bin/busybox
/sbin/init -> /bin/busybox
busybox with no arguments lists everything compiled in, which is the fastest way to learn what a device can do:
$ busybox
BusyBox v1.31.1 (2020-06-03) multi-call binary.
Currently defined functions:
[, [[, ash, awk, base64, cat, chmod, ... telnetd, tftp, top, ...
You can also invoke an applet explicitly, which is useful when the symlink is missing: busybox wget http://....
Why one binary
Size. Statically linking coreutils, util-linux, procps, net-tools and a shell separately costs tens of megabytes; BusyBox costs one, because all the applets share the same libc, the same startup code and the same helper functions. On a device with 8 MB of flash, that is the difference between shipping and not shipping.
The cost is functionality. Every applet is a reduced implementation. ls may not have --color, ps may not accept BSD-style options, awk handles less than GNU awk, and find supports fewer predicates. This is the single most common source of confusion when working on an embedded target: a command exists, has the right name, and does not accept the option you typed.
What matters for an assessment
busyboxwith no arguments is reconnaissance. The applet list tells you whethertelnetd,tftp,nc,wget,dropbearorftpgetare available before you go looking for them. It tells you what an attacker on the device has to work with, and what you have to work with.- The version string is in the banner, and BusyBox has a real CVE history. Version alone is weak evidence, though: distributors patch selectively, and the applet in question may not even be compiled in.
- The shell is
ash, not bash. No arrays, no[[ ]], no process substitution, differentechobehaviour. Scripts written on a desktop routinely fail on the target for this reason alone. initis often BusyBox init, reading/etc/inittab. That file tells you what starts, on which console, and whether a shell is spawned on the serial line.- Applets can be suid-relevant. A single suid BusyBox binary with a permissive applet set has historically been a straightforward privilege escalation, though on most of these devices everything already runs as root.
In a firmware image
After unpacking a rootfs with binwalk, three things are worth checking immediately: bin/busybox --help output or the version string via strings, the set of symlinks in /bin and /sbin (which is the applet list without running anything), and /etc/inittab for what BusyBox init is told to start.
Pitfalls
- Assuming GNU behaviour. Check
busybox <applet> --helpon the target rather than the man page on your machine. - Assuming an applet exists because the symlink does, or does not exist because it does not. The compiled-in set is the authority; symlinks can be stale.
- Dropping your own statically linked binary onto the device is often easier than fighting a reduced applet, provided you build for the right architecture.
What it pairs with
embedded-linux is the wider environment, rootfs and squashfs-concept cover where it lives, binwalk is how you get to it, and u-boot is what starts the kernel that starts it.
Further reading
Used in these courses
UART is the most common debug interface left exposed on IoT devices. This course takes you from understanding the electrical signal all the way to getting a root shell - the exact path a hardware hacker follows in the field. Every major embedded device you'll ever audit has UART. Learn it once, use it everywhere.
Firmware IoT: Extraction & AnalysisYou have a firmware blob. What now? This course teaches the complete analysis workflow: identify the format, extract the filesystem, explore the structure, and find what matters. Every IoT device has firmware - this is how you read it.