逆向so_安卓逆向 | 分析调试与so调用实战

声明:本教程用于学习交流,如有侵权联系本人删除!

点击上方“逆向小白”,选择“加为星标”

第一时间关注逆向技术干货!

使用fiddler抓取某app登录接口的时候,没有看到任何相关的数据包,猜测app做了防抓包或者不走http协议,尝试proxyDroid、小黄鸟还是不行,最后使用Packet Capture成功抓到数据。看了下登陆接口提交的参数,不知道sign值是怎么来的,所以目标很明确,就是需要逆向分析sign的生成算法。

49debd5a558f6cc840ed6cb24dc8cdc3.png

将apk文件拖到jadx中进行反编译,ctrl+shift+f 搜索关键词sign出来很多信息但没找到有用的,试试搜索"sign",仔细查看发现图示可疑位置,点进去看看。

3da487543dcf38c5deffa3b56d0980dd.png

看到图示内容,可以确定找对了地方,sign值是getSign方法执行后的结果,getSign方法中调用了SignManager类getSign方法,传入了三个参数,第一个参数不确定其值,第二个参数是token值,前面抓包发现这个值是空的,第三个值是时间戳,右击getSign跳到方法声明的地方。

423fbf5f08406802c1ca1717e70b6284.png

加载so、通过native关键字定义了需要调用的方法getSign,也就是说,它这里调用的是so层的加密算法,so是什么?简单来说,它是c/c++编译后的产物。既然目标app能调用,那我们也可以。在搞之前,还有个参数不确定。这里就用jeb调试一下看看。

ce670050ffb9d2ea505aa9cb446b03ea.png

将apk拖到jeb中进行反编译,dex反编译成smali,我们可以调试这个smali代码, ctrl+f 搜索"sign", 找到getSign方法,ctrl+b下断点。

af437c7b763cdbc3ff269d7b6bd932ae.png

a2ce3eed4d7a05fe356f4ca0f198bca4.png

确保手机已root并且可调试,如果没有开启调试,到网上去下载相应的mprop,  使用adb推送到手机里,通过如下方法可以临时设置调试状态,这个方法是修改内存中的值,重启手机后恢复不可调试状态。如果你想要永久设置,到网上找相应的教程。然后可以通过adb连接手机,确保jeb可以识别到手机。

8221e59ac856dcb579b65a4731d2f9dd.png

点击附加调试,选择需要调试的进程包名附加进程。

722b30ee62d7fbe79abe9eb572b7b342.png

手机上输入账号密码点击登陆触发断点

70c173067318d7c1f4448569798c0a48.png

上面分析过,断点处的getSign传入了四个参数,而真正用到的是后面三个,这三个参数值分别放在寄存器v1、v2、 v3中,将int修改为string, 可以看到,v1中的值是空的,v2中的值是空的,v3中的值应该是时间戳,如果你不放心可以多次尝试。

22619621b4d487c433b76dd8bf69392e.png

三个参数值确定了,下面要做的工作就是调用so层的加密算法获取sign值,关于so调用,可以去学学逆向大佬花哥的教程,通过压缩软件打开apk,因为我手机的cpu类型是arm64-v8a, 是向下兼容的,选择使用armeabi-v7a中的so文件是可以的。

c1907473fd32fbab41954d1176fae6aa.png

将so文件复制到安卓项目的libs->armeabi-v7a下面,并且在app->build.gradle中限制支持的平台,不加这个我这是报错的,加上限制条件,app也不会显得那么臃肿。

518489cdc7aefe7f04a58ccb98bd3eee.png

在src->main->java下新建一个包名为com.sichuanol.cbgc.util的包,在包下面创建一个名叫SignManager的类,复制源码过来就行。

bc555a135b37864dc11e7fea0bc235fb.png

然后在控制器中调用getSign方法,运行项目安装到手机上,启动服务。

78f86d8da5835be656b7f8e9e4c3090f.png

浏览器访问服务接口,返回的是so文件名,竟然翻车了!!!

aa2270151dcf4687c106ab8f469c35fb.png

看了下日志信息,缺少了某个类,尝试复制对应的文件过来,但还是报错缺各种东西,猜测是不是有签名校验,那么调用so的方案就失败了?问题总得解决,换另一个方案,用IDA逆向分析so。跟着大佬学习一下IDA的调试过程,做一个简单的记录。

95e0124345fe3b4435b08059101ff9af.png

将so文件拖到IDA中,Exports->**getSign,双击点进去。

783bb5a84db7b0488c3e57718c4f63d6.png

这是so反编译出来的汇编代码,看不懂啊,像我这种菜鸡还是去看看伪c代码吧,按F5或者Tab。

f362680d156ad532d55f8a3aaefa18d5.png

**getSign函数中五个参数,第一个参数是JNIEnv类型指针,它指向java环境,通过这个指针就可以对java的代码进行操作,第二个参数是java传递过来的类/类实例,后面参数就是我们上面分析的那三个,有人说,这里的参数类型明明都是int,而且看代码似c不c,其实是这样的,ida反编译so不可能百分之百还原c/c++代码,  而且这里还用到jni函数,jni又是什么?简单的说,有了jni可以实现java代码和c/c++代码的互调。 

a950f3744c568478ae1b3bc6037bfcf8.png

这些强制类型转换看着太不舒服了,右击hide casts把它们隐藏。

5bfccf1fc987c8f9ca367cf4ed64efcb.png

看到一些*v5加上数字这又是什么操作,上面分析过,第一个参数a1是JNIEnv指针,赋值给v5, 那么这一些操作好像是指针偏移,可能是取了jni的函数或者变量。

6bb2330d9863db8c0e93b409e89e2a19.png

为了让人能看懂这些jni函数,我们需要导入jni.h头文件,然后改第一个参数为JNIEnv类型指针。

75149e318d1e6d4c1350e125116ab74d.png

选中第一个参数a1, 右击选择convert to struct*, 选_JNIEnv, 然后再更改指针名为env。

24f4eba2c332fcdeb6f61f8fcef45d67.png

我们将v5的名字也改一下,改成env_,改完之后你会发现,这才是人能看懂的代码啊。

83dc5909074c6dbbdef923556d72c99a.png

GetStaticMethodID获取java静态方法ID, "getAppSign"为方法名,如果没有取到方法ID就会进行一系列操作。好吧,这就解释了为啥我们调用so报错了。

e30c0630f60d497bf1438f83e2babbd7.png

用jadx搜一下getAppSign方法,我们看到,方法所在的类就是之前报错缺失的,getAppSign方法取了签名值,如果异常返回一个空字符串。要知道,你不改动apk文件的情况下,这个app签名值是固定不变的。看c代码中没有涉及到其他java自写方法,那我们只要拿到这个签名值,so调用的方案不就简单了吗?

d0bf3224d8de388a23a79777c632679a.png

编写一个xposed模块进行hook操作,不会的请参考上一篇教程 xposed模块编写实战

920b018132968a715b366824f00916d9.png

把取签名方法所在的类文件复制到so调用的项目里,放在同样的包名下,把多余的方法删掉,getAppSign方法只需要返回这个固定字符串就可以了。

96631d26758b45c820cd5c523adc7771.png

运行项目安装apk开启服务,我们拿教程第一张图中的时间戳进行验证,浏览器访问这个接口发现拿到数据了,这个结果跟抓包的结果是一样的。那么简单的so调用就这么搞定了。那么我们是否可以用IDA调试继续来搞呢?

8ca4eb41b8d3508df050a0b33ce6edf9.png

回到伪c代码,大概看看代码你应该知道,取了签名值之后,又有字符串拼接等操作,后面执行MD5Digest函数传入了三个参数,第一个是字符串,第二个是字符串的长度,第三个用于存放运行结果,我们只需要最终需要加密的字符串就好办了,看伪c代码是看不出来的,顶多可以猜一下。

eeb9ed22a2cfcdbabf5c102b2b4c9c3c.png

调试状态下为了效率问题并不会完全解析代码,就会有个问题,我们不好找下断点的地方,因为函数名变成我们不认识的,那么我们需要另一种方法,从函数开始的位置往下数,看MD5Digest位于第几个BLX, 记住这个位置。

304c77dada2926e347404a855d06b7f9.png

到网上下载相应的android_server,用adb将其推送到手机里,具体参考网上教程,然后把名称和端口号最好改一下,有的app会根据这个名称和端口号进行反调试,但是本教程案例没有反调试,默认也可以,然后开启服务,进行端口转发。

9cbc2fb67587e9f529940d6e69ec69e1.png

重新打开IDA, 远程附加进程。

e59dcca04f922bf2580151d716ef691f.png

9575b7bdf0ef5c1ef8056bca7f36d64d.png

16bf3b658f82516386e9c6f2841d6534.png

慢慢等待,出来下图所示的界面点击左上角的启动按钮,让app在调试状态下运行,然后找到Modules, ctrl+f 搜索你需要调试的so, 点进去找到需要调试的函数

282b1e0b7724c6d24509ffed451d069f.png

8de7f170692c59a6223ed311009bf787.png

926d833384d0eab92c856cb4eda6a97e.png

一般情况下,当某个函数被调用的时候,R0, R1, R2, R3寄存器存放函数的参数值,因为MD5Digest函数,传入了三个值,所以我们后面调试的时候,只需要关注R0、R1、R2寄存器就可以了,接下来,我们需要找到下断点的位置。

1ea242611a61fa0ba18d0c425f077cd6.png

找到前面记住的BLX位置,如果你不确定这个位置是否正确,可以点进去,然后按c键,可以看到这个地方就是我们需要下断点的位置,把方法函数名改一下,方便查看。

b3fdc384de2bff03bb9caeaea451a872.png

cefbb40f5a9a1a8a7d57aaf331b10ec0.png

51cecac5d56849d9955df24cdaacf9eb.png

按F2添加断点,手机输入账号密码点击登陆触发断点。到Hex View-1右击同步R0寄存器

b22620fbf105ac0c0e5d1e068b7f9c4f.png

b672c553abe8217357db0750dd101cec.png

c7ccc3e355c298e1b1fc8272d29be77e.png

根据R0寄存器的地址找到存放的数据,可以看到该值是一个字符串,字符串前一部分就是我们上面取到的签名值,后面一部分是时间戳,把这个字符串复制一下以遍后面验证使用

04b0a3db7da065e01b374a2efcf662f6.png

R1寄存器中存放的值是16进制数值2D, 转换为十进制为45,正好是R0寄存器存放的字符串的长度。

a379f21ede3801923e8ebd5024f6990f.png

同步R2寄存器,因为MD5Digest函数还没有执行,所以这里的值不是最终的结果,我们按F8继续执行

d6716b3f219e2df2b2f8c1db0c99e0c4.png

下图标出来的就是计算后的结果,那么这个MD5Digest和python的md5计算结果是否一样呢?

c22c4854b67245e16be1bd034c61a455.png

经过验证,发现结果是一样的。本教程案例没有遇到反调试,app加固等情况,加密函数的逻辑比较简单容易处理,即使这样,搞起来还是很费劲的,app逆向需要掌握很多知识,只能慢慢啃,急不得。

e0983e53a6710e69e43a9a85e2e6faad.png

如果觉得教程不错,帮忙分享转发,谢谢!

喜欢文章,点个在看 e27ab774cc697a6589ebbea765cbd14d.png 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/506608.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电容的q值计算公式_在设计电路中电容容量大小、耐压等级选取详解 (转)

原文链接:在设计电路中电容容量大小、耐压等级选取详解 作者:张飞电容的计算 我们对电容的计算,目的是要知道,我们在电路中需要一个多大的电容。为什么要需要这么个电容?它的电压要多高?它的容量要多大?这是…

一个显示器分两个屏幕_桌面改造计划2.0:一个显示器不够那就两个,桌面好物分享...

日常生活节奏快,工作压力大应该目前年轻人的共识。为了适应快节奏的生活,使得大家往往不得不接受996或者997甚至更长的工作时间。而随着更长的工作时间也导致大家在电脑显示器前的时间更长,从而带来更多的不良影响,这两年过劳死的…

python寻找屏幕上的特定字符_库Turtle:用Python指挥小海龟在屏幕上绘图,流行的儿童编程...

海龟绘图(Turtle Graphics)是向儿童介绍编程的流行方式,源于Wally Feurzig和Seymour Papert1966年开发的LOGO语言。Python内置了Turtle库,基本包含所有原始功能。想象绘图区左上角有一只小海龟,代码就是指挥它动作的命…

flutterapp部分手机无法打开_Flutter run无法在iPhone上打开应用,直接在iphone也无法打开...

在电脑端运行flutter run后,报错信息如下:$ flutter runLaunching lib/main.dart on yuan的 iPhone in debug mode...Automatically signing iOS for device deployment using specified development team in Xcode project: 9D2Q3H854TRunning Xcode bu…

centos7 mysql 安装_CentOS7安装MySQL8.0图文教程(相对最齐全)

登录主机,然后进行下载第一步:在mysql官网下载源文件第二步:Select Operating System: 选择 Red Hat ,CentOS 是基于红帽的,Select OS Version: 选择 linux 7第三步:选择 RPM Bundle 点击 Download第四步&a…

cesium等高线_Cesium开源三维地球离线地图发布源码示例功能

一、概述Cesium开源三维地球离线地图发布源码提供了地图切换、查询定位、模型加载、专题图叠加显示和测量功能等,旨在为用户提供一个可以在Cesium快速加载离线地图或在线地图的解决方案,并提供技术支持。除了现有基本功能之外,还可以根据用户…

python 爬取贝壳网小区名称_Python爬虫实战:爬取贝壳网二手房40000条数据

前言本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理以下文章来源于啤酒就辣条 ,作者啤酒就辣条一、网页分析爬取贝壳网石家庄二手房信息,先打开链接https://sjz.ke.com/ershoufang…

hive mysql5.7_安装并使用mysql5.7作为hive的metastore

前言hive的metastore默认是使用derby来作为metastore,但是derby有一个缺点是不能支持多用户链接,虽然你可以通过切换目录来支持,但是不同目录的metastore会不一致,所以这里使用mysql来作为hive的metastore。在linux上安装mysql数据…

gitee如何搭建mysql_Windows基于gitee使用hexo搭建个人博客笔记

声明"全局变量"(以后我提到的站点配置文件和主题配置文件地址):"站点配置文件"位置为 hexo/_config.yml"主题配置文件"位置为 hexo/themes/next/_config.yml搭建hexo安装hexo命令行中输入以下命令(npm即为Node.js环境,如果…

mysql error nr.2003_[MySQL]在安装windows版MySQL时遇到过如下问题Error Nr.1045和Error.Nr.2003,相应解决办法如下...

1、准备mysql server-5.0.27.exe2、按照指导安装,在安装到最后一步时遇到如下两个错误:2.1、出现错误Error Nr.1045解决办法:a).停止MySQL服务:我的电脑-->右键-->管理-->服务和应用程序-->服务 找到名为"MySQL&…

java 数据结构 迷宫_JAVA数据结构与算法之递归(一)~ 迷宫问题

递归递归需要遵守的重要规则1) 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)2) 方法的局部变量是独立的,不会相互影响, 比如 n 变量3) 如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据.4) 递归 必须向退出递归…

cache数据库和mysql_并发环境下,先操作数据库还是先操作缓存?

原标题:并发环境下,先操作数据库还是先操作缓存?来源:捡田螺的小男孩前言在分布式系统中,缓存和数据库同时存在时,如果有写操作,先操作数据库还是先操作缓存呢?本文将分5种方案 展开…

java 查看垃圾收集器_JVM系列:查看JVM使用的什么垃圾收集器

一、方法一打印虚拟机所有参数[rootlocalhost ~]# java -XX:PrintFlagsFinal -version | grep :uintx InitialHeapSize : 258689024 {product}uintx MaxHeapSize : 4139778048 {product}bool PrintFlagsFinal : true {product}bool UseCompressedOops : true {lp64_product}boo…

java在W n8安装_在windows中安装JDK8并配置环境变量-java环境变量设置

学习JAVA,必须得安装一下JDK(Java development kit java开发工具包),配置一下环境就可以学习JAVA了,下面是下载和安装JDK的教程:一、去oracle官网上下载jdk8的下载地址:https://www.oracle.com/technetwork/java/javas…

java将图片上传数据库_〔技巧实例〕轻松实现将上传图片到数据库

很久就想自己写一写程序了,不过由于赖就不想写我,今天刚好有空,所以写了这个小小的程序很容易一看就知道的,不多说了就此开始:我们做一个上传的。数据据库的字段就id自动编号 big 字段类型是 OLE 呵呵就简单的那个字段…

java计算雷达扫描范围_雷达扫描 - linyinmobayu - 博客园

1、设计思想雷达扫描图,在影视作品中见到较多,比如飞机雷达、舰艇雷达,有一个扫描线转圈代表雷达一周旋转或一个批次的收发,发现目标就在表盘上标记位置。和汽车仪表盘类似,汽车仪表盘有底盘背景图、同圆、刻度、刻度值…

mysql降序后去重_Mysql 数据记录去重后按字段排序

实现效果:去重—取最新的—排序例子 : 按用户ID获取历史记录中某个人的记录,要求非重复的且每条只获取最新的,同时按添加时间倒序排列的实现 :SELECT *FROM (SELECT *FROM historysWHERE types_id1ORDER BY created DESC) AS BGRO…

linux php 守护进程,PHP程序员玩转Linux系列 使用supervisor实现守护进程

PHP程序员玩转Linux系列文章:首先遇到的问题是,部署nodejs的博客程序时,我把执行nodejs的命令放到后台,使用加&和nohup命令如:nodejs index.js & 或者 nohup nodejs index.js &&这个使用是当退出此次终端会话的时候就会停止, nohup这个命令理论上是…

计算机初级包括php吗,计算机的基本组成包括什么

计算机的基本组成包括控制器、运算器、存储器、输入设备和输出设备。其中,控制器是整个计算机的中枢神经,它的功能是对程序规定的控制信息进行解释,根据其要求进行控制,调度程序、数据,协调计算机各部分工作及内存与外…

ubuntu11.10 源码编译安装php5.3.8,Ubuntu 11.10编译安装Nginx、PHP 5.3.8、MySQL、MongoDB、Memcached、SSL、SMTP...

手动安装php mongo扩展sudo apt-get install autoconfwget http://pecl.php.net/get/mongo-1.2.6.tgztar -zxvf mongo-1.2.6.tgzcd mongo-1.2.6/usr/local/php/bin/phpize./configure --with-php-config/usr/local/php/bin/php-configmakesudo make installecho extension mon…