APP版本 11.15.0
接口分析
# URL
https://app.zhuanzhuan.com/zz/transfer/search# header
cookie xxx
x-zz-monitoring-metrics feMetricAntiCheatLevel=V1
zztk
user-agent Zhuan/11.15.0 (11015000) Dalvik/2.1.0 (Linux; U; Android 10; Pixel 3 Build/QQ3A.200805.001)
zzreqallparam zztk|zzReqT|tabId|filterModuleServerParamsInput|b2cInfoCardAB|requestmark|pushcode|searchPageSource|searchAccurateFilterAB|pagenum|extendParams|pageIdParams|sessionStr|pagesize|recModelAB|searcfilterhmove2zzsearch|search_9_0_0|searchStandardPropertiesAB|keyword|searchfrom|changeIntention|usePgParam
zzreqsign 0b832cdce0b84776da0de6f233ef5651 # 分析
zzreqt 1752138119444
zzht a_15
zzreferer https://app.zhuanzhuan.com/zz/15/E1007
referer https://app.zhuanzhuan.com/zz/15/E1007
content-type application/x-www-form-urlencoded; charset=UTF-8
content-length 1551
accept-encoding gzip# data
searchAccurateFilterAB 2
pagenum 4
extendParams {"sessionId":"xxxxxxxxxxx"}
pageIdParams {"refpagequery":"from\u003d14","refpagetype":"V1008"}
sessionStr {"abtest":"brandSeriesHightlightsAb.exp_brandSeriesHightlights0620:cvr.base_cvr0630:feedwords.base_feedwords_0407_aa1:flow_management_632.agroup_flow_management_632:flow_management_682.cgroup_flow_management_682:flow_management_690.exp_flow_management_690_1:flow_management_691.bgroup_flow_management_691:flow_management_692.agroup_flow_management_692:flow_management_693.agroup_flow_management_693:hourday.hourday0512:mixCateGradeUseNewRecallAb.exp_mixCateGradeUseNewRecallAb:rank_root.base_rankroot0630:segment.base_segment_0412_aa1:sortstrategy.base_sortstrategy_0407_base:zzbrank.rank0702","session":"C2D3902C0C0FBxxxxxxxC0B28C8B"}
pagesize 20
recModelAB 1
searcfilterhmove2zzsearch 1
search_9_0_0 B
searchStandardPropertiesAB B
keyword iphone15promax
searchfrom 116
changeIntention 0
usePgParam 1
zzreqsign定位
request = addHeader.addHeader(SignUtil.SING_KEY_SIGN, str3).addHeader(SignUtil.SING_KEY_TIME, str5).addHeader("zzht", "a_15").build();
zzreqsign分析
Pair<String, String> sign = SignUtil.getSign(linkedHashMap);# 跟進 getSign
String sortParams = getSortParams(map); // 猜測排序
String sign = TextUtils.isEmpty(sortParams) ? null : getSign(sortParams, c0.getContext()); // 最終
# 跟進getSignstatic {System.loadLibrary("signLib");}
public static native String getSign(String str, Context context);
入參一b2cInfoCardAB%3DBchangeIntention%3D0extendParams%3D%7B%22sessionId%22%3A%22V25103bBq%22%7DfilterModuleServerParamsInput%3D%7B%22clickItems%22%3A%7B%22st7%22%3A%5B%7B%22cmd%22%3A%22sortpolicy%5Cu003d0%22%2C%22selectType%22%3A%220%22%2C%22style%22%3A%22320%22%2C%22value%22%3A%22sp00%22%7D%5D%7D%2C%22tab%22%3A%220%22%2C%22keyword%22%3A%22iphone15promax%22%2C%22filterModuleParam%22%3A%7B%22version%22%3A%221.8.0%22%2C%22appType%22%3A%221%22%7D%2C%22searchScene%22%3A%221%22%2C%22scene%22%3A%221%22%7Dkeyword%3Diphone15promaxpageIdParams%3D%7B%22refpagequery%22%3A%22from%5Cu003d14%22%2C%22refpagetype%22%3A%22V1008%22%7Dpagenum%3D2pagesize%3D20pushcode%3D3recModelAB%3D1requestmark%3D1752140437494searcfilterhmove2zzsearch%3D1searchAccurateFilterAB%3D2searchPageSource%3D14searchStandardPropertiesAB%3DBsearch_9_0_0%3DBsearchfrom%3D3sessionStr%3D%7B%22abtest%22%3A%22brandSeriesHightlightsAb.exp_brandSeriesHightlights0620%3Acvr.base_cvr0630%3Afeedwords.base_feedwords_0407_aa1%3Aflow_management_632.agroup_flow_management_632%3Aflow_management_682.cgroup_flow_management_682%3Aflow_management_690.exp_flow_management_690_1%3Aflow_management_691.bgroup_flow_management_691%3Aflow_management_692.agroup_flow_management_692%3Aflow_management_693.agroup_flow_management_693%3Ahourday.hourday0512%3AmixCateGradeUseNewRecallAb.exp_mixCateGradeUseNewRecallAb%3Arank_root.base_rankroot0630%3Asegment.base_segment_0412_aa1%3Asortstrategy.base_sortstrategy_0407_base%3Azzbrank.rank0702%22%2C%22session%22%3A%22C2D3902C0xxxADFE9E57EC0B28C8B%22%7DtabId%3D0usePgParam%3D1zzReqT%3D1752140445346zztk%3D, 入參二 context=com.wuba.zhuanzhuan.ApplicationWrapper@9b17ae0返回值 7c22a35599dbc85c46ce1da93e9733f6# ida打開 靜態注冊
Java_com_zhuanzhuan_sign_SignUtil_getSign
int __fastcall Java_com_zhuanzhuan_sign_SignUtil_getSign(JNIEnv a1, jobject a2, jstring a3, int a4)
{const char *app_sign_sha1; // r0int v9; // r8signed int v10; // r5int DevID; // r0int v12; // r8int v13; // r9int v14; // r6int v15; // r10_BYTE *v16; // r8signed int i; // r11char v18; // r4int v19; // r1JNIEnv v20; // r4int v21; // r9int MD5; // r10int v26; // [sp+8h] [bp-30h]int v27; // [sp+Ch] [bp-2Ch]int v28; // [sp+10h] [bp-28h]JNIEnv v29; // [sp+14h] [bp-24h]int v30; // [sp+18h] [bp-20h]if ( !a3 )return 0;app_sign_sha1 = get_app_sign_sha1(a1, a4);if ( !app_sign_sha1 )return 0;if ( strcmp(app_sign_sha1, app_sing_str) )return 0;v9 = toBytes(a1, a3); // 字符串 encode utf-8v10 = (*(a1->reserved0 + 171))(a1, v9);v30 = (*(a1->reserved0 + 184))(a1, v9, 0, *(a1->reserved0 + 184), a2, a3, a4);DevID = getDevID(a1, a2); // 固定值 C2D3902C0C0FBFExxxxx9E57EC0B28C8Bif ( !DevID )return 0;v28 = v9;v26 = DevID;v12 = toBytes(a1, DevID); // C2D3902C0C0FBxxxxFE9E57EC0B28C8B encode utf-8v13 = 0;v14 = (*(a1->reserved0 + 184))(a1, v12, 0);v29 = a1;v27 = v12;v15 = (*(a1->reserved0 + 171))(a1, v12);v16 = malloc(v10); // 異或for ( i = 0; i < v10; ++i ){v18 = *(v30 + v13 % v10);v19 = (v13 + 1) % v15;v13 += 2;v16[i] = *(v14 + v19) ^ v18;}v20 = v29;v21 = (*(v29->reserved0 + 176))(v29, v10 + 9);(*(v20->reserved0 + 208))(v20, v21, 0, v10, v16);(*(v20->reserved0 + 208))(v20, v21, v10, 9, "smiletozz");// 拼接到最后smiletozzMD5 = getMD5(v29, v21); // 最終結果(*(v20->reserved0 + 23))(v20, v21);free(v16);(*(v20->reserved0 + 23))(v20, v26);(*(v20->reserved0 + 192))(v20, v27, v14, 0);(*(v20->reserved0 + 192))(v20, v28, v30, 0);(*(v20->reserved0 + 23))(v20, v27);(*(v20->reserved0 + 23))(v20, v28);return MD5;
}
Python直接還原和app簽名一致
帶入代碼請求測試通過