逆向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,一经查实,立即删除!

相关文章

ide打开项目运行和调试按钮都是灰色的_如何开发一个IDE

IDE对于语言来说非常重要,让新手能更快入门,让老手能有更高的开发效率。所以我摸索着开发了Fanx语言的IDE。这里分享一些IDE内部工作原理和经验。IDE和编译器IDE为了实现功能,需要对源码进行解析。经过词法分析、语法分析、语义分析。相当于编…

电容的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…

mysql定时导入_MySQL导入、导出、数据库定时备份

本篇使用的MySQL版本是5.7.30,注意不同版本之间可能会有差异。一、导出操作1、查找mysqldump命令位置which mysqldump2、mysqldump导出示例用户名和密码分别是root和123456;导出远程库,使用-hIP和-port端口,如下所示。后面的命令默…

ubuntu mysql 初始化_Ubuntu初始化MySQL碰到的坑

想着将MySQL初始化,改变一下存放数据文件的位置:rootubuntu:/lvmdata# mkdir datarootubuntu:/lvmdata# chown -R mysql:mysql /lvmdata/data修改MySQL配置文件:datadir /lvmdata/data然后初始化:rootubuntu:/lvmdata# mysqld --…

mysql 攻击密码_MySQL用户Root密码为弱口令的攻击

1、连接到对方MYSQL 服务器mysql -u root -h 192.168.0.1mysql.exe 这个程序在你安装了MYSQL的的BIN目录中。2、让我们来看看服务器中有些什么数据库mysqlshow databases; MYSQL默认安装时会有MYSQL、TEST这两个数据库,如果你看到有其它的数据库那么就是用户自建的数…

mysql封装执行_解决Mysql封装类执行报错——Mysql::insert() should not be called

今天在写程序的时候使用了别的程序员写的一个Mysql封装类,但是执行后php会报错:Strict standards: Non-static method Mysql::insert() should not be called statically in关于这个错误的的处理方法是修改类文件,将对应报错的“function ins…

mysql建立从库同时备份_mysql主从库配置读写分离以及备份

1,什么是读写分离?其实就是将数据库分为了主从库,一个主库用于写数据,多个从库完成读数据的操作,主从库之间通过某种机制进行数据的同步,是一种常见的数据库架构。一个组从同步集群,通常被称为是…

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

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

mat 和asmatrix的区别_R语言的稀疏矩阵太大可能就不能用as.matrix了

一个很大的矩阵, 320127 行, 8189列,假如用一个全为0的普通矩阵来存储,需要用到9.8Gbcols rows mat print(object.size(mat), unit"GB")# 19.5 Gbmat print(object.size(mat), unit"GB")# 9.8 Gb这里的0其实也要区分这里…

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

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

python入门基础系列八_Python 入门系列 —— 21. dict 的介绍

Dictionary字典常用于存储键值对的集合,它是一种无序,可修改并且不允许重复,字典是用 {} 来表示,并带有 k/v 键值对,比如下面定义的字典结构。thisdict {"brand": "Ford","model": "Mustang&…

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

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

centos禁用exec_CentOS停用按下Ctrl-Alt-Del 重启系统的功能

在Linux里,由于对安全的考虑,我们允许任何人按下Ctrl-Alt-Del来重启系统。但是在生产环境中,应该停用按下Ctrl-Alt-Del 重启系统的功能。[rootlocalhost ~]# cat /etc/inittab# Trap CTRL-ALT-DELETE#ca::ctrlaltdel:/sbin/shutdown -t3 -r n…

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&…

python定制框架知识点_python框架中flask知识点总结

有很久没有更新我的博客了,在学习flask去了,别人都说flask不难,其实现在我也这么觉得,但是在刚接触的时候还是有点吃力的。在学习的过程中查阅了不少,也了解了许多,今天想做个总结。。。以免觉得学了那么久…