Analizando viejo stub.dll de troyano frutas RAT versiΓ³n PiΓ±a

Todo empezΓ³ una vez de esas que andaba aburrido como siempre, y ejecute un .jar al parecer cualquiera, pero en realidad no, era un p@to server del engendro del mal adwind, aΓ±o 2017 mΓ‘s o menos en Noviembre.

Pues como se eso? primeramente intente decompilarlo de otras maneras absurdas ajajaj como por ejemplo, con CFF Explorer, sin resultado alguno, ya que este no contiene runPE, pues lo supe despuΓ©s.

image

El stub.dll en realidad es un .jar (esta vez como no estΓ‘ cifrado nos bastarΓ­a con solo renombrarlo a .jar y ya) el cΓ³digo para extraer las clases del el stub.dll es el siguiente, lo que hace es leerlo completamente y guardarlo en un .jar

public class CrearJar implements ShowData {
     
    private static final Path STUB_PATH =  Paths.get("src/main/resources/stub.dll");
    private static final Path DESTINO_STUB = Paths.get("src/main/resources/clasesStub.jar");
     
    public CrearJar() {
        init();
    }
     
    /**
    * lee el path donde esta el stub.dll y lo volca el contenido en un .jar
     */
    private void init() {
     
        try(final JarInputStream jarInputStream = new JarInputStream(Files.newInputStream(STUB_PATH ));
        final BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(DESTINO_STUB ));
        final JarOutputStream jarOutputStream = new JarOutputStream(bos, jarInputStream.getManifest())) {
     
               JarEntry jarEntry;
     
               while((jarEntry = jarInputStream.getNextJarEntry()) != null) {
                   if(predicate(jarEntry)) {
                       getLogger().info(jarEntry.getName());
                       jarOutputStream.putNextEntry(jarEntry);
                       jarOutputStream.write(readAllBytes(jarInputStream));
                       jarOutputStream.flush();
                   }
               }
           }catch (IOException ex) {
               getLogger().severe(ex.getMessage(),ex);
           }
        }
     
    /**
    * Validar el jarEntry
    * @param jarEntry que se le hara el test
    * @return boolean true si son solo clases, y que no sean directorios, ni tengan $
    */
    private boolean predicate(final JarEntry jarEntry) {
        final Predicate predicate = p -> !jarEntry.isDirectory()
                                                      && jarEntry.getName().endsWith(".class")
                                                      && !jarEntry.getName().contains("$"),
                                                      || jarEntry.getName().contains("_");
        return predicate.test(jarEntry);
    }
        
    /**
    *
    * @return all bytes from stub
    */
    private byte[] readAllBytes(final InputStream input) {
        try(ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
              final byte[] bytesread = new byte[1024];
              int dataRead;
              while((dataRead = input.read(bytesread)) != -1) {
                  baos.write(bytesread,0,dataRead);
              }
              return baos.toByteArray();
        } catch (IOException ex) {
            getLogger().severe(null,ex);
        }
        return new byte[0];
    }
}           

Salida linea 23 del mΓ©todo init(), todas las clases que estΓ‘n contenidas en dicho .jar

19:08:06.783 [main] INFO CrearJar - Desinstala.class
19:08:06.783 [main] INFO CrearJar - Principal.class
19:08:06.783 [main] INFO CrearJar - extra/ClassLoaderMod.class
19:08:06.783 [main] INFO CrearJar - extra/Constante.class
19:08:06.783 [main] INFO CrearJar - extra/Constantes.class
19:08:06.783 [main] INFO CrearJar - extra/RegistryUtils.class
19:08:06.799 [main] INFO CrearJar - opciones/Archivo.class
19:08:06.799 [main] INFO CrearJar - opciones/DesUAC.class
19:08:06.799 [main] INFO CrearJar - opciones/EnviarFile.class
19:08:06.799 [main] INFO CrearJar - opciones/Informacion.class
19:08:06.799 [main] INFO CrearJar - opciones/Instalador.class
19:08:06.799 [main] INFO CrearJar - opciones/Interface_.class
19:08:06.799 [main] INFO CrearJar - opciones/Kille.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion1.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion10.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion12.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion13.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion14.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion2.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion5.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion6.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion7.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion7b.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion8.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion9.class
19:08:06.799 [main] INFO CrearJar - opciones/Opcion9b.class
19:08:06.799 [main] INFO CrearJar - opciones/OrdenCaptura.class
19:08:06.799 [main] INFO CrearJar - opciones/PassAll.class
19:08:06.799 [main] INFO CrearJar - opciones/Pina.class
19:08:06.799 [main] INFO CrearJar - opciones/WebBot.class
19:08:06.799 [main] INFO CrearJar - opciones/a.class
19:08:06.799 [main] INFO CrearJar - opciones/interfaceInfo.class
19:08:06.799 [main] INFO CrearJar - opciones/passFilezilla.class
19:08:06.799 [main] INFO CrearJar - opciones/passIDM.class
19:08:06.799 [main] INFO CrearJar - opciones/passNoip.class

Esta clase es la encargada de decifrar los .class con DES

package extra;
import java.io.ByteArrayOutputStream;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
     
public class Constante {
   public Constante() {
   }
     
    public static byte[] Constantino(String contrasena, byte[] input) {
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            SecretKeyFactory skf = SecretKeyFactory.getInstance(new String(new char[]{'D', 'E', 'S'}));
            DESKeySpec kspec = new DESKeySpec(contrasena.getBytes());
            SecretKey ks = skf.generateSecret(kspec);
            Cipher c = Cipher.getInstance(new String(new char[]{'D', 'E', 'S'}));
            c.init(2, ks);
            byte[] tmp = c.update(input, 0, input.length);
            out.write(tmp);
            tmp = c.doFinal();
            out.write(tmp);
            out.close();
            return out.toByteArray();
        } catch (Exception var8) {
            return null;
        }
     }
}

AquΓ­ esta la main class, el servidor lee el password contenido en un .xml, para descifrar los bytecodes en runtime y cargarlos en memoria por medio del custom Classloader, se ven otras versiones de arabes donde esa contraseΓ±a estΓ‘ expuesta por un endpoint aparentemente ofuscado.

image

Versiones mΓ‘s nuevas de este troyano (Unrecom, Alien spy, JSocket etc), son anti-virtual machine, anti vmware, y mΓ‘s , aquΓ­ muestro algunos .exe que este malware bloquea, que en realidad el cΓ³digo que ejecuta dichas acciones esta cifrado en los .class correspondientes y ofuscados, el mismo paso del Classloader anterior es realizado, parece que el mismo procedimiento se ha heredado a travΓ©z de las versiones de estos RAT

image

La cantidad de .exe que bloquean es algo alta de paso establecen conexiΓ³n vΓ­a SSL/TLS

image

Comments