某友sig分析

h5 sig

'{ "appid": 330002, "app_key_vs": "1.0.0", "app_key": "0n003Fo004931Z20" }',

url = "https://cs-ol.sns.sohu.com/330002/v8/userapi/user/show"
params = {
    "profile_user_id": "1140727494190770176",
    "flyer": "1744199170717",
    "appid": "330002",
    "app_key_vs": "1.0.0",
    "sig": "be9e2476455f4b7479e942a5131a6794"
}

params 按Key排序拼接后md5得出sig:

app_key_vs=1.0.0appid=330002flyer=1744199170717profile_user_id=11407274941907701760n003Fo004931Z20

sig为:be9e2476455f4b7479e942a5131a6794

在这里插入图片描述

s-pid 为 1140727494190770176

import hashlib

def calculate_sig(params,appkey):
    keys = sorted(params.keys())
    param_str = ""
    for key in keys:
        if key!= "sig":
            param_str += f"{key}={params[key]}"
    param_str = param_str+appkey
    md5 = hashlib.md5()
    md5.update(param_str.encode('utf-8'))
    new_sig = md5.hexdigest()
    return new_sig

new_sig = calculate_sig(params = {
    "profile_user_id": "1140727494190770176",
    "flyer": "1744199170717",
    "appid": "330002",
    "app_key_vs": "1.0.0",
    "sig": "be9e2476455f4b7479e942a5131a6794"
},appkey="0n003Fo004931Z20")

print(new_sig)

小程序sig

小程序和h5一样,换下app_key就行。

解包搜索即可找到app_key

APPID=330008
app_key_vs:"6.4.0"
app_key: "760W*******140F"


app sig

可找到 @hy.sohu.com.app.common.net;
在这里插入图片描述

简单hook:

Java.perform(function () {
    console.log("1111")
    Java.openClassFile('/data/local/tmp/r0gson.dex').load()
    const gson = Java.use('com.r0ysue.gson.Gson')

    let a = Java.use("hy.sohu.com.app.common.net.a");
    a["getSignMap"].implementation = function (requestBaseMap) {
        console.log(`start : ${gson.$new().toJson(requestBaseMap)}`)
        let result = this["getSignMap"](requestBaseMap);
        console.log(`end : ${gson.$new().toJson(result)}`);
        return result;
    };
});
start : {"circle_id":"1105277072533822848","S-CID":"011285761868497073152","count":10,"extras":"1","withTop":1,"exposed_circle_pos_feed_id":"","stpl":"1,2,3,4,7,9,11,12","app_key_vs":"6.7.0","flyer":"1744203686922","list_type":2,"score":0.0,"tpl":"1,3,24,26","log_user_id":"1211457320777882752","S-PPID":"1816720971126923264@sohu.com","S-PID":"1211457320777882752","appid":"330000"}

end : {"circle_id":"1105277072533822848","count":10,"extras":"1","withTop":1,"exposed_circle_pos_feed_id":"","stpl":"1,2,3,4,7,9,11,12","app_key_vs":"6.7.0","flyer":"1744203686922","sig":"5aee33621de4878c09a0b2c361335a5b","list_type":2,"score":0.0,"tpl":"1,3,24,26","log_user_id":"1211457320777882752","appid":"330000"}

String sig = sa.a.f53141a.cscd130065c407(treeMap, null);
在这里插入图片描述

hook可知

let a = Java.use("sa.a");
a["cscd130065c407"].implementation = function (treeMap, str) {
    console.log(`start [Method] a.cscd130065c407 is called: treeMap=${treeMap}, str=${str}`);
    let result = this["cscd130065c407"](treeMap, str);
    console.log(`end   [Method] a.cscd130065c407 result=${result}`);
    return result;
};
start [Method] a.cscd130065c407 is called: treeMap={S-CID=011285761868497073152, S-PID=1211457320777882752, S-PPID=1816720971126923264@sohu.com, app_key_vs=6.7.0, appid=330000, circle_id=1105277072533822848, count=10, exposed_circle_pos_feed_id=, extras=1, flyer=1744204049807, list_type=2, log_user_id=1211457320777882752, score=0.0, stpl=1,2,3,4,7,9,11,12, tpl=1,3,24,26, withTop=1}, str=null

end   [Method] a.cscd130065c407 result=587f1d45b193158d64041d5f513b56e4

找到 System.loadLibrary("CtaApiJni");
在这里插入图片描述
IDA直接搜 cscd130065c407
在这里插入图片描述

cscd130065c407伪代码的关键部分:

void __fastcall Java_sa_a_cscd130065c407(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
  unsigned __int64 v4; // x22
    if ( v8 ){
    #省略
    }
    else
    {
    # 省略部分
    sub_69600(&v32, &v30);
    sub_6A290(&v32);
    if ( word_E4E10 & 1 )
      v18 = (char *)qword_E4E20;
    else
      v18 = (char *)&word_E4E10 + 1;
    if ( word_E4E28 & 1 )
      v19 = (char *)qword_E4E38;
    else
      v19 = (char *)&word_E4E28 + 1;
    if ( (unsigned int)strcmp(v19, "sleep,") )
    {
      if ( strstr(v19, "cdt1")
        || strstr(v19, "cdt2-1")
        || strstr(v19, "cdt2-2")
        || strstr(v19, "cdt3")
        || strstr(v19, "cdt4") )
      {
        std::__ndk1::operator+<char,std::__ndk1::char_traits<char>,std::__ndk1::allocator<char>>(
          "cjf---check_log: ",
          &word_E4E28);
        sub_67E70(v5, &v21);
        if ( v21 & 1 )
          operator delete(v22);
LABEL_30:
        if ( *(_QWORD *)(v4 + 40) == v36 )
          exit(0LL);
        return;
      }
    }
    else
    {
      #省略
  }
  else if ( *(_QWORD *)(v4 + 40) == v36 ){v7();}}

sub_67804 ,将传入的Java Map对象遍历,转换为key=value格式的字符串

在这里插入图片描述

v8是传入的app_key,这里v8=null

在这里插入图片描述

sub_69600是哈希算法的Final阶段实现,负责数据填充和结果生成,大概率是 ‌MD5算法‌ 的实现。
sub_6A290该函数将 result + 92 处的二进制数据转换为十六进制字符串, 符合MD5的输出特征。

hook sub_6a290

const module = Process.getModuleByName("libCtaApiJni.so");
const funcOffset = 0x6a290;
const funcPtr = module.base.add(funcOffset);
Interceptor.attach(funcPtr, {
    onEnter: function(args) {
        const context = this.context;
        this.inputPtr = context.x0.add(92);
        this.a3 = context.x8;      
        this.inputData = Memory.readByteArray(this.inputPtr, 16);
    },
    onLeave: function(retVal) {
        console.log("原始数据 (HEX):", hexdump(this.inputData));
        const outputStruct = this.a3;
        const capacity = outputStruct.readU64();
        const length = outputStruct.add(8).readU64();
        let dataPtr;
        if (length > 0x16) {
            dataPtr = outputStruct.add(16).readPointer();
        } else {
            dataPtr = outputStruct.add(1);
        }
        const outputBytes = Memory.readByteArray(dataPtr, Number(length));
        console.log("加密结果 (HEX):", hexdump(outputBytes));
        try {
            console.log("加密结果 (UTF-8):", Memory.readUtf8String(dataPtr));
        } catch(e) {
            console.log("加密结果非 UTF-8 字符串");
        }
    }
});

在这里插入图片描述

结果确实是md5,和抓包一致


hook sub_69600

可发现填充salt:

file

app端计算sig时,需要把S-CID、S-PPID、S-PID加入params一同计算。

各端salt整理

【温馨提示:此处隐藏内容需要付费订阅后才能查看!】

点赞

发表回复