Skip to content

Instantly share code, notes, and snippets.

@Jukoo
Last active July 25, 2025 20:02
Show Gist options
  • Select an option

  • Save Jukoo/b432dfac0ed4a7d1a2f1f2fc9d28a5f5 to your computer and use it in GitHub Desktop.

Select an option

Save Jukoo/b432dfac0ed4a7d1a2f1f2fc9d28a5f5 to your computer and use it in GitHub Desktop.
Technical exploration – BusyBox and the art of the chameleon binary

Technical exploration – BusyBox and the art of the chameleon binary

After using BusyBox for a long time in several custom Linux projects (BusyBox/Linux), one question kept coming back to me: How can a single executable transform into many others, simply by changing its name?

Let me explain: If you rename the busybox binary to ls, it behaves like the ls command. Rename it to cat? It does cat. Same for echo, mkdir, etc. In /bin, all these tools are actually just symbolic links pointing to a single binary:

$ ls    -> busybox
$ cat   -> busybox
$ mkdir -> busybox

And depending on the name under which it is invoked, it adapts its behavior. Impressive, isn't it? 👀

🤔 Intrigued, I had a hypothesis, but nothing certain. So I thought to myself, “Why not reproduce it myself to understand it better?”

Result: it works! 🎉 And it's really very ingenious. Bravo to the creators of BusyBox 👏

💡 Moral of the story: Sometimes, reinventing the wheel is the best way to understand how it turns.

Tinker with the code, break it, test it, adapt it to your needs.

Share your ideas or comments with me—that would be great!

💬 Do you have a Linux tool or command that you'd like to understand or recreate? Leave a comment, I'd be happy to take a look, and maybe even try to recreate it myself 👨‍🔧

⚠️ WARNING: This is a personal implementation based on my understanding. If any experts are reading this, your feedback is welcome!

Have fun—maybe it will spark some new ideas for fun projects 😄.

To compile

$  gcc  metamorphosis.c -o  <elfname> 

Here are some examples you should try after compilation

$  ./<elfname>  ls -l   

Rename the executable

$  mv ./<elfname>   ls 

Create a symbolic link

$  ln -s  ./<elfname>   ls # or cat mkdir, whatever 

HAPPY HACKING ... 🚀

/* @file metamorphosis.c
* @brief Simple reproduction of BusyBox's multi-command behavior
* via argv[0]. One binary, many uses.
* @author Umar Ba <jUmarB@protonmail.com> <github.com/Jukoo>
* @music INTERWORLD - METAMORPHOSIS
* */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/cdefs.h>
#include <string.h>
#include <errno.h>
#include <err.h>
#define METAPATHBINS \
"/usr/bin" \
":/usr/sbin" \
":/usr/local/sbin" \
":/usr/local/bin" /*You can put more paths... */
#define RLS 0x2f2e /* For relative launch symbole "./" #dot-slashed */
#define __not(__rc) (!(~0 ^ __rc))
#define perr(__fsyscall , ... ) \
do{perror(#__fsyscall) ;err(errno , __VA_ARGS__); }while(0)
struct __metamorph_t {
char *_progbn ; /* The Target program basename */
char **_xtrargv ; /* Extra arguments after program basename */
} metamorph ;
/*
* @fn in_systempathbin(const char * )
* @brief check if the passed command is available in path (see METAPATHBINS macro)
* you can add more path ...
* @param const char * - the target command that you look for.
* @return int 0 OK otherwise ~0 not found
*/
int in_systempathbin(const char * target)
{
int is_cmdbuiltin = ~0;
char *syspath =(char *) &(const char[]) {METAPATHBINS},
*token = (__ptr_t )00,
binloc[0xff]={0};
while ((__ptr_t)00 !=(token = strtok(syspath, ":")))
{
if(syspath) syspath=(char *)00;
sprintf(binloc , "%s/%s",token , target) ;
if(__not(access(binloc , F_OK|X_OK)))
{
bzero(binloc , strlen(binloc));
continue ;
}
is_cmdbuiltin^=is_cmdbuiltin;
metamorph._progbn =strdup(binloc);
break ;
}
return is_cmdbuiltin ;
}
/*
* @fn program_basename(const char **)
* @brief checks the base name of the program and preformats it by removing
* the “./” see (RLS macro). Here are two scenarios
1) The base name of the program is the executable itself but not in the system binary path
in this case, you must pass a valid command as 1 parameter
for example ./exec ls -l
the “ls -l” will be executed
2) The base of the program has exactly the same name as one of the commands available on your system.
In this case, the program will act in the same way as your named command
* @param const char ** - the argument vector
* @return int 0 OK otherwise -1
*/
int program_basename(const char **av )
{
metamorph._progbn = (char*)*(av) ;
/* check if the program launch start with ./ #dot-slashed */
unsigned int start_with = *metamorph._progbn | *(metamorph._progbn+1) << 8 ;
if (!(start_with & 0xffff) ^ RLS)
/* prettyfy the program basename without the './' #dot-slashed */
metamorph._progbn = (metamorph._progbn+02) ;
/* See if the program basename is available in system binary path */
return in_systempathbin(metamorph._progbn) ;
}
int main(int ac , char **av , char **env)
{
int pstatus = EXIT_SUCCESS ;
/* See if the program basename is an builtin command */
int builtin = program_basename((const char ** )av) ;
if (__not(builtin))
{
/*
If the basename executable is not a built-in command,
it automatically checks whether the user provides a valid command as the first argument.
*/
/*See if the program receive a valid argument*/
if(!(ac & ~(1)))
{
fprintf(stdout , " %s : USAGE : <COMMAND> [ARGS...]\n", metamorph._progbn);
return EXIT_SUCCESS;
}
metamorph._xtrargv = (av+1);
if (__not(in_systempathbin(*metamorph._xtrargv)))
{
perr(lookup_systempathbin , "Not able to found this '%s' command\n",*(av +1)) ;
free(metamorph._progbn) ;
metamorph._progbn = (__ptr_t)00 ;
return EXIT_FAILURE ;
}
}else
{
*(av) = metamorph._progbn ;
metamorph._xtrargv = av ;
}
/* Creating Sandbox Execution using fork())
* INFO: If you want to go more futher for more precise control ...
* please consult the manpage(2) of clone*/
pid_t sandbox = fork() ;
if (__not(sandbox))
{
perr(fork , "Cannot create Sandbox execution\n") ;
free(metamorph._progbn),metamorph._progbn=00;
pstatus = EXIT_FAILURE ;
}
/* Sanbox Context Execution : a chilp process */
if(!(sandbox & 0xffff))
{
int sandbox_ctexec = execvpe(metamorph._progbn , metamorph._xtrargv,env);
if(__not(sandbox_ctexec))
return errno;
return 0 ;
}
/* Handle sandbox execution: */
if(sandbox & 0xffff)
{
int status =0 ;
wait(&status) ;
/*TODO : Analyse return code status for clean exit */
free(metamorph._progbn) ;
metamorph._progbn = (__ptr_t)00 ;
}
return pstatus ;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment