Android 逆向之安全防护基本策略
对抗反编译
混淆
使用混淆主要可以减小包的大小。混淆对于安全保护来说,只是增加了阅读难度而已。混淆不会把关键代码混淆掉,比如MainActivity,Application等,可以通过分析smali和阅读jar包定位代码。
资源混淆也是换汤不换药,针对加载资源代码getString(2131230929)进行进制转换,变成16进制,从public.xml里面查找对应的资源,就能定位到资源内容。
签名保护
这个是防止二次打包验证,但是,对于java代码的签名保护,可以很容易地进行修改smali代码绕过验证。
手动注册native方法
安全性也不是很高,只是一种会增加破解成本的方式。一般Native方法根据命名规则生成头文件然后写cpp代码,这种方式属于静态注册。手动动态注册是复写JNI_OnLoad方法,在该函数中手动注册方法名和对应的方法签名,方法名可以自定义,这样避免了静态注册的命名规则,让破解者难以根据规律找到要破解的方法。不过破解者可以分析JNI_OnLoad函数的汇编代码找到register函数找到注册的native方法。
反调试检测
IDA进行so动态调试是基于进程的注入技术,然后使用linux中ptrace机制,进行调试目标进程的附加操作。
ptrace机制有一个特点:如果一个进程被调试了,在它进程status文件中有一个字段TracerPid会记录调试者的进程id值
cat /proc/pidxx/status 可以看到TracerPid字段
方法是检测该TracerPid值,大于0就退出。但破解者会通过IDA工具给JNI_OnLoad下断点,检测轮询代码,使用nop指令跳过检测指令。
对抗Xposed
原理
Zygote
在Android系统中App进程都是由Zygote进程“孵化”出来的。Zygote进程在启动时会创建一个虚拟机实例,每当它“孵化”一个新的应用程序进程时,都会将这个Dalvik虚拟机实例复制到新的App进程里面去,从而使每个App进程都有一个独立的Dalvik虚拟机实例。
Zygote进程在启动的过程中,除了会创建一个虚拟机实例之外还会将Java Rumtime
加载到进程中并注册一些Android核心类的JNI(Java Native Interface,Java本地接口)方法。一个App进程被Zygote进程孵化出来的时候,不仅会获得Zygote进程中的虚拟机实例拷贝,还会与Zygote进程一起共享Java Rumtime
,也就是可以将XposedBridge.jar
这个Jar包加载到每一个Android App进程中去。安装Xposed Installer
之后,系统app_process
将被替换,然后利用Java的Reflection
机制覆写内置方法,实现功能劫持。下面我们来看一下细节。
Hook和Replace
Xposed Installer
框架中真正起作用的是对方法的Hook和Replace。在Android系统启动的时候,Zygote进程加载XposedBridge.jar
,将所有需要替换的Method通过JNI
方法hookMethodNative
指向Native方法xposedCallHandler
,这个方法再通过调用handleHookedMethod
这个Java方法来调用被劫持的方法转入Hook逻辑。
上面提到的hookMethodNative
是XposedBridge.jar
中的私有的本地方法,它将一个方法对象作为传入参数并修改Dalvik虚拟机中对于该方法的定义,把该方法的类型改变为Native并将其实现指向另外一个B方法。
换言之,当调用那个被Hook的A方法时,其实调用的是B方法,调用者是不知道的。在hookMethodNative的实现中,会调用XposedBridge.jar
中的handleHookedMethod
这个方法来传递参数。handleHookedMethod
这个方法类似于一个统一调度的Dispatch例程,其对应的底层的C++函数是xposedCallHandler
。而handleHookedMethod
实现里面会根据一个全局结构hookedMethodCallbacks
来选择相应的Hook函数并调用他们的before
和after
函数,当多模块同时Hook一个方法的时候Xposed
会自动根据Module
的优先级来排序。
调用顺序如下:A.before -> B.before -> original method -> B.after -> A.after。
检测
在做Android App的安全防御中检测点众多,Xposed Installer
检测是必不可少的一环。对于Xposed框架的防御总体上分为两层:Java层和Native层。
Java层检测
需要说明的是,Java层的检测基本只能检测出基础的Xposed Installer
框架,而不能防护其对App内方法的Hook,如果框架中带有反检测则Java层检测大多不起作用。
下面列出Java层的检测点,仅供参考。
① 通过PackageManager查看安装列表
最简单的检测,我们调用Android提供的PackageManager
的API来遍历系统中App的安装情况来辨别是否有安装Xposed Installer
相关的软件包。
PackageManager packageManager = context.getPackageManager();
List applicationInfoList = packageManager.getInstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo applicationInfo: applicationInfoList) {if (applicationInfo.packageName.equals("de.robv.android.xposed.installer")) {// is Xposed TODO... }}
通常情况下使用Xposed Installer
框架都会屏蔽对其的检测,即Hook掉PackageManager的getInstalledApplications
方法的返回值,以便过滤掉de.robv.android.xposed.installer
来躲避这种检测。
② 自造异常读取栈
Xposed Installer
框架对每个由Zygote孵化的App进程都会介入,因此在程序方法异常栈中就会出现Xposed
相关的“身影”,我们可以通过自造异常Catch
来读取异常堆栈的形式,用以检查其中是否存在Xposed
的调用方法。
try {throw new Exception("blah");
} catch(Exception e) {for (StackTraceElement stackTraceElement: e.getStackTrace()) {// stackTraceElement.getClassName() stackTraceElement.getMethodName() 是否存 在Xposed}
}
E/GEnvironment: no such table: preference (code 1): while compiling: SELECT keyguard_show_livewallpaper FROM preference
...
at com.meituan.test.extpackage.ExtPackageManager.checkUpdate(ExtPackageManager.java:127)
at com.meituan.test.MiFGService$1.run(MiFGService.java:41)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5072)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
...
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132) //发现Xposed模块
at dalvik.system.NativeStart.main(Native Method)
③ 检查关键Java方法被变为Native JNI方法
当一个Android App中的Java
方法被莫名其妙地变成了Native JNI
方法,则非常有可能被Xposed Hook
了。由此可得,检查关键方法是不是变成Native JNI
方法,也可以检测是否被Hook。
通过反射调用Modifier.isNative(method.getModifiers())
方法可以校验方法是不是Native JNI
方法,Xposed同样可以篡改isNative
这个方法的返回值。
④ 反射读取XposedHelper类字段
通过反射遍历XposedHelper
类中的fieldCache
、methodCache
、constructorCache
变量,读取HashMap缓存字段,如字段项的key中包含App中唯一或敏感方法等,即可认为有Xposed
注入。
boolean methodCache = CheckHook(clsXposedHelper, "methodCache", keyWord);private static boolean CheckHook(Object cls, String filedName, String str) {boolean result = false;String interName;Set keySet;try {Field filed = cls.getClass().getDeclaredField(filedName);filed.setAccessible(true);keySet = filed.get(cls)).keySet();if (!keySet.isEmpty()) {for (Object aKeySet: keySet) {interName = aKeySet.toString().toLowerCase();if (interName.contains("meituan") || interName.contains("dianping") ) {result = true;break;} }}...return result;
}
Native层检测
由上文可知,无论在Java层做何种检测,Xposed都可以通过Hook相关的API并返回指定的结果来绕过检测,只要有方法就可以被Hook。如果仅在Java层检测就显得很徒劳,为了有效提搞检测准确率,就须做到Java和Native层同时检测。每个App在系统中都有对应的加载库列表,这些加载库列表在/proc/
下对应的pid/maps
文件中描述,在Native层读取/proc/self/maps
文件不失为检测Xposed Installer的有效办法之一。由于Xposed Installer
通常只能Hook Java层,因此在Native层使用C来解析/proc/self/maps
文件,搜检App自身加载的库中是否存在XposedBridge.jar
、相关的Dex、Jar和So库等文件。
bool is_xposed()
{bool rel = false;FILE *fp = NULL;char* filepath = "/proc/self/maps";...string xp_name = "XposedBridge.jar";fp = fopen(filepath,"r")) while (!feof(fp)) {fgets(strLine,BUFFER_SIZE,fp); origin_str = strLine;str = trim(origin_str);if (contain(str,xp_name)){rel = true; //检测到Xposed模块break;}}...
}
相关文章:
Android 逆向之安全防护基本策略
对抗反编译 混淆 使用混淆主要可以减小包的大小。混淆对于安全保护来说,只是增加了阅读难度而已。混淆不会把关键代码混淆掉,比如MainActivity,Application等,可以通过分析smali和阅读jar包定位代码。 资源混淆也是换汤不换药&…...
基站机房:保障通信网络稳定,如何解决安全隐患?
基站机房作为无线通信网络的关键组成部分,承载着大量的网络设备和通信设施,对于运营商和通信服务提供商来说具有重要意义。 无论是大型运营商还是通信服务提供商,动环监控系统都将成为他们成功运营和管理通信网络的关键工具。 客户案例 案例…...
sqlmap -os-shell 使用方法
一、burp suite抓包。 如上图所示,红框处很明显是一个传参点,我们就在这个页面抓包。 抓到包之后将内容保存到桌面的1000.txt文件下。 二、sqlmap跑包。 打开sqlmap跑包。 python sqlmap.py -r C:\Users\16434\Desktop\1000.txt -dbmsmysql --os-shell…...
Go语言并发之Select多路选择操作符
1、Go语言并发之Select多路选择操作符 select 是类 UNIX 系统提供的一个多路复用系统 API,Go 语言借用多路复用的概念,提供了 select 关键字,用 于多路监听多个通道。当监听的通道没有状态是可读或可写的,select 是阻塞的&#…...
黄金回收小程序开发功能有哪些?
一、用户端: 1、实时查询:通过对接三方接口实现实时金价动态查看; 2、多种类珠宝实时回收:小程序支持多品类珠宝的实时回收包含黄金饰品、金条、铂金、K金、白银等,同步实现价格实时更新; …...
nginx的详解与应用
前言 说明 要义 nginx 有一个master 进程和多个worker 进程。主进程的主要目的是读取和评估配置,以及维护工作进程。工作进程对请求进行实际处理。nginx 采用基于事件的模型和依赖于操作系统的机制在工作进程之间有效地分发请求。工作进程的数量在配置文件中定义…...
SpringBoot激活profiles的几种方式
多环境是最常见的配置隔离方式之一,可以根据不同的运行环境提供不同的配置信息来应对不同的业务场景,在SpringBoot内支持了多种配置隔离的方式,可以激活单个或者多个配置文件。 激活的profiles要在项目内创建对应的配置文件,格式…...
【Java】Java核心要点总结:58
文章目录 1. java中 怎么确保一个集合不能被修改2. 队列和栈是什么 有什么区别3. Java8开始的ConcurrentHashMap为什么舍弃了分段锁4. ConcurrentHashMap 和 Hashtable有什么区别5. ReadWriteLock和StampeLock 1. java中 怎么确保一个集合不能被修改 Java 中可以使用 Collectio…...
前端面试题---作用域链和原型链
一.JavaScript 中的作用域链是如何工作的? JavaScript 中的作用域链(Scope chain)是一种用于查找变量和函数的机制,它是由嵌套的作用域环境组成的链式结构。 当在 JavaScript 中访问一个变量或函数时,解析器会首先在当前作用域…...
零售品牌私域流量池如何运营?火山引擎数智平台提供全套产品组合
虽然距离6月18日还有两周时间,但各大平台的第一波618战绩(预售尾款)已经相继出炉。 5月31日晚8点,京东率先公布618开门红10分钟销售战报:10分钟内,成交额破亿品牌数同比增长23%,超六成的新商家…...
rk3568 SD卡启动
rk3568 SD卡启动 SD卡启动系统,它可以让rk3568在没有硬盘或其他存储设备的情况下启动和运行操作系统。这使得rk3568变得与树梅派一样灵活切换系统,与此同时进行故障排查和修复,而不需要拆卸设备或者使用专业的烧录工具。SD卡启动还可以方便地…...
English Learning - L3 作业打卡 Lesson5 Day34 2023.6.7 周三
English Learning - L3 作业打卡 Lesson5 Day34 2023.6.7 周三 引言🍉句1: The woman reading the romantic novel could be a lawyer.成分划分弱读连读爆破语调 🍉句2: She just wants a light read to take her mind off work.成分划分弱读连读爆破语调…...
【运筹优化】最短路算法之A星算法 + Java代码实现
文章目录 一、A星算法简介二、A星算法思想三、A星算法 java代码四、测试 一、A星算法简介 A*算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法。算法中的距离估算值与实际值越接近,最终搜索速度越快。 二、A星算…...
[6]PCB设计实验|认识常用元器件|电阻器|18:30~19:00
目录 一、电阻器主要用途 1. 稳定和调节电路中的电流和电压 2. 作为分流、分压和负载使用 二、常见电阻器 1. 贴片电阻 2. 热敏电阻 3. 限流电阻 4. 可调电阻 5. 排阻(网络电阻) 三、几种常用电阻器的结构特点 四、电阻的参数 1. 额定功率 电阻器功率的表示 2…...
Webots R2021a教程
文章目录 Windows安装设置中文打开世界添加贴图 为外部控制器配置Anaconda解决报错:CondaSSLError: Encountered an SSL error. Most likely a certificate verification issue.调用Python API Windows 安装 进入下载页面 https://github.com/cyberbotics/webots/r…...
C++ 输出格式控制
C 输出格式控制 需包含头文件: 浮点数精度、域宽、填充 操作符功能right-alignedright-alignedsetprecision(int n)设置以n表示的数值精度setw(int n)设置以n表示的域宽setfill(char c)设置以c表示的填充字符 输出格式 操作符功能oct以八进制格式输出数据dec以…...
【C++】引用和右值引用
目录 1. 引用 1.1 引用的概念 1.2 引用的特性 1.3 引用的使用场景 1.3.1 作为参数 1.3.2 作为返回值 1.4 常量引用 1.5 引用和指针的区别 2. 左值和右值 3. 右值引用 3.1 右值引用的概念 3.2 左值持久;右值短暂 3.3 变量是左值 3.4 标准库move函数 1.…...
NodeJS MongoDB⑦
文章目录 ✨文章有误请指正,如果觉得对你有用,请点三连一波,蟹蟹支持😘前言Node&MongoDB 第一步 连接数据库 第二步 创建User Mongodb模型 第三步 简单使用 Mongodb命令 第四步 规范使用 Mongodb命令 (…...
情感分析实战(中文)-共现语义篇
情感分析实战(中文)-共现语义网络分析 背景:该专栏的目的是将自己做了N个情感分析的毕业设计的一个总结版,不仅自己可以在这次总结中,把自己过往的一些经验进行归纳,梳理,巩固自己的知识从而进一步提升,而帮助各大广大学子们,在碰到情感分析的毕业设计时,提供一个好的…...
【数据结构与算法】03 队列(顺序队列--循环队列--优先级队列--链队列)
一、概念1.1 队列的基本概念1.2 队列的顺序存储结构1.21 顺序队列(静态队列)1.22 循环队列1.23 优先级队列 1.3 队列的链式存储结构 二、C语言实现2.1 顺序存储2.11 顺序队列2.12 循环队列2.13 优先级队列 2.2 链式存储 一、概念 1.1 队列的基本概念 队…...
【区块链 | L2】作为Layer2赛道的领跑者,如何理解 Arbitrum?
上周我们介绍了以太坊L2扩展解决方案Optimism,本周我们继续介绍另一个L2解决方案——Arbitrum。Arbitrum 是以太坊的一个 Optimistic Rollup L2 可扩展性解决方案。 Part.1 什么是Arbitrum? Arbitrum 是一个构建在以太坊之上的区块链网络。你可以使用 Arbitrum 链来做任何在…...
【协议】NVMe over RoCE |nvmeof
什么是nvme nvme ssd和普通ssd区别 ssd是固态硬盘,普通的ssd配的是SATA口(AHCI协议),nvme ssd配的是PCIe口(nvme传输协议) 相比普通SSD的SATA口,nvme的PCIe口有巨大的性能优势。 更多详情见&…...
硬件设计电源系列文章-DCDC转换器布局设计
文章目录 概要 整体架构流程 技术名词解释 1.开关电源PCB布局要点 2.输入电容的放置 3.二极管的放置 4.散热孔的放置 5.反馈路径的走线 小结 概要 提示:这里可以添加技术概要 例如: 本文主要DCDC转换器布局方面的知识。 整体架构流程 提示…...
「从入门到精通,一位设计师分享学习Illustrator的技巧和经验!」
学习Illustrator的个人笔记:从入门到精通 Adobe Illustrator是一款广泛使用的矢量图形软件,用于创建各种设计作品,如商标、海报、名片等。在本篇博客中,我将分享学习Illustrator的经验和技巧,帮助您更好地掌握这一工具…...
RedisGraph的整体架构
The architecture of RedisGraph 本文关注RedisGraph的整体架构,分别从图存储模型、索引、并发控制、和执行计划四个方面简要阐述。下图为RedisGraph的整体架构图。 1 图存储模型 了解一个图数据库的架构,最重要的就是其图存储模型,即其中的…...
C#可视化 家用轿车信息查询系统(具体做法及全部代码)
目录 题目: 效果图: 数据库: 做法: combobox值更新 查询按钮功能(非空验证,查询数据) datagirdview设置 全部代码: DBHelper类 From1主窗体代码 题目: 效果图&#…...
Nautilus Chain全球行分享会,上海站圆满举办
在北京时间 6 月 9 日,由 Nautilus Chain 主办的“Layer3 模块化区块链的发展探讨”为主题的全球行活动,在上海顺利举办,本次分享会联合主办方还包 括 Stanford Blockchain Accelerator、Zebec Protocol、Tiger VC DAO、Crypto PHD、Rootz La…...
day50_mybatis
今日内容 0 复习昨日 一、分页插件 二、ORM映射【重点】 三、多表联查 【重点】 四、动态SQL 【重点】 五、$和# 零、复习昨日 mybatis orm框架,作用于持久层,高效开发,只关注sql,其他不用关心 思考MyBatis到底帮你省了哪些事情? jdbc第四步sql自己编写之外,其他mybatis都做了…...
第十一届“创业江苏”科技创业大赛正式启动
为深入实施创新驱动战略, 推进高水平科技自立自强,强化企业创新主体地位,加速推动创新要素向企业集聚,促进科技和金融深度融合,优化科技创新创业生态,吸引优秀创业团队及企业到苏州创新发展,根据…...
EasyX实现简易贪吃蛇
📝个人主页:认真写博客的夏目浅石. 📣系列专栏:夏目的C语言宝藏 文章目录 前言一、头文件包含二、创建蛇与食物的结构体三、游戏的初始化四、游戏的绘画事件五、蛇的移动事件六、输入方向七、生成食物八、吃食物九、游戏失败的判定…...
专业建站公司服务/关键词排名提升工具
这是一个基于MVCDAO的留言管理系统,包含增删改查,其中查询,有全部查询和按关键字进行模糊查询的功能。文章底部附件是源码程序。大家共同学习,共同进步。具体如下: NoteDAO.java package cn.mldn.lxh.note.dao ;import…...
40个常见的html标签及含义/桔子seo网
第1部分:如何使用dr.fone解锁没有密码的iPad?通过dr.fone - Unlock(iOS)可以帮助你解锁设备而不会对其造成任何损坏。作为dr.fone工具包的一部分,它是一个非常先进的工具,从死机到处于恢复模式,从数据备份到恢复&#…...
泉州模板建站平台/优化网站建设
标签(空格分隔): 三省吾身 原文地址:你应当怎样学习C(以及编程) 本人反思自己这些年在学校学得稀里糊涂半灌水。看到这篇文章,感觉收获不少。仿佛有指明自己道路的感觉,当然真正困难的还是坚持学习…...
做进口货的电商网站/游戏推广员是做什么的
Nuxt.js 和 Vue 一样,支持插件,可以分为三种类型:自定义插件、Vue 插件和外部包和模块。 虽然 Nuxt 文档 详细讨论了最后两个,但它们仅简要说明了如何在 Nuxt 应用程序中构建和使用自定义插件。 全局自定义插件可以在几种情况下派…...
网站备案 上一级服务商名称/网站整站优化公司
我一直都有看网络电视的习惯,不用跟别人抢电视摇控噐,呵呵。所以用LINUX系统后就好想找一个好的网络电视软件,网上都说gmlive和qsopcast是最好的,因为这几天都在找安装包,在官网论坛上有gmlive的rpm包下载安装…...
怎么做幼儿园的网站/百度云盘登录
今天项目中需要自定义图片上传的保存路径,并且不需要按照日期自动创建存储文件夹和文件名,我的ueditor版本是1.3.6。下面记录一下我配置成功的方法,如果有什么不对的地方欢迎指出,共同学习: 1:我在本地项目…...