Segunda etapa: más sideloading
Como ya se ha mencionado, una de las cosas más emocionantes de esta investigación fue descubrir una nueva variante del DLL sideloading: el uso de una segunda aplicación “limpia” como etapa secundaria del ataque. En estos ataques inusuales, el principio (cargador de la primera etapa) y el final (carga útil) eran iguales; la única diferencia estaba en la segunda etapa de este sideloading.
En la Figura 8 anterior, señalamos “Aplicación.exe”, para el que el instalador dejó un acceso directo en el escritorio. En la Figura 11 lo vemos de nuevo. En realidad es el programa XLGame.exe, firmado por Shenzhen Thunder Networking Technologies Ltd, pero renombrado por los atacantes a Application.exe. Tiene una dependencia limpia, libexpat.dll, que forma parte del paquete.
XLGame realizará automáticamente una actualización si encuentra un programa llamado XLGameUpdate.exe en el mismo directorio. El proceso de carga hace uso de esta funcionalidad de actualización automática, ya que el paquete malicioso contiene un ejecutable con este nombre, pero no es el verdadero XLGameUpdate.exe. Se trata más bien de un .exe limpio y firmado por Beijing Baidu Netcom Science and Technology Co.,Ltd.
Y ahora volvemos al proceso habitual de DLL sideloading. Este cargador de segunda fase tiene una dependencia, BASICNETUTILS.dll, que los atacantes han sustituido por una DLL maliciosa. La DLL maliciosa encuentra templateX.txt en el mismo directorio, carga el contenido, desencripta el shellcode del cargador de carga útil y lo ejecuta. (Por supuesto, todos estos archivos se encuentran en el mismo directorio, como se ve en la Figura 7).
Segunda etapa: más sideloading (una variación)
Como se indicó en la introducción, parece que a los atacantes les gusta mucho su estrategia de doble DLL sideloading, intercambiando varias aplicaciones limpias en el nuevo lugar del proceso de sideloading. La Figura 16 muestra un flujo muy similar al esquema anterior, pero el ejecutable limpio es diferente en el cargador de segunda fase. En consecuencia, hay que cambiar el nombre de la DLL del cargador malicioso para que refleje la dependencia de la aplicación limpia sustituida.
Como antes, “Aplicación.exe” es en realidad XLGames.exe. El cargador limpio de la segunda fase se renombra de nuevo a XLGameUpdate.exe, pero su nombre original (real) es KingdomTwoCrowns.exe. No está firmado digitalmente, por lo que no está claro cuál puede ser el beneficio de sustituir el cargador limpio y firmado de Baidu por éste.
Tiene la siguiente ruta PDB
C:\buildslave\unity\build\artifacts\WindowsPlayer\Win32_nondev_i_r\WindowsPlayer_Master_il2cpp_x86.pdb
Este cargador de segunda fase se utiliza para el escenario habitual de sideloading; su dependencia, UNITYPLAYER.dll, se sustituye por una DLL de cargador malicioso. El cargador malicioso encuentra templateX.txt en el mismo directorio, carga el contenido, desencripta el shellcode del cargador de carga útil y lo ejecuta.
Así pues, el cargador limpio de la segunda etapa es diferente, pero el cargador malicioso de la segunda etapa y los archivos de carga útil de esta variación son esencialmente los mismos que en la variación descrita en la sección anterior (aparte de que se les ha cambiado el nombre). De hecho, uno de los archivos de carga encriptados (3fc9405cfe92723bd96aacfd082c16b392fea6e0f108545138026aa6f79137) se utilizó en ambos escenarios. (Hablaremos de la carga útil en la sección final de este artículo).
Segunda etapa: más sideloading (una variación más)
Una vez más, este escenario cambia el ejecutable limpio en el cargador de la segunda etapa, esta vez abusando de una herramienta limpia, firmada digitalmente y ofrecida en su día por HP. Es muy similar al esquema anterior, pero como el ejecutable limpio vuelve a ser diferente en el cargador de segunda etapa, la DLL del cargador malicioso tiene que renombrarse de nuevo para reflejar la diferente dependencia.
El cargador limpio de la segunda fase vuelve a renombrarse como XLGameUpdate.exe. Su nombre original es d3dim9.exe. Está firmado digitalmente por HP Inc.
Este cargador de segunda fase se utiliza para el escenario habitual de sideloading. Su dependencia, d3dx9_43.dll, se sustituye por una DLL cargadora maliciosa. Esa DLL encuentra templateX.txt en el mismo directorio y, una vez más, carga el contenido, desencripta el shellcode del cargador de carga útil y lo ejecuta.
Tercera etapa: por fin, la DLL maliciosa
Los cargadores de la segunda etapa tenían variaciones interesantes, pero todos los caminos conducen a una cosa: el robo de criptocarteras. Para ello, las cargas útiles que vimos en esta investigación fueron bastante constantes.
Al final de la etapa 2, el cargador limpio de segunda etapa (cualquiera que se esté utilizando) llama a una DLL específica y obtiene la versión maliciosa, de nombre idéntico, que los atacantes han colocado en el mismo directorio, al modo clásico de carga oculta de DLL. La DLL maliciosa carga la carga útil desde el archivo template.txt, y luego la desencripta.
El cifrado de la carga útil es una simple combinación de SUB bytewise y XOR:
int __fastcall decrypt(int a1, int a2) { int result; // eax for ( result = 0; result < a2; ++result ) *(_BYTE *)(result + a1) = (*(_BYTE *)(result + a1) - 122) ^ 0x19; return result;
El contenido descifrado es un shellcode cargador, que descomprime y ejecuta la carga útil final. Este registro de ejecución muestra esta descompresión de la carga útil final:
4010ae GetProcAddress(LoadLibraryA) 4010ae GetProcAddress(VirtualAlloc) 4010ae GetProcAddress(VirtualFree) 4010ae GetProcAddress(lstrcmpiA) 401153 LoadLibraryA(ntdll) 4010ae GetProcAddress(RtlZeroMemory) 4010ae GetProcAddress(RtlMoveMemory) 40148e VirtualAlloc(base=0 , sz=20a00) = 600000 401635 GetProcAddress(LoadLibraryA) 401697 LoadLibraryA(ntdll) 401635 GetProcAddress(RtlDecompressBuffer) 4016bd RtlDecompressBuffer(fmat=102,ubuf=600000, usz=20a00, cbuf=4016e3, csz=16789) (Outsz: 20a00) = 0 4011e2 VirtualAlloc(base=0 , sz=26000) = 621000 4011f9 RtlMoveMemory(dst=621000, src=600000, sz=400) 401235 RtlMoveMemory(dst=622000, src=600400, sz=17e00) 401235 RtlMoveMemory(dst=63a000, src=618200, sz=4c00) 401235 RtlMoveMemory(dst=63f000, src=61ce00, sz=1800) 401235 RtlMoveMemory(dst=643000, src=61e600, sz=200) 401235 RtlMoveMemory(dst=644000, src=61e800, sz=2200) 4012ed LoadLibraryA(KERNEL32.dll)
Después de esto, el shellcode carga la DLL de la carga útil final en la memoria y la ejecuta.
Cuarta etapa: la carga útil
La DLL de la carga útil contiene una exportación de nombre no muy apropiado:
dllname: ServerDll.dll 0 1 0x14780 0x15380 F■ck
Esto crea una clave de bandera en el registro. El nombre de la clave será HKCU\SOFTWARE\%COMPUTERNAME%, si GetComputerName devuelve un valor; si no, se utilizará UnkNow.
Bajo esta clave se almacenan múltiples valores:
- Time: registra la fecha y hora de instalación del malware
- CopyC: dirección C2 actualizada (codificada con bytewise XOR 5 + BASE64)
- ARPD: lista de nombres, separados con | . crea un nuevo hilo para cada uno; busca las cadenas isARDll, PluginMe, getDllName – pueden ser nombres de exportación
- ZU: el valor se utiliza en el procedimiento que lee la semilla del monedero para la extensión de Chrome; probablemente proporciona información de destino para la exfiltración del contenido del monedero
- Remark: almacena el nombre de host
La puerta trasera admite un conjunto de códigos de comando numéricos:
Establece la clave de registro “ZU
Códigode | Acción |
0 | Apagar/Reiniciar/Apagar |
1 | |
2 | Establece la clave de registro “Remark”. |
3 | |
4 | Borrar registros de eventos |
5 | Obtener el estado de la extensión nkbihfbeogaeaoehlefnkodbefgpgknn |
6 | Descargar y ejecutar archivo |
8 | Ejecutar comando con ShellExecute, ventana visible |
9 | Ejecutar comando con ShellExecute, ventana oculta |
112 | Obtener contenido del portapapeles |
113 | Establecer contenido del portapapeles |
125 | Ejecuta el comando en una ventana cmd oculta |
126 | Escribe el búfer en un archivo y ejecútalo |
128 | Establece la clave del registro CopyC |
35-37,101-111, 127 | Comprueba las exportaciones PluginMe, isARDL, getDllName, isCSDll, y quizás más |
También contiene una cadena relacionada con MetaMask. MetaMask es un monedero de criptomonedas (Ethereum) disponible, entre otras cosas, como extensión de Chrome. En el pasado, los atacantes que buscaban robar de las criptocarteras se han dirigido a usuarios que tenían instalada esta extensión, y eso es lo que parece estar ocurriendo aquí.
C:\Users\%s\AppData\Local\Google\Chrome\User C:\Users\%s\AppData\Local\Google\Chrome\User Data\Default\Extensions\nkbihfbeogaeaoehlefnkodbefgpgknn\
El nombre del servidor C2, nsjdhmdjs[.]com, se ha asociado a Operation Dragon Breath (también conocida como “APT-Q-27” o “Golden Eye Dog”, como arriba). Algunas de las características de DLL sideloading que hemos demostrado y también el nombre ServerDll.dll son igualmente característicos de este actor de la amenaza.
Cuarta etapa: variaciones de la carga útil: una versión de compilación de depuración y el gh0st de una muestra
También encontramos, en VirusTotal, una versión específica de la carga útil (SHA256: d86f1292d83948082197f0a29fcb69fdec9feb4bf3898d7b8e693c7d5a28099c) que contenía más información interna de lo habitual. También se trata de un ejecutable, a diferencia de las cargas útiles habituales (que son DLL).
La ruta PDB es la habitual
D:\Work\3远控\企业远程控制\Debug\ServerDll.pdb
En este caso, sin embargo, contiene el código fuente de RAT gh0st. Se supone que el archivo fuente debe ser arrojado por uno de los procedimientos, pero ese código nunca se ejecuta:
hFile = CreateFileA(lpFileName, 0x40000000u, 1u, 0, 2u, 0, 0); if ( hFile == (HANDLE)-1 ) v4 = 0; if ( WriteFile(hFile, &gh0st_rat_src, 0xE5B1Au, &NumberOfBytesWritten, 0) ) v4 = 1; CloseHandle(hFile); return v4;
Para esta muestra, el servidor C2 es 23[.]225[.]147[.]227.
También vimos en VirusTotal una muestra similar (sha256: 64613eadd91a803fe103bef5349db04ddfc01b8d115ba7a24a694563123d38ad) que contenía el código fuente de RAT gh0st, pero sin información de depuración ni información PDB. Estas dos versiones de depuración se enviaron a VirusTotal desde Hong Kong, una de las regiones que se sabe que están afectadas, por lo que es probable que se utilizaran en ataques.
La lista completa de IoC está disponible en nuestro GitHub.
Conclusión
El DLL sideloading, identificado por primera vez en productos Windows en 2010 pero frecuente en múltiples plataformas, sigue siendo una táctica eficaz y atractiva para los actores de amenazas. Esta técnica de doble aplicación limpia empleada por el grupo Dragon Breath, dirigida a un sector de usuarios (juegos de azar online) que tradicionalmente ha sido menos examinado por los investigadores de seguridad, representa la vitalidad continuada de este enfoque. Aunque especular sobre futuros usos de la técnica queda fuera del alcance de este post, puede ser útil para los defensores estar atentos al comportamiento que hemos documentado aquí.
Agradecimientos
Gracias a Xinran Wu de SophosLabs y a Andrew Brandt de X-Ops Comms por su ayuda en este artículo.
Dejar un comentario