今天分析的app是 6Jyc6Zuq5Yaw5Z+OXzIuMi42
抓包
很明显的有一个sign字段
反编译
由于新版本有360壳,此处使用旧版本2.2.6
打开jeb反编译 全局搜索sign
可以定位到
定位到 d.a可以得到
package com.mxbc.mxsa.network.feima;
import android.text.TextUtils;
import android.util.Base64;
import com.alibaba.fastjson.a;
import com.meituan.robust.ChangeQuickRedirect;
import com.meituan.robust.PatchProxy;
import com.meituan.robust.PatchProxyResult;
import com.mxbc.mxsa.base.service.common.SerializableService;
import com.mxbc.mxsa.base.utils.s;
import com.mxbc.mxsa.network.c;
import com.mxbc.mxsa.network.f;
import com.mxbc.service.e;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;
public class d {
private static String a = "";
private static String b = "";
private static String c = "";
public static ChangeQuickRedirect changeQuickRedirect;
static {
}
private static String a() {
PatchProxyResult patchProxyResult0 = PatchProxy.proxy(new Object[0], null, d.changeQuickRedirect, true, 0x10A2, new Class[0], String.class);
if(patchProxyResult0.isSupported) {
return (String)patchProxyResult0.result;
}
if(c.a()) {
d.b = (String)((SerializableService)e.a(SerializableService.class)).deserializeBase64(f.a(true));
return "";
}
d.a = (String)((SerializableService)e.a(SerializableService.class)).deserializeBase64(f.a(false));
return "";
}
public static String a(String s) {
PatchProxyResult patchProxyResult0 = PatchProxy.proxy(new Object[]{s}, null, d.changeQuickRedirect, true, 0x10A3, new Class[]{String.class}, String.class);
if(patchProxyResult0.isSupported) {
return (String)patchProxyResult0.result;
}
try {
PKCS8EncodedKeySpec pKCS8EncodedKeySpec0 = new PKCS8EncodedKeySpec(Base64.decode(d.a(), 2));
PrivateKey privateKey0 = KeyFactory.getInstance("RSA").generatePrivate(pKCS8EncodedKeySpec0);
Signature signature0 = Signature.getInstance("SHA256withRSA");
signature0.initSign(privateKey0);
signature0.update(s.getBytes());
return Base64.encodeToString(signature0.sign(), 2);
}
catch(Exception exception0) {
exception0.printStackTrace();
return "";
}
}
public static String a(Map map0) {
PatchProxyResult patchProxyResult0 = PatchProxy.proxy(new Object[]{map0}, null, d.changeQuickRedirect, true, 4260, new Class[]{Map.class}, String.class);
if(patchProxyResult0.isSupported) {
return (String)patchProxyResult0.result;
}
HashMap hashMap0 = new HashMap(map0);
TreeSet treeSet0 = new TreeSet(hashMap0.keySet());
StringBuilder stringBuilder0 = new StringBuilder();
for(Object object0: treeSet0) {
String s = (String)object0;
Object object1 = hashMap0.get(s);
String s1 = ((object1 instanceof Byte)) || ((object1 instanceof Short)) || ((object1 instanceof Integer)) || ((object1 instanceof Long)) || ((object1 instanceof Float)) || ((object1 instanceof Double)) || ((object1 instanceof Boolean)) || ((object1 instanceof Character)) || ((object1 instanceof String)) ? String.valueOf(object1) : a.toJSONString(hashMap0.get(s));
if(TextUtils.isEmpty(s1)) {
continue;
}
stringBuilder0.append(s);
stringBuilder0.append('=');
stringBuilder0.append(s1);
stringBuilder0.append('&');
}
if(stringBuilder0.length() > 0) {
stringBuilder0.deleteCharAt(stringBuilder0.length() - 1);
}
if(com.mxbc.mxsa.base.utils.e.a().b()) {
s.d("NetRequest", stringBuilder0.toString());
}
return d.b(stringBuilder0.toString()).replace("\n", "").replace("\r", "");
}
private static String b(String s) {
PatchProxyResult patchProxyResult0 = PatchProxy.proxy(new Object[]{s}, null, d.changeQuickRedirect, true, 0x10A5, new Class[]{String.class}, String.class);
if(patchProxyResult0.isSupported) {
return (String)patchProxyResult0.result;
}
try {
d.c = (String)((SerializableService)e.a(SerializableService.class)).deserializeBase64(f.b(false));
PKCS8EncodedKeySpec pKCS8EncodedKeySpec0 = new PKCS8EncodedKeySpec(Base64.decode("", 2));
PrivateKey privateKey0 = KeyFactory.getInstance("RSA").generatePrivate(pKCS8EncodedKeySpec0);
Signature signature0 = Signature.getInstance("SHA256withRSA");
signature0.initSign(privateKey0);
signature0.update(s.getBytes());
return Base64.encodeToString(signature0.sign(), 8);
}
catch(Exception exception0) {
exception0.printStackTrace();
return "";
}
}
}
大概意思就是通过a将传入的参数序列化组成字符串再用b进行SHA256withRSA加密,最后再用base64编码一下
objection动态调试
objection -g com.wudaokou.hippo explore
android hooking watch class_method com.mxbc.mxsa.network.feima.d.b --dump-args --d
ump-return --dump-backtrace
很明显是相同的
进一步hook
android hooking watch class_method android.util.Base64.decode --dump-args --dump-r
eturn --dump-backtrace
整合下代码
import base64
import time
import requests
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
def sign(str):
private_key_pem = """-----BEGIN PRIVATE KEY-----
xxxxxxxxxxxxxxxxxx
-----END PRIVATE KEY-----"""
# 直接加载PEM格式的私钥
private_key = serialization.load_pem_private_key(
private_key_pem.encode('utf-8'), # 将字符串转换为字节
password=None, # 私钥未加密,不需要密码
backend=default_backend()
)
signature = private_key.sign(
str.encode('utf-8'),
padding.PKCS1v15(),
hashes.SHA256()
)
return base64.b64encode(signature).decode().replace("/", "_").replace("+", "-")
def create_str_before_sign(e):
# 获取字典的键,并按照字母顺序排序
sorted_keys = sorted(e.keys())
# 构建最终的查询字符串
result = ""
for n, key in enumerate(sorted_keys):
# 检查值是否存在,或者是否为0
if e[key] or e[key] == 0:
# 如果不是第一个键值对,前面加上 & 符号
result += ("&" if n > 0 else "") + f"{key}={e[key]}"
return result.replace("'", '"').replace(" ", "")
if __name__ == "__main__":
url = "https://mxsa.mxbc.net/api/v1/adinfo/list"
t = int(time.time() * 1000)
json_data = {
"areaId": "",
"t": t,
# "t": 1725575959740,
"appId": "ba660596c1d911ebabac005056883e3e",
"adPlaceCodeList": [
"HomeFloatBanner", "HomeMagnet"
]
}
print(create_str_before_sign(json_data))
json_data["sign"] = sign(create_str_before_sign(json_data))
print(json_data)
headers = {
'User-Agent': "okhttp/4.4.1",
'Connection': "Keep-Alive",
'Accept-Encoding': "gzip",
'app': "mxbc",
'appchannel': "huawei",
'appversion': "2.2.6",
'Access-Token': "",
'Content-Type': "application/json; charset=UTF-8"
}
response = requests.post(url, json=json_data, headers=headers)
print(response.json())
Comments NOTHING