记录第一次APP逆向(挠头)的过程。
APP最大的门槛,莫过于要有一台配好环境的手机。老早就想看看APP是什么情况,奈何家里几个手机试下来都失败了,就没搞了。
不过刚好公司拿了一台,这下就可以操作辣!!
本次的APP是:X米赚X
注:由于是第一次搞,如果有错的地方还请见谅,可以在下方评论交流喔~
0. 手机root以及magisk
为什么是0开头呢,因为写这个的时候1,2已经写好了。
公司发的手机已经root过了,我要做的就是刷上magisk和lsp,这个其实还好,到github就可以下载到软件了g已经root过了,我要做的就是刷上magisk和lsp,这个其实还好,到github就可以下载到软件了
https://github.com/topjohnwu/Magisk/releases/tag/v28.0
https://github.com/LSPosed/LSPosed/releases/tag/v1.9.2
当然,如果你看了下面几条,那就知道意外总会发生。
当我安装了magisk后,提示我检测到其他su文件,我想删掉但一直没成功,最后懒得管了,发现好像不太影响
1. 电脑连接手机
我是真没想到这个能变成第一个点,为什么呢。因为拼多多买的线,他连上了识别不了!

害得我拔插半天。最后换了一个伊拉克战损线就连上了。。
大伙还是买个贵一点的线😂
2. 无线网卡
我是真没想到这个能变成第二个点,为什么呢。不是我水字数,是因为我电脑没无线网卡,是直接插得网线,跟手机连的wifi不是同一个网络,这还怎么抓包啊。看来要放弃了,但是刚好,公司有多一个无线网卡!
可惜事情没有这么简单,不然这玩意怎么能到第二点来。。我使用的无线网卡是 腾达U6免驱版 我寻思好小子这么贴心,驱动都不用我去找。插上电脑之后就弹出来选项让你运行,就可以安装了。
但是!事情还是没有这么简单。驱动安装到95%的时候会卡很久,这其实没问题。问题是安装完之后,无线网卡仍然是没起效果。在我反复拔插多次删除驱动重装红温后,我打开了设备管理器。看到了这么个东西:
Tenda Wireless USB Adapter Windows 仍在设置此设备的类配置。 (代码 56)
不是哥们,你在干什么啊。搜了一下,说是配置过VMware的虚拟网卡导致的,最后去问了客服,客服发了一个修复软件给我,重启了之后就好了:
3. 证书与抓包
历经九九三难,终于是连到了同一个wifi里面,插线的时候使用 adb devices 来连接到手机,再查看手机wifi的ip地址,使用 adb connect 192.168.x.xx 就可以做到无线连接手机了,不过好像没什么必要,插着线搞就行了。
打开Charles,安装证书,但是发现 chls.pro/ssl 这个用来安装证书的网页手机上面打不开,只好先保存证书到电脑。

但是意外发生了:

保存到这个目录的证书不翼而飞!懵逼的你再一次保存到这里的时候,你就会发现他弹了个框:

不是哥们,这谁写的,怎么直接拿文件夹的名当文件名了,感情上面不是让我选文件夹吗!
遂来到上一级目录(Admin)

好吧,adb push C:\Users\Admin\Documents.pem /data/local/tmp 丢到手机里面,再从 设置-安全-加密与凭证-从存储设备安装 这里去安装证书
OKK,总算是装上证书了!在手机wifi设置一下代理:代理服务器主机名:电脑在这个wifi下的ip,代理服务器端口:Charles监听端口8888;然后在Charles允许接受请求,大功告成!!
了吗,其实还没有,因为当我打开app访问页面的时候,Charles上愣是api是一个都没见着,只能看到图片请求。后面发现其实是因为虽然证书已经安装了,但并没有进到证书根目录,而且默认的pem格式的证书有问题,要手动改成crt格式,最后打开github,用magisk安装移动证书的工具,重启后即可!
https://github.com/ys1231/MoveCertificate/releases/tag/v1.5.2
4. Jadx与FRIDA-DEXDump
Jadx用于反编译dex文件到java代码,可以看到APP的部分源码。
https://github.com/skylot/jadx/releases/tag/v1.5.1
无需安装,下载解压后直接打开,将apk文件拖进去

在Source code – com包里面的就是APP的源码。但实际上只是部分源码,因为有的源码被藏在了classes.dex文件(用压缩软件打开就能看到apk里面的东西)里面。这个就叫壳。

老规矩,百度一下可得,这个时候需要脱壳,那么就使用frida-dexdump进行脱壳:
frida-dexdump -U -f com.xxx.xxxx -d
就会得到很多很多dex

把他们全部添加到jadx里面就可以了

5. Frida
看看包先

说实话,我感觉是我道行太浅,漏东西没处理,但是我不知道哪里不对,在jadx反编译的代码里面根本就搜不到这个api和其中的参数,难道是在鼎鼎有名的so文件里面?
那没办法,只能使用瞪眼法,看到所需的sign参数是32位的,盲猜一个md5,然后在jadx里面搜:

好家伙,搜出来这么多。不过实际上真正在用md5的就是我选中的那附近几行,过去看一下

总所周知,Frida是用来hook函数的,那么就试试hook一下这个md5好了。
update方法会把明文传进去,在通过digest输出密文的二进制数据,再使用ByteString.of().hex()变成熟悉的32位16进制字符串,也就是说我们需要同时hook update和digest方法。在经过十来分钟的跟gpt拉扯,最终得到Frida代码如下:
import frida
import sys
# Frida 脚本
script_code = """
Java.perform(function () {
var MessageDigest = Java.use("java.security.MessageDigest");
MessageDigest.update.overload('[B').implementation = function (input) {
let value = String.fromCharCode(...eval("[" + Java.array('byte', input) + "]"))
if (value) {
console.log("MessageDigest.update(byte[] input) called");
console.log("Input: " + value);
}
this.update(input);
};
MessageDigest.digest.overload().implementation = function () {
var result = this.digest();
console.log("Digest result (hex): " + bytesToHex(result));
return result;
};
function bytesToHex(bytes) {
var hex = '';
for (var i = 0; i < bytes.length; i++) {
var byte = bytes[i] & 0xFF; // 确保是无符号字节
hex += (byte < 16 ? '0' : '') + byte.toString(16);
}
return hex
}
});
"""
def on_message(message, data):
if message['type'] == 'send':
print("[*] {}".format(message['payload']))
else:
print("[!] {}".format(message))
def main(target_app):
# 启动目标应用
process = frida.get_usb_device().spawn([target_app])
session = frida.get_usb_device().attach(process)
# 加载 Frida 脚本
script = session.create_script(script_code)
script.on('message', on_message)
script.load()
# 恢复目标应用
frida.get_usb_device().resume(process)
print("[*] Hooking...")
# 保持脚本运行
sys.stdin.read()
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage: python hook_message_digest.py <package_name>")
sys.exit(1)
target_app = sys.argv[1]
main(target_app)
首先使用adb启动手机上的frida-server:
adb shell
su
cd /data/local/tmp
./frida-server-16.5.7-android-arm64
然后在终端输入:python hook.py com.xxx.xxxx 你就可以看到手机在重启这个APP,同时终端里面在不停输出md5的明文和结果:

消停一会儿之后,我们打开页面,可以看到确实有数据被打印出来了,数量不多,这时候跟抓包软件上面的参数进行对比一下:


可以看到,sign其实是 -1 + 时间戳 + haql!@~000%#$ 得到的,此外,还能看到下面加密了这里发包的参数拼接而成的字符串,也生成了一个md5,发现其实他就是data里面的pwd参数取前18位
至此,虽然不知道明文怎么来的,不知道发包在哪发的,不知道盐是在哪加的。但是我们依旧完成了任务!
最后写一个python脚本请求一下:

OKK,任务完成!
6. 其他
有一说一,当时我怀疑是so的时候搜了一下,发现确实啊,确实有个so文件,名字叫libjiagu.so
古德古德,一看就是加固了,百度了一下说是360壳,但是不知道咋搞这个东西,丢到ida里面也看不懂,以后学了so怎么逆向再干他吧

发表回复