L'accéléromètre - alias G-sensor - est aujourd'hui l'un des capteurs les plus courants. Vous pouvez le rencontrer dans presque tous les gadgets modernes. L'accéléromètre effectue une tâche assez simple - il mesure l'accélération de l'appareil. Voyons comment il le fait - analysons les mécanismes des capteurs d'API Android en utilisant l'exemple de la tâche n ° 7 de la phase en ligne de NeoQUEST-2019.
Selon la légende, nous avons reçu 2 fichiers:
7.apk et
7.txt . Les conclusions suivantes peuvent être tirées du texte de la tâche (et toutes les tâches sont toujours disponibles
ici ):
7.apk - un programme de
cryptage qui utilise d'une manière ou d'une autre les paramètres de l'accéléromètre de l'appareil;
7.txt - cryptogramme généré par l'encodeur. Ce qui suit y est écrit:
[1749054104147639] [2.07154922] [10.001905] [4.5387093] [1749056073889025] [5.7193284] [8.221763] [0.01391537] [1749058029180773] [4.684068] [12,05614] [0,0377285] [1749060105291613] [4,6900544] [6,9307165] [4,7094293] [1749062123327502 ] [4.4682417] [7.512769] [6.037215] [1749067640096818] [1.0396843] [8.798672] [4.9335976] [1749070016073380] [2.3173676] [10.180047] [4.948362] [1749072343679582] [126060] 2,48394698] [10,834006] [6,306282] [1749075827770391] [0,2795044] [13,279829] [0,19391555]Nous voyons que le texte est un groupe répétitif de 4 valeurs, dont l'une est un entier, et les 3 restants sont des nombres à virgule flottante. Pour plus de commodité, nous les mettons en lignes distinctes:
[1749054104147639] [- 2.07154922] [10.001905] [4.5387093]
[1749056073889025] [5.7193284] [8.221763] [0.01391537]
[1749058029180773] [- 4.684068] [12.05614] [0.0377285]
[1749060105291613] [4.6900544] [6.9307165] [- 4.7094293]
[1749062123327502] [4.4682417] [7.512769] [6.037215]
[1749067640096818] [1.0396843] [8.798672] [- 4.9335976]
[1749070016073380] [- 2.3173676] [10.180047] [4.948362]
[1749072343679582] [- 4.3660607] [12.218135] [0.5312999]
[1749073674459611] [- 2,48394698] [10.834006] [- 6,306282]
[1749075827770391] [0,2795044] [13,279829] [- 0,19391555]Le format du cryptogramme a été trié, mais quelles sont ces valeurs ne sont pas connues. Quelques paramètres de l'accéléromètre de l'appareil, sans précision. Et allons sur le site des développeurs Android et
voyons ce que l'accéléromètre peut montrer en général.
Nous voyons la description suivante:
Nous avons compris de quoi les paramètres à virgule flottante sont responsables - c'est l'accélération de l'appareil le long des axes X, Y et Z. Mais comment comprendre de quel axe chacun d'eux est responsable? Il est temps de lancer l'application. Cela ressemble à ceci:
Il existe 2 options pour déterminer le comportement de l'application: décompiler
.apk et analyser les valeurs résultantes. Ensuite, nous considérons la deuxième méthode et donnons l'insertion du code décompilé qui est responsable des actions considérées de l'application.
Le cryptogramme contient des valeurs positives et négatives (nous savons que ce sont des accélérations le long de différents axes), nous pouvons donc faire une hypothèse: si les vecteurs d'inclinaison de l'appareil le long de l'axe sont opposés, alors les accélérations seront approximativement égales en valeur absolue, et la différence ne sera qu'en signe.
Voici une liste de codes pour stocker les informations d'accélération:
public class MotionSnapshot { public final float angle_alpha; public final float angle_beta; public final float angle_gamma; public final long event_time; ... }
Sur la base de ces considérations, nous sommes confrontés aux tâches suivantes:
- Déterminer quelle valeur dans le cryptogramme correspond à la pente de l'appareil
- Définir le modèle d'écart
- À chaque chiffre d'associer un modèle de déviation pour le décryptage
Les 2 premières tâches seront effectuées en parallèle. Au téléphone, nous pouvons tester 2 types d'inclinaison:
- De moi / à moi
- Gauche / droite
Le code responsable de la gestion des événements de l'accéléromètre public class SensorListener implements SensorEventListener { private MotionTrace Trace; public SensorListener(MotionTrace trace, MainActivity activity) { Trace = trace; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { Trace.addSnaphot(new MotionSnapshot(event.values, event.timestamp)); } }
Le code responsable de la génération de la pente de l'appareil en un clic de bouton public class MotionTrace { private ArrayList<MotionSnapshot> Deltas; private long Length; private MotionSnapshot LastSnapshot; public MotionTrace(long len) { LastSnapshot = new MotionSnapshot(0,0,0,0); Deltas = new ArrayList<>(); Length = len; } public void addSnaphot(MotionSnapshot snapshot) { if (Deltas.size() >= Length) { Deltas.remove(0); } MotionSnapshot delta = new MotionSnapshot(0,0,0,0); if (Deltas.size() > 0) { delta = snapshot; } Deltas.add(delta); } public ArrayList<MotionSnapshot> getDeltas() { return new ArrayList<>(Deltas); } }
Le code responsable de la génération du cryptogramme public void SaveCiphertext() { Log.d(Config.MAIN_TAG, "SAVING - {{" + Ciphertext + "}}"); try { File root = new File(Environment.getExternalStorageDirectory(), Config.DIRNAME); if (!root.exists()) { Log.d(Config.MAIN_TAG, "Creating directory - [" + root + "]"); if (!root.mkdirs()) { Log.d(Config.MAIN_TAG, "Error creating directory"); } } File out_file = new File(root, Config.FILENAME); Log.d(Config.MAIN_TAG, "Out - [" + out_file + "]"); PrintWriter writer = new PrintWriter(out_file, "UTF-8"); writer.println(Ciphertext); writer.close(); Toast.makeText(this, "Saved to - [" + out_file + "]", Toast.LENGTH_LONG).show(); } catch (IOException ex) { Toast.makeText(this, "Error saving data", Toast.LENGTH_SHORT).show(); } Ciphertext = ""; }
Commençons dans l'ordre. Pour tester les pentes du premier type, nous sélectionnons les nombres 2 et 8. Cliquez sur chaque 3 fois avec un effort croissant. On obtient le résultat suivant:
[2687418463227102] [- 0,23700714] [10,764615] [- 0,9759079]
[2687419411042043] [- 3,5834892] [13,591138] [- 1,7036858]
[2687420383026907] [- 5,575793] [13,533228] [- 1,3104248]
[2687421461360546] [0,6850295] [6.0002656] [0,5568123]
[2687422317256542] [4.1720495] [1.8675026] [1.545407]
[2687423250514599] [7.9689393] [- 3.600097] [0.33846742]Eh bien, les différences dans le paramètre 2 sont visibles à l'œil nu. Commençons à remplir le modèle.
Nous représentons le modèle sous la forme de plages de valeurs des champs correspondants dans la ligne de cryptogramme. Nous marquons d'un point d'interrogation ce que nous ne savons pas encore.
[? ]
[(<0) - déviation de soi-même; (> 0) - auto-rejet]
[?]
[?]De même, nous effectuerons des tests avec les boutons 4 et 6. Résultats:
[2688019191605386] [1.7270225] [9.541045] [0.0397171]
[2688020247971353] [1.0615791] [9.794326] [4.9135437]
[2688021887957875] [1.0974716] [7.5535636] [7.8307548]
[2688023749896352] [1,3328063] [9,43923] [- 0,27600938]
[2688024849688832] [1.1357567] [9.9313135] [- 2.4410355]
[2688026002520864] [0,30400848] [6,4610033] [- 8,0956335]Mettre à jour le modèle en tenant compte du motif étudié:
[? ]
[(<0) - déviation de soi-même; (> 0) - auto-rejet]
[?]
[(<0) - déviation vers la droite; (> 0) - déviation vers la gauche]De toute évidence, la troisième valeur est l'écart haut / bas, car c'est le seul vecteur restant. Et nous n'avons pas vraiment besoin de le vérifier, car pour la détermination sans ambiguïté du bouton pressé, nous avons déjà le modèle bien connu.
Nous allons maintenant créer un modèle pour chaque chiffre du clavier, basé sur la position des boutons et le modèle développé (* - le paramètre ne nous intéresse pas):
1 - [*] [<0] [*] [> 0]
2 - [*] [<0] [*] [proche de 0]
3 - [*] [<0] [*] [<0]
4 - [*] [] [*] []
5 - [*] [proche de 0] [*] [proche de 0]
6 - [*] [proche de 0] [*] [<0]
7 - [*] [> 0] [*] [> 0]
8 - [*] [> 0] [*] [proche de 0]
9 - [*] [> 0] [*] [<0]
0 - [*] [> 0] [*] [proche de 0]Comme le montre la figure, les boutons 8 et 0 ont les mêmes paramètres, de sorte que leur décryptage peut être ambigu - lorsque vous rencontrez une telle combinaison dans un cryptogramme, vous devriez essayer les deux options. Maintenant, nous appliquons les modèles obtenus au cryptogramme et nous obtenons 2 réponses: 1029761235 et 1829761235, dont
1829761235 est
vrai . Affectation terminée!
Très prochainement - le 26 juin - le Concours Face à Face NeoQUEST 2019 aura lieu! Dépêchez-
vous de vous
inscrire sur le site Web de l'événement. Dans un avenir proche, habrastatya sera publié avec l'annonce du programme, ne manquez pas!