Amongst all the files captured in my honeypot all had a common thing: they were executables. All but one. A single lonely C source file. Naturally, this caught my attention, so I decided to read the source code.

After all, it was a rudimentary port scanner by someone going by the alias of Lupu to scan B-class networks. What really got my attention was this line of code:

strcpy(argv[0],"/bin/bash");

That... can not work, right? I mean, is really Linux going to report my process as being the obviously innocuous bash shell just because I modified locally argv[0]?

Well, it does. Take the following source as an example:

#include <unistd.h>
#include <string.h>

int main (int argc, char ** argv) {  
        strcpy(argv[0], "/bin/bash");
        while(1) {
                sleep(10);
        }
}

Compile and execute it.

$ gcc -o sl superloop.c 
$ ./sl arg1 arg2 searchme

And search for the process.

$ ps aux | grep searchme
fernando   4550  0.0  0.0   4220   716 pts/2    S+   10:20   0:00 /bin/bash arg2 searchme  

Hocus pocus! My process is gone.
If you noticed the arg1 parameter is gone from the grep output. Why is that? Because Linux stores all argv strings sequentially and /bin/bash is larger than sl (which is how we called our program). So our memory before the substitution is something like: sl\0arg1\0arg2\0searchme\0 and we are smashing that by writing /bin/bash in the position where sl is located. In C there is no variable overflow checks, and /bin/bash is obviously larger than sl, so we will overwrite some of the following data, which in this case is argv[1].

We can even suppress parameters so it looks like a bare bash shell.

#include <unistd.h>
#include <string.h>

int main (int argc, char ** argv) {  
    strcpy(argv[0], "/bin/bash");
    for (int i = 1; i < argc; i++) {
        strcpy(argv[i], "");
    }
    while(1) {
        sleep(10);
    }
}
$ ./sl arg1 arg2 searchme

$ ps aux | grep searchme
fernando   4623  0.0  0.2  13692  2136 pts/17   S+   10:38   0:00 grep --color=auto searchme

$ ps aux | grep bash
fernando   1931  0.0  0.5  26948  5504 pts/2    Ss   09:15   0:00 bash  
fernando   4538  0.0  0.5  26888  5356 pts/17   Ss   10:20   0:00 bash