首页 > 其他分享 >Android应用数据安全存储加固

Android应用数据安全存储加固

时间:2023-07-25 11:01:47浏览次数:41  
标签:存储 加密 Dalvik content 数据安全 SharedPreferences 寄存器 加固 Android

目前移动领域已经出现了相当部分的安全问题,新的恶意软件层出不穷,另一方面,企业对敏感数据保密性意识日益提高,作为移动开发者,有责任对最终用户的隐私和安全承担更多责任。

本文主要讨论移动安全存储策略,设计了安全加固方案,实现了移动应用逆向分析、安全代码自动注入等全流程的一键式加固工具,并进行了验证。


移动数据存储

Android平台实现数据存储的基本方式:

  • 数据共享(SharedPreferences)
  • 内部存储(File)
  • SQLite数据库存储
  • 外部存储
  • 网络存储

本文主要讨论前三种数据存储类型,实现了加密解密SDK,并实现对APP的安全存储注入。首先我们来简单讨论下Android中数据存储的位置——考虑数据安全,有必要更改android应用的存储位置吗?

在非root设备上,数据已可通过沙盒得到很好地安全保护(当然,我们也不可以完全忽略设备存在内核漏洞或虚拟机漏洞时可能发生的后果)。“自定义存储位置”也是一种设计方式,使得难以确定存储的路径,并完全控制了存储实现,以进行加密和解密保护。但这样做,失去了Android自身完善的特权分离机制(安全沙盒),将数据文件完全暴露在沙盒外,弊大于利,实际上意义不大。

因此这里仍选择沙盒作为数据的存储位置,接下来主要讨论对于root的设备,如何增强数据的安全性。在root设备上,需要通过数据擦除或数据加密,实现数据的安全存储,降低数据暴露的可能性。


加密方案选择

涉及到了加密,我们需要选择一种加密算法,加密算法的选择无穷无尽,本文采用AES加密算法,选择128位秘钥加密方式。以下是三种存储类型在AES算法下的具体实现方式:

  • SharedPreferences存储加密解密方式:对key和value同时加密,存储类型都为String类型,数据读取时根据需要进行类型转换。
  • File文件存储加密解密方式:对数据流进行加密解密。
  • SQLite数据库存储加密解密方式:基于Sqlcipher进行实现。

代码注入方案设计

注入方案比较

在”哪里”或者如何将我们提供的SDK注入到已有APP中,以及如何修改此APP中的实现。这里注入的层面可以是:java字节码(.class)或DEX字节码(.smali),二者分别对应反编译和反汇编过程。这里选择后者作为注入方案,原因如下:

(1) smali语法定义明确,易于直接替换对象类型;

(2)在反编译流程中,更直接。

DEX字节码

Dalvik虚拟机运行Dalvik字节码,由java字节码转换而来,又称为” Dalvik汇编语言”,是Dalvik指令集组成的代码,Dalvik指令集是Dalvik虚拟机为自己专门设计的一套指令集,严格说它不属于正式语言。我们来看一下它对方法的定义:

invoke-virtual {p0, v2, v3}, Landroid/content/Context;->getSharedPreferences(Ljava/lang/String;I)Landroid/content/SharedPreferences; move-result-object v1

这里调用了类android.content.Context的getSharedPreferences方法,其中p0寄存器存储context实例,方法的参数是两个:一个是java.lang.String类型,一个是int类型,两个参数分别保存在寄存器v2和v3中,返回值是android.content.SharedPreferences类型,并把返回值保存到v1寄存器中。

Dalvik字节码中使用了寄存器保存变量和参数。我们知道,Java虚拟机基于栈架构,程序需频繁从栈上读取或写入数据,会耗费CPU(指令分派、内存访问次数);Dalvik虚拟机基于寄存器架构,数据访问通过寄存器直接传递。两者都为每个线程维护一个PC计数器与调用栈,PC计数器以字节为单位记录当前运行位置距离方法开头的偏移量。不同的是,Java栈记录Java方法调用的活动记录,以帧为单位保存线程的运行状态,每调用一个方法就会分配新的栈帧压入Java栈上,方法返回则弹出并撤销相应的栈帧;而Dalvik栈维护一份寄存器表。

每个Dalvik寄存器都是32位,对于大于这个长度的类型,用两个相邻寄存器存储。寄存器被设计为两种表示方法:v命名法和p命名法。具体请参考相关资料。


加固流程设计

App加固总流程如下:

apk反汇编 -> sdk注入 -> Smali文件扫描 -> 代码修正 -> 正向汇编 -> apk签名


加固流程实现

这里以SharedPreferences存储为例,例举SDK和代码修正的实现方式。(其他步骤实现略)


安全存储SDK

SDK中提供了针对SharedPreferences存储类型的加密解密方式,我们对外提供了一个SecureSharedPreferences类,它实现了android.content.SharedPreferences接口,并实现了接口所提供的各个方法,将android.content.SharedPreferences类型实例作为参数,传递给构造方法。当读取数据时,使用这个参数进行查询并返回值,当存储数据时,在edit方法处,返回一个实现android.content.SharedPreferences.Editor接口的类,进行数据的添加。

这样的SDK设计使得代码注入可行,并只需要较少的修正量。


代码修正

在调用SharedPreferences存储时,某种实现方式可以是(java代码):

SharedPreferences sp =context.getSharedPreferences("config", 0);

我们需要将其修正为调用我们提供的SDK方式来实例化sp对象。DEX字节码如下:

invoke-virtual {p0, v2, v3},

Landroid/content/Context;->getSharedPreferences(Ljava/lang/String;I)Landroid/content/SharedPreferences;

我们首先将这个结果保存到一个寄存器下,这里可以使用v2或者v3寄存器,它们分别对应两个类型的参数:java.lang.String和int,而且之后不会再对它们进行使用,因而它们是可用的两个寄存器。这里我们选择v3寄存器:

move-result-object v3

接下来新建一个SecureSharedPreferences对象,并将它放到某寄存器下,这个寄存器需要是java中sp对象存储的寄存器,并且用这个寄存器的值进行SharedPreferences方法的调用,如v1寄存器:

new-instance v1,Lcom/…/SecureSharedPreferences;

继而需要调用这个对象的构造函数,并把之前保存在v3寄存器中的值作为参数传递(SharedPreferences类型):

invoke-direct {v1, v3},

Lcom/…/SecureSharedPreferences;->(Landroid/content/SharedPreferences;)V

这样就完成了修正过程。

其他存储类型以及调用方式的修正方式与以上类似,这里不再赘述。


验证实践

这里我们将整个流程所需的各个依赖包、库文件、各个工具、代码修正实现及我们提供的SDK集成到一起,形成一个一键式的加固工具(bat形式)。以一个DEMO为例,DEMO中实现了以上三种存储方式的数据存储和读取,其中存储都以默认方式(明文)实现,没有进行安全加密。

Android应用数据安全存储加固_android

将DEMO APK放到工作目录下,启动并得到加固后的安全APK(secure_demo.apk),其中demo文件夹为中间过程产生的数据文件。

Android应用数据安全存储加固_移动安全_02

将它运行到一个root的Android测试机上,并使用R.E.Explorer工具查看存储,可见数据已经过了加密存储,并能够正确的解密并获得原始数据。SQLite数据库对存储本身进行了加密,因而加密后,通过工具(android内置查看器或SQLite Expert Professional查看工具)已无法打开db文件。


总结

本文主要讨论了Android设备数据存储安全问题,重点关注于针对一个已有的、非安全存储的移动应用,如何将其加固为一个达到安全存储结果的应用。


标签:存储,加密,Dalvik,content,数据安全,SharedPreferences,寄存器,加固,Android
From: https://blog.51cto.com/u_16186510/6843381

相关文章

  • Android平台如何实现第三方模块编码后(H.264/H.265/AAC/PCMA/PCMU)数据实时预览播放
    技术诉求我们在做GB28181设备对接模块和RTMP直播推送模块的时候,遇到这样的技术需求,设备(如执法记录仪)侧除了采集传统的摄像头外,还需要对接比如大疆等第三方数据源,确保按照GB28181规范和RTMP协议规范,接入到国标平台侧和RTMP服务,除了正常的接入需求外,还需要对第三方数据源回调过来的编......
  • Android开发笔记[2]-传统XML方式界面布局
    摘要使用传统的XML方式对Androidapp界面进行布局.平台信息AndroidStudio:ElectricEel|2022.1.1Patch2Gradle:distributionUrl=https://services.gradle.org/distributions/gradle-7.5-bin.zipjvmTarget='1.8'minSdk24targetSdk34compileSdk34开发语言:Kotl......
  • Android时间工具类
    ✍️作者简介:沫小北(专注于Android、Web、TCP/IP等技术方向)......
  • 适用于Android手机的Debian GNU/Linux和Windows兼容环境
    Github地址:https://github.com/jinshulumengchuang/Debian-Wine-Android食用方法:从github下载release安装得到的apk文件把tarball放在内部存储的根目录给termux存储权限打开termux输入:cd..;tarxvf/sdcard/rootfs.tar.xz回车等候指令执行完成.($符号重新出现)......
  • android开发 - ListView
    android中很多应用都是用ListView来显示数据就像系统中的设置里面,每一行,就是构成的ListViewprivateListViewlistview;privatePersonServiceperson;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstan......
  • android开发 - Widgets窗口小部件
    Widgets指的窗口小部件 自定义一个Widgets做时间的窗口小部件一个widget是一个广播接受者,需要在清单中注册第一,有一个widgetpublicclassMainWidgetextendsAppWidgetProvider{@OverridepublicvoidonUpdate(Contextcontext,AppWidgetManagerappWidgetManager,i......
  • android 软件更新代码
     AndroidF#    应用软件经常会因为功能的增加而升级,升级经常是在客户端给用户升级的提示,然后用户下载最新的apk程序包,软件升级过程大多数需要在线完成。      android在线安装apk程序包,主要用到系统自带的apk安装器进行安装。用到系统自带的apk安装器安装......
  • 怎么把Android的主题改成白色
    怎么把Android的主题改成白色在Android开发中,我们经常需要调整应用的主题颜色来满足设计需求。本文将介绍如何将Android应用的主题改为白色。步骤一:创建新的主题首先,我们需要创建一个新的主题来修改应用的颜色。在res/values/styles.xml文件中,添加以下代码:<stylename="AppThem......
  • 在android虚拟机中安装app
    在Android虚拟机中安装App在Android开发中,我们经常需要在虚拟机中安装App以进行调试和测试。本文将介绍如何在Android虚拟机中安装App,并提供代码示例。创建虚拟机首先,我们需要创建一个Android虚拟机。可以使用AndroidStudio提供的虚拟设备管理器来创建和管理虚拟机。以下是创建......
  • Android开发本地验证码
    Android开发本地验证码验证码(VerificationCode)是一种用来区分人类用户和计算机程序的一种机制。它通常是由一系列的字符或数字组成,用户需要将其输入到相应的输入框中。验证码的作用是防止恶意程序自动化执行某些操作,如注册、登录、访问敏感信息等。本文将介绍如何在Android开发中......