Le stockage des mots de passes

android

Il y a quelques jours, je regardai le projet lancé par hackaday de faire un password keeper qui soit offline : Mooltipass

Je me suis dis que c’était quand même bien pratique et que j’en aurai bien besoin sur mon téléphone mobile. Comme ça faisait pas mal de temps que je n’avais pas développé sur Android, c’était l’occasion de réfléchir au plus gros problème que l’on retrouve sur les mobiles, ils ne disposent pas d’un espace sécurisé.

Vous pouvez récupérer l’application sur google play directement à cette adresse : Téléchargement

Le mécanisme de protection

Afin de réaliser ce projet, j’ai supposé que le mobile n’était pas vérolé à priori et qu’aucun touchlogger n’était présent sur celui ci.

En plus de cela, j’ai supposé que l’utilisateur été suffisamment doué pour choisir un mot de passe solide dont on peut sauvegarder le hash sans qu’il soit casser rapidement.

L’idée est donc de chiffrer l’ensemble des mots de passe de l’utilisateur en utilisant un secret que seul l’utilisateur connait.

Pour cela nous allons utiliser les API java cryptographiques et utiliser l’algorithme AES.

Afin de générer le secret pré partagé, nous allons utiliser une phrase secrete. Ce secret consiste en une phrase que seul l’utilisateur connait. Nous utiliserons alors une fonction de hashage pour générer la clé de chiffrement à partir de la phrase secrète de l’utilisateur. A cela nous ajoutons un salt, ceci permet de diversifier le secret pré partagé en fonction de son usage.

La fonction de diversification a été codé comme suis :

private byte[] diversify(String password, String salt) {
	password = password + salt;
	byte[] key = new byte[16];
	MessageDigest sha1 = null;
	try {
		sha1 = MessageDigest.getInstance("SHA");
	} catch (NoSuchAlgorithmException e) {
		e.printStackTrace();
	}
	sha1.update(password.getBytes());
	byte[] hash = sha1.digest();
	System.arraycopy(hash, 0, key, 0, 16);
	return key;
}

Le stockage des données

Afin de stocker les données, nous allons transporter la clé dérivée pour la session courante et utiliser une base de données Android pour stocker les mots de passe. L’ensemble du contenu de la base de données est bien entendu chiffré avant insertion.

Chaque entrée est identifiée par les champs suivants :

public class PasswordReference {
 
	private int id;
	private String description;
	private String login;
	private String password;

L’id est stocké en clair, pour les autres champs, nous utilisons un salt différents pour chacun.

Attaques possibles

La première attaque possible est de regarder par dessus l’épaule. Ainsi l’utilisateur récupère le secret pré partagé.
Une seconde attaque serait d’utiliser un key logguer. Afin de palier à ce genre d’attaque, il faudrait ajouter un deuxième paramètre dans la génération du secret pré partagé. Ce deuxième paramètre serait un code pin avec clavier dynamique. Ainsi un touchlogger deviendrait inefficace pour récupérer le code pin.

Cependant cette technique n’empêcherait pas de bruteforcer les solutions restantes et avec un code pin à 4 chiffres, ça ne fait que 10 000 essais.
L’attaque par bruteforce reste la dernière possible et celle ci peut être évitée à condition de choisir un mot de passe sure et de le changer régulièrement.

Sources

L’ensemble des sources de ce petit programme peut être télécharger sur github à l’adresse suivante : https://github.com/julien14/secretKeeper
Bien sur le programme est libre et sous licence GPL. Enjoy !

La réalité augmentée c’est facile avec Android

android

La réalité augmentée c’est à la mode et ça parait super compliqué. Dans les faits, réaliser une librairie de réalité augmentée, c’est placé correctement des points sur une image en fonction de la position de l’utilisateur. La dite image est retranscrite à partir du capteur CCD du téléphone mobile (comprenais la caméra quoi).

Nous n’allons pas réaliser la librairie mais plutôt réutiliser l’excellent travail de aka pishman3579. Vous pouvez trouver son projet sur gihub ici.

Réaliser la librairie

Avant de commencer, nous allons utiliser son application afin de générer une librairie android. Pour cela commencer par cloner le dépôt github.

git clone https://github.com/phishman3579/android-augment-reality-framework.git

Ensuite dans les propriétés Android, coché isLibrary :

isLibrary

Enfin, vous allez devoir supprimer le fichier Demo.java qui apparaît maintenant avec des erreurs. Ceci est normal, nous le réimplémenterons dans votre application.

Voilà, vous venez maintenant de créer votre librairie de réalité augmentée.

Utiliser la librairie

Commencer par créer un nouveau projet Android et par linker la librairie de réalité augmentée à ce projet :

addLib

Une fois que ceci est fait, ajouter les permissions suivantes à votre manifest :

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

Créer maintenant un activitée en réutilisant le fichier Demo.java que vous avez supprimé. Vous pouvez le copier coller ici.

Modifier votre fichier manifest.xml afin de préciser que cette activity se lance sans tilte bar et en mode landscape:

<activity android:name=".activity.MainActivity"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
    android:screenOrientation="landscape">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>            
</activity>

Conclusion

Si vous compilez vous pouvez observer autour de vous les données récupérées depuis wikipédia. Il est très facile de modifier ce fichier afin d’y ajouter votre propre set d’event récupéré depuis un serveur web ou bien localement. Je vous laisse regarder les fichiers ainsi que le fichier de démo qui est assez explicite. Quoi qu’il en soit si vous avez des questions n’hésitez pas à nous laisser un petit commentaire, nous nous ferons un plaisir de vous répondre.

Google MAP avec un fragment dynamique

android
Pour avoir Google Map dans son application, 4 étapes sont nécessaires :

  • Obtenir une clé pour utiliser l’API
  • Récupérer le Google Map service
  • Ajouter les informations nécessaires dans Google MAP
  • Implémenter le fragment dans l’application

Obtenir une clé pour utiliser l’API

Tout d’abord, il faut se connecter sur le site de Google API Console . Puis dans le menu gauche, il faut cliquer sur API Access et cliquer sur « Create New Android Key… ».

Nous avons besoin de récupérer l’empreinte de notre clé grâce au SHA1, pour cela il faut se placer dans le répertoire cd ~/.android/. C’est ici que se trouve votre clé debug.keystore.

keytool -list -v -alias androiddebugkey -keystore debug.keystore -storepass android -keypass android

Grâce a cette commande, on peut récupérer une empreinte du certificat. En l’occurrence, la ligne qui nous intéresse est celle avec clé SHA1.

Copier cette ligne sur le site de google API et ajouter à la fin un ; + le nom du package.

Cela va générer une API clé qu’il faudra utiliser dans votre manifest.

Note: : Pour définir le nom du package, il faut regarder dans votre manifest le package définit. En ce qui me concerne, j’ai choisi : fr.oversimple.applicationdemo

Récupérer le Google Map service

Afin d’utiliser Google Map, il faut télécharger la librairie : Google Play services via le Android SDK Manager
Google Play Services

Une fois le téléchargement effectué il faut l’ajouter comme librairie dans l’environnement de développement. Le répertoire se trouve dans extra/google/google_play_services . Pour Eclipse, il faut le déclarer comme une librairie (Clic droit sur le projet -> Properties -> Android -> Is Library) Puis pour le projet, au lieu de le déclarer comme librairie, il faut l’ajouter comme librairie.

En ce qui concerne Android studio (ou Intellij), il faut l’importer comme module.

Ajouter les informations nécessaires dans Google MAP

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="fr.oversimple.applicationdemo"
    android:versionCode="1"
    android:versionName="1.0" >
 
    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="19" />
 
    <permission
            android:name="fr.oversimple.applicationdemo.permission.MAPS_RECEIVE"
            android:protectionLevel="signature" />
 
    <uses-feature
            android:glEsVersion="0x00020000"
            android:required="true"/>
 
    <!-- Google map -->
    <uses-permission android:name="fr.oversimple.applicationdemo.permission.MAPS_RECEIVE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
 
    <uses-permission android:name="android.permission.INTERNET" />
 
 
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.OrangeNoActionBar" >
        <activity android:name=".activities.MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
 
        <!-- https://code.google.com/apis/console/ -->
        <meta-data
                android:name="com.google.android.gms.version"
                android:value="@integer/google_play_services_version" />
        <meta-data
                android:name="com.google.android.maps.v2.API_KEY"
                android:value="Votre API KEY" />
    </application>
 
</manifest>

Implémenter le fragment dans l’application

Le XML correspondant map_main_activity.xml :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <com.google.android.gms.maps.MapView
            android:id="@+id/mapView"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
</RelativeLayout>

Le code correspondant pour la map :

public class MapsFragment extends Fragment {
 
    private MapView map;
 
    public MapsFragment() {
    }
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.map_main_activity, container, false);
 
        if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity().getApplicationContext()) == ConnectionResult.SUCCESS) {
 
            //Initialze mapview
            MapsInitializer.initialize(getActivity());
 
            map = (MapView) view.findViewById(R.id.mapView);
            map.onCreate(savedInstanceState);
 
            GoogleMap gMap = map.getMap();
            gMap.addMarker(new MarkerOptions().title("title").snippet("description").position(new LatLng(49.5594950, -1.8414880))).showInfoWindow();
 
        } else {
            Toast.makeText(getActivity(), "Please install google play services", Toast.LENGTH_LONG).show();
        }
        return view;
    }
 
    @Override
    public void onResume() {
        super.onResume();
        map.onResume();
    }
 
    @Override
    public void onPause() {
        super.onPause();
        map.onPause();
    }
 
    @Override
    public void onDestroy() {
        super.onDestroy();
        map.onDestroy();
    }
 
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        map.onLowMemory();
    }
}

Pour appeler le fragment, l’id content frame correspond à mon cœur d’application. En l’occurrence, je l’ai utilisé avec le navigation drawer d’Android afin d’avoir un menu sur la gauche.

mapFragment = new MapsFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, mapFragment).commit();

Ce fragment de Google Map peut être remplacé facilement par un autre fragment.

It’s oversimple, isn’t it?

Un peu de Volley sous Android!

android
Pour ceux qui ne connaisse pas Volley, c’est LE Framekwork de communication réseau.

Pour commencer, voici une trés bonne vidéo de présentation réalisée par Ficus Kirkpatrick .

L’article ci-dessous permet de faire une introduction à l’utilisation Volley.

Si vous n’avez pas regardé la vidéo, vous allez me dire, il existe déjà plusieurs framework réseau sous Android, pourquoi utiliser un autre framework?

A ma connaissance, il existe 2 possibilités de framework sous Android, afin de faire du HTTP. Le premier est Apache HTTP Client, c’est celui-ci que j’utilisais avant de découvrir Volley. Mais comme vous le savez sans doute, Apache HTTP Client possède des bugs et celui-ci n’est pas forcement maintenu par l’équipe Android.
La seconde API est HttpURLConnection que je n’ai jamais utilisé mais celle-ci possède des bugs.

Pour chacun de ces 2 frameworks, il faut rédefinir des Thread afin de ne pas rester dans le main thread. Cela impliquait l’utilisation des Asynctask.

Volley permet de s’abstenir de toute cette couche. C’est facile, puissant et rapide! De plus, celui-ci possède un cache mémoire ou disque.

C’est bien beau, mais comment ça fonctionne?

Son fonctionnement est aussi simple, il possède une queue que l’on doit initialiser UNE fois  (cette initialisation est assez coûteuse en performance). Ensuite, on ajoute dans cette queue les REQUETES que l’on doit effectuer. Le reste est géré par Volley.

Et comment on l’utilise?

Tout d’abord, il faut penser à mettre le user permission Internet dans le manifest d’Android :

<uses-permission android:name="android.permission.INTERNET" />

Puis, il faut récupérer le JAR ou le projet:

git clone https://android.googlesource.com/platform/frameworks/volley
cd volley
android list targets #Choisir l'ID pour la compilitation du JAR
android update project -p . --target ID_DE_TARGETS
ant jar

Une fois le JAR généré, il faut le placer dans le répertoire libs de votre projet. (Penser à l’ajouter au classpath en faisant clic droit add as library)

pour la création de la QUEUE,  je considère que l’on en a besoin partout dans notre Application donc on l’initialise qu’une fois. Cette initialisation est faite dans le contexte de l’application (extends Application) :

public class IntroApplication extends Application {
    private RequestQueue volleyRequestQueue;
 
    @Override
    public void onCreate() {
        super.onCreate();
        volleyRequestQueue = Volley.newRequestQueue(this);
        volleyRequestQueue.start();
    }
 
    @Override
    public void onTerminate() {
        volleyRequestQueue.stop();
        super.onTerminate();
    }
 
    public RequestQueue getVolleyRequestQueue() {
        return volleyRequestQueue;
    }
}

Vu que l’on extends Application, il faut penser à l’ajouter dans le manifest dans l’ application android:name= ».IntroApplication ».

Une fois cette initialisation faite, c’est bon, on peut travailler avec Volley. Il existe plusieurs type de Request dans Volley, String, JSONObject, JSONArray etc… (on peut bien sûr extends Request)

Un exemple avec String:

        StringRequest stringRequest = new StringRequest("url",new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                Log.d("MainActivity","On doit traiter ici la reponse : " + s);
            }
        },new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.d("MainActivity","On doit gérer ici l'erreur");
            }
        });

En ce qui concerne les deux listener(la réponse et l’erreur), il faut implémenter les interfaces : Response.Listener et Response.ErrorListener.
Une fois que notre stringRequest est géré, il faut l’ajouter dans la Queue.

IntroApplication introApplication = (IntroApplication) getApplication();
mVolleyRequestQueue = introApplication.getVolleyRequestQueue();
mVolleyRequestQueue.add(stringRequest);

Cette exemple est valable pour String mais il fonctionne tout aussi bien avec les JsonObjectRequest, JsonArrayRequest. Il faut aussi remplacer les types des listener par JSONObject ou bien JSONArray.

En ce qui concerne les images au lieu d’utiliser les ImageView, nous allons utiliser les Images pour Volley, c’est à dire NetworkImageView (com.android.volley.toolbox.NetworkImageView). Cette modification doit être effectuée au niveau du XML et ainsi au niveau des CAST pour utiliser un objet de type NetworkImageView au lieu d’un ImageView.
Il faut également ajouter dans le contexte de l’application, le chargement des images.
mVolleyImageLoader = new ImageLoader(mVolleyRequestQueue, new BitmapLruCache());
Avant le start de volley request start de préférence.

Le XML:

    <com.android.volley.toolbox.NetworkImageView
            android:id="@+id/monImage"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher"/>

BitmapLruCache :

public class BitmapLruCache extends LruCache&lt;String, Bitmap&gt; implements ImageLoader.ImageCache {
 
    /**
     * @param maxSize for caches that do not override {@link #sizeOf}, this is
     *                the maximum number of entries in the cache. For all other caches,
     *                this is the maximum sum of the sizes of the entries in this cache.
     */
    public BitmapLruCache(int maxSize) {
        super(maxSize);
    }
 
    public BitmapLruCache() {
        this(getDefaultLruCacheSize());
    }
 
    public static int getDefaultLruCacheSize() {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        final int cacheSize = maxMemory / 8;
        return cacheSize;
    }
 
    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight() / 1024;
    }
 
    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }
 
    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }
}

Un exemple d’utilisation, super simple:

NetworkImageView networkImageView = (NetworkImageView) findViewById(R.id.monImage);
networkImageView.setImageUrl("lienDeLimage",mVolleyImageLoader);

Et si on désire passer des paramètres? Sans problème, il faut juste extends Request et redéfinir la méthode getParams (Hasmap de String/String).
Un exemple est présent dans l’archive ci-jointe : JSONParams

HashMap<String,String> map = new HashMap<String,String>();
map.put("UnParametre","laValeurDuParametre");
JSONParams jsonParams = new JSONParams("url",map,this,this);
mVolleyRequestQueue.add(jsonParams);

Et si on souhaite annuler une requête dans la QUEUE?
Super simple, il faut sur chaque Request mettre un setTag afin de pouvoir les identifier. Une fois identifiée, il faudra juste annuler celle que l’on désire:
Par exemple, si je reprends l’exemple de stringRequest avant de l’ajouter dans la queue, j’effectue un setTag

stringRequest.setTag("identifiantDeMaStringRequest");
mVolleyRequestQueue.add(stringRequest);
mVolleyRequestQueue.cancelAll("identifiantDeMaStringRequest");

Vous pouvez télécharger l’archive ici.

It’s Oversimple, isn’t it?

Retour sur le Hackathon de ce weekend !

Petit retour sur le Hackhathon organisé par le conseil général du Calvados pendant que c’est encore chaud.

L’équipe

Tout d’abord nous souhaiterions remercier toutes les personnes qui nous ont aidé à réaliser l’équipe et qui nous ont soutenu durant cette aventure incroyable.
L’équipe qui a participé et avec laquelle nous avons pris énormément de plaisir est la suivante :

  • Etienne Oriez – Communication/Marketing
  • Thomas Guesnon – Graphiste/designer d’interface
  • Paul Martin – Technicien SIG / Algorithmique
  • Pierre Leger – Développeur Android / Réseau
  • Julien Hatin – Développeur Android/ gestion de projet

Vous pouvez retrouver le site de Thomas Guesnon à cette adresse : http://www.uneverstealentour.com. Félicitation, tu as été magistral tout le week end.

Le but de ce hackathon était de créer un prototype d’application Android sur le thème du 70ème anniversaire du débarquement et en s’intégrant la problématique du tourisme numérique.

Déroulement du hackathon

Un petit résumé est disponible sur le blog du rond point du numérique : Rapport de l’opération 70thBDayHACKATHON

De notre point de vue (Pierre et Julien), cet évènement a été particulièrement réussi. Il faut dire que les M&ms gratuits et à volonté ont largement participé à la réussite de cet évènement. L’organisation avait vu les choses en grand puisque nous avons été chouchouté tout le week end. Après l’étape importante du choix du nom de l’équipe nous avons finalement retenu : « Bonjour Messieurs »

BFfQ1g7CAAIApUr

Du café aux plateaux repas, tout était apporté à notre table de travail. Ce qui nous a permis de travailler sans relâche durant ces deux jours. Le plus intéressant mais aussi le plus difficile a été de faire cohabiter les différents profils.

Le prototype

L’objectif de ce hackathon est de créer un prototype d’application android sur la thématique du 70 ème anniversaire du Débarquement et de la Bataille de Normandie. Plus d’information dans le PDF qui nous a été transmis Guide-Hackathon-2013.

Nous avons donc réalisé un prototype en 2 jours. Voici la vidéo (réalisé par Thomas) présentant notre prototype du weekend :

OVERSIMPLE : Hackathon du 70ème anniversaire du… par oversimple

On remercie l’ensemble de l’organisation car l’évènement était super !

Plus d’informations sur :
https://twitter.com/rondpointnum
Rapport de l’opération 70thBDayHACKATHON
Le journal du 70thBDayHACKATHON en tweets

Désassembler une application Android (complément)

android

Cet article est un complément de celui de Julien.

Partons d’un APK Crackme01.apk. Le fichier est disponible ici.

Voici à quoi ressemble le Crack Me :
capture1Presentation

Deux methodes existent pour reverser une application android :

  1. La première avec dex2jar et jd-gui, cette méthode permet d’obtenir quasiment le code original, facile à analyser du code java et simple d’utilisation.Cependant avec cette méthode on ne peut pas modifier le code java (.class), nos ressources sont présentes sous la forme numérique uniquement dans les findviewbyid, par exemple.
  2. La seconde avec smali(assembleur) et baksmali(desassembleur), on retrouve ces outils dans apktool (d pour desassembler, b pour assembler).Lorsque l’on désassemble on obtient un code source smali, et on peut le réassembler. Une bible pour le code smali est présente ici : http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html

 

Le but de ce crackme est de trouver le mot de passe pour la méthode 1.
Dans la seconde méthode, on ajoute un message rapide (Toasts) « Simple, non ? »

Methode 1 : Dex2jar et JD-GUI

On décompresse notre archive ZIP :

$ unzip Crackme01.apk 
Archive:  Crackme01.apk
  inflating: res/layout/activity_crack_me01.xml  
  inflating: res/menu/activity_crack_me01.xml  
  inflating: AndroidManifest.xml     
 extracting: resources.arsc          
 extracting: res/drawable-hdpi/ic_launcher.png  
 extracting: res/drawable-ldpi/ic_launcher.png  
 extracting: res/drawable-mdpi/ic_launcher.png  
 extracting: res/drawable-xhdpi/ic_launcher.png  
  inflating: classes.dex             
  inflating: META-INF/MANIFEST.MF    
  inflating: META-INF/CERT.SF        
  inflating: META-INF/CERT.RSA

Avant de continuer, on est obligé de vous parler de la machine Dalvik. Cette machine dalvik est une machine virtuelle utilisée par Android. Elle a été développée par Google pour ne pas utiliser la JVM. La différence notable avec la JVM est la gestion du registre. Pour la JVM, la gestion est basée sur la pile contrairement à la machine Dalvik qui est illimitée. Cette machine utilise un fichier .dex qui est le regroupement de l’ensemble des classes JAVA compilées.

Obtenons un jar de notre fichier .dex :
$ dex2jar classes.dex
dex2jar classes.dex -> classes-dex2jar.jar

Utilisons JD-GUI, afin de voir nos fichiers .class qui sont présents dans l’archive .JAR
jd-gui classes-dex2jar.jarjd-gui

Dans le fichier Crackme01.class on peut voir la ligne suivante :
final EditText localEditText = (EditText)findViewById(2131165185);

Cette ligne fait référence a un id, qui a pour intitulé motDePasse comme on peut le voir dans le fichier R.class :
public static final int motDePasse = 2131165185;

C’est l’EditText qui est utilisé pour saisir notre mot de passe.

On retourne dans le fichier Crackme01.class :

if ((localEditText.getText().toString() != null) &amp;&amp; (localEditText.getText().toString().equals("oversimple")))
          localToast.setText(2130968580);

On voit que l’on compare notre EditText avec une chaîne de caractère « oversimple ». Cette chaine de caractère « oversimple » est notre mot de passe.

Méthode 2 : Smali & backsmali

Pour la deuxieme méthode avec smali et backsmali, on utilisera apktool qui contient un ensemble d’outils. De plus, celui ci est simple d’utilisation alors pourquoi s’en priver ?

On décompile notre APK.

$ apktool d Crackme01.apk reverseCrackme01/
I: Baksmaling...
I: Loading resource table...
I: Loaded.
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /home/pierre/apktool/framework/1.apk
I: Loaded.
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Done.
I: Copying assets and libs...

On obtient un répertoire reverseCrackme01 :

$ cd reverseCrackme01/
$ ls   
AndroidManifest.xml  apktool.yml  res  smali

La premiere chose a regarder est le Manifest :

$ cat AndroidManifest.xml 
<!--?xml version="1.0" encoding="utf-8"?-->

On peut voir que notre main est le fichier CrackMe01 car celui-ci possède les intents nécessaires (MAIN et LAUNCHER)

Regardons maintenant les fichiers avec le code source smali :

$ ls smali/fr/oversimple/crackme01/
BuildConfig.smali  CrackMe01$1.smali  CrackMe01.smali  R$attr.smali  R$drawable.smali  R$id.smali  R$layout.smali  R$menu.smali  R$string.smali  R$style.smali  R.smali

Si on regarde dans le fichier CrackMe01\$1.smali, on peut voir la méthode onClick. Cette méthode correspond à un clic sur le bouton « Valider ». Voici un bref aperçu du code smali :

invoke-interface {v0}, Landroid/text/Editable;-&gt;toString()Ljava/lang/String;
move-result-object v0
const-string v1, "oversimple"
invoke-virtual {v0, v1}, Ljava/lang/String;-&gt;equals(Ljava/lang/Object;)Z
move-result v0

Ce bout de code permet de comparer notre mot de passe « oversimple » avec notre EditText(dans le but de simplifier, on affiche uniquement le retour du toString)

Et le test de comparaison final :

if-eqz v0, :cond_0
 
.line 29
iget-object v0, p0, Lfr/oversimple/crackme01/CrackMe01$1;-&gt;val$toast:Landroid/widget/Toast;
const v1, 0x7f040004
invoke-virtual {v0, v1}, Landroid/widget/Toast;-&gt;setText(I)V
 
.line 33
:goto_0
iget-object v0, p0, Lfr/oversimple/crackme01/CrackMe01$1;-&gt;val$toast:Landroid/widget/Toast;
invoke-virtual {v0}, Landroid/widget/Toast;-&gt;show()V
 
.line 34
return-void
 
.line 31
:cond_0
iget-object v0, p0, Lfr/oversimple/crackme01/CrackMe01$1;-&gt;val$toast:Landroid/widget/Toast;
const v1, 0x7f040005
invoke-virtual {v0, v1}, Landroid/widget/Toast;-&gt;setText(I)V
goto :goto_0

Si l’instruction if-eqz est égale à 0 alors nous allons à la condition cond_0. sinon on continue la suite donc .line 29.
Pour information, les valeurs qui nous intéressent se trouvent dans le fichier R$string.smali :
.field public static final ok:I = 0x7f040004
.field public static final ko:I = 0x7f040005

Le but de la deuxième méthode n’étant pas forcement de voir le mot de passe mais d’ajouter un message au démarrage de l’application.

Dans le fichier CrackMe01.smali, ligne 37 et après nous avons :

const-string v4, ""
 
const/4 v5, 0x1
 
invoke-static {v3, v4, v5}, Landroid/widget/Toast;-&gt;makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
 
move-result-object v1

Nous souhaitons juste ajouter notre message, donc à la place de «  » mettons : « Simple, non ? » et appelons la méthode afin de le rendre visible :
invoke-virtual {v1}, Landroid/widget/Toast;->show()V

Ce qui donne :

const-string v4, "Simple, non ?"
 
const/4 v5, 0x1
 
invoke-static {v3, v4, v5}, Landroid/widget/Toast;-&gt;makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
 
move-result-object v1
 
invoke-virtual {v1}, Landroid/widget/Toast;-&gt;show()V

On reconstruit l’application avec apktool b, il faut se placer dans le répertoire racineCrackme01 (ou ce trouve le fichier apktool.yml)

$ apktool b 
I: Checking whether sources has changed...
I: Smaling...
I: Checking whether resources has changed...
I: Building resources...
I: Building apk file...

Un nouveau repertoire apparait dist/

On crée une clé afin de signer notre application :
keytool -genkey -v -keystore oversimple.keystore -alias oversimple -keyalg RSA -validity 25000

Une fois la clé créée, on signe notre application :
jarsigner -digestalg SHA1 -sigalg MD5withRSA -verbose -keystore oversimple.keystore dist/Crackme01.apk oversimple

Notre apk est signée de source inconnu.

On envoie notre apk :

adb install dist/Crackme01.apk 
978 KB/s (184902 bytes in 0.184s)
	pkg: /data/local/tmp/Crackme01.apk
Success

Un article suivant présentera les commandes utiles de ADB.

Résultat au démarrage de notre APK :

resultatFinal

Conclusion

Pour cette introduction au reverse d’application Android, rien de bien difficile, plusieurs articles en tête, notammennt un article sur les commandes adb et les pouvoirs de cette commande 😉

Sources

dex2jar : http://code.google.com/p/dex2jar/
jd-gui : http://java.decompiler.free.fr/?q=jdgui
apktool : http://code.google.com/p/android-apktool/

It’s oversimple isn’t it?

Décompiler une application android

android

On trouve de nombreux malwares sous android. Ceux ci utilisent généralement des applications payantes crackées pour se diffuser.

Nous allons aujourd’hui voir comment décompiler et visualiser une apk.
Pour cela nous allons utiliser deux outils :

  • JD-GUI
  • dex2jar

La machine de Dalvik

La machine de Dalvik est une machine virtuelle présente sur les téléphones android. Elle est très proche d’une JVM.
D’après Wikipédia, « Un outil appelé dx est utilisé pour convertir quelques .class Java en .dex ».
Si on ouvre un apk avec gestionnaire d’archive on obtient quelque chose comme ça :

archiveAPK

Le fichier classe.dex est celui que nous allons décompiler.

dex2jar

Le logiciel dex2jar est téléchargeable à l’adresse suivante : http://code.google.com/p/dex2jar/downloads/list

Pour l’utiliser il suffit de décompresser le fichier et pour l’utiliser :

$ ./dex2jar.sh classes.dex

On obtient alors un fichier jar. Pour visualiser le .jar, utilisons le logiciel JD-GUI.

JD-GUI

Le logiciel JD-GUI permet d’afficher les fichiers d’un .jar. Les fichiers .class sont alors affichés d’une manière user friendly.

DecompAPK

Conclusion

Il est tellement simple d’observer le contenu d’un apk qu’il serait stupide de s’en passer. Si vous souhaitez en savoir plus sur le langage utilisé par la machine de Dalvik, je vous recommande l’article suivant de Virtualabs :
http://virtualabs.fr/Reversing-d-applications-Android

It’s oversimple isn’t it?