1 今日目标
# 得物app
-采集首页推荐信息
# 版本选择
-4.74.5版本
2 绕过强制更新
# -*- coding: utf-8 -*-
'''
@IDE : PyCharm
@version : 3.9
@Auth : 恍惚
@time : 2024/2/25 8:01
@Description: Null
'''
import frida
import sys
rdev = frida.get_remote_device()
pid = rdev.spawn(["com.shizhuang.duapp"])
session = rdev.attach(pid)
scr = """
Java.perform(function () {
var AlertDialog = Java.use('androidx.appcompat.app.AlertDialog');
AlertDialog.show.implementation = function(){
console.log("执行了");
//this.show();
}
});
"""
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
rdev.resume(pid)
sys.stdin.read()
3 抓包(反代理)
如果没开SocksDroid,发现根本抓不到返回的结果
发现就是这个api返回的结果
# 1 该app进制了手机端代理,需要使用SocksDroid代理
-切记:一定要把之前配置的手机代理删除
# 2 打开charles,抓包
# 3 分析接口
-地址:https://app.dewu.com/sns-rec/v1/recommend/all/feed
-请求方式:get
-请求头:都可以删除,只剩 X-Auth-Toke
User-Agent duapp/4.74.5(android;11)
X-Auth-Toke # 不能删,需要携带
-请参数:
lastId # 空:第一页 或 1:继续加载
limit 20 # 每次显示多少条
newSign 178d802feef18d6a75caad8c048e10cf # 像加密的,测试可以删除,但是必须破,否则后续的完成不了
-----以下的都可以不携带-----
abType social_brand_strategy_v454
abValue 1
deliveryProjectId 0
abVideoCover 2
abRectagFengge 0
abRecReason 0
-请求体:无
# 4 分析完,我们破解目标
-newSign
-X-Auth-Token
4 破解newSign(难)
4.1 反编译app
# 1 把 得物app ,拖到 jadx中,搜索 "newSign
-发现 addQueryParameter比较像
-QueryParameter名字就是请求地址中问号后面的东西
-大胆猜测,就是它----》后面要做hook验证
# 2 分析host.addQueryParameter("newSign", RequestUtils.c(hashMap2, currentTimeMillis));
# 3 调用了RequestUtils.c,传了两个参数进去
# 4 写个hook脚本,测试是否走了这个c
-通过写hook脚本,确认走了这个c
4.2 hook-RequestUtils.c
# -*- coding: utf-8 -*-
'''
@IDE : PyCharm
@version : 3.9
@Auth : 恍惚
@time : 2024/2/25 10:01
@Description: Null
'''
import frida
import sys
# 连接手机设备
rdev = frida.get_remote_device()
session = rdev.attach("得物(毒)")
scr = """
Java.perform(function () {
// 包.类
var RequestUtils = Java.use("com.shizhuang.duapp.common.utils.RequestUtils");
// Hook,替换
RequestUtils.c.implementation = function(map,j2){
console.log('--------------------------------')
// 执行原来的方法
console.log('1.参数字典为:',map); // 此处直接打印map,发现打印的是对象,我们需要转换一下
console.log('2.参数字典类型为:',JSON.stringify(map)); // 查看一下类型 :java.util.HashMap
// 以下是固定格式
var Map = Java.use('java.util.HashMap');
var obj = Java.cast(map, Map);
console.log('3.参数字典转成字符串类型为:',obj.toString());
console.log("传入的参数j2为:",j2);
var res = this.c(map,j2)
console.log("加密后为:",res);
return res;
}
});
"""
#367368
script = session.create_script(scr)
def on_message(message, data):
print(message, data)
script.on("message", on_message)
script.load()
sys.stdin.read()
'''
--------------------------------
1.参数字典为: [object Object]
2.参数字典类型为: "<instance: java.util.Map, $className: java.util.HashMap>"
3.参数字典转成字符串类型为: {abValue=1, deliveryProjectId=0, abRectagFengge=0, abType=social_brand_strategy_v454, limit=20, lastId=, abRecReason=0, abVideoCover=2}
传入的参数j2为: 1708847014908
加密后为: 8508b78f222c3cdd5d183d0033005db0
--------------------------------
1.参数字典为: [object Object]
2.参数字典类型为: "<instance: java.util.Map, $className: java.util.HashMap>"
3.参数字典转成字符串类型为: {type=1}
传入的参数j2为: 1708847014910
加密后为: 5e7d26e2b8ca0eeee312f744885c1052
'''
4.3 分析RequestUtils.c--java源码--干了5个事
public static synchronized String c(Map<String, String> map, long j2) throws UnsupportedEncodingException {
synchronized (RequestUtils.class) {
PatchProxyResult proxy = PatchProxy.proxy(new Object[]{map, new Long(j2)}, null, changeQuickRedirect, true, 6612, new Class[]{Map.class, Long.TYPE}, String.class);
if (proxy.isSupported) {
return (String) proxy.result;
} else if (map == null) {
return "";
} else {
//1 往map中放了很多 key-value
map.put("uuid", DuHttpConfig.d.getUUID());
map.put("platform", "android");
map.put("v", DuHttpConfig.d.getAppVersion());
map.put("loginToken", DuHttpConfig.d.getLoginToken());
map.put("timestamp", String.valueOf(j2));
//2 把上面的map放到arrayList中,做排序
ArrayList arrayList = new ArrayList(map.entrySet());
Collections.sort(arrayList, new Comparator<Map.Entry<String, String>>() {
public static ChangeQuickRedirect changeQuickRedirect;
@Override
public int compare(Map.Entry<String, String> entry, Map.Entry<String, String> entry2) {
PatchProxyResult proxy2 = PatchProxy.proxy(new Object[]{entry, entry2}, this, changeQuickRedirect, false, 6618, new Class[]{Map.Entry.class, Map.Entry.class}, Integer.TYPE);
return proxy2.isSupported ? ((Intege