文章目录

最近步步高的平板被熊孩子的家长爆料了,说里面有有黄色内容。后面发现是一些免费的第三放学习应用内置广告,在后台弹窗口广告,结果有些无节操的广告就蹦出来了,例如下面那个:

然后这边就让想办法屏蔽这些第三方应用内的广告。发现市场上有不少工具类的软件可以检测,并且拦截第三应用内的广告。例如腾讯手机管家、360安全卫士等。下载下来研究了下,从这些软件检测出来的结果好像可以看出一点线索:


(上面那个是腾讯手机管家的)

它列出的广告软件,后面都带有一些包名。虽然后面那些 a、b、c 之类应该是混淆过的,但是前面的前缀就很明显了。一般应用的广告都是集成一些广告或是平台的 sdk 。这里 sdk 一般都是 jar 包,虽然可以混淆,但是一般包名的前缀会保留,一般如果全部混淆弄成 a、b、c 之类,作为库来说,极易和其他混淆后的库或是程序本身的名字冲突。

这就给我们检测提供了机会了。我发现腾讯管家在扫描的时候会提示,正在扫描应用,然后之后会提示正在云端检测。好,这下我就能确定了(虽然可以反编译 apk 然后慢慢看,但是腾讯管家代码太多了,拦截广告只是它的一个小功能,我就懒得慢慢看了,这种时候需要大胆猜猜,呵呵)。它应该是可以扫描出 apk 调用了哪些类,然后应该有个广告的类名字数据库,本地匹配玩之后,再到它们的服务进行匹配(前面说了就算混淆了,但是前缀就能够识别了)。

于是去度娘了一下(度娘能解决的,就不请谷姐了,免得天天翻墙),发现 android 的 dex 还真有接口可以枚举出一个 apk 调用哪些 class 文件。下面直接上代码了:

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
private void collectInstalledPkgs(ArrayList<String> output) {
if (null == output) {
Log.d(TAG, "output data is null, we can't collect installed pkgs");
return;
}
List<PackageInfo> pkgInfos = mPm.getInstalledPackages(0);
output.clear();
for (PackageInfo info : pkgInfos) {
if (null == info) continue;
output.add(info.packageName);
Log.d(TAG, "collect pkg: " + info.packageName);
}
pkgInfos.clear();
}
private void scanPkgDexFile(String pkgName) {
if (null == pkgName) {
Log.d(TAG, "the target pkgName can't null !");
return;
}
ApplicationInfo info = null;
try {
info = mPm.getApplicationInfo(pkgName, 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
return;
}
if (null == info) {
return;
}
// we ignore system app or our bbk app
if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0
|| (info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0
|| pkgName.startsWith("com.eebbk")
|| pkgName.startsWith("com.bbk")) {
Log.d(TAG, "pkg: " + pkgName + " is system app or bbk app, we ignore it.");
return;
}
try {
DexFile dexFile = new DexFile(info.sourceDir);
Enumeration<String> entries = dexFile.entries();
Log.d(TAG, "scan pkg: " + pkgName + " source path: " + info.sourceDir);
while (entries.hasMoreElements()) {
Log.d(TAG, entries.nextElement());
}
Log.d(TAG, " ");
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "scan dex file failed !");
}
}

然后贴下输出:


(很明显这个是 google 的 admob)

但是感觉好像和腾讯的有点不太一样。然后我在 framework 的 DexFile.java(ibcore/dalvik/src/main/java/dalvik/system/DexFile.java) 中加了打印,发现腾讯的好像没调这个接口。有点奇怪了,不知道它是通过什么方式检测的,可能通过 DexFile 是比较初级的办法,不过这个确实可以检测得出来。

另外在 AndroidManifest.xml 里面申明广告 sdk 的 activity 的一般都是插屏广告(就是那种弹出式的,整个大屏幕的)。也有接口可以解析 AndroidManifest 中申明的 activity 的,这样可以更加细化检测到的广告。

文章目录