app逆向小试牛刀
app: 'aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzgxNzMwNTAvaGlzdG9yeV92Nzg=' (如果要更新就更到最新)
逆向接口:
'aHR0cHM6Ly9hcGkuYXBwLnhpYW9iYWl0ZWNoLmNuL2FwaS9zY2hJbmZvL2ZpbmRBbGxCeVRpbWU='

一,参数分析
我们使用Charlse抓包发现请求参数data是加密的,如下图

我们第一想到的就是hook Map的put方法,果然,我们在hook Map的put方法中发现data
[HashMap put]入参key: data入参val: A97lKxBc/GuJsRY7DZ9pnAqiLyQQIzZqisLkHzxixwhMLRc48iTVk2Vll5SxFtBLwUKhlUvbqF9cmndlaImn2rFPOQCpcCvpwlQwoJC7cc+4XJJMUujJCVTsAd6nmGxzGf1u/15Dkw+szVoy/6J5y4Gy...竟然能hook到,那么我们查看一下堆栈信息,下面是获取的堆栈信息
堆栈是:java.lang.Exception at java.util.HashMap.put(Native Method) at com.xbkaoyan.xschool.params.SchoolParams$Companion.schScreenNewsParams(SchoolParams.kt:102) at com.xbkaoyan.xschool.viewmodel.SchoolViewModel$homeSchNewsItem$1$1.load(SchoolViewModel.kt:408) at androidx.paging.PageFetcherSnapshot.doInitialLoad(PageFetcherSnapshot.kt:275) at androidx.paging.PageFetcherSnapshot.access$doInitialLoad ...我们很容易发现,data被put的前一个栈是com.xbkaoyan.xschool.params.SchoolParams$Companion.schScreenNewsParams
我们在jadx-gui中搜索com.xbkaoyan.xschool.params.SchoolParams$Companion 对象:

找到对象后在源码中搜索schScreenNewsParams方法:

最终我们发现密文是通过companion.rsaEncode(json)方法生成:

我们用frida hook companion.rsaEncode(json)方法发现
[Android Emulator 5554::小白考研 ]-> Companion.rsaEncode is called: str:::{"province":"11","_t":"1782210201809","pn":1}Companion.rsaEncode result:::cCs8L4rXbG5kRu3gngm9gHKgCc1Q1Muq33iBa+XBR3dO8W7DAR6U3L6BR8oI7JhNCnUZ/C6c9kv4...我们直接将companion.rsaEncode(json)方法代码丢给ai,要ai给我们生成python的加密代码
二,成果展示
import timeimport requestsimport jsonimport base64from cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives import serializationfrom cryptography.hazmat.primitives.asymmetric import paddingdef rsa_encode(raw_str: str) -> str:# 源码里固定公钥base64字符串 pub_key_b64 = """MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzNeplg5ePk1LrFBCvt7zTn1aNrXkKACNM/femFrR9FQ7sNktkqFacUiX7DbG2Vyp0bvkN7bDzHXyXnxYVA2mW/zaOvhRxRVElznm9KOO+/fYzRDsa0CxAj7hpxzkVo8Vb/XgcxkcxwDUM/JYEaJBBJ2VLl5+oP5w+3b7XJjSNCBAgpR2WItXlR32Xe2a1s6PgogFtoP0up3bDTZhinxOgSMVgpHwmj9EKaLjqCZGdP6I5Fqv59ogxPIYeKNb+BCkSXykHtip0TziNSIr7bQSA7QacFTYByCqLHthCr1ACNJSazVreDOBDyAS/PceOwGN6iiyx8U2mVPC8io1aVr1xwIDAQAB"""try:# 去除换行符,解码公钥二进制 pub_key_b64_clean = pub_key_b64.replace("\n", "") pub_key_bytes = base64.b64decode(pub_key_b64_clean)# 加载X509公钥 public_key = serialization.load_der_public_key( pub_key_bytes, backend=default_backend() )# RSA/ECB/PKCS1Padding 加密 data = raw_str.encode("utf-8") encrypted = public_key.encrypt( data, padding.PKCS1v15() )# base64编码返回字符串 result = base64.b64encode(encrypted).decode("utf-8")return resultexcept Exception as e:print(e)return ""headers = {"platform": "Android","model": "DLT-A0","brand": "blackshark","system": "PQ3B.190801.05072014","appVersion": "6.6.6","Content-Type": "application/json; charset=utf-8","Host": "api.app.xiaobaitech.cn","User-Agent": "okhttp/5.0.0-alpha.6"}url = "https://api.app.xiaobaitech.cn/api/schInfo/findAllByTime"for province in range(10,100): data = {"province": str(province),"_t": str(int(time.time()*1000)),"pn": 1 } data = {"data": rsa_encode(json.dumps(data, separators=(',', ':'))) } response = requests.post(url, headers=headers, data=json.dumps(data, separators=(',', ':')))print(response.json())三,附录
hook代码(最终版本)
function main() {Java.perform(function () {const HashMap = Java.use("java.util.HashMap");// 拦截putHashMap.put.implementation = function (k, v) {let res = this.put(k, v);if (k == "data") {console.log("\n[HashMap put]");console.log("入参key:", k);console.log("入参val:", v);console.log("堆栈是:")console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new())); }return res; }// hook rsaEncode(json)var Companion = Java.use("com.xbkaoyan.libcore.rsa.RSA$Companion");Companion["rsaEncode"].implementation = function (str) {console.log(`Companion.rsaEncode is called: str:::${str}`);let result = this["rsaEncode"](str);console.log(`Companion.rsaEncode result:::${result}`);return result; }; });}main()
夜雨聆风