先charles抓包,api.xxxxxx.com域名的包
分析包 看到路径参数如下
appkey=1d8b6e7d45233436&build=5531000&channel=dw056&mobi_app=android&mode=0&oid=326052200&plat=2&platform=android&ps=20&statistics=%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%225.53.1%22%2C%22abtest%22%3A%22%22%7D&ts=1705305495&type=1&sign=2c9086d4acc853a017ec087699902634
可以看到一个sign,是个32字符,128位,直觉告诉我可能是个md5签名
然后用jadx打开xxx.apk包,全局搜索sign字符串,在众多函数方法中,找到一个SignedQuery函数,跟进去看,发现又个loadLibrary(xxx),那么直接告诉我是在一个so里
用apktool把xxx.apk decode出来,拿到libxxx.so
用ida打开该libxxx.so,直接看JNI_OnLoad函数,找到这一行
if ( (*v5)->RegisterNatives(v5, v4, (const JNINativeMethod *)®ister_native_struct, 5) < 0
register_native_struct跟进去
每个函数进去看下,有惊喜,确实是个md5算法,找到 md5_impl,跟进去看看算法参数
分析代码,发现关键在 check_app_key_get_type和global_key,一个是app key获取type,还有一个存着类似于secret key的 global key
整体看下来,结论就是 md5加密,按参数字典序排序,然后拼接SecretKey,再md5得到sign,取其中一个type来验证下:
和app请求生成的sign一样,secret key打码,如果想要,可以按步骤自己去试试,实测成功,关键地方都写清楚了
最后,写个python脚本试试,确实都能访问,这里脚本就不放了,求赞求加精,求账号升级,感谢
int
__fastcall md5_impl(JNIEnv
*
a1, jobject (
*
a2)(JNIEnv
*
, jclass, jmethodID, ...))
{
JNIEnv
*
v2;
/
/
r11
jobject (
*
v3)(JNIEnv
*
, jclass, jmethodID, ...);
/
/
r6
const char
*
v4;
/
/
r2
const char
*
v5;
/
/
r1
int
result;
/
/
r0
int
v7;
/
/
r0
JNIEnv v8;
/
/
r1
int
v9;
/
/
r0
int
v10;
/
/
r4
int
v11;
/
/
r0
int
v12;
/
/
r10
signed
int
v13;
/
/
r9
int
v14;
/
/
r5
int
v15;
/
/
r8
time_t v16;
/
/
r0
int
v17;
/
/
r6
int
v18;
/
/
r5
const char
*
input_str;
/
/
r8
_DWORD
*
v20;
/
/
r10
int
v21;
/
/
r4
_DWORD
*
v22;
/
/
r0
int
v23;
/
/
r1
int
v24;
/
/
r2
int
v25;
/
/
r0
unsigned
int
input_len;
/
/
r5
signed
int
v27;
/
/
r4
char
*
v28;
/
/
r5
int
v29;
/
/
r4
const char
*
v30;
/
/
[sp
+
8h
] [bp
-
C0h]
int
v31;
/
/
[sp
+
8h
] [bp
-
C0h]
int
v32;
/
/
[sp
+
Ch] [bp
-
BCh]
char v33;
/
/
[sp
+
10h
] [bp
-
B8h]
int
s;
/
/
[sp
+
38h
] [bp
-
90h
]
int
v35;
/
/
[sp
+
3Ch
] [bp
-
8Ch
]
int
v36;
/
/
[sp
+
40h
] [bp
-
88h
]
int
v37;
/
/
[sp
+
44h
] [bp
-
84h
]
char v38[
24
];
/
/
[sp
+
90h
] [bp
-
38h
]
int
v39;
/
/
[sp
+
A8h] [bp
-
20h
]
v2
=
a1;
v3
=
a2;
if
( !sub_2D20((
int
)a1) )
goto LABEL_5;
v4
=
"com.xxxxxxxx.nativelibrary.SignedQuery"
;
v5
=
"java/lang/ClassNotFoundException"
;
LABEL_3:
sub_401C((
int
)v2, (
int
)v5, (
int
)v4);
result
=
0
;
while
( _stack_chk_guard !
=
v39 )
{
LABEL_5:
if
( !v3 )
{
v5
=
"java/lang/NullPointerException"
;
v4
=
"Null params!"
;
goto LABEL_3;
}
v7
=
is_empty(v2, (
int
)v3);
v8
=
*
v2;
if
( v7 )
{
v3
=
v8
-
>NewObject;
result
=
((
int
(__fastcall
*
)(JNIEnv
*
,
int
,
int
, _DWORD, _DWORD))v3)(
v2,
cls_signed_query,
signed_query_init,
0
,
0
);
}
else
{
v9
=
((
int
(__fastcall
*
)(JNIEnv
*
, const char
*
))v8
-
>NewStringUTF)(v2,
"appkey"
);
v10
=
v9;
v11
=
sub_60CC(v2, (
int
)v3, v9);
/
/
/
/
校验appkey
v12
=
v11;
if
( v11 )
{
v30
=
(const char
*
)((
int
(__fastcall
*
)(JNIEnv
*
,
int
, _DWORD))(
*
v2)
-
>GetStringUTFChars)(v2, v11,
0
);
v13
=
check_app_key_get_type(v30);
}
else
{
v13
=
-
1
;
v30
=
0
;
}
v14
=
((
int
(__fastcall
*
)(JNIEnv
*
, const char
*
))(
*
v2)
-
>NewStringUTF)(v2,
"ts"
);
v15
=
sub_60CC(v2, (
int
)v3, v14);
if
( !v15 )
{
v36
=
0
;
v37
=
0
;
s
=
0
;
v35
=
0
;
v16
=
time(
0
);
sprintf((char
*
)&s,
"%ld"
, v16);
((void (__fastcall
*
)(JNIEnv
*
,
int
*
))(
*
v2)
-
>NewStringUTF)(v2, &s);
sub_6188((
int
)v2);
}
sub_41D0(v2, v14);
sub_41D0(v2, v15);
v17
=
((
int
(__fastcall
*
)(JNIEnv
*
,
int
,
int
, jobject (
*
)(JNIEnv
*
, jclass, jmethodID, ...)))(
*
v2)
-
>CallStaticObjectMethod)(
v2,
cls_signed_query,
method_signed_query_r,
v3);
v18
=
0
;
if
( sub_3F70((
int
)v2) )
v17
=
0
;
v32
=
v17;
input_str
=
(const char
*
)((
int
(__fastcall
*
)(JNIEnv
*
,
int
, _DWORD))(
*
v2)
-
>GetStringUTFChars)(v2, v17,
0
);
if
( v13 !
=
-
1
)
{
((void (__fastcall
*
)(JNIEnv
*
,
int
, const char
*
))(
*
v2)
-
>ReleaseStringUTFChars)(v2, v12, v30);
v20
=
malloc(
0x10u
);
if
( v20 )
{
v31
=
v10;
v21
=
global_key[v13];
v22
=
&global_key[v13];
v23
=
v22[
5
];
v24
=
v22[
10
];
v25
=
v22[
15
];
*
v20
=
v21;
v20[
1
]
=
v23;
v20[
2
]
=
v24;
v20[
3
]
=
v25;
_aeabi_memclr8(&v33,
33
);
input_len
=
strlen(input_str);
_aeabi_memclr8(v38,
24
);
_aeabi_memclr8(&s,
88
);
md5_init(&s);
md5_update((
int
)&s, (
int
)input_str, input_len);
sprintf(v38,
"%08x"
, v21);
md5_update((
int
)&s, (
int
)v38,
8u
);
v27
=
1
;
do
{
sprintf(v38,
"%08x"
, v20[v27]);
md5_update((
int
)&s, (
int
)v38,
8u
);
+
+
v27;
}
while
( v27 !
=
4
);
md5_final((
int
)v38, (
int
)&s);
v28
=
&v33;
v29
=
0
;
do
{
sprintf(v28,
"%02x"
, (unsigned __int8)v38[v29
+
+
]);
v28
+
=
2
;
}
while
( v29 !
=
16
);
free(v20);
v10
=
v31;
v18
=
((
int
(__fastcall
*
)(JNIEnv
*
, char
*
))(
*
v2)
-
>NewStringUTF)(v2, &v33);
}
else
{
v18
=
0
;
}
}
sub_41D0(v2, v10);
v3
=
(
*
v2)
-
>NewObject;
result
=
((
int
(__fastcall
*
)(JNIEnv
*
,
int
,
int
,
int
,
int
))v3)(v2, cls_signed_query, signed_query_init, v32, v18);
}
}
return
result;}
int
__fastcall md5_impl(JNIEnv
*
a1, jobject (
*
a2)(JNIEnv
*
, jclass, jmethodID, ...))
{
JNIEnv
*
v2;
/
/
r11
jobject (
*
v3)(JNIEnv
*
, jclass, jmethodID, ...);
/
/
r6
const char
*
v4;
/
/
r2
const char
*
v5;
/
/
r1
int
result;
/
/
r0
int
v7;
/
/
r0
JNIEnv v8;
/
/
r1
int
v9;
/
/
r0
int
v10;
/
/
r4
int
v11;
/
/
r0
int
v12;
/
/
r10
signed
int
v13;
/
/
r9
int
v14;
/
/
r5
int
v15;
/
/
r8
time_t v16;
/
/
r0
int
v17;
/
/
r6
int
v18;
/
/
r5
const char
*
input_str;
/
/
r8
_DWORD
*
v20;
/
/
r10
int
v21;
/
/
r4
_DWORD
*
v22;
/
/
r0
int
v23;
/
/
r1
int
v24;
/
/
r2
int
v25;
/
/
r0
unsigned
int
input_len;
/
/
r5
signed
int
v27;
/
/
r4
char
*
v28;
/
/
r5
int
v29;
/
/
r4
const char
*
v30;
/
/
[sp
+
8h
] [bp
-
C0h]
int
v31;
/
/
[sp
+
8h
] [bp
-
C0h]
int
v32;
/
/
[sp
+
Ch] [bp
-
BCh]
char v33;
/
/
[sp
+
10h
] [bp
-
B8h]
int
s;
/
/
[sp
+
38h
] [bp
-
90h
]
int
v35;
/
/
[sp
+
3Ch
] [bp
-
8Ch
]
int
v36;
/
/
[sp
+
40h
] [bp
-
88h
]
int
v37;
/
/
[sp
+
44h
] [bp
-
84h
]
char v38[
24
];
/
/
[sp
+
90h
] [bp
-
38h
]
int
v39;
/
/
[sp
+
A8h] [bp
-
20h
]
v2
=
a1;
v3
=
a2;
if
( !sub_2D20((
int
)a1) )
goto LABEL_5;
v4
=
"com.xxxxxxxx.nativelibrary.SignedQuery"
;
v5
=
"java/lang/ClassNotFoundException"
;
LABEL_3:
sub_401C((
int
)v2, (
int
)v5, (
int
)v4);
result
=
0
;
while
( _stack_chk_guard !
=
v39 )
{
LABEL_5:
if
( !v3 )
{
v5
=
"java/lang/NullPointerException"
;
v4
=
"Null params!"
;
goto LABEL_3;
}
v7
=
is_empty(v2, (
int
)v3);
v8
=
*
v2;
if
( v7 )
{
v3
=
v8
-
>NewObject;
result
=
((
int
(__fastcall
*
)(JNIEnv
*
,
int
,
int
, _DWORD, _DWORD))v3)(
v2,
cls_signed_query,
signed_query_init,
0
,
0
);
}
else
{
v9
=
((
int
(__fastcall
*
)(JNIEnv
*
, const char
*
))v8
-
>NewStringUTF)(v2,
"appkey"
);
v10
=
v9;
v11
=
sub_60CC(v2, (
int
)v3, v9);
/
/
/
/
校验appkey
v12
=
v11;
if
( v11 )
{
v30
=
(const char
*
)((
int
(__fastcall
*
)(JNIEnv
*
,
int
, _DWORD))(
*
v2)
-
>GetStringUTFChars)(v2, v11,
0
);
v13
=
check_app_key_get_type(v30);
}
else
{
v13
=
-
1
;
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2024-1-16 17:33
被mb_qjzbupqg编辑
,原因: 标题重复