Contents

Reto Hackplayers Android Crackme

Introducción

  • Pueden descargar el crackme #1 de hackplayers aquí

Cada vez voy aprendiendo más a la hora de resolver, modificar y hacer ingeniería inversa a las aplicaciones de Android. Y le he cogido gusto a resolver crackmes, la verdad es que me van pareciendo cada vez más sencillos. Así que… ¡Empecemos!

Comportamiento de la app

Instalamos el apk y vemos la pantalla:

E introducimos datos de prueba (usuario: mgp25 y contraseña: 12345).

Y al darle a Login nos muestra: Login incorrecto.

Análisis

¡Hora de analizar el código! Por cierto, estoy usando APK Analyser.

Siguiendo el código llegamos a esto:

Que básicamente lo que hace es comprobar que el usuario sea admin3 y la contraseña es modificada por el método doConvert, y que comprueba que el resultado sea igual a la contraseña introducida. Si se introduce el usuario o la contraseña mal, nos llevará al mismo lugar: Login incorrecto.

Aquí podeis ver el código de mejor manera:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
              .local v0 -> java.lang.String password
   1C   61    const-string v3, "PBAGENFRAN456"

   1E   61    invoke-static {v3}, com.hpys.crackmes.crackme1hpys.doConvert(java.lang.String)java.lang.String

   21   61    move-result-object v1


              .local v1 -> java.lang.String secreto
   22   63    const-string v3, "admin3"

   24   63    invoke-virtual {v2, v3}, java.lang.String.equals(java.lang.Object)boolean

   27   63    move-result v3

   28   63    if-eqz v3, COND_3C:

   2A   63    invoke-virtual {v0, v1}, java.lang.String.equals(java.lang.Object)boolean

   2D   63    move-result v3

   2E   63    if-eqz v3, COND_3C:


   30   64    iget-object v3, p0, com.hpys.crackmes.crackme1hpys$1.this$0:com.hpys.crackmes.crackme1hpys

              #getter for: com.hpys.crackmes.crackme1hpys.lblResult:android.widget.TextView
   32   64    invoke-static {v3}, com.hpys.crackmes.crackme1hpys.access$2(com.hpys.crackmes.crackme1hpys)android.widget.TextView

   35   64    move-result-object v3

   36   64    const-string v4, "\u00a1Bien hecho!"

   38   64    invoke-virtual {v3, v4}, android.widget.TextView.setText(java.lang.CharSequence)void


GOTO_3B:
   3B   68    return-void


COND_3C:
   3C   66    iget-object v3, p0, com.hpys.crackmes.crackme1hpys$1.this$0:com.hpys.crackmes.crackme1hpys

              #getter for: com.hpys.crackmes.crackme1hpys.lblResult:android.widget.TextView
   3E   66    invoke-static {v3}, com.hpys.crackmes.crackme1hpys.access$2(com.hpys.crackmes.crackme1hpys)android.widget.TextView

   41   66    move-result-object v3

   42   66    const-string v4, "Login incorrecto."

   44   66    invoke-virtual {v3, v4}, android.widget.TextView.setText(java.lang.CharSequence)void

   47   66    goto GOTO_3B:

Podemos extraer el método doConvert y pasarle el String para que nos devuelva la verdadera contraseña. Así que obtenemos las clases del apk y la pasamos a java.

Aquí se ve mucho mejor:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
  public void onClick(View paramView)
  {
    String str1 = crackme1hpys.access$0(this.this$0).getText().toString();
    String str2 = crackme1hpys.access$1(this.this$0).getText().toString();
    String str3 = crackme1hpys.doConvert("PBAGENFRAN456");
    if ((str1.equals("admin3")) && (str2.equals(str3)))
    {
      crackme1hpys.access$2(this.this$0).setText("¡Bien hecho!");
      return;
    }
    crackme1hpys.access$2(this.this$0).setText("Login incorrecto.");
  }

Solución

Y aquí tenemos el código que nos devuelve la contraseña correcta:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.io.*;

public class clave
{

	public static String doConvert(String s)
	{
   		int abyte = 0;
   		StringBuffer localStringBuffer = new StringBuffer();
   		int i = 0;
   		do
   		{
       		int j = s.length();
       		if(i >= j)
           		return localStringBuffer.toString();
       		abyte = s.charAt(i);
       		int k = abyte & 0x20;
       		int l = abyte;
       		int i1 = ~k;
       		abyte = l & i1;
       		int j1;
       		char c;
       		StringBuffer localStringBuffer2;
       		if(abyte >= 65 && abyte <= 90)
           		j1 = ((abyte - 65) + 13) % 26 + 65;
       		else
           		j1 = abyte;
       		abyte = j1 | k;
       		c = (char)abyte;
       		localStringBuffer2 = localStringBuffer.append(c);
       		i++;
   		} while(true);
	}

    public static void main(String[] args)
    {
  		System.out.println("La contraseña es: " + doConvert("PBAGENFRAN456"));
    }
}

Probamos a ver si funciona esto…

¡Bien! Hemos conseguido que funcione. Pero sin embargo yo quiero que funcione con cualquier usuario y con cualquier contraseña, así que vamos a modificar el bytecode para que haga lo que nosotros queremos.

Anteriormente, puse el código smali, así que simplemente citaré el código donde se hace la comparación del usuario y la contraseña y según su resultado, vaya a un lado u otro.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
const-string v3, "PBAGENFRAN456"

    invoke-static {v3}, Lcom/hpys/crackmes/crackme1hpys;->doConvert(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v1

    .line 63
    .local v1, secreto:Ljava/lang/String;
    const-string v3, "admin3"

    invoke-virtual {v2, v3}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v3

    if-eqz v3, :cond_0

    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v3

    if-eqz v3, :cond_0

Cambiamos esto:

1
invoke-virtual {v2, v3}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

A esto otro..

1
invoke-virtual {v2, v2}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

Y esto:

1
invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

a esto…

1
invoke-virtual {v0, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

Construímos e instalamos de nuevo la apk, y probamos a ver si funciona:

¡Reto superado con éxito!

Espero que os haya gustado, ¡y hasta la siguiente entrada!