【Android端APP 安装包检查】安装包检查具体内容及实现方法

一、安装包检查的具体包含内容有哪些?

 

1、安装包检查的一般内容包括:

 

安装包基本信息检查:

文件大小: xx MB

包名: com.xx

名称:  xx

本次安装包证书与外网证书对比一致性:是

版本号: xx.xx.xx

内部版本号: xx

min SDK:xx

log是否关闭:是

是否混淆: 是

重复文件个数:xx 项

重复文件大小:xx KB/MB

 

资源文件空文件列表:

 

资源文件重复文件列表:(共xx项)

 

二、获取具体的内容的方案:

 

具体需要获取的内容如下:

(一)关于混淆

1、什么是混淆?

混淆代码是为了防止代码被反编译之后,能够得到代码的实现逻辑等;

Android端的代码混淆的方案:

程序中能够看到一个文件,是:project.properties,找到这个文件,就能找到混淆配置的文件路径了,如:

然后这里可以看到proguard.config = proguard.cfg,然后找到这个文件,就能看到类似这样的结构:

 

其中意义如下:

 a. 把所有你的jar包都申明进来,例如:

 -libraryjars libs/apns_1.0.6.jar

 -libraryjars libs/armeabi/libBaiduMapSDK_v2_3_1.so

 -libraryjars libs/armeabi/liblocSDK4.so

-libraryjars libs/baidumapapi_v2_3_1.jar

-libraryjars libs/core.jar

-libraryjars libs/gesture-imageview.jar

-libraryjars libs/gson-2.0.jar

-libraryjars libs/infogracesound.jar

-libraryjars libs/locSDK_4.0.jar

-libraryjars libs/ormlite-android-4.48.jar

-libraryjars libs/ormlite-core-4.48.jar

-libraryjars libs/universal-image-loader-1.9.0.jar

b. 将你不需要混淆的部分申明进来,因为有些类经过混淆会导致程序编译不通过,如下:

-keep public class * extends android.app.Fragment  

-keep public class * extends android.app.Activity

-keep public class * extends android.app.Application

-keep public class * extends android.app.Service

-keep public class * extends android.content.BroadcastReceiver

-keep public class * extends android.content.ContentProvider

-keep public class * extends android.app.backup.BackupAgentHelper

-keep public class * extends android.preference.Preference

-keep public class * extends android.support.v4.**

-keep public class com.android.vending.licensing.ILicensingService

--以上都是API里边的类,最好都要避免混淆

有些很特殊的,例如百度地图,你需要添加以下申明:

-keep class com.baidu.** { *; } 

-keep class vi.com.gdi.bgl.android.**{*;}

 

2、判定代码是否混淆的方案判定?

首先可以通过手工的方式来判定代码是否经过了混淆,可以通过以下几种方式:

(1)先对安装包进行解压,之后能够得到classes.dex这样的文件,然后从网上下载dex2jar的工具先将dex转成jar,之后再使用jd-gui的exe将jar包转成class文件:

现在dex2jar.bat可以直接后面加classes.dex的路径就能生成到对应的文件,所以可以通过如下方式调用命令行:

 

D:\Program Files\反编译工具\反编译工具\dex2jar-2.0\dex2jar-2.0>d2j-dex2jar.bat C

:\Users\58\Desktop\赶集生活app包\GJAndroid_release_20161115\classes.dex C:\Users

\58\Desktop\赶集生活app包\GJAndroid_release_20161115\classes2.dex C:\Users\58\De

sktop\赶集生活app包\GJAndroid_release_20161115\classes3.dex  --force

dex2jar C:\Users\58\Desktop\赶集生活app包\GJAndroid_release_20161115\classes.dex

 -> .\classes-dex2jar.jar

dex2jar C:\Users\58\Desktop\赶集生活app包\GJAndroid_release_20161115\classes2.de

x -> .\classes2-dex2jar.jar

dex2jar C:\Users\58\Desktop\赶集生活app包\GJAndroid_release_20161115\classes3.de

x -> .\classes3-dex2jar.jar

 

其中--force的含义是:强制删除之前的结果文件,用新的文件覆盖老的文件

 

D:\Program Files\反编译工具\反编译工具\dex2jar-2.0\dex2jar-2.0>d2j-dex2jar.bat C

:\Users\58\Desktop\赶集生活app包\GJAndroid_release_20161115\classes.dex -o e:\11

1\111.jar -f

dex2jar C:\Users\58\Desktop\赶集生活app包\GJAndroid_release_20161115\classes.dex

 -> e:\111\111.jar

以上命令只能一条一条用,-o的命令行选项只能一次对应一个文件

 

如果有三个classes.dex的类似文件的话,可以循环,执行三条命令(解压之后扫描文件即可)

————————————————————————————————————————

接下来可以通过jd-gui的工具查看jar包:

 

需要首先确定我们的APP的代码的路径,比如赶集是:com.ganji.android的这个路径下面的;因为可能里面包含很多第三方的jar包本身就已经是混淆过的了。

 

(2)可以通过.smali的方式对资源文件进行判定,如果没有经过混淆,那就需要根据LaunchActivity.smali的文件内容来确定:

针对部分APK来说,直接通过apktool来判断R.smali之类的文件是否存在就可以判定,如果存在说明进行了混淆,如果不存在,则需要继续搜索LaunchActivity(启动Activity)的文件,对文件内容进行扫描。

首先,apktool通过命令行的使用方式如下:

C:\Users\58>apktool d  C:\Users\58\Desktop\赶集生活app包\all\GJAndroidClient15\ant-build\signed\GJAndroidClient15-gray-release.apk -o  E:\weihunxiao -f

主要参数如下:d 代表的是将apk文件进行decode, -o 代表的是进行output的dir, -f 指的是force,即强行覆盖安装

 

之后打开对应的文件夹,找到smali/com/ganji/android这个目录,看下方图示中的文件是否存在

如果资源文件经过了混淆的话,就不会存在这些文件,否则就会存在;以58主app为例,58主app的资源文件做了混淆,因此不存在R.smali这样的文件:

 

所以针对58主app这类的资源文件经过了混淆的,就找不到以上提到的R.samli的文件,此种情况下可以认为已经经过资源混淆;

第二步就是:针对赶集这样的,资源文件没有经过混淆的,就需要继续找LaunchActivity(启动Activity)的文件,通过对文件内容的判定来确定是否经过了混淆。

 

如何找到LaunchActivity的文件,就需要通过aapt的命令得到启动的Activity,然后通过这个文件路径去找,比如赶集网的APP的launchActivity.smali的路径如下:(备注:有可能文件比较多的情况下,会生成多个smali的文件夹,会命名为smali、smali2、smali3这样的,如果是三个文件夹都存在,就需要对三个文件夹都进行对应的文件路径Path拼接,之后判断是否存在对应的文件,再做进一步的文件内容的判定)

找到这个文件之后,打开,能够看到:

以上截图中能看到的只是针对#instance fields的内容,文件中还包含:#direct methods的内容

具体程序实现时,需要处理的就是:

通过文件行数扫描的方式,先得到:# interfaces,# annotations,# static fields,# instance fields,# direct methods这一行,之后继续往下扫描,如果下一行非空且不是以#开头的,就可以先放入到一个以 interfaces、annotations等为key的value为list的列表中。

之后就可以对内容进行判定了,比如说针对instance fields的list中的内容做判断,需要遍历,比如说:.field private a:J,按照冒号分割之后取index为0的部分:.field private a,然后再获取以空格分割的-1的index值的内容,判断该值是否存在于rulelist中,其中rulelist可以先暂定从a到z的26个字母。

其他类似。

 

(二) 关于资源文件的判定:空文件和重复文件的检测

 

首先安卓端的解压也可以直接用unzip.exe进行,这个工具直接搜索下载即可,有windows和linux下的。

然后解压之后可以生成到一个新的文件夹,然后针对整个新文件夹做一个资源文件的扫描。

 

命令行使用:unzip 安卓APK的路径 -d 解压之后的dest目录

 

如何判定资源文件呢?不能简单通过后缀名,需要对文件格式的文件头进行判定:

下面是从网上查到的文件格式 文件头(十六进制)   

JPEG (jpg) FFD8FF

PNG (png) 89504E47

GIF (gif) 47494638

TIFF (tif) 49492A00

Windows Bitmap (bmp) 424D

CAD (dwg) 41433130

Adobe Photoshop (psd) 38425053

Rich Text Format (rtf) 7B5C727466

XML (xml) 3C3F786D6C

HTML (html) 68746D6C3E

Email [thorough only] (eml) 44656C69766572792D646174653A

Outlook Express (dbx) CFAD12FEC5FD746F

Outlook (pst) 2142444E

MS Word/Excel (xls.or.doc) D0CF11E0

MS Access (mdb) 5374616E64617264204A

 

然后通过对文件进行遍历,在遍历的过程中判断文件的类型,是资源文件的才走下一步的判定,如果是资源文件,则判定大小,如果大小为0,则append到emptyFileList中;如果两个文件的大小一致,之后判断md5值是否一致,如果是的话,则将set(file1, file2)append到sameFileList中。

 

注意:针对相同文件的判定中,因为通过循环判定,因此需要进行去重,就需要通过set的方式进行去重。

然后下面针对这个空文件的list和重复文件的list进行输出即可。

 

(三)针对其他项的获取:

 

先通过aapt.exe获取——包名、名称、版本号、内部版本号、以及Min.SDK、权限

调用方法是:aapt dump badging APK包的路径

如下:

——>包名、内部版本号、版本号:

package: name='com.ganji.android' versionCode='470' versionName='7.7.0'

——>sdkVersion:'15'——把sdk版本与安卓的版本对应起来

——>权限的话——参照官方文档,将英文翻译成对应的中文权限即可

——>文件md5值:

可以通过如下方式获得:

 1 def md5_for_file(file_path, block_size=2**20):
 2     md5 = hashlib.md5()
 3     f = open(file_path, 'rb')
 4     try:
 5         while True:
 6             data = f.read(block_size)
 7             if not data:
 8                 break
 9             md5.update(data)   
10     except Exception, e:
11         print e
12     finally:
13         f.close()
14     return md5.hexdigest()

——>证书的md5值:

通过:

(1)unzip.exe -j apk /META-INF/*.RSA -d 自定义的文件夹,就能得到证书

(2)得到证书文件之后,通过keytool -printcert -file  .RSA文件的路径(其中keytool只要配置了java的环境变量就可以使用,参考资料可见:http://www.micmiu.com/lang/java/keytool-start-guide/)

需要跟APP正确的md5值进行比较,sha1也可以输出,比较之后,如果一致,认为OK

例如:比如下方是转转APK的,直接解压apk文件夹之后,进入到META-INF\zhuanzhuan.RSA 

命令是keytool -printcert -file RSA文件的路径,然后就能得到证书指纹 MD5:xxx 和 SHA1:xxx

证书文件的获得:可以先通过unzip命令将APK包的*.RSA文件先解压生成到rr的这个文件夹下:

——>大小:os.path.getsize(APK的文件路径)即可

 

(四)关于日志输出的检查:

——>日志是否关闭的判断,可以通过两种方式来走,如果你的app中有配置文件可以直接查看就可以获取文件内容,如果不是,就需要通过运行程序截取文件的日志信息,然后进行判定。

posted on 2016-12-13 10:40  可可_小虾米  阅读(2930)  评论(0编辑  收藏  举报

导航