大家好,欢迎来到IT知识分享网。
一.前言
前面铺垫了那么多,今天来讲第一个基础案例,车智赢登录逆向,作为我们的入门案例。因为是第一次讲案例,所以说的详细一点。
二.下载
这里给出下载网站,大家在这里下载apk就好
车智赢+下载页 (che168.com)https://appdownload.che168.com/usedcar/csy/index.html?pvareaid=106101下载好了,我们就执行如下命令,把apk安装到手机(前面和大家讲基础已经说过了)
到此,我们再将这个apk拖入jadx,进行反编译
反编译完成,我们开始抓包
三.抓包分析
我们打开charles,然后手机打开车智赢进行等录,我们可以发现如下的包
可以发现这个就是我们要登录的包,我们现在对参数进行分析
headers里面
form表单里面
我们可以改包测试一下,但是这里因为是教程,我就和大家说一下
_sign | E4D026D3BD0FCFB |
pwd | 1bbd5e5d605ed |
udid | zdn9tFAwgxo0N+yAgUPg9cZ7ysEHmIQAPGxcCxmPcO+txvzHMjeFfJavAF VeNjtbv0GQtbZVcHeupsTu5AVQ== |
这几个值是需要逆向的,我们就开始逆向,首先我们肯定选择_sign,我们可以看出这个很像是一个摘要算法,大家肯定看到我输入的密码是,一下就能看出来是md5摘要,当然作为教程我还是跟着大家一步步找
四.逆向分析
4.1 逆向pwd
根据之前所说的,优先搜索部分url,这里我们在jadx搜索 login/login.ashx
我们点进去,然后查找用例,干好搜到一个,再点击进去,就可以看到这个
可以看到,这里看到一个md5加密,但是我们得保证写代码的人有没有骗我们,我们再点进去
我们现在是不是就得hook一下encodeMD5方法了
我们现在来进行hook,hook之前得进行端口转发,不知道的人可以看看我day4HOOK,
然后我们就得在手机端启动frida,不知道的人可以看看day4HOOK,
这里我就只给出hook代码
import frida import sys # 连接手机设备 rdev = frida.get_remote_device() session = rdev.attach("车智赢+") # 写获取手机上的软件名 scr = """ Java.perform(function () { var SecurityUtil = Java.use("com.che168.atclibrary.base.SignManager"); // Java.use("需要hook的地方的包名和大类名") //普通方法的重载 SecurityUtil.signByType.implementation = function(i, treeMap){ console.log("明文i:",i); console.log("明文treeMap:",treeMap); console.log("明文treeMap:",treeMap.toString()); var res = this.signByType(i,treeMap); //调用原来函数加密密文 console.log("加密结果=",res); console.log("加密结果=",res.toString()); return res; } }); """ script = session.create_script(scr) def on_message(message, data): print(message, data) script.on("message", on_message) script.load() sys.stdin.read()
hook得到的截图,可以发现定位到的位置是正确的
并且就是md5其实大家可以记下几个固定值的摘要的 ,接下来就是要逆向剩下两个了,按照常理肯定是随机逆向一个,但是这里我和大家说,先逆向udid方便一点,因为后面的sign也用到了udid
4.2 逆向udid
我们搜索put(“udid”,可以发现有很多个
但是一看最后两个包名直接排除,这里大家可以一个个hook,我就直接告诉大家 是第三个,其他的大家可以试试。
我们双击进去,发现
再次双击进去,发现
我们hook这个,这里给出hook代码
import frida import sys # attach:手动运行app,打开APP后,再运行Hook脚本。 # 连接手机设备 rdev = frida.get_remote_device() session = rdev.attach("车智赢+") # 写获取手机上的软件名 scr = """ Java.perform(function () { var AppUtils = Java.use("com.che168.autotradercloud.util.AppUtils"); // Java.use("需要hook的地方的包名和大类名") //普通方法的重载 AppUtils.getUDID.implementation = function(content){ console.log("传入的字符串:",content); var res = this.getUDID(content); //调用原来函数加密密文 console.log("最后得到的结果",res); return res; } }); """ script = session.create_script(scr) def on_message(message, data): print(message, data) script.on("message", on_message) script.load() sys.stdin.read()
运行截图:
发现这里正确,那我们现在就来分析这段代码
public static String getUDID(Context context) { return SecurityUtil.encode3Des(context, getIMEI(context) + HiAnalyticsConstant.REPORT_VAL_SEPARATOR + System.nanoTime() + HiAnalyticsConstant.REPORT_VAL_SEPARATOR + SPUtils.getDeviceId()); }经过上面分析抓包看出传入到SecurityUtil.encode3Des主要是两个参数,我们拆分一下,发现
第一个 context 是Context类型的,我们先不管
第二个参数是几个拼接起来的
getIMEI(context) + #获取imei
HiAnalyticsConstant.REPORT_VAL_SEPARATOR + #全大写常量 | 双击就能看到
System.nanoTime() + #手机开机时间,gpt问下
HiAnalyticsConstant.REPORT_VAL_SEPARATOR + 常量 |
SPUtils.getDeviceId() #获取设备id号
介绍 context上下文对象
在安卓(Android)开发中,Context是一个非常重要的概念,它代表了应用程序的当前状态信息。每个Android应用程序都有一个Context,它允许应用程序访问系统资源和执行各种操作。Context通常是由Android系统传递给应用程序的各个组件(如Activity、Service、BroadcastReceiver等),以便它们能够与系统和其他组件进行交互。
Context的主要作用包括:
访问资源:通过Context,您可以访问应用程序的资源,如布局文件、字符串、图片等。这是因为Context持有对应用程序资源的引用,使您能够在应用程序中加载和使用这些资源。
启动组件:通过Context,您可以启动其他组件,如Activity、Service、BroadcastReceiver等。例如,您可以使用Context启动一个新的Activity来打开新的界面。
获取系统服务:通过Context,您可以获取系统级别的服务,例如获取系统的传感器、网络状态、存储管理等。这些服务是通过系统提供的服务注册表(Service Registry)来获取的。
# 应用程序级别的操作:Context还可以用于执行应用程序级别的操作,如发送广播、获取应用程序包名、获取应用程序的数据目录等。
4.2.1 getIMEI(context)
我们这次来找 getIMEI 我们双击进去
我们来分析以下这段代码,可以直接丢给gpt分析
1 去xml中取–》没有–》一旦生成过,以后就有了
2 取getDeviceId,如果没有,去mac地址
3 使用随机数生成uuid(getDeviceId或mac地址)
4 随机生成uuid,没有使用随机数
—–IMEI就是uuid—–
5 存到了xml中
可以选择的策略策略
1 直接随机生成uuid 我们用这个
2 直接使用sssss 不太好
3 去xml中找出来用 可以看day10的安卓技巧
4.2.2 System.nanoTime()
我们可以python直接伪造
import random nano_time = random.randint(73,73)
4.2.3 SPUtils.getDeviceId()
什么时候生成设备id号的呢?
1 程序刚刚启动时,通过某个算法得到,存到了xml中,以后都不变了
-好多app有这种操作
2 app刚启动,向后端发送请求–》获取到值—》存到xml,以后一直用
-这个app就是这种方案
我们直接双击进来
可以看到getDeviceId,但是我们应该要查找上面的saveDeviceId的用例
可以看到这个,那我们就可以发现,是在设备第一次启动,在上面那个地址获取了id,那我们把app的数据全部清除,再次抓包
可以发现生成了这个数据,我们多清楚几次多抓几次包,发现这都是固定的
4.2.4 encode3Des加密
进来可以发现
双击可以发现这个iv是定值appapich,现在主要就是key了,我们双击getDesKey,进去可以发现
因为key一般都是定的,我们就可以hook查看返回值,也可以继续跟,(这里提前告诉大家,这个继续跟就是jni了,需要去.so文件),我们就通过hook,一会最后给大家补充。
import frida import sys # attach:手动运行app,打开APP后,再运行Hook脚本。 # 连接手机设备 rdev = frida.get_remote_device() session = rdev.attach("车智赢+") # 写获取手机上的软件名 scr = """ Java.perform(function () { var AHAPIHelper = Java.use("com.autohome.ahkit.AHAPIHelper"); // Java.use("需要hook的地方的包名和大类名") //普通方法的重载 AHAPIHelper.getDesKey.implementation = function(content){ console.log("传入的字符串:",content); var res = this.getDesKey(content); //调用原来函数加密密文 console.log("最后得到的结果",res); return res; } }); """ script = session.create_script(scr) def on_message(message, data): print(message, data) script.on("message", on_message) script.load() sys.stdin.read()
可以得到key是appapiche168comappapiche168comap
那我们再来hook一下encode3Des和python的des3加密对比一下
对比正确,至此,udid逆向成功 但是发现这个des加密后在第61个位置添加了个空格 但是可以不用管的
4.3 逆向_sign
搜索 “_sign” 这里不能搜索 当然大大家也可以踩踩坑,搜索put(“_sign,因为结果是第五个我们在第五个双击进去
查找用例的话会发现很多,因为是教程,我就和大家说真的位置,就是在这一层,我们往下滑,就可以看到
读一下逻辑,可以发现是对载荷进行处理,然后再放进载荷,再对这些数据进行加密,最后再添加到treemap里
我们对这个进行hook(相信大家已经会hook了)这里就不给hook代码,不记得的话可以看前面的hook章节,那里有详细教程,hook得到的结果是
我们现在来读逻辑
{_appid=atc.android, appversion=3.53.0, channelid=csy, pwd=7ec28f0d5c8a87b72e16365b208c832c, signkey=, type=, udid=zdn9tFAwgxo0N+yAgUPg9cZ7ysEHmIQAPGxcCxmPd3fg/KYWOW7EpYXS+E vpjvDdJWuadmTuJJDmJiAZLMvw==, username=}
先在一个空字符串添加”W@oC!AH_6Ew1f6%8″(因为i=1)
就是对这个treemap进行一个个拼接,得到keyvaluekeyvalue这个格式,再添加”W@oC!AH_6Ew1f6%8″,最后添加然后进行md5,最后再转大写
对此,全部逆向成功
五.总结
pwd 就是对密码进行md5加密
udid就是将几个值拼接起来进行des加密,最后再第61个位置加上空格(可忽略)
_sign 对载荷进行拼接后 前面加上一串字符,后面加上一串字符进行md5
六.运行结果
七.DES3加密的.so获取key
当我们当时找key的时候,一直找,可以看到这个
看到System.loadLibrary(“native-lib”)我们就能想到是jni的静态注册嘛(不记得的赶快去看我前面的jni开发,记得点赞关注加收藏);
现在我教教你们如何看.so文件
把apk后缀改成.zip,然后解压缩,在lip下的arm64-v8a找到libnative-lib.so,因为前面的名字是native-lib.so,lib是前缀
然后把他拖入64位的idea
然后点eport,搜索java,第一个就是
双击进来,按F5
然后右键
点这个就能够隐藏变量了(看起来更清晰)
然后点这些,导入jin.h
点击__int64,然后右键,选择下图这个
再选择这个
再双击DES3_KEY
悬浮在上面
可以看到key就是appapiche168comappapiche168comap
至此,本篇教学完成!!!
补充
有不懂的地方可以主页咨询我,有球必应
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/151295.html