Android 应用安全防御措施

1,566

一:静态代码块分析

    使用静态代码分析可以再不运行程序的前期下对程序存在的潜在问题进行分析,如控制内存使用越界等。SDK提供了一个静态代码分析工具lint,这个工具可以再通过扫描工程的所有代码和资源文件后根据所得结果,将检测的问题分为6大类
正确性、可用性、安全性、无障碍性、性能、国际化。可以根据问题类型和内容将代码进行修改和优化。

二:Android Java代码混淆

    混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。被混淆过的程序代码,仍然遵照原来的档案格式和指令集,执行结果也与混淆前一样,只是混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,在缺乏相应的函数名和程序注释的况下,即使被反编译,也将难以阅读。同时混淆是不可逆的,在混淆的过程中一些不影响正常运行的信息将永久丢失,这些信息的丢失使程序变得更加难以理解。

三:apk数字签名校验的防止应用被重新打包

    Android 应用程序在发布前,都必须被签名。假设用于签名的密钥不被泄露或共享,我们可以认为,当被破解的Android软件重新打包后,其 “签名”必然与官方版本不同
其核心点就是在你的打包发布apk应用中,如果输入了你的私钥,会同时自动生成一个公钥的,并且这个公钥根据你每次打包的时候私钥的变化而发生变化的。
而这个私钥只有你自己知道,公钥是可以公开的,当然对于发布的应用开发者他也不知道公钥到底公开,怎么公开,公开给谁。

public  String getApkSignatureMD5(String apkPath) throws Exception {
        Class clazz = Class.forName("android.content.pm.PackageParser");
        Method parsePackageMethod = clazz.getMethod("parsePackage", File.class, String.class, DisplayMetrics.class, int.class);

        Object packageParser = clazz.getConstructor(String.class).newInstance("");
        Object packag = parsePackageMethod.invoke(packageParser, new File(apkPath), null, content.getResources().getDisplayMetrics(), 0x0004);

        Method collectCertificatesMethod = clazz.getMethod("collectCertificates", Class.forName("android.content.pm.PackageParser$Package"), int.class);
        collectCertificatesMethod.invoke(packageParser, packag, PackageManager.GET_SIGNATURES);
        Signature mSignatures[] = (Signature[]) packag.getClass().getField("mSignatures").get(packag);
        Signature apkSignature = mSignatures.length > 0 ? mSignatures[0] : null;
        if(apkSignature != null) {
        return StringUtils.md5(apkSignature.toCharsString());
        }
        return null;
        }

四:使用第三方工具对于apk应用进行加壳

    目前已经有一些搞安全的公司在做一些apk加密,加壳的工作,其中有梆梆加密,爱加密, apkprotectlite 等软件能够将你的apk加密,加壳,防止应用被黑客破解掉,加大软件的安全性。

五:数据存储加密

    数据安全的隐患有:
    数据备份,如果应用程序允许用户备份私有数据,数据就可以直接复制到pc 上,这样数据就会完全暴露给用户。
恶意软件:恶意软件有可能已用漏洞访问到私有数据,造成数据泄露。
对非常重要的数据在保存到文件之前,需要对数据进行加密操作。
    数据加密考虑的因素有:
    密钥:加/解密使用的密钥不能写在代码中,可以由用户输入或程序随机产生。
    密钥的存储:密钥尽量不要存储到设备上,可以将密钥分成几段乱序存储,并且密钥经过一些计算后作为加/解密的密钥。如SHA-1.
加密后数据处理:由于加密算法加密后的数据为二进制数据,因此在保存时,为了防止出错,可以将数据转换成ASCII字符的形式。一般推荐使用Base64。

六:BroadCast Receive 安全

    1. 一些敏感的广播并不想让第三方的应用收到 ;
    2. 要限制自己的Receiver接收某广播来源,避免被恶意的同样的ACTION的广播所干扰,我们可以为BroadCast Receive 添加相应的权限来控制,可以从接收方和发送方两个方面加以保护。
    发送方措施:谁有权收我的广播
这种情况下,可以在应用发广播时添加参数声明Receiver所需的权限。
(1)首先,在Androidmanifest.xml中定义新的权限,譬如:

<permission android:name= "com.android.permission.XXX_XXX"/>

(2)然后发送广播时将此权限当做参数传入:

sendBroadcast("com.android.XXX_ACTION","com.android.permission.XXX_XXX");

(3)在Receiver应用的AndroidManifest.xml中要添加对应的XXX_XXX权限。

<uses-permission android:name="com.android.permission.XXX_XXX"/>

    这样做之后就使得只有具有permission权限的Receiver才能接收此广播要接收该广播,
接收方措施:谁有权给我发广播
(1)在AndroidManifest.xml中定义新的权限SEND_XXX,例如

<permission android:name="com.android.SEND_XXX"/>

(2)在Receiver app的Androidmanifest.xml中的tag里添加权限SEND_XXX的声明,如下:

<receiver android:name=".XXXReceiver" 
          android:permission="com.android.permission.SEND_XXX"> 
    <intent-filter>
         <action android:name="com.android.XXX_ACTION" /> 
    </intent-filter>
</receiver>

(3)要发送这种广播,需要在AndroidManifest.xml中也声明使用该权限即可,如下:

<uses-permission android:name="com.android.permission.SEND_XXX"/>

    这样一来,该Receiver便只能接收来自具有该send_permission权限的应用发出的广播。
所以,广播可以从发送方和接收方两个方面加以保护,发送方可以通过为BroadCast Intent 设置权限的方式,确保该BroadCast Intent 只允许被授权的BroadCast Receive 接收,防止将BroadCast Intent 误传给危险的接收方;相反的,接收方Receive 也可以为自己设定访问权限,要求所接收的BroadC ast Intent 必须必备所设权限,防止误收到危险的BroadCast Intent。可以将两者结合使用,才能确保组件安全地接收来自授权的发送的信息。