Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
BlackLotus-Z2A-Challenge — BlackLotus-Z2A-Challenge, Nada que ver aquí por ahora, por favor siga de largo. | Kitploit
Herramientas/GitHubGitHub/spiralbl0ck/blacklotus-z2a-challenge
Análisis EstáticoIngeniería InversaAnálisis de MalwareCTFAprendizaje y Educación
GitHubspiralbl0ck/blacklotus-z2a-challenge

BlackLotus-Z2A-Challenge

BlackLotus-Z2A-Challenge, Nada que ver aquí por ahora, por favor siga de largo.

Ver Repositorio

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
32hace 3 añosAún no revisado

BlackLotus-Z2A-Challenge

BlackLotus-Z2A-Challenge, nada que ver aquí por ahora, por favor sigue adelante

Primero lo primero Capture23

Solo por razones estéticas, tomaré prestadas (robaré) descaradamente :)) de la solución de @darthmaulware(Ryan “DM” Smith) las reglas de detección de YARA solo para que se vea profesional. Ve a revisar su Twitter, ¡es una persona jodidamente genial! PD. Ryan, por favor no te enojes porque te las robé :))) y gracias por el apoyo en Discord :)

Por favor revisa también su trabajo :)

https://gitlab.com/malre-rcs/zero2automated/-/blob/main/solutions/bi_weekly_challenge/BlackLotus_20230321/BlackLotus_HTTP_Downloader.ipynb``` rule Blacklotus_HTTP_Downloader { meta: description = "Rule to detect Blacklotus HTTP Downloader" author = "Darth Maulware" sha256 = "d68f668b4240f9518e4f80499d93d8c5a1eddece0771658c33ae916cc54f5a66"

root@kitploit:~
    strings:
        $opcode1 = {48 89 4C 24 08 48 89 54 24 10 4C}
        $opcode2 = {89 44 24 18 4C 89 4C 24 20 48 83}
        $opcode3 = {EC 28 B9 31 62 D7 2E 90 90 E8 ??}
        $opcode4 = {?? ?? ?? 48 83 C4 28 48 8B 4C 24}
        $opcode5 = {08 48 8B 54 24 10 4C 8B 44 24 18}
        $opcode6 = {4C 8B 4C 24 20 4C 8B D1 90 90}

    condition:
        (uint16(0) == 0x5a4d and filesize < 500KB and all of them)

}

root@kitploit:~
Además, por razones estéticas, también robaré esto porque se ve genial :) de nuevo, lo siento ryan, por favor no te enojes conmigo :)```
        C:\\Users\\REM\\Desktop>capa.exe -f pe -r capa-rules-5.0.0 d68f668b4240f9518e4f80499d93d8c5a1eddece0771658c33ae916cc54f5a66.exe
        matching: 100%|████████| 124/124 [00:02<00:00, 46.96 functions/s, skipped 1 library functions (0%)]

        +------------------------+------------------------------------------------------------------------------------+
        | ATT&CK Tactic          | ATT&CK Technique                                                                   |
        |------------------------+------------------------------------------------------------------------------------|
        | DEFENSE EVASION        | Obfuscated Files or Information T1027                                              |
        | DISCOVERY              | Process Discovery T1057                                                            |
        | EXECUTION              | Shared Modules T1129                                                               |
        +------------------------+------------------------------------------------------------------------------------+

        +-----------------------------+-------------------------------------------------------------------------------+
        | MBC Objective               | MBC Behavior                                                                  |
        |-----------------------------+-------------------------------------------------------------------------------|
        | ANTI-BEHAVIORAL ANALYSIS    | Debugger Detection::Process Environment Block BeingDebugged [B0001.035]       |
        |                             | Debugger Detection::Process Environment Block NtGlobalFlag [B0001.036]        |
        | CRYPTOGRAPHY                | Encrypt Data::RC4 [C0027.009]                                                 |
        |                             | Generate Pseudo-random Sequence::RC4 PRGA [C0021.004]                         |
        | DATA                        | Encode Data::XOR [C0026.002]                                                  |
        | DEFENSE EVASION             | Obfuscated Files or Information::Encoding-Standard Algorithm [E1027.m02]      |
        +-----------------------------+-------------------------------------------------------------------------------+

        +------------------------------------------------------+------------------------------------------------------+
        | CAPABILITY                                           | NAMESPACE                                            |
        |------------------------------------------------------+------------------------------------------------------|
        | execute syscall instruction (35 matches)             | anti-analysis                                        |
        | check for PEB BeingDebugged flag (2 matches)         | anti-analysis/anti-debugging/debugger-detection      |
        | check for PEB NtGlobalFlag flag                      | anti-analysis/anti-debugging/debugger-detection      |
        | encode data using XOR (2 matches)                    | data-manipulation/encoding/xor                       |
        | encrypt data using RC4 PRGA (2 matches)              | data-manipulation/encryption/rc4                     |
        | get process heap flags                               | host-interaction/process                             |
        | get ntdll base address (3 matches)                   | linking/runtime-linking                              |
        | parse PE header (2 matches)                          | load-code/pe                                         |
        | resolve function by parsing PE exports (2 matches)   | load-code/pe                                         |
        +------------------------------------------------------+------------------------------------------------------+

Siendo honesto, si yo fuera tú no confiaría al 100% en capa (al menos en este caso específico) porque aquí dice que la muestra usa rc4 cuando en realidad usa aes, pero da igual, como se mencionó, esto es estrictamente por estética :)

Antes de empezar, te encontrarás a lo largo de este informe con un montón de

1

Por favor, ignora esto, ya que ida no logra desensamblar esto correctamente; esto es

1

¿Y esto crashea el depurador? ¿Por qué?

porque intenta escribir en la dirección 0, lo que en el folclore hacker se conoce como escribir en una dirección de puntero nulo, algo que fue explotado ampliamente para obtener CE (ejecución de código), y esto obviamente ha sido mitigado.

Y con la mitigación actual, si intentas escribir en 0, ese proceso fallará; en nuestro caso, el malware y, en consecuencia, el depurador.

Ahora si abrimos esto en ida

1

Renombré cada función para indicar alguna lógica que hace. Empecemos con la primera función, do_syscall() Capture23

Notamos inmediatamente el uso de syscalls, que es un método conocido para hacerle la vida más difícil a un analista cuando se trata de análisis dinámico.

Para aquellos que no estén familiarizados con las syscalls en Windows, aquí hay un buen video hecho por oalabs(https://www.youtube.com/watch?v=Uba3SQH2jNE). Por favor, míralo porque yo también lo hice y me ayudó mucho a entender qué sucede en esta función

Si inspeccionamos el "pseudo-código" resuelto por ida, vemos que se ve así

Capture4

Si inspeccionamos estáticamente solve_hash, se ve así

1

2

Desde una perspectiva pseudo, se ve así

4

Por favor, consulta solve_hash.py para ver mi "emulación" de esto, en caso de que quieras ver una pieza de automatización y quieras descubrir cómo se resuelven las syscalls mediante un algoritmo de búsqueda por hash. Pero aun así, esto es parte de un proyecto llamado SysWhispers2, o al menos eso es lo que supongo que los autores del malware usaron como inspiración. Aun así, por favor consulta el videoclip anterior de oalabs para una mejor comprensión.

De todos modos, la función anti_debug es fácilmente evadible y bien conocida(https://anti-debug.checkpoint.com/techniques/debug-flags.html#manual-checks-ntglobalflag). La forma de evadirla es tener scyllahide instalado y la opción NtGlobalFlag marcada (que deberías tener activada por defecto si usas x86dbg). Aun así, esto es lo que se supone que debes comprobar

4

Y así es como se ve la "pseudo-función" anti-debug

4

Bastante simple, si me preguntas.

A continuación tenemos la función check_inmemory_ldr, que se ve así

1

2

Ahora, para el propósito del análisis de la función, si le preguntamos amablemente a x86dbg, podemos ver que si ejecutamos hasta la instrucción syscall, x86dbg será tan amable de devolvernos la syscall que está a punto de ejecutar. En nuestro caso

2

Ahora, según el contexto actual, podemos suponer que Ntsetinformationthread se usará como una especie de truco anti-análisis. Seguramente, si hacemos una búsqueda rápida en Google, encontramos esto: https://ntquery.wordpress.com/tag/ntqueryinformationthread/

Afortunadamente, fácilmente evadible, solo hay que parchearlo con nop+ret :)

=============================================================================

Siguiendo el orden de ejecución, después de esta función viene

4

Una vez más, si inspeccionamos para ver qué hace

Capture4

Simplemente comprueba una bandera en el TEB para ver si el proceso actual (el exe en nuestro caso) está siendo depurado. Esto es, nuevamente, fácilmente evadible, ya que es un método conocido(https://anti-debug.checkpoint.com/techniques/debug-flags.html#manual-checks-peb-beingdebugged-flag). De la misma manera que usamos scyllahide, esta vez debes tener marcada
Capturez

que debería estar activada por defecto

=============================================================================

Ahora custom_hash2_and_aplib_possible, que se ve así

2

Y desde una perspectiva de grafo

3

Por favor, consulta decompress_aplib.py para ver la "emulación" de esta función.

Explorando get_ntdll_and_unhook2, se ve así

1

2

Desde una vista de grafo, se ve así

1

No está nada mal :))

Retrocediendo un poco, tenemos aplib_decompress, que ahora se ve así

1

Desde un análisis de código estático se ve así

1

2

3

4

Mmm, un poco grande, pero nada de qué preocuparse, amigos; es factible :)

Si usas el script de emulación aplib_decompress.py, deberías terminar con algo como esto

1

Una cosa interesante que no noté en otros blogs/análisis fue esto: si volvemos a mirar el pseudo-código de ida para ntdll_and_unhook2

1

verás un memcpy interesante

en un momento, cuando estaba haciendo el análisis dinámico, noté que se cargaba otro dll, que era otra versión de ntdll

1

si miramos en el depurador, se ve así

1

No pude detectar qué estaba enganchado/parcheado, pero si alguien lo sabe, por favor haga un pull request y edite este documento. También, en mis intentos de encontrar qué se engancha, intenté hacer bindiff entre los dos ntdll y desafortunadamente no encontré nada, pero podría ser porque ya estaba haciendo diff sobre un dll del sistema que estaba infectado, así que no fue una ejecución limpia, por eso quizás ¯_(ツ)_/¯

1

=============================================================================

Continuando con el proceso de análisis, entre las funciones no explicadas tenemos some_hasing y ntquertyinformationprocess_anti_debug, que no han sido explicadas. check_if_being_debug_through_teb y anti_debug ya han sido explicadas, afortunadamente, porque se usaban en la/las funciones anteriores, así que por favor lee las secciones anteriores si quieres repasar el conocimiento sobre ellas. Me gustaría empezar primero con ntquertyinformationprocess_anti_debug y luego terminar con some_hasing.

Inspeccionándola, vemos que la misma función se llama 3 veces.

1234

Y desde una perspectiva de ensamblador

1

2

Por conveniencia, ya la he nombrado, que es ntquertyinformationprocess_ProcessDebugPort. ¿De dónde supe que las funciones llamadas eran ntquertyinformationprocess_ProcessDebugPort? Inspeccionándolas se revela una llamada a función ya vista/algoritmos conocidos para nosotros

1

¿Y qué hay de los comentarios hechos en ida? Bueno, si buscas ntqueryinformationprocess en Google, nos encontramos con un buen recurso sobre anti-debugging(https://anti-debug.checkpoint.com/techniques/debug-flags.html). Si lo seguimos, podemos ver que nos explica que, basándose en ciertos valores pasados como parámetros a estas funciones, puede usarse como método anti-debugging.

Por ejemplo, para la primera llamada podemos ver los siguientes argumentos de pila en el depurador

1

Si ahora vamos y consultamos la página de MSDN para ntqueryinformationprocess

1

El mismo proceso se repite para las siguientes dos syscalls

2

donde 0x1e es específico para el método anti-debug ProcessDebugObjectHandle(https://www.apriorit.com/dev-blog/367-anti-reverse-engineering-protection-techniques-to-use-before-releasing-software)

y finalmente ProcessDebugFlags

2

¿Entonces cómo las evadimos? Cálmate, amigo, porque ScyllaHide te cubre las espaldas

obama-pew

Como puedes ver

1

¡Así que estamos a salvo! No del todo. Aunque ScyllaHide nos cubre para las primeras 2 syscall, para la última syscall tenemos que hacerlo manualmente. ¿Y qué demonios hago? Bueno, ¡solución simple! Regresamos de esta función, es decir, de toda ntquertyinformationprocess_anti_debug, y ponemos eax a 0. Entonces, en circunstancias normales, se ve así

1

Y con nuestra "ayuda" se ve así, y dejamos que la ejecución continúe de forma segura :)

1

=============================================================================

Ahora some_hasing, ya conoces el procedimiento

1

Y ahora el pseudo-código

2

Notamos algo extraño aquí. El pseudo-código de ida falla aquí... porque si seguimos el grafo después de call_syscall, hay más instrucciones por desensamblar. Entonces, ¿qué hacemos ahora? Pues nos apoyaremos en el depurador para analizar este código dinámicamente...

Así que vemos que la syscall que hace es

1

Ahora, si buscamos ntquerydefaultlocale, Google muestra que es una API no documentada que toma 2 argumentos(http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FLocale%2FNtQueryDefaultLocale.html). Genial, ¿y qué hace? Devuelve el identificador de configuración regional actual. Genial, entonces ¿qué demonios es un identificador de configuración regional? Según MSDN (https://learn.microsoft.com/en-us/windows/win32/intl/locale-identifiers), es un valor de 32 bits que consiste en un identificador de idioma y un identificador de orden de clasificación. En resumen, qué idioma hablas en ese PC :)

Después comprueba si la API no falló al ejecutarse, y si no falló, toma el valor devuelto por ntquerydefaultlocale, le resta 0x419 y lo compara con 0x26 (probablemente una constante), como puedes ver en la imagen a continuación.

1

Si no es menor o igual a 0x26, lo compara con 0x818; de lo contrario, hace la misma comparación con 0x819, como puedes ver claramente

2

Entonces, ¿qué demonios está pasando aquí? ¿Y por qué estas constantes específicas? Bueno, iré al grano. Mientras buscaba diferentes constantes, me topé con este artículo(https://www.cnblogs.com/DirWang/p/17281690.html#autoid-8-0-0), de un investigador que ya analizó BlackLotus mejor de lo que yo podría. Y como alguien dijo una vez: "No puedes hacer trampa en el análisis de malware, solo puedes hacer tu trabajo más fácil". Entonces, lo que dijo el investigador es que, básicamente, esta función comprueba constantes específicas que identifican qué idioma se habla en el ordenador. En su artículo, proporciona un enlace a esto(https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-LCID/[MS-LCID].pdf), que es como un documento estándar de Microsoft con cada identificador de idioma.

Ahora, usando nuestra lógica hax00r l33t, podemos deducir que probablemente 0x26 sea como un desplazamiento utilizado, es decir, los siguientes 0x26 identificadores de idioma después de 0x419, que son

2

Si también inspeccionamos ese documento, podemos ver que 0x818 corresponde a

2

y 0x819 a

2

Y sabemos por "investigaciones" anteriores/informes en línea que este malware no se ejecutaba en ciertos PC de ciertas regiones del mundo, por lo que podemos concluir que esta función comprueba en qué región se encuentra la máquina infectada.

=============================================================================

Una locura hasta ahora, ¿no, colega? ¿Qué sigue? ¡Le servimos la función some_more_syscall! ¡De acuerdo! ¿Qué tienes ahí, tío? Aquí está

1

¡Queremos más! ¡Claro que sí, colega!

2

3jgukd

1

Hmmmm

1

Así que comprueba si hay un kernel debugger presente(https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi/system_information_class.htm)(0x23), ¡a comprobar, a comprobar!

¿Y qué? ¡Ajá! Tenemos pcr (fiesta de pilas y combinaciones)

2

=============================================================================

Ahora si inspeccionamos la función iterate_over_modules(), se ve así

1

Desde una perspectiva de "pseudo-código", se ve así

2

Desde un punto de vista independiente, parece que el ensamblador y el pseudo-código de ida coinciden. Entonces, ¿cuál es la lógica de esta función? Bueno, bastante simple: itera sobre los módulos en memoria (dll's) y los compara contra una lista de hashes :) v4[0] = 0x1E7EACEF; v4[1] = 0x4468A620; v4[2] = 0x68536B95; v4[3] = 0x73EBBB53; v4[4] = 0xDA165168; v4[5] = 0xB24D33A7; v4[6] = 0xB1E2CEC6; v4[7] = 0x5136992; v4[8] = 0x98C500D9; v4[9] = 0x3E0169B6;

Y si no se encontraron dll's en memoria con el mismo hash, devolvemos 0; de lo contrario, 1, y crasheamos el depurador. Entonces, con tal conclusión, podemos decir que este es otro método anti-análisis. Correcto, pero ¿qué hay de cada uno de los valores hash? Bueno, haré trampa de nuevo (como alguien dijo una vez, no puedes hacer trampa en el análisis de malware, solo hacer tu vida más fácil :) ). El investigador asiático mencionado anteriormente fue tan amable de proporcionarnos una lista de valores de los cuales se derivaron estos valores.

sbiedll.dll dbghelp.dll api_log.dll dir_watch.dll pstorec.dll vmcheck.dll wpespy.dll cmdvrt64.dll avghookx.dll snxhk.dll

Ahora, para ver dinámicamente si alguno de los valores corresponde a algún dll mencionado

2

Y efectivamente, así es :)

Pero, ¿cómo llegué a la conclusión de que el algoritmo comprueba estos valores? Bueno, cuando emulé una parte de este malware, tuve que reimplementar iterate_over_module_name_and_hash (en el archivo solve_hash_syscalls.py) y en esta función tenemos

1

donde x (argumento pasado) en este caso es v2, que es un array (un puntero) de valores que se incrementa (hacia dónde apunta en el array) siempre que no coincida con ninguno de los valores ya mencionados anteriormente. Vaya, eso es un trabalenguas :P

¡Genial! Siguiente

=============================================================================

iterate_over_modules2, más o menos la misma historia aquí

1

Y pseudo-código

2

Más o menos la misma historia, solo que con hashes diferentes :)

v5[0] = 0x7D73878E; v5[1] = 0xEF36424B; v5[2] = 0xAF64BC2B; v5[3] = 0x1DBBC879; v5[4] = 0xAE6D1D56; v5[5] = 0x7B3242F2; v5[6] = 0x14D922B9; v5[7] = 0x4C92DF53;

que corresponden a

sample.exe bot.exe sandbox.exe malware.exe test.exe klavme.exe myapp.exe testapp.exe

=============================================================================

iterate_over_modules3, la misma historia aquí

1

Y pseudo-código

2

la misma historia, hashes diferentes :)v4[0] = 0x42D12D59; v4[1] = 0xEC5D7AA; v4[2] = 0x861E460F; v4[3] = 0x84BCC8DB; v4[4] = 0x6474D72B; v4[5] = 0xB8B9C504; v4[6] = 0x69A0620E; v4[7] = 0x6017EE43; v4[8] = 0xE93BE2E0; v4[9] = 0x149EFC55; v4[10] = 0xE3FA84A4; v4[11] = 0x7CFDD7AF; v4[12] = 0x5B098C67; v4[13] = 0x2F1FB18E; v4[14] = 0xFE8F2B18;

que corresponden a

prl_cc.exe prl_tools.exe qemu-ga.exe vmtoolsd.exe vmwaretray.exe vmwareuser.exe VGAuthService.exe vmacthlp.exe vboxservice.exe vboxtray.exe VMSrvc.exe VMUSrvc.exe xenservice.exe

=============================================================================

Anti_debug_measure_1 terminé renombrándolo a anti_debug_measure2_RtlAddVectoredExceptionHandler_int3. Por qué, lo verás en un minuto. Así que se ve así

1

Y desde una perspectiva de pseudocódigo se ve así

1

Entonces, ¿qué demonios es esto? Bueno, básicamente está creando un manejador de excepciones para __debugbreak(int 3) que ejecutará código cada vez que se genere int3. Terminé buscando más y encontré esto

(https://blog.lexfo.fr/dridex-malware.html) que es un recurso interesante que nos permite saber que esto es simplemente un mecanismo anti-debug, y en nuestro caso simplemente ejecutamos esta función, ignoramos sub_13F2820D0 que se activa cada vez que ejecutamos int3 y parcheamos eax a 0 :) así que en la ejecución en memoria se ve así :)

Antes del parche

1

Después del parche

1

Después de eso sales de la función y también editas rax/eax a 0 para saltarte el jne que hace fallar al depurador

1

=============================================================================

Anti_debug_measure_2 que luego cambié a anti_debug_measure2_RtlAddVectoredExceptionHandler_int2

1

2

Otra vez nada nuevo bajo el sol, lo mismo solo que enganchando otra int/syscall, esta vez int2, el mismo truco para evadirlo: usar parcheo dinámico del valor de retorno para omitirlo :)

Si buscas "anti analysis 2dh" en Google aparecerá un montón de cosas, así que sí, puedes usarlo como referencia para aprender más sobre eso; no pasé mucho tiempo con esto :)

Para este, incluso si intentas saltarlo (step over), terminará en ret como aquí

1

y para evadirlo simplemente ejecuta hasta el retorno y listo :)

=============================================================================

Ahora viene anti_debug measure heap, que luego renombré a iterate_over_current_process_and_check_again_hases

1

Y una característica interesante de esta función es que usa ntquerysysteminformation dentro de iterate_over_current_process_and_hash_check para listar todos los procesos en ejecución. Así se ve iterate_over_current_process_and_hash_check

1

2

Bien, pero ¿cómo diablos llegué a la conclusión de que iterate_over_current_process_and_hash_check hace lo que su nombre sugiere? Bueno, primero está la llamada a ntquerysysteminformation, que si buscas en Google verás que se usa para obtener una lista de procesos en ejecución, y luego simplemente hice una suposición fundamentada basada en el siguiente fragmento de código LODWORD(v4) = RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, 8u, v10); v3 = v4; v5 = ntquerysysteminformation(); v6 = v3; .... memcpy(v9, v6[8], *(v6 + 28)); v9[*(v6 + 28) >> 1] = 0; if ( some_hash_0x1003F(v9) == a1 ) de que copiaría la lista de procesos, iteraría sobre cada uno y compararía cada hash del array anterior con el proceso que estuviera en ejecución. Ahora de nuevo, gracias al blog de investigación del asiático porque no sé cómo demonios llegó a obtener el nombre real de los valores del array v4. Consulta iterate_over_modules.py por si quieres ver cómo emulé esto.

PD.: si depuras esta función dinámicamente, terminarás encontrándote con int 2d de nuevo, y la solución es la misma que la mencionada arriba, solo que básicamente corres hasta el retorno 0xf veces, lo que básicamente recorre el heap, y después de eso, si quieres asegurarte de llegar al retorno de iterate_over_current_process_and_check_again_hases, simplemente pon un breakpoint al final de esta función y estarás a salvo :)

============================================================================= anti_debug_measure_heap

1

2

1

Así que sí, tenemos la suerte de que esto no es tan grande, y además ya hemos implementado demangle_strings. Ahora he reimplementado esto para arrays más grandes; por favor ve a anti_debug_measure.py .

esto básicamente comprueba contra``` \Registry\Machine\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters \Registry\Machine\SYSTEM\ControlSet001\Services\vioscsi \Registry\Machine\SYSTEM\ControlSet001\Services\VirtIO-FS Service \Registry\Machine\SYSTEM\ControlSet001\Services\VirtioSerial \Registry\Machine\SYSTEM\ControlSet001\Services\BALLOON \Registry\Machine\SYSTEM\ControlSet001\Services\BalloonService \Registry\Machine\SYSTEM\ControlSet001\Services\netkvm \Registry\Machine\SOFTWARE\VMware, Inc.\VMware Tools \Registry\Machine\HARDWARE\ACPI\DSDT\VBOX__ \Registry\Machine\HARDWARE\ACPI\FADT\VBOX__ \Registry\Machine\HARDWARE\ACPI\RSDT\VBOX__ \Registry\Machine\SOFTWARE\Oracle\VirtualBox Guest Additions \Registry\Machine\SYSTEM\ControlSet001\Services\VBoxGuest \Registry\Machine\SYSTEM\ControlSet001\Services\VBoxMouse \Registry\Machine\SYSTEM\ControlSet001\Services\VBoxService \Registry\Machine\SYSTEM\ControlSet001\Services\VBoxSF \Registry\Machine\SYSTEM\ControlSet001\Services\VBoxVideo

root@kitploit:~
Ahora get_oem_key

![1](https://assets.kitploit.com/production/public/readmes/44337/2a188d30cf6be94954d1432a2928bc11c0546da19b9092e5dfc7d2c195e47d54.png)

![2](https://assets.kitploit.com/production/public/readmes/44337/aa44c5cb77b983c38dfa6be61b9ed0482df4082a81ebe73c7f295dd43844669f.png)

![3](https://assets.kitploit.com/production/public/readmes/44337/6227b500e17378e4f4682e86ce1928898be52b0781b496156ce8a975f4ae1226.png)

![4](https://assets.kitploit.com/production/public/readmes/44337/67227ce4e2999496337e5894b1990937f519ebf72574d20532e6ea9a2170f864.png)

![5](https://assets.kitploit.com/production/public/readmes/44337/82fa372a01bbc8dba4d2dec1b0a0ca46836c9c9cd514aecb8637ebcfd6059435.png)

![1](https://assets.kitploit.com/production/public/readmes/44337/24973f6832bf4752014bfe5f77dbc75b2a5254e5ed809b980f98803d35464824.png)

![2](https://assets.kitploit.com/production/public/readmes/44337/b976c0dad1e2b872649a6df1b61d19b220863b0cb770feb5caa92c93ffa9bad7.png)

Primero desenmaraña la cadena a```
 \Registry\Machine\HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0
 \Registry\Machine\SYSTEM\ControlSet001\Control\SystemInformation
 \Registry\Machine\HARDWARE\Description\System
 Identifier
 SystemManufacturer
 SystemBiosVersion
 VMWARE
 QEMU
 VBOX

Y luego consulta
\Registry\Machine\HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0 \Registry\Machine\SYSTEM\ControlSet001\Control\SystemInformation \Registry\Machine\HARDWARE\Description\System

y comprueba sus valores contra qemu,vbox,VMWARE, como se puede ver en el snippet de IDA y en la ventana de x86 :)

1

2

Como se puede ver en el primer snippet, comprueba vmware contra los valores que estaban almacenados en mi VM en el momento del análisis :)

no es gran cosa, solo ejecuta esta función hasta ret y cambia eax al volver a 0 :) para omitir este método antianálisis :)

=============================================================================

ahora get_oem_from_firmware

1

2

3

4

5

Ahora algo interesante: vemos que esta función comienza con sub_13F267288() a la que se le pasa 0x52534D42 como parámetro. Si buscas este valor en Google, te encontrarás con muchas preguntas interesantes en distintos foros, p. ej. (https://ru.stackoverflow.com/questions/778618/c-%D0%9A%D0%B0%D0%BA-%D0%B4%D0%BE%D1%81%D1%82%D0%B0%D1%82%D1%8C-%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D1%8E-%D0%BE%D0%B1-%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B0%D1%85-%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%B0-%D0%BD%D0%B5-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D1%83%D1%8F-wmi) (https://msdn-whiteknight.github.io/answers/html/tools/html/ru.stackoverflow.com/posts/780170.html) (https://www.maldun.com/analysis/YXNkZmRzZmFkc2Y2NDEwNjlkc2Zhc2RmYXNkZg==/) o esto (https://github.com/digitalocean/go-smbios/blob/master/smbios/stream_windows.go), pero lo más interesante es que, después de leer esto y buscar RSMB, puedes llegar a este enlace https://evasions.checkpoint.com/techniques/firmware-tables.html, que nos explica que esto es un método antianálisis :) Genial, entonces, ¿qué diablos hace esto?

Primero vuelca la SMBIOS Firmware Table, luego desofusca una cadena, siendo la primera cadena qemu, y después llama a sub_13F2655E0 con la cadena desofuscada y la tabla de firmware como parámetros. Desde el análisis estático

1

2

precisamente, si ( v4 != v5) llegué a la conclusión de que esto es una implementación tipo strcmp: comprobará lo que haya en la tabla de firmware con la cadena desofuscada. Como se puede ver en el depurador

1

r8 es un puntero a la tabla de firmware y, más interesante aún, podemos ver que bla bla bla algo... virtualbox es el nombre que se encuentra en la tabla de firmware y luego rcx es qemu, por lo que podemos decir con seguridad que esto es una implementación tipo strcmp. Y ciertamente, como se puede ver, estamos a salvo :) en esta comprobación

1

Ahora este proceso se repite para las cadenas VirtualBox, vbox, VBOX, VMware :) En general, la solución para omitir la comprobación de esta función es ejecutarla hasta ret, parchear eax y continuar el análisis :)

============================================================================

Genial, ahora check_oem_key ()

1

2

3

1

2

3

Entonces, ¿qué hace esto? Bueno, el mismo truco explicado anteriormente, pero esta vez con la tabla ACPI. ¿Qué quiero decir con esto? Bueno, es mejor leer estas 14 diapositivas (https://dc4420.org/slides/2015-11-24/acpi_vm_detect.pdf), ellos lo explican mejor, pero es el mismo truco barato :)) esta vez contra BOCHS,BXPC,VMWARE

1

2

============================================================================

Quiero empezar con la función anti_debug_processor_Timing() y luego terminar con check_for_flags(). Así que

1

Así se ve. Entonces, ¿qué hace? Lee el valor actual del timestamp del procesador, luego toma el nombre del procesador (en nuestro caso GenuineIntel), resta el timestamp recuperado del nombre del procesador y simplemente comprueba si el resultado es mayor que 19999.

Después de rdtsc

1

después de cpuid

1

Como se puede ver, la cadena está dividida en 3 registros

1

Y en nuestro caso vemos que "fallamos" esta comprobación y establecemos eax en 1

1

La solución para esta anti-comprobación es simplemente retornar de la función y parchear eax a 0 :)

============================================================================

Ahora entry_to_peb()

1

2

3

4

5

6

7

Desde una perspectiva de pseudocódigo

1

2

3

Entonces, hasta la comprobación if no hay nada nuevo: ya vimos este tipo de algoritmo, así que ¿qué hay de ello? Bueno, si vas al write-up ya referenciado de la investigación asiática, verás que dice que comprueba si la versión de Windows es mayor que win7/server 2008 r2. Pero, ¿cómo se le ocurrió esta idea? Bueno, si leemos http://waleedassar.blogspot.com/2012/08/major-minorsubsystemversion.html, dice

1

también, si además lees esto :)

https://reverseengineering.stackexchange.com/questions/26157/how-to-show-kuser-shared-data-members-in-decompiled-c-code

y aplicas lo que dice aquí, que si se convierte automáticamente a la estructura KUSER_SHARED_DATA, pero aquí mi IDA estaba con errores durante el análisis, así que es lo que hay :)

Para no aburrirte con la misma repetición de más o menos el mismo algoritmo, aquí están las cadenas finales de las funciones obtenidas y desofuscadas :) este fue un proceso agotador, ya que se hizo con un depurador :) fui demasiado perezoso para emular esto.``` user32.dll advapi32.dll Rpcrt4.dll bcrypt.dll ole32.dll Cabinet.dll

CreateWindowExW
ShutdownBlockReasonCreate
ShutdownBlockReasonDestroy
DestroyWindow CloseHandle
CreateProcessW InitializeProcThreadAttributeList
UpdateProcThreadAttribute LoadAppInitDlls Sleep
GetExitCodeProcess
MoveFileExW
OpenSCManagerW OpenServiceW
QueryServiceStatus
StartServiceW
CloseServiceHandle
GetUserNameW
ConvertSidToStringSidW
LookupAccountNameW
CreateWellKnownSid
LookupPrivilegeValueW
ConvertStringSecurityDescriptorToSecurityDescriptorW
RpcStringBindingComposeW
RpcBindingFromStringBindingW
RpcStringFreeW RpcBindingSetOption
RpcBindingSetAuthInfoExW
RpcBindingFree
NdrClientCall2
NdrClientCall3
BCryptOpenAlgorithmProvider
BCryptSetProperty
BCryptGenerateSymmetricKey
BCryptDecrypt
BCryptDestroyKey
BCryptCloseAlgorithmProvider
BCryptGetProperty BCryptGenRandom
CoCreateInstance
CoInitializeEx
CoUninitialize CoInitializeSecurity
CoSetProxyBlanket
if >win7/server 2008 r2 { CreateDecompressor
CloseDecompressor Decompress
}

root@kitploit:~
Y con esto marcamos el final de la primera mitad del desafío de análisis de blacklotus.

============================================================================

Para la segunda mitad

Perspectiva de ensamblador

![1](https://assets.kitploit.com/production/public/readmes/44337/f509798bf72f72025531efc98bbd0a850e571d003e3a39b7ac2e6438d1da93c8.png)

Perspectiva de pseudocódigo

![1](https://assets.kitploit.com/production/public/readmes/44337/23fafc5104114ff3d2086230e1be3d9b2dbe1660120b55ad100af0c8a12baec5.png)

Comenzaremos la disección con la función some_hash()

============================================================================

Perspectiva de grafo

![1](https://assets.kitploit.com/production/public/readmes/44337/2c8d738be9b2f025155521050ba0ea68aaeebd7cf3bd9a5c4fcd122c24722712.png)

Perspectiva de ensamblador

![1](https://assets.kitploit.com/production/public/readmes/44337/04fb6139172c8f4fab8898395d505ad40b8ba52051ca387a2ec93ffe56ff8674.png)

![2](https://assets.kitploit.com/production/public/readmes/44337/7133eb6348241a56009a6a0d1ce87c26a840bbbc2da99bd459b40c8f5654d366.png)

![3](https://assets.kitploit.com/production/public/readmes/44337/1f60aef395eccf029138d3ca7bcbccafd5328b5056bcae635deabadb8005e2c0.png)

Perspectiva de pseudocódigo

![1](https://assets.kitploit.com/production/public/readmes/44337/3ae95f232939daab4e4b2b68fa31d94150b4e9b69abd0cd324e5ecc4f8ffe14b.png)
Descargar herramienta