【实战】某习通app逆向分析(一)检测切屏、拍照、上传

【实战】某习通app逆向分析(一)检测切屏、拍照、上传

前言

Android 上的应用安装文件是 apk 格式,这个 apk 文件其实就是个归档文件压缩包,把应用相关的源码、资源文件、配置文件等乱七八糟的东西都简单粗暴的归档打包,其包内文件结构大体如下:

文件或目录 作用
META-INF/ 存放签名信息,用来保证 apk 包的完整性和系统的安全。
res/ 存放资源文件的目录
libs/ 若存在,则存放的是 ndk 编译出来的 so 文件库
AndroidManifest.xml 程序全局配置文件
classes.dex 最终生成的 dalvik 字节码
resources.ars 编译后的二进制资源文件。通常本地化、汉化资源存储在该文件文件中。

因此,我们将 apk 后缀改成 zip 压缩格式并直接解压就能得到 app 的 dalvik 指令集 dex 文件,然后再将其反编译为 smali 文件,还可以再反编译为 java 代码文件,这样就几乎等同于拿到了 app 就能拿到可读性还蛮清晰的源码,导致逆向破解的门槛几乎很低;没有做防范措施的 app 几乎等同于在裸奔,因此后来演变出来一些保护措施,让 apk 被反编译后获取的代码难理解。

准备阶段

查壳

image-20220615123824732

发现是某梆加固,但是 pkid 查壳有不确定性,打开 apk -> lib 发现了特征 DexHelper 确定了加固

image-20220615124218806

脱壳

在这里不再进行二代壳脱壳讲解,这里有个小技巧,把这些 dex 文件重命名为 classes.dex、classes1.dex、…, 然后压缩成 zip,把后缀改为 apk。再用 jadx 打开这个 apk,就能一次载入所有的 dex 文件了。(或者使用 jadx 1.2,这个版本可以打开多个 dex 文件,我也是后来才发现)

但是前提是要将他们进行 dex 修复后才可以打包

开始

对于安卓来说,检测用户切屏无非就是两个权限

  1. 获取手机某个权限(例如:悬浮窗)
  2. root
    对于第二条来说 root 基本是不可能的,所以我们的中心是第一条

分析

我们知道学习通在考试的时候会检测切屏 悬浮窗 复制粘贴 人脸拍照等等,在上网查相关资料时候发现 在 2020 年时候检测切屏会发一个请求img

img

当我搜索关键字”离开“的时候 只搜索到了

image-20220615115939958

用户状态 = ? 离开会议 所以没有继续深入研究下去


问题来了:app 如何检测用户的呢? 带着这个疑惑 我们去百度查一下开发 API 发现好像并没有什么用image-20220615120118859

带着这个问题 进入到 app 内部进行分析 打开脱壳后的 app 发现 app 并没有做什么混淆image-20220615120903076

所以我们找到 exam 这个包点进去看 发现了一个内部类 关键函数出来了 onDown

onScroll onSingleTapUp

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
public class C4515b extends GestureDetector.SimpleOnGestureListener {

/* renamed from: c */
public int f14877c;

/* renamed from: d */
public int f14878d;

public C4515b() {
}

@Override // android.view.GestureDetector.SimpleOnGestureListener, android.view.GestureDetector.OnGestureListener
public boolean onDown(MotionEvent motionEvent) {
int[] iArr = new int[2];
ExamFaceWindow.this.f14867d.getLocationOnScreen(iArr);
this.f14877c = iArr[0];
this.f14878d = iArr[1];
return super.onDown(motionEvent);
}

@Override // android.view.GestureDetector.SimpleOnGestureListener, android.view.GestureDetector.OnGestureListener
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent2, float f, float f2) {
float rawX = motionEvent2.getRawX() - motionEvent.getRawX();
float rawY = motionEvent2.getRawY() - motionEvent.getRawY();
WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) ExamFaceWindow.this.f14867d.getLayoutParams();
int i = (int) (this.f14877c + rawX);
int i2 = (int) (this.f14878d + rawY);
FloatViewLocation.m25890a(i);
FloatViewLocation.m25888b(i2);
layoutParams.x = i;
layoutParams.y = i2;
ExamFaceWindow.this.f14866c.updateViewLayout(ExamFaceWindow.this.f14867d, layoutParams);
return super.onScroll(motionEvent, motionEvent2, f, f2);
}

@Override // android.view.GestureDetector.SimpleOnGestureListener, android.view.GestureDetector.OnGestureListener
public boolean onSingleTapUp(MotionEvent motionEvent) {
if (ExamFaceWindow.this.f14875l != null) {
ExamFaceWindow.this.f14875l.m103234a();
return true;
}
return true;
}
}

所以目前来说 我们只需要去 hook 干掉这三个检测的函数就可以实现屏蔽检测切屏这个功能了

但是我们怎么知道他什么时候拍照了 怎么拍照的呢?那是不是得有一个状态 Status,所以进行了进一步搜索与跟进

image-20220615121555324

当我在查看 FaceCollectManager 这个包的时候,发现了一串新的代码

1
2
3
4
5
6
7
8
9
10
11
12
public void mo20960a(String str) {
if (FaceCollectManager.this.m103256s()) {
return;
}
this. CollectData.setLocalPath(str);
this. CollectData.setCollectStatus(1);
this. CollectData.setUploadStatus(0);
this.f CollectData.setCompleteTime(System.currentTimeMillis());
FaceCollectManager.this.m103280g();
FaceCollectManager.this.m103297a(this.f14859a);
}

看到了这个 setUploadStatus 方法,既然有上传状态设置,那必然有上传这个函数或者类,有了这个思路我们去搜索,果然发现了

image-20220615123101371

ExamUploader 这个上传类里包含了这个方法 跟进这个方法看到

1
2
3
4
5
6
7
public void m25900a(String str) {
Map<String, List<CollectData>> map = this.f93983b;
if (map == null || map.isEmpty() || !Checkman.m45768d(this.f93985d)) {
return;
}
m25898a(this.f93985d, str, this.f93983b.get(this.f93985d));
}

发现了这个类,由于现在的环境属于静态调试,所以无法进行 hook 和动态调试查看里面的内容,但是根据代码来说,这个 m25900a 应该就是上传的关键函数。

总结

由于环境问题,无法进行动态调试与分析,所有的调试过程均处于静态调试,所以各位也不要以身犯险,文章仅用于学习参考,切勿用于非法途径。

我自己也是逆向新人,也看过一些针对新人的逆向教程,常因教程不详细而产生过许多疑惑。本篇文章已尽可能地详细,但因精力有限,难免有照顾不到的地方。希望本篇文章能给读者有所启发,

参考文章

https://zhuanlan.zhihu.com/p/143704706?ivk_sa=1024320u

https://developer.android.com/guide/topics/media/camera?hl=zh-cn#capture-video

https://zhuanlan.zhihu.com/p/143210581

https://sentrylab.cn/blog/2022/%E5%AE%89%E5%8D%93%E9%80%86%E5%90%91-%E8%84%B1%E5%A3%B3%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/

【实战】某习通app逆向分析(一)检测切屏、拍照、上传

https://www.mineseb.cn/2022/06/15/【实战】某习通app逆向分析(一)检测切屏、拍照、上传/

作者

Codecat

发布于

2022-06-15

更新于

2022-06-15

许可协议

评论