jueves, 29 de diciembre de 2016

CERBER #Ransomware: Nueva campaña con documentos word con Macros.


Bueno, tenia pensado ya cerrar la persiana del blog por este año, pero no.
Vamos a comentar esta campaña de Ransomware que pide un rescate por los archivos encriptados de las víctimas.

Fuente del correo recibido, no tiene subject.





Contiene un .zip con parte del nombre igual al correo de la victima.




Al abrir el documento una imagen nos indica activar el contenido (Macros).



Aquí los macros que contiene el .DOC



Probamos la ejecución en una VM vemos que hace la descarga del siguiente elemento.




Descarga del Ejecutable con el querido malzilla.




El ejecutable contiene el icono de un supuesto .pdf

Utiliza un packer de NullSoft (PiMP SFX)




Analisis en V.T. con un indice mínimo de detecciones.



Función anti Debugging.






Dumpeamos en ResumeThread




Strings obtenidos en el Dump




Analisis en VT sin el Crypter.




Prueba Dinámica.







Parte de la Config del Ransomware

ntuser.dat
thumbs.db
folders
:\$getcurrent\
:\$recycle.bin\
:\$windows.~bt\
:\$windows.~ws\
:\boot\
:\documents and settings\all users\
:\documents and settings\default user\
:\documents and settings\localservice\
:\documents and settings\networkservice\
\intel\
:\msocache\
:\perflogs\
:\program files (x86)\
\windows10upgrade\
\program files\
:\programdata\
:\recovery\
:\recycled\
:\recycler\
:\system volume information\
:\temp\
:\windows.old\
\appdata\local\
:\windows\
:\winnt\
%I64d
\appdata\locallow\
\appdata\roaming\
\local settings\
\public\music\sample music\
\public\pictures\sample pictures\
\public\videos\sample videos\
\tor browser\
languages
+-0123456789.Ee
0
check
language
close_process
close_process
process
sqbcoreservice.exe
agntsvc.exeagntsvc.exe
agntsvc.exeencsvc.exe
ocssd.exe
agntsvc.exeisqlplussvc.exe
dbeng50.exe
dbsnmp.exe
fbserver.exe
firefoxconfig.exe
msftesql.exe
mydesktopqos.exe
mydesktopservice.exe
mysqld-nt.exe
mysqld-opt.exe
mysqld.exe
ocautoupds.exe
ocomm.exe
sqlbrowser.exe
oracle.exe
sqlwriter.exe
sqlagent.exe
tbirdconfig.exe
sqlservr.exe
.orf
synctime.exe
p
p
.nyf
xfssvccon.exe
debug
default
site_1
onion.to
site_2
onion.cab
site_3
onion.nu
site_4
onion.link
site_5
tor2web.org
tor
p27dokhpz2n7nvgr
encrypt
bytes_skip
divider
encrypt
files
.123
.1cd
.3dm
.3ds
.3fr
.3g2
.3gp
.3pr
.602
.7z
.7zip
.aac
.ab4
.abd
.acc
.accdb
.accde
.accdr
.accdt
.ach
.acr
.act
.adb
.adp
.ads
.aes
.agdl
.ai
.aiff
.ait
.al
.aoi
.apj
.apk
.arc
.arw
.ascx
.asf
.asm
.asp
.aspx
.asset
.asx
.atb
.avi
.awg
.back
.backup
.backupdb
.bak
.bank
.bat
.bay
.bdb
.bgt
.bik
.bin
.bkp
.blend
.bmp
................................................

.jpg
data_finish
file_extension
\steam\
files_name
_{RAND}_README_
run_by_the_end
self_deleting
statistics
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF2a3R5NXFocUV5ZFI5MDc2RmV2cAowdU1QN0laTm1zMUFBN0dQUVVUaE1XYllpRVlJaEJLY1QwL253WXJCcTBPZ3Y3OUsxdHRhMDRFSFRyWGdjQXAvCk9KZ0JoejlONThhZXdkNHlaQm0yY29lYURHdmNHUkFjOWU3Mk9iRlEvVE1FL0lvN0xaNXFYRFd6RGFmSThMQTgKSlFtU3owTCsvRytMUFRXZzdrUE9wSlQ3V1NrUmI5VDh3NVFnWlJKdXZ2aEVySE04M2tPM0VMVEgrU29FSTUzcAo0RU5Wd2ZOTkVwT3BucE9PU0tRb2J0SXc1NkNzUUZyaGFjMHNRbE9qZWsvbXVWbHV4amlFbWMwZnN6azJXTFNuCnFyeWlNeXphSTVEV0JEallLWEExdHAyaC95Z2JrWWRGWVJiQUVxd3RMeFQyd01mV1BRSTVPa2hUYTl0WnFEMEgKblFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==
background
text
whitelist
folders
\bitcoin\
\excel\
\microsoft sql server\
\microsoft\powerpoint\
\microsoft\excel\



La Public Key



Les dejo el sample y el dump, tener mucho cuidado!!!!

https://dl.dropboxusercontent.com/u/80008916/cerber-29-12-16.rar



Eso es todo por este 2016 @Dkavalanche 





martes, 27 de diciembre de 2016

Resolviendo el reto Nro 10 Android de ESET Ekoparty 2016 #eko12 - PARTE 2



Como habíamos quedado en la PARTE 1 el CrackmeBaby.apk desencripta un nuevo.apk

content.apk SHA256: 94317deb79ced2ece91b413d142492c76c876a320957a0f21bdf2a8150d6d427





Arrancamos la APP y nos muestra esta imagen, evidentemente algo mal estamos haciendo.





Decompilamos con APK-Multy-tool 

Existen dos activities SuperActivity y SuperbActivity.

Esto lo vemos en el AndroidManifest.xml





Y la actividad que se esta iniciando por default es SuperActivity y vemos en el código que solo muestra una imagen (la de Obi Wan)





SuperbActivity hace cosas mas interesantes y vemos que nunca arranca por lo que vamos a forzar su arranque




Para arrancar la actividad modificamos el AndroidManifest.xml para que arranque la SuperbActivity y luego volvemos a compilar y firmar.




Así vamos a obtener una segunda aplicación que siempre arrancará la actividad correcta para resolver este reto, por lo que a partir de ahora seguiremos trabajando con ella.




La arrancamos y vemos lo siguiente:



Una imagen de Fsociety y un contador decreciente, no tenemos ningún ingreso de datos como en el apk de la Parte 1.


En el código vemos



try
      {
        if ((SuperbActivity.b <= 0.0D) && (SuperbActivity.a < 0))
        {
          SuperbActivity.a += 1;
          SuperbActivity.access$002(SuperbActivity.this, 10.0D * (int)Math.log(Math.pow(SuperbActivity.a, SuperbActivity.a)));
          SuperbActivity.b = SuperbActivity.this.c;
          String str = SuperbActivity.this.getPreferences(4).getString("password", "no_password");
          if (e.SHA1(str).equalsIgnoreCase("249192f0a4f70aa25aa5c7521625f7d6e4021042"))
            new a().execute(new b[] { new b(SuperbActivity.this.getApplicationContext(), d.decrypt(str, "Jhv1Bk0Qi07jOVEeyImynOQmiiz1MvZakazhOaAld-0=")) });
        }
        SuperbActivity.this.t.setText(String.format("Próximo intento: %.1f", new Object[] { Double.valueOf(SuperbActivity.b) }));
        SuperbActivity.b -= 0.1D;
        SuperbActivity.this.g.postDelayed(this, 100L);
        return;
      }
      catch (Exception localException)
      {
        Log.e(SuperbActivity.this.getResources().getString(2131099668), "Oops!");

      }



Podemos observar que por otro lado hay un hash de SHA1 y un d.decrypt que toma como ingreso la cadena Jhv1Bk0Qi07jOVEeyImynOQmiiz1MvZakazhOaAld-0=


Vemos también:


  protected void onCreate(Bundle paramBundle)
  {
......................................
    paramBundle.putString("password", "insert_password_here");
    paramBundle.apply();

  }


Revisando el codigo SMALI veo lo siguiente:


.source "SuperbActivity.java"

  .line 61
    .local v0, "editor":Landroid/content/SharedPreferences$Editor;

    const-string v2, "password"


Significa que existe una shared memory en la cual deberemos poner una clave para que luego sea comparada con el hash del SHA1 y si machea se ejecuta la función d.decrypt("clave",Jhv1Bk0Qi07jOVEeyImynOQmiiz1MvZakazhOaAld-0=)

Busque el hash por internet sin suerte, por lo que intente con hashcat y probar una clave de 10 dígitos incremental....

hashcat64.exe -m 100 -a 3 example0.hash ?s?s?s?s?s?s?s?s?s?s --incremental 

Probé con solo numéricos, con alfa + may/minusculas sin éxito, para luego pasar al set con caracteres espaciales. Hasta los siete caracteres fue rápido y luego paso de horas a días y años... por lo que descartamos esté método debido a que un reto en una confer no nos puede llevar tanto tiempo a menos que tengamos una maquina cuántica...

Probe con hashcat porque al ver a Obi se me vino a la mente "Usa la Fuerza"...fuerza bruta....mmmm.... no...no.... solo fue una trampita :D


La password debería estar en otro lugar, revisando las imágenes de los recursos se las pase al exiftool y en la imagen de fsociety se puede ver lo siguiente en el Thumbnail


exiftool -b -ThumbnailImage image.jpg > my_thumbnail.jpg







Ahora que tengo la password r4bb!th0l3 se la puedo poner en el shared memory con el ADM en /data/data/eset.ekoparty.challenge.crackmeharder/shared_prefs/SuperbActivity.xml







O asignar la password directamente en el SuperbActivity.smali y me olvido.

Lógicamente vuelvo a compilar y firmar la aplicación.


.source "SuperbActivity.java"

  .line 61
    .local v0, "editor":Landroid/content/SharedPreferences$Editor;
    const-string v2, "password"

    const-string v3, "r4bb!th0l3"


Cuando machea el SHA1, como habíamos comentado antes, se 
ejecuta d.decrypt( r4bb!th0l3,Jhv1Bk0Qi07jOVEeyImynOQmiiz1MvZakazhOaAld-0=) 
obteniendo como resultado el string f0ll0w_th3_wh!t3_r4bb!t!

Acá la podemos ver en un dump de memoria previo.




Cada vez que el contador se pone en cero o se da click en el label, el apk llama a la class b y visita un sitio.

        SuperbActivity.this.t.setText(String.format("Próximo intento: %.1f", new Object[] { Double.valueOf(SuperbActivity.b) }));
        SuperbActivity.b -= 0.1D;

        SuperbActivity.this.g.postDelayed(this, 100L);



class b
{
  .................................
  String getUrl()
  {
    return "http://desafioseset.com/";
  }

}


En el LOGCAT se ve lo siguiente





Por otro lado se llama a la Class n a la cual se le pasa el string f0ll0w_th3_wh!t3_r4bb!t!


 SuperbActivity.FLAG = new n().func(localb.getKeyword());



class n
{
  static
  {
    System.loadLibrary("dostuff");
  }


Por lo que si hacemos un DUMP de la memoria.








Obtenemos la FLAG :D

eko_eset_m0b!l35



El APK lo deje modificado para que ingrese directamente a la actividad que corresponde, tome la clave y la imprima en el logcat.







Les dejo el apk original y la modificada con los archivos SMALI que toque.


https://dl.dropboxusercontent.com/u/80008916/Crackmeharder.7z



Eso es todo por este 2016 @Dkavalanche 










lunes, 26 de diciembre de 2016

Resolviendo el reto Nro 10 Android de ESET Ekoparty 2016 #eko12 - PARTE 1


Buenas, decidí terminar el año posteando como resolver este reto Android de ESET que me pareció muy bueno.

Vamos a necesitar APK-Multi-tool, dex2jar, JD-GUI, signapk.jar y un emulador de Android, en mi caso use bigNOX porque tengo una maquina con AMD y el emulador de Google de Windows no permite la aceleración de VM si no se posee un cpu Intel.

El Desafio:

**************************************************
Este es el desafío de reversing en Android.

Para encontrar el flag deberás utilizar técnicas sencillas de análisis de APK y algo de ingenio.

Al comienzo, probablemente debas utilizar algún motor de búsqueda para dar con la contraseña correcta, que es la respuesta a una adivinanza.

Encontrarás pistas que te guiarán en la dirección correcta.

Mucha suerte y happy reversing.


ROMPIENDO CrackMeBabe.apk

SHA256: ca80b0c050233ad6c9d70793ba76effeaffb9ede79508993f965beb04598233d



Cargamos el APK y ni bien lo lanzamos obtenemos la siguiente imagen de un personaje de Tv, por lo que se debe estar haciendo algún tipo de comprobación.





Decompilamos el APK con Multi-tool opción 9, con el obtendremos los archivos SMALI y el classes.dex que luego lo pasaremos por el dex2jar para obtener un .jar para abrirlo con el JD-Gui






d2j-dex2jar.bat classes.dex 

dex2jar classes.dex -> .\classes-dex2jar.jar

JD-Gui




Tenemos varias classes (Login, a, b, c, d, e, f)

Vamos a repasar a ojo de pájaro las principales funciones que me van a permitir sortear el entuerto.


Class f

Función  chk 
(se hacen comprobaciones de que tipo de dispositivo se esta utilizando y lo comprueba con un llamado a la clase d)

 if ((!Build.MODEL.contains(d.h)) && (!Build.MODEL.contains(d.i)) && (!Build.MODEL.contains(d.m)) && (!Build.FINGERPRINT.startsWith(d.k)) && (!Build.FINGERPRINT.startsWith(d.l)) && (!Build.MANUFACTURER.contains(d.n)) && (!Build.PRODUCT.contains(d.c)) && (!Build.MODEL.contains(d.c)))

Función chks(boolean) 

  return Build.VERSION.SDK_INT == 22;

Retorna verdadero si la versión del APLI level es 22 (Android Lollipop 5.0 - 5.1.1)
Por lo que tendríamos que ejecutarlo en un dispositivo con ese nivel de S.O. o emularlo con el AVD correspondiente.



Nombre códigoNúmero de versiónFecha de lanzamientoNivel de API
Apple Pie1.023 de septiembre de 20081
Banana Bread1.19 de febrero de 20092
Cupcake1.527 de abril de 20093
Donut1.615 de septiembre de 20094
Eclair2.0–2.126 de octubre de 20095–7
Froyo2.2–2.2.320 de mayo de 20108
Gingerbread2.3–2.3.76 de diciembre de 20109–10
Honeycomb13.0–3.2.622 de febrero de 201111–13
Ice Cream Sandwich4.0–4.0.418 de octubre de 201114–15
Jelly Bean4.1–4.3.19 de julio de 201216–18
KitKat4.4–4.4.4, 4.4W–4.4W.231 de octubre de 201319–20
Lollipop5.0–5.1.112 de noviembre de 201421–22
Marshmallow6.0–6.0.15 de octubre de 201523
Nougat7.0 - 7.122 de agosto de 201624 - 25

-----------------------------------------------------------------------------------------------------



Class Login en la cual se hacen varias comprobaciones para presentar el frame de login y pasar a la segunda etapa del desafío que es la de desencriptar un recurso y ejecutarlo (otro apk).

Función chkn (boolean) retorna verdadero si la latitud es 40 y la longitud es -74 en la geolocalización del dispositivo.

public boolean chkn()
  {
    int j = 0;
    int i = j;
    if (this.l != null)
    {
      i = j;
      if ((int)this.l.getLatitude() == 40)
      {
        i = j;
        if ((int)this.l.getLongitude() == -73)
          i = 1;
      }
    }
    return i;
  }

Acá tenemos una comprobación importante, se debe cumplir las dos, la chkn (lat:40 y long:-73) y la chks (version del SDK) de la class f para mostrar el frame del login, por otro lado se imprime un hint en el logcat

if ((chkn()) && (f.chks()))


    {
      setContentView(2130968602);
      this.bt = ((Button)findViewById(2131492970));
      this.tx = ((EditText)findViewById(2131492969));
      this.vw = ((TextView)findViewById(2131492971));
      this.vw.setOnClickListener(new c());
      Toast.makeText(this.con, "HINT: *Escucha* lo que Gollum responde y la clave encontrarás, o encuentra el enlace ofuscado que te guiará.", 1).show();
      Log.i(d.z, "HINT: *Escucha* lo que Gollum responde y la clave encontrarás, o encuentra el enlace ofuscado que te guiará.");
      return;
    }

Tenemos un hash md5 que corresponde a una clave a ingresar.


  public void onClick(View paramView)
  {
    if (((paramView instanceof Button)) && (paramView == this.bt))
      try
      {
        paramView = this.tx.getText().toString();
        MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
        localMessageDigest.update(paramView.getBytes("UTF-8"));
        paramView = String.format("%032x", new Object[] { new BigInteger(1, localMessageDigest.digest()) });
        if (!paramView.equalsIgnoreCase("16cc45d14201e8caf26d48e636b1c48d"))


Buscamos en internet el MD5 y corresponde a  3gg535


Desencripción del recurso "enc" localizado en assets/ mediante la class b  función b.decrypt();





protected String doInBackground(String[] paramArrayOfString)
    {
      try
      {
        File localFile = new File(Environment.getExternalStorageDirectory().getPath() + "/content.apk");
        if ((localFile.exists()) && (localFile.length() > 0L))
          return "Error";
        InputStream localInputStream = Login.this.getApplicationContext().getResources().getAssets().open("enc");
        FileOutputStream localFileOutputStream = new FileOutputStream(localFile);
        b.decrypt(paramArrayOfString[0], localInputStream, localFileOutputStream);
        paramArrayOfString = new Intent("android.intent.action.VIEW");
        paramArrayOfString.setDataAndType(Uri.fromFile(localFile), "application/vnd.android.package-archive");
        Login.this.startActivity(paramArrayOfString);
        this.blnResult = true;
        return "Executed";
      }
      catch (Exception paramArrayOfString)
      {
        while (true)
        {
          paramArrayOfString.printStackTrace();
          Log.e(d.z, paramArrayOfString.getMessage());
        }
      }
    }


-----------------------------------------------------------------------------------------------------

Class d donde se llama a la class e y se desencriptan varios strings que serán utilizados en la class f para comprobar en que tipo de dispositivo especifico se esta ejecutando y desviar un poco la atención del reverser.

package eset.ekoparty.challenge.crackmebabe;

public class d
{
  public static String a = "12321322869";
  public static final String b = e.pqz("htDaDYyZOg==");
  public static final String c = e.pqz("tNrV");
  public static final String g = e.pqz("5Y6OT9PAbvGYtDsxJChCQI0=");
  public static final String h = e.pqz("5dnREIScO57b4GAj");
  public static final String i = e.pqz("5fvTCo+RKq7apg==");
  public static final String k = e.pqz("5dnbEYaCN6KK");
  public static final String l = e.pqz("5cvQFI2fKa+K");
  public static final String m = e.pqz("5f/QG5GfN6WI109KNHoHGcNbxcOzZ57tl8xC");
  public static final String n = e.pqz("5fnbEZqdMbXB62Uj");
  public static final String y = e.pqz("r8rKD9nfca3F439nbTYRH8IA2tThctH5w48NXoLVdHkq1Yo=");
  public static final String z = e.pqz("hMzfHIjQE6SIxmpjcQ==");
}


Decodificadas quedan

a = 12321322869
b = Android
c = sdk
g = 000000000000000
h = google_sdk
i = Emulator
k = generic
l = unknown
m = Android SDK built for x86
n = Genymotion
y = http://lmgtfy.com/?q=gollum+riddles
z = Crack Me Babe

-----------------------------------------------------------------------------------------------------


Class e se encarga de pasar a texto las cadenas base64 encontradas en la classe d

public class e
{
  static String pqz(String paramString)
  {
    try
    {
      paramString = new String(new a(d.a.getBytes("UTF-8")).a(Base64.decode(paramString.getBytes(), 0)), "UTF-8");
      try
      {

        String str = paramString.replace("\"", "");


-----------------------------------------------------------------------------------------------------


Bueno como salimos de este lio....

La clave la tenemos que es 3gg535 quiere decir que lo mas difícil son las comprobaciones de las funciones de las class Login y F

Entonces vamos a modificar el código SMALI  para que nos permita pasar a la pantalla de ingreso de password y lograr desencriptar el recurso enc.

Luego de modificar los .SMALI  re-compilamos con el APK-Multi-tool y firmamos con el signapk.jar 



Modificando Login.SMALI


Código java:

Cambiamos el  if ((chkn()) && b(f.chks())) por  if ((f.chks()) && (f.chks())) 


if ((f.chks()) && (f.chks())) 
    {
      setContentView(2130968602);
      this.bt = ((Button)findViewById(2131492970));
      this.tx = ((EditText)findViewById(2131492969));
      this.vw = ((TextView)findViewById(2131492971));
      this.vw.setOnClickListener(new c());
      Toast.makeText(this.con, "HINT: *Escucha* lo que Gollum responde y la clave encontrarás, o encuentra el enlace ofuscado que te guiará.", 1).show();
      Log.i(d.z, "HINT: *Escucha* lo que Gollum responde y la clave encontrarás, o encuentra el enlace ofuscado que te guiará.");
      return;

    }

En .SMALI sería:

    .line 63
    :cond_1
    invoke-static {}, Leset/ekoparty/challenge/crackmebabe/f;->chks()Z

    move-result v0

    if-eqz v0, :cond_2

    invoke-static {}, Leset/ekoparty/challenge/crackmebabe/f;->chks()Z

    move-result v0


    if-eqz v0, :cond_2


Modificando f.SMALI

Código java:

Modificamos  chks()  para que retorne verdadero si utilizamos una versión menor a 99, con esto podemos probarlo en cualquier API level.



  public static boolean chks()
  {
    return Build.VERSION.SDK_INT < 99;

  }


En .SMALI sería:

    sget v0, Landroid/os/Build$VERSION;->SDK_INT:I

    const/16 v1, 0x63 
                   
    if-ge v0, v1, :cond_0


Compilamos con opción 12 de APK-Multi-tool




Luego firmamos el APK con signapk.jar


set usrc=0
set heapy=512
echo Signing Apk
java -Xmx%heapy%m -jar signapk.jar -w testkey.x509.pem testkey.pk8 in.apk out.apk




Instalamos y ejecutamos el APK.


Y vemos que ya paso de largo las comprobaciones y nos muestra el ingreso de la password.



Ingresamos la password 3gg535 y se descifra el recurso enc.





Para luego solicitar ser instalado.







Instalamos y ejecutamos.... pero lo vemos la próxima.


Les dejo el apk original, el apk parchado y los .SMALI para que pueda hacerlo 
Uds. en sus casas.

https://dl.dropboxusercontent.com/u/80008916/CrackMeBabe.7z


Próxima entrega antes de fin de año :D

Eso es todo por el momento @Dkavalanche 2016 







 Hola, me mudé a medium .... nos vemos!!! FELIZ 2022!!!