范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

如何构建透明的加密框架以保护Android应用程序(上)

  也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大
  少走了弯路,也就错过了风景,无论如何,感谢经历
  更多关于Android安全的知识,可前往:
  https://blog.csdn.net/ananasorangey/category11955914.html
  本篇文章转载 :
  https://www.4hou.com/index.php/posts/PJqy
  导语:本文将对希望使数据加密过程可靠且方便的 Android 应用程序开发团队有用。
  Android 应用程序收集有关其用户的各种敏感数据:财务记录、个人偏好、地理位置,甚至健康指标。存储这样的数据为用户提供了便利。但是,如果设备已植根,它也会使敏感数据面临安全风险。
  为了加强数据保护,谷歌建议在内部存储中加密机密数据。但是使用谷歌提供的工具来做这件事可能是一个相当大的挑战,因为开发人员必须为他们想要保护的每个文件定义加密参数。在我们的一个 Android 开发项目中,我们决定创建一个可以方便且透明地加密文件的库。
  在本文中,我们将引导您完成开发框架以实现透明加密的过程,即使设备已植根,也能保护数据。本文将对希望使数据加密过程可靠且方便的 Android 应用程序开发团队有用。
  默认情况下,Google 会为 Android 开发人员提供用于数据加密的原生工具,例如JetPack 安全库。Android 还会加密设备上用户数据分区中的所有文件。
  但是,为了确保特定应用程序的数据加密,应用程序开发人员必须定义应加密哪些文件以及每个文件的加密参数。这样做会花费开发人员很多时间。如果开发人员忘记指定某个文件或在加密参数中出错,它还会为人为错误留下空间。
  在我们的一个 Android 开发项目中,我们决定创建一个自定义库,我们只需调用一次即可加密数据。它建立了自动数据加密的框架,使加密过程清晰,让我们能够专注于应用程序开发。
  与任何项目一样,构建透明加密框架我们需要的第一件事是一个可靠的计划。
  规划框架
  Android 应用程序中的加密过程通常对开发人员隐藏。假设 Android 开发人员使用以下代码保存SharedPreferences的值: SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);  Editor editor = prefs.edit();  editor.put("key", value);  editor.commit();
  在这种情况下,当使用 SharedPreferences 写入文件时,该值已经被加密。读取此文件时,我们会取回解密后的值。对于开发人员来说,这是一个他们无法改变的不透明过程。
  改变加密和解密过程的唯一方法是完全控制它们。在 Android 应用程序内部的某个地方,Java 函数调用write和read C 函数,因此我们可以添加和返回一个新值。如果我们可以在调用write和read时将这些函数的执行重定向到我们自己的函数,我们就可以在进程中添加加密和解密。
  但是我们如何重定向函数呢?
  我们已经在共享 ELF 库中的重定向函数一文中介绍了如何重定向共享 Linux 库中的函数。由于 Android 是一个类 UNIX 系统,我们也可以使用我们在该文章中描述的方法来处理这个项目。
  我们的透明加密框架应该拦截读写函数的执行并将执行重定向到包装函数。拦截读取函数将启动文件数据的读取和解密,拦截写入函数将启动初步加密并记录加密数据到文件。
  下面是我们Android透明加密框架开发所需要的: 定义调用read和write的库的位置 打开库文件。 在库文件的.dynsym部分中找到对应于读写函数的符号,并保存该符号的索引。 使用保存的索引在库文件的 rel.plt 或 rel.dyn 部分中查找重定位值。 找到原函数地址的位置,即库地址和重定位地址之和。 用包装函数的地址重写原始地址。
  要在安卓应用中实现一个加密框架,我们需要知道以下几点: 我们需要拦截的函数名称 我们将把原始函数重定向到的包装函数的地址 库的名称及其在文件系统中的路径 图书馆地址
  我们已经知道我们需要拦截的函数是read和write,并且我们知道包装函数的对应地址。经过一番研究,我们发现我们可以从 libjavacore 库中获取所需的其余信息。让我们看看如何为Android应用程序实现一个加密框架,从发现这个库的地址和库文件的路径开始。
  发现 libjavacore 库的详细信息
  经过一番研究,我们发现需要修改libjavacore库来拦截读写函数。该库在应用程序启动时加载到应用程序的进程内存中。
  我们可以使用dl_iterate_phdr函数处理加载到应用程序内存的对象: int dl_iterate_phdr(                  int (*callback) (struct dl_phdr_info *info,                                   size_t size, void *data),                  void *data);
  该函数为应用程序内存中的每个对象调用回调函数,并将指针传递给存储加载对象数据的 dl_phdr_info 结构。这是这个结构的样子: struct dl_phdr_info {                ElfW(Addr)        dlpi_addr; /* Base address of object */                const char       *dlpi_name; /* (Null-terminated) name                                                 of object */                const ElfW(Phdr) *dlpi_phdr; /* Pointer to array of                                                ELF program headers                                                for this object */                ElfW(Half)        dlpi_phnum;/* # of items in dlpi_phdr                                                */                unsigned long long dlpi_adds;                                /* Incremented when a new object may                                   have been added */                unsigned long long dlpi_subs;                                /* Incremented when an object may                                   have been removed */                size_t dlpi_tls_modid;                                /* If there is a PT_TLS segment, its module                                   ID is as used in TLS relocations, else zero */                void  *dlpi_tls_data;                                /* Address of the calling thread"s instance                                   of this module"s PT_TLS segment if it has                                   one and it has been allocated in the calling                                   thread, otherwise a null pointer */            };
  我们对这个结构中的两个字段特别感兴趣:dlpi_addr 包含加载的库的地址和 dlpi_name,其中包含文件系统中库文件的路径。
  使用这些数据,我们可以开始拦截函数。
  拦截读写函数
  让我们从创建名为 ldelib 的 Android 库开始。我们会将其添加到各种应用程序中以加密其本地数据。
  为此,我们将在没有Activity类的 Android Studio 中启动一个新项目。这个类帮助最终用户与应用程序交互,但它在我们的库中没有用。因此,让我们在应用程序级别删除 build.gradle 文件中的以下行: plugins {     id "com.android.application" }
  我们需要用以下行替换它: plugins {     id "com.android.library }
  现在,让我们从 Java 中添加Lde类。在我们将 ldelib 库添加到应用程序后,它的公共功能将变得可用。
  Lde类加载将拦截所需函数的本机库。它只有一个公共方法,称为 EnableEncryption。此方法接受带有到文件目录的路由的条目作为参数。我们将使用此路由来过滤需要加密的文件以及使用 Tink 库。EnableEncryption 还将调用本机Enable函数。
  为了实现库的本机部分,让我们通过单击项目窗口中的应用程序目录并从上下文菜单中选择将 C++ 添加到模块选项来添加一个 C++ 模块。
  在这个模块中,我们可以定义我们的包装函数。此时,他们只会记录事件并调用原始函数: ssize_t ReadHook(int fd, void *buf, size_t count) {    LOGI("Hooked read function!");    ssize_t res = read(fd, buf, count);    return res; } ssize_t WriteHook(int fd, const void *buf, size_t count) {    LOGI("Hooked write function!");    ssize_t res = write(fd, buf, count);    return res; }
  dl_iterate_phdr函数还可以帮助我们获取加载到内存中的库的地址。回调函数将检查对象的名称是否与库的名称相对应。如果是,该函数会将路径添加到库中,并将加载地址添加到 libInfo 结构中。以下是dl_iterate_phdr函数如何与库一起使用: namespace {    struct LoadLibInfo    {        std::string libPath;        size_t baseAddress;    };    struct DataToCallback    {        std::string libName;        LoadLibInfo info;    }; } static int Callback(struct dl_phdr_info *info, size_t /*size*/, void *data) {    auto libInfo = static_cast(data);    if (info->dlpi_name != nullptr)    {        std::string libName = info->dlpi_name;        if (libName.find(libInfo->libName) != std::string::npos)        {            libInfo->info.libPath = libName;            libInfo->info.baseAddress = info->dlpi_addr;        }    }    return 0; } LoadLibInfo GetLibInfo(const std::string& libName) {    DataToCallback data = {libName, {"", 0}};    data.libName = libName;    dl_iterate_phdr(Callback, &data);    return data.info; }
  现在,让我们回到Enable函数,它获取有关 libjavacore 库的信息并使用elf_hook()函数将读取和写入函数重新路由到包装函数。我们在共享 ELF 库中的重定向函数中详细介绍了此函数。在我们的例子中,elf_hook()函数可以执行我们拦截计划的所有步骤。以下是我们如何实现它: extern "C" JNIEXPORT jboolean JNICALL Java_com_example_ldelib_Lde_Enable(JNIEnv *env, jclass clazz, jstring pathToAppFiles) {    auto info = GetLibInfo("libjavacore");     if (info.libPath.empty())   {        LOGE("Failed to set hooks. libjavacore is not loaded into process");        return JNI_FALSE;    }    LOGI("libjavacore is loaded into the process. Path: "%s". Address: 0x%llx", info.libPath.c_str(), info.baseAddress);      void* originalWriteAddress = elf_hook(info.libPath.c_str(), reinterpret_cast(info.baseAddress), "write", reinterpret_cast(WriteHook));    if (originalWriteAddress == nullptr){        LOGE("Failed to find "write" function in plt");        return JNI_FALSE;    }    LOGI("Set hook for "write" function. Original address: 0x%llx", reinterpret_cast(originalWriteAddress));      void* originalReadAddress = elf_hook(info.libPath.c_str(), reinterpret_cast(info.baseAddress), "read", reinterpret_cast(ReadHook));    if (originalReadAddress == nullptr){        LOGE("Failed to find "read" function in plt");        return JNI_FALSE;    }    LOGI("Set hook for "read" function. Original address: 0x%llx", reinterpret_cast(originalReadAddress));    return JNI_TRUE; }
  现在我们可以通过将我们的库添加到我们的 Android 应用程序来检查我们的包装函数是如何工作的。首先,我们需要创建新的应用程序项目。然后,我们通过单击文件 -> 项目结构,选择 JAR/AAR 依赖项,然后添加到 AAR 存档的路由来添加 Android 存档 (AAR) ldelib 依赖项。之后,build.gradle 文件将在指向 ldelib 库implementation files的部分中有一行。dependencies
  接下来,我们在 MainActivity 文件中添加名为 com.example.ldelib 的导入包和Lde类。这使得 Lde 类的公共函数对应用程序可用,并允许我们在onCreate方法中调用EnableEncryption函数。
  要检查拦截是否有效,我们需要尝试读取和写入 SharedPreferences。由于当我们请求一个新写入的值时 SharedPreferences 不会从文件中读出,我们用 读取该值key,然后写入一个新的对"key_1"="value_1": import com.example.ldelib.Lde;   public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Lde.EnableEncryption(getFilesDir().getPath());        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);        String value = prefs.getString("key", "");        SharedPreferences.Editor editor = prefs.edit();        editor.putString("key_1", "value_1");        editor.apply();    } }
  如果挂钩正常工作,日志将包含有关新包装函数的消息: 挂钩读取功能!和钩写功能!:
  现在,我们的库可以拦截读写函数了。在下一章我们将要把这个自定义的透明加密框架添加到 Android 应用程序中,看看它是如何工作的。

高社交焦虑者会在社交情境中存在更高的自我聚焦注意水平自我聚焦注意是指当注意资源指向自身内部时,个体对与自我相关的身体感觉认知加工及情绪状态等内部信息的一种觉知。而过度的自我聚焦注意被证明与各种负面情绪状态及心理障碍均有联系。在对高低我国历史有1500年空白期,无任何史料,究竟发生了什么最近看到很多人又在讨论中国1500年空白期的问题,也就是中国从黄帝开始的五千年文明史中,有1500年是没有文字和考古佐证的,不能被认为是信史的事情。许多营销号甚至借此质疑这段历史的粤港澳大湾区启动加速键新华社广州2月18日电随着疫情防控实现平稳转段内地与港澳人员往来全面恢复,粤港澳大湾区正启动加速键。包括香港澳门特区和广东广州深圳珠海等珠三角九市的粤港澳大湾区,是我国开放程度最高多国狂欢节重启中国制造派对产品热销由于疫情导致的被取消或者规模缩减的世界各地的狂欢节,在今年开始陆续重启,其中比较知名的巴西里约狂欢节就将于明天正式拉开大幕,这给中国制造的派对产品,带来了新的增长点。央视财经经济信社保缴费满15年可不缴?别被忽悠了丁家发日前,有网友咨询请问社保缴费是缴满15年吗?我最近到一家新公司,人事和我商量说我的社保已经满了15年,可以不交了,也不影响我退休,而且这样不扣我个人部分到手的钱还要多一笔,请侨助广东高质量发展扎根南沙17载,企业发展迎来春天作为一名科技创业者,广东晶科电子股份有限公司董事长广东芯粤能半导体有限公司董事长广州市荣誉市民肖国伟已扎根广州南沙17年,他和创始团队引入并孵化了在香港科技大学工作期间开发的专利技江苏将统一医保最低缴费年限,男满25年女满20年,还有哪些变化?江苏将延长医保缴费年限的消息引发关注,男性医保最低缴费年限满25年,女性医保最低缴费年限满20年。虽然医保最低缴费年限统一了,但是还有一些新的变化,值得关注。具体是什么呢?江苏统一鞍山人社政策天天讲(第五讲)养老保险常见情况(中)为做好共性诉求问题办理,及时回应企业百姓关切,现开设人社政策天天讲专栏,对鞍山人社政策进行权威发布。第17条多重养老保险关系如何处理?参保人员流动就业,同时在两地以上存续基本养老保社保缴费年限,会提高到25年到30年吗?这是不是真的?社保的缴费年限,会不会提高到25年到30年呢?这是不是真的呢?严格来讲,我们的社保分为养老保险和医疗保险,如果单纯的来考虑,养老保险的缴费年限,那么目前的规定,是有一个全国统一性的油车出局!欧盟电动化市场前景看好,中国锂电企业该如何奔赴?跨越百余年,欧洲汽车产业将在2035年迎来转型的关键节点。当地时间2月14日,欧洲议会在斯特拉斯堡以340票赞成,279票反对和21票弃权,通过了欧委会和欧洲理事会达成的2035年河南2022年城乡居民医保集中缴费延期至3月底河南省2022年城乡居民医疗保险参保缴费进入收尾阶段。记者从河南省医疗保障局了解到,为确保符合条件的城乡居民应保尽保,经河南省医保省税务两部门确定,全省各地分别延长了居民医保集中缴
中世纪晚期,意大利的政治局面文巴普罗的独白编辑巴普罗的独白国家整体处于分裂状态意大利位于地中海沿岸,非洲西欧与东方的贸易来往都交汇于此,是中世纪晚期世界重要贸易航线的必经之地。繁忙的贸易为意大利带来了富庶的经违反政治中立原则俄罗斯车队将UCI告上法庭一纸诉状将国际自盟UCI告上体育仲裁法庭,俄燃气车队目前仍在等待判决结果,而这个结果预计很快就会揭晓日前外媒还采访到了俄燃气车队的总经理哈米杜林(RenatKhamidulin),罗斯福总统的第一任期(1933年1937年)当罗斯福于1933年3月就职时,美国正位于史上大萧条的最谷底。有四分之一的劳动人口失业。农民随着农产品价格下降了60正处于水深火热中。工业生产下降了自1929年以来的一半以上。有2秦汉时期的武器生产及其管理制度200万年前人类由非洲传播到亚欧大陆,演化为不同人种,以色列著名作家尤瓦尔赫拉利的人类简史认为,有比较大的大脑会使用工具有超凡的学习能力还有复杂的社会结构,都是人类的巨大优势。但在A股全面发行注册制制度规则发布实施!2月17日,中国证监会发布全面实行股票发行注册制相关制度规则,自公布之日起施行。证券交易所全国股转公司中国结算中证金融证券业协会配套制度规则同步发布实施。创投昆仑万维盛天网络伯特利按季申报小规模纳税人自行开具3的专票尚未申报纳税,享受增值税减免政策是否必须追回已开具发票?问我是个体工商户,属于按季申报的增值税小规模纳税人。2023年1月5日,自行开具了1张征收率为3的增值税专用发票,提供给下游客户用于抵扣进项税额,尚未申报纳税。请问对于这笔销售收入从古至今,追求财富乃人之常情,别大惊小怪战国时期的苏秦连横说秦失败时回到家中妻不下纫,嫂不为炊,父母不与言。苏秦喟叹曰妻不以我为夫,嫂不以我为叔,父母不以我为子,是皆秦之罪也。乃夜发书,陈箧数十,得太公阴符之谋,伏而诵之武则天喝醉后给一小国赐名,沿用至今,现在已发展为发达国家日本,对每个中国人来说都是耳熟能详的国家名。在我国不乏一些通过音译命名的国家,比如美利坚,日本的发音与日本英文Japan很像,但事实上,日本这个名字的由来与其英文没有关系。早在七世坚守信仰的纯洁公务组织,才是国家无患长盛不衰的根本!面对全球经济持续下行的势态,全世界都要做好过苦日子的准备!三年疫情对我们的考验,让我们看到一切繁华都是浮云。民生凋敝,经济脆弱,共同富裕还是一个遥远的梦。几十年几代人的艰苦奋斗,为总投资3000万美元!又一瑞士百年企业落户常州国家高新区外资招引迎来开门红,招大引强实现新突破。2月20日,瑞士埃莱普精密汽车零部件研发制造项目签约落户常州高新区,项目总投资3000万美元。区委书记周庆会见瑞士埃莱普公司董事会成员中国区55岁国家一级演员,给半个娱乐圈演妈,新剧能否超越人世间影视圈,有一个长相大气的神秘女演员!演女主不出名,演别人的妈,倒是一个接一个全是爆款!她都演过谁的妈呢?从黄渤靳东姜文李晨,到朱亚文雷佳音孙俪宋佳等等,凡是娱乐圈能叫得上名字的知名