加速度计(也称为G传感器)是当今最常见的传感器之一。 您几乎可以在每个现代小工具中都可以找到它。 加速度计执行一项相当简单的任务-测量设备的加速度。 让我们看看他是如何做到的-让我们使用NeoQUEST-2019在线阶段任务7的示例分析Android API传感器的机制。
根据传说,我们得到了2个文件:
7.apk和
7.txt 。 从任务的文本中可以得出以下结论(所有任务仍在
此处提供 ):
7.apk-一种
加密程序,以某种方式使用设备的加速度计设置;
7.txt-编码器生成的密码。 内容如下:
[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]我们看到文本是4个值的重复组,其中一个是整数,其余3个是浮点数。 为了方便起见,我们将它们放在单独的行中:
[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]密码格式已被整理出来,但是这些值的未知是未知的。 设备加速度计的某些参数,没有任何具体说明。 让我们转到Android开发人员网站,
查看加速度计的一般显示内容。
我们看到以下描述:
我们弄清了浮点参数的作用-这是设备沿X,Y和Z轴的加速度,但是如何了解它们各自负责哪个轴呢? 现在是启动应用程序的时候了。 看起来像这样:
有2个用于确定应用程序行为的选项:反编译
.apk和分析结果值。 接下来,我们考虑第二种方法,并插入负责应用程序操作的反编译代码。
密码包含正值和负值(我们知道这些是在不同轴上的加速度),因此我们可以做一个假设:如果设备沿轴的倾斜矢量相反,那么加速度值的绝对值将近似相等,而差值只会是正负号。
以下是用于存储加速信息的代码清单:
public class MotionSnapshot { public final float angle_alpha; public final float angle_beta; public final float angle_gamma; public final long event_time; ... }
基于这些考虑,我们面临以下任务:
- 确定密码中的哪个值对应于设备的斜率
- 定义偏差模式
- 给每个数字关联一个偏差模式以进行解密
前两个任务将并行执行。 在电话上,我们可以测试2种类型的倾斜:
- 从我自己/到我自己
- 左/右
负责处理来自加速度计的事件的代码 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)); } }
单击按钮即可生成设备斜率的代码 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); } }
负责生成密码的代码 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 = ""; }
让我们按顺序开始。 为了测试第一种类型的斜率,我们选择数字2和8。每增加3次单击一次。 我们得到以下结果:
[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]好吧,用肉眼可以看到2参数中的差异。 让我们开始填写模板。
我们以密码行中相应字段的值范围的形式表示模板。 我们用问号标记我们尚不知道的内容。
[? ]
[(<0)-偏离自己; (> 0)-自我拒绝]
[?]
[?]同样,我们将使用按钮4和6进行测试。结果:
[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]考虑到学习的模式来更新模板:
[? ]
[(<0)-偏离自己; (> 0)-自我拒绝]
[?]
[(<0)-向右偏离; (> 0)-向左偏移]显然,第三个值是向上/向下偏差,因为这是唯一剩余的向量。 而且我们真的不需要检查它,因为对于确定按下的按钮的明确确定,我们已经有了众所周知的模板。
现在,我们将基于按钮的位置和开发的模板为键盘上的每个数字创建一个模板(*-参数对我们不感兴趣):
1-[*] [<0] [*] [> 0]
2-[*] [<0] [*] [接近0]
3-[*] [<0] [*] [<0]
4-[*] [] [*] []
5-[*] [接近0] [*] [接近0]
6-[*] [接近0] [*] [<0]
7-[*] [> 0] [*] [> 0]
8-[*] [> 0] [*] [接近0]
9-[*] [> 0] [*] [<0]
0-[*] [> 0] [*] [接近0]从图中可以看出,按钮8和0具有相同的参数,因此它们的解密可能是模棱两可的-当在密码中遇到这种组合时,您应该尝试两个选项。 现在我们将获得的模板应用于密码,我们得到2个答案:1029761235和1829761235,其中
1829761235是
true 。 作业完成!
很快-6月26日-NeoQUEST 2019面对面会议将举行! 赶快在活动网站上
注册 。 在不久的将来,habrastatya将随着该程序的发布而发布,请不要错过!