【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值:
可以通过如下方式获得:
def md5_for_file(file_path, block_size=2**20):
md5 = hashlib.md5()
f = open(file_path, 'rb')
try:
while True:
data = f.read(block_size)
if not data:
break
md5.update(data)
except Exception, e:
print e
finally:
f.close()
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中有配置文件可以直接查看就可以获取文件内容,如果不是,就需要通过运行程序截取文件的日志信息,然后进行判定。
【Android端APP 安装包检查】安装包检查具体内容及实现方法的更多相关文章
- 【Android端 APP GPU过度绘制】GPU过度绘制及优化
一.Android端的卡顿 Android端APP在具体使用的过程中容易出现卡顿的情况,比如查看页面时出现一顿一顿的感受,切换tab之后响应很慢,或者具体滑动操作的时候也很慢. 二.卡顿的原因 卡顿的 ...
- 【Android端 APP 内存分析】使用工具进行APP的内存分析
Android端可以通过adb 命令直接获取内存信息,当然Android studio也提供了对内存的监控分析工具,并且后续可以结合MAT做分析 今天介绍的是通过Android studio和MAT工 ...
- 【Android端 APP 启动时长获取】启动时长获取方案及具体实施
一.什么是启动时长? 1.启动时长一般包括三种场景,分别是:新装包的首次启动时长,冷启动时长.热启动时长 冷启动 和 热启动 : (1)冷启动:当启动应用时,后台没有该程序的进程,此时启动的话系统会分 ...
- C#服务端通过Socket推送数据到Android端App中
需求: 描述:实时在客户端上获取到哪些款需要补货. 要求: 后台需要使用c#,并且哪些需要补货的逻辑写在公司框架内,客户端采用PDA(即Android客户端 版本4.4) . 用户打开了补货通知页面时 ...
- 将报表移动端集成到自有移动端app方法【IOS、Android】
应用场景 用户有自己的app,希望把报表的移动端[本文中以FineReport移动端为例]功能集成到他们的app里面去,而不需要安装两个app.Android端和IOS端的集成接口是不一样的,下面我们 ...
- 微信app支付(android端+java后台)
本文讲解使用微信支付接口完成在android开发的原生态app中完成微信支付功能, 文章具体讲解了前端android如何集成微信支付功能以及后台如何组装前端需要支付信息, 话不多话, 具体看文章内容吧 ...
- 使用Chrome开发者工具调试Android端内网页(微信,QQ,UC,App内嵌页等)
使用Chrome开发者工具调试Android端内网页(微信,QQ,UC,App内嵌页等) 前言 移动端页面调试一直是好多朋友头疼的问题,iOS 由于其封闭的特性和整体较高的性能,整体适配相对好做,调试 ...
- 移动端App开发 - 02 - iPhone/iPad/Android UI尺寸规范
移动端app开发 - iPhone/iPad/Android UI尺寸规范 本笔记抛去无用的前期分析什么的,全是干货,简洁干练 本笔记不单独针对 ios 或者 Android,两种都介绍,当然我们实际 ...
- windows 代理服务器的搭建,提供Android 端访问公网.
这段时间遇到一个情况,移动的网络收费.但是可以访问学校内部的网络,比如说学校官网图书馆之类了.所以我这里便想到一个方法,用学校内部一个可以访问互联网的主机充当代理服务器(我这里使用自己的电脑,非服务器 ...
随机推荐
- WEB页面采集器编写经验之一:静态页面采集器
严格意义来说,采集器和爬虫不是一回事:采集器是对特定结构的数据来源进行解析.结构化,将所需的数据从中提取出来:而爬虫的主要目标更多的是页面里的链接和页面的TITLE. 采集器也写过不少了,随便写一点经 ...
- 提交到github远程仓库遇到的问题
1.could not read from remote repository 可能原因是没有将ssh 密匙添加到github,所以没有权限 解决办法: 1. ssh-keygen -C 'your@ ...
- 在windows编译MariaDB
OS: Windows XP sp3 IDE: VS2010 MariaDB: V5.5 (到目前为止2016.5,中文域(.cn)只有清华大学 TUNA 镜像源可用) (.tar.gz为源码:.zi ...
- verilog断言(SVA:systemverlog assertion)语法 ---- 转载
转载自:http://blog.sina.com.cn/s/blog_4c270c730101f6mw.html 作者:白栎旸 断言assertion被放在verilog设计中,方便在仿真时查 ...
- 十四、View Port 2.0
1. 分为以下几类: (1) data classes: 用来访问scene中的geometry 和 shaders (2)scene override: 主要是用户自定义的drawing .shad ...
- mapreduce核心原理
1:第一阶段: 第一阶段的task每一个nodemanager并发运行程序,完全并发,各不影响.这就是map阶段 运行的task时maptask 2:第二个阶段的task并发实例互不相干,但是他们的数 ...
- Effective c++
static 声明在堆上申请静态存储 对于局部变量,将存储方式改为静态存储 对于全局变量,将连接方式局限在文件内 类中static变量:属于整个类,独立存储,没有this指针 inline inlin ...
- 浅尝辄止——在C++中调用C#的回调函数——COM方式
这种方式比较简单,给大家分享一下,同时讲一下SafeArray内定义结构体的方法 1. 需求描述 需求是这样的,C++代码和C#代码相互通信(C++一般做服务,C#做客户端),C++一侧准备好数据,然 ...
- Ninject之旅之十:Ninject自定义提供者
摘要 提供者是特殊的工厂类,Ninject使用它来实例化解析类型.任何时候我们绑定一个服务类型到一个组件,我们都隐式地关联那个服务类型到一个可以实例化那个组件的提供者.这个隐藏的提供者被称为Stand ...
- NHibernate系列文章二十四:NHibernate查询之Linq查询(附程序下载)
摘要 NHibernate从3.0开始支持Linq查询.写Linq to NHibernate查询就跟写.net linq代码一样,非常灵活,可以很容易实现复杂的查询.这篇文章使用Linq to NH ...