日期:
来源:看雪学苑收集编辑:行简
本文为看雪论坛优秀文章
看雪论坛作者ID:行简
一
Kit
设备:K40 刷 piexl 11 rom
抓包工具:Charles
反汇编工具:JEB、JADX、IDA
inject:frida
二
抓包
POST /v1/api/app/login/doLogin HTTP/1.1X-OsVersion: 30User-Agent: Mozilla/5.0 (Linux; Android 11; M2012K11AC Build/RQ3A.211001.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 CSDNApp/5.0.0(Android)wToken/0.0.1X-RandomNum: 54736X-Access-Token: 00871d5df0d4f51efb5883b3b2fd2359platform: androidX-Ca-Signature-Headers: X-Ca-Timestamp,X-Ca-Key,X-Ca-NonceAuthorization:X-OS: Androidc_appVersion: 5.0.0X-App-ID: CSDN-APPX-App-Theme: daycontent-type: application/json; charset=UTF-8X-Ca-Signature: BqhPpXbobBOndykiyCtOVK06GHLkfLbs1y4B3Ek0gnY=X-ConnectionType: WIFIUserToken:X-TimeStamp: 1671939318488Cookie: UserName=;UserToken=X-Ca-Key: 203789067Accept: application/jsonX-Device-ID: aid0f0fef992b53479187546b3c621157f0wToken: e447_5rU5WWYQegPo5EMOZSnKzF4YPtJSetwo+lGrEUrtZaKEe73GkiTOoE83PLp0yivsi4pZV7HySc+lbsebppMqHlXmQwVLx0vrlQpYC0b99vOYBRZWnVbeMhLZ4WUuAAKH/V07WkNSNXORUsgHumLj1BZZ7x1riK8beahdp9ctmSwP3AdA/sZA4OkzEVF4rJ+G6nwyyGcI/JLoRH0/1hPUT91sdBKKA64yj1QKRAZuJjsX9WRcqo9xYgfcJDnpqVnhObGQD96CfSok8z8d9otv+Fl6ULZrddvcnvzs6cJhjuW3ryBn151Xat/2CU/9EXUEKG3e0g4/K9rEaDRb2JhDGEDwIj+Qd5RU1uaBKxS/7jlSVq8wQ7x3qVVN1tHqS4AXhVow6eMABT6PArcEfkFm42bwXOFWsAUd5C7uGvHGIlTGytU6Vx/CJPwPvCuSffef5mQL7daszEzN+zQJ9VjxgOrjKXkDVkt6O6UpyA+1u3lowOqUaSPK6u2vND/Xqus7&ff4b_85475962D8E15A4E7AE60ED42FF3568E8EDB86EE620E495591X-DeviceModel: Redmi M2012K11ACversion: 5.0.0X-Ca-Nonce: be0eca5c-e959-4b0f-b4e7-22e00118157eX-Ca-Timestamp: 1671939318489X-Sign: 70B21B02FD0EFD2353F0D7F4F2E7CDB6FC1C3C42Host: passport.csdn.netConnection: Keep-AliveAccept-Encoding: gzipContent-Length: 95{"pwdOrVerifyCode":"123456","loginType":"1","userIdentification":"17750659921","checkAli":true}
X-Sign、wToken、X-Ca-Signature、X-Access-Token、X-Ca-Timestamp三
分析
跟进得:
public static Map<String, String> z(String url, Map<String, String> requestMap) {String str;String a2 = wo3.a(CSDNApp.csdnApp);HashMap hashMap = new HashMap();hashMap.put("platform", "android");hashMap.put("version", xn3.u());hashMap.put("c_appVersion", xn3.u());if (!TextUtils.isEmpty(it3.g())) {hashMap.put("JWT-TOKEN", it3.g());no3.a("==JWT-TOKEN==", it3.g());}hashMap.put("Authorization", StringUtils.isEmpty(it3.g()) ? "" : "Bearer " + it3.g());hashMap.put("X-Device-ID", a2);hashMap.put("X-OS", "Android");hashMap.put("X-App-ID", "CSDN-APP");hashMap.put("X-Access-Token", MD5.md5(a2 + "AndroidCSDN-APPb85fF96d-7Aa4-4Ec1-bf1D-2133c1A45656"));hashMap.put("X-OsVersion", Build.VERSION.SDK_INT + "");String str2 = Build.BRAND + Operators.SPACE_STR + Build.MODEL;int length = str2.length();for (int i = 0; i < length; i++) {char charAt = str2.charAt(i);if ((charAt <= 31 && charAt != '\t') || charAt >= 127) {str2.replace(charAt, ' ');}}hashMap.put("X-DeviceModel", str2);hashMap.put("X-ConnectionType", yp3.b(CSDNApp.csdnApp));hashMap.put("UserToken", StringUtils.isEmpty(it3.q()) ? "" : it3.q());hashMap.put("X-App-Theme", CSDNApp.isDayMode ? "day" : "night");int c2 = xn3.c(10000, 99999);String str3 = new Date().getTime() + "";try {str = mq3.a(a2 + c2 + str3 + zf1.o);} catch (DigestException e2) {e2.printStackTrace();str = "";}hashMap.put("X-Sign", str);hashMap.put("X-RandomNum", c2 + "");hashMap.put("X-TimeStamp", str3);StringBuilder sb = new StringBuilder();sb.append("UserName=");sb.append(it3.p());sb.append(";UserToken=");sb.append(StringUtils.isEmpty(it3.q()) ? "" : it3.q());hashMap.put(IWebview.COOKIE, sb.toString());if (!StringUtils.isEmpty(url) && requestMap != null && requestMap.containsKey("category")) {hashMap.put("X-PageKey", "blog." + requestMap.get("category"));hashMap.put("X-Path", "app.csdn.net/blog/" + requestMap.get("category"));}if (!StringUtils.isEmpty(url) && url.equals(s22.G0)) {hashMap.put("X-PageKey", vr3.Q6);hashMap.put("X-Path", "app.csdn.net/blog/detail");if (requestMap != null && requestMap.containsKey("from")) {hashMap.put("X-Referer", "blog." + requestMap.get("from"));}}hashMap.put("User-Agent", CSDNApp.csdnApp.userAgent + " CSDNApp/" + xn3.u() + "(Android)wToken/0.0.1");try {hashMap.put("wToken", TigerTallyAPI.vmpSign(1, str3.getBytes("UTF-8")));} catch (UnsupportedEncodingException e3) {e3.printStackTrace();}return hashMap;}
hashMap.put("platform", "android"); // 固定值hashMap.put("version", xn3.u()); // 固定值hashMap.put("c_appVersion", xn3.u()); // 固定值hashMap.put("Authorization", StringUtils.isEmpty(it3.g()) ? "" : "Bearer " + it3.g()); // 无用,请求头中为空hashMap.put("X-Device-ID", a2); // a2 在 String a2 = wo3.a(CSDNApp.csdnApp);
function main() {Java.perform(function () {var wo3 = Java.use("wo3");wo3["a"].implementation = function (context) {console.log('a is called' + ', ' + 'context: ' + context);var ret = this.a(context);console.log('a ret value is ' + ret);return ret;};});}setImmediate(main)
a is called, context: net.csdn.csdnplus.CSDNApp@dc96acba ret value is aid0f0fef992b53479187546b3c621157f0
hashMap.put("X-OS", "Android"); // 固定值hashMap.put("X-App-ID", "CSDN-APP"); // 固定值hashMap.put("X-Access-Token", MD5.md5(a2 + "AndroidCSDN-APPb85fF96d-7Aa4-4Ec1-bf1D-2133c1A45656")); // a2 就是上面的 X-Device-ID 再进行加盐处理后进行 MD5 加密复现一下:
from hashlib import md5def encrypt_md5(mes):new_md5 = md5()# 这里必须用encode()函数对字符串进行编码,不然会报 TypeError: Unicode-objects must be encoded before hashingnew_md5.update(mes.encode(encoding='utf-8'))# 加密return new_md5.hexdigest()if __name__ == '__main__':print(encrypt_md5('aid0f0fef992b53479187546b3c621157f0AndroidCSDN-APPb85fF96d-7Aa4-4Ec1-bf1D-2133c1A45656'))
hashMap.put("X-OsVersion", Build.VERSION.SDK_INT + ""); // sdk 版本吧,可随机的样子hashMap.put("X-DeviceModel", str2); // 通过上面获取来的,分析一下就是手机 + 手机名称hashMap.put("X-ConnectionType", yp3.b(CSDNApp.csdnApp)); // 网络连接类型hashMap.put("UserToken", StringUtils.isEmpty(it3.q()) ? "" : it3.q()); // 抓包为空值,放弃hashMap.put("X-App-Theme", CSDNApp.isDayMode ? "day" : "night"); // 主题模式hashMap.put("X-Sign", str);
int c2 = xn3.c(10000, 99999);String str3 = new Date().getTime() + "";try {str = mq3.a(a2 + c2 + str3 + zf1.o);} catch (DigestException e2) {e2.printStackTrace();str = "";}hashMap.put("X-Sign", str);
c2:10000 - 99999 之间的随机值;str3:时间戳转字符串;a2:上面分析过为 X-Device-ID 值;zf1.o:跟进查看为定值:public static final String o = "F403F982CA92F73AC142D50FFA69853D";
public static String a(String decrypt) throws DigestException {try {MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");messageDigest.update(decrypt.getBytes());byte[] digest = messageDigest.digest();StringBuffer stringBuffer = new StringBuffer();for (byte b : digest) {String hexString = Integer.toHexString(b & 255);if (hexString.length() < 2) {stringBuffer.append(0);}stringBuffer.append(hexString);}return stringBuffer.toString().toUpperCase();} catch (NoSuchAlgorithmException e) {e.printStackTrace();throw new DigestException("签名错误!");}}
function main() {Java.perform(function () {var mq3 = Java.use("mq3");mq3["a"].implementation = function (decrypt) {console.log('a is called' + ', ' + 'decrypt: \n' + decrypt);var ret = this.a(decrypt);console.log('a ret value is ' + ret);return ret;};});}setImmediate(main)// frida -FU -l CSDN/csdn.js
a is called, decrypt:aid0f0fef992b53479187546b3c621157f0709751671957807054F403F982CA92F73AC142D50FFA69853Da ret value is E11539C9183644EEB69C7FEBAC1D58A2D874895C
import hashlib# 使用sha1加密算法,返回str加密后的字符串def sha1_secret_str(s: str):sha = hashlib.sha1(s.encode('utf-8'))encrypts = sha.hexdigest()return encrypts.upper()if __name__ == '__main__':# 待加密的字符串s = 'aid0f0fef992b53479187546b3c621157f0709751671957807054F403F982CA92F73AC142D50FFA69853D'res = sha1_secret_str(s)print(res)
hashMap.put("X-RandomNum", c2 + ""); // 10000 - 99999 之间的随机值;hashMap.put("X-TimeStamp", str3); // str3:时间戳转字符串;hashMap.put(IWebview.COOKIE, sb.toString()); // 看抓包结果应该是 Cookie 值,对照结果 UserName=;UserToken= 啥操作没做,应该是要登录后才有值也是固定值hashMap.put("User-Agent", CSDNApp.csdnApp.userAgent + " CSDNApp/" + xn3.u() + "(Android)wToken/0.0.1");
// Mozilla/5.0 (Linux; Android 11; M2012K11AC Build/RQ3A.211001.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 CSDNApp/5.0.0(Android)wToken/0.0.1hashMap.put("wToken", TigerTallyAPI.vmpSign(1, str3.getBytes("UTF-8")));
private static native String _genericNt3(int i, byte[] bArr);private static Map<String, String> c(StringBuilder strBuilder, Map<String, String> headerParams) {if (ft3.b() != 1) {headerParams.put("X-Ca-Stage", ft3.b() == 2 ? "TEST" : "PRE");}try {Mac mac = Mac.getInstance("HmacSHA256");byte[] bytes = y12.c.getBytes("UTF-8");mac.init(new SecretKeySpec(bytes, 0, bytes.length, "HmacSHA256"));String str = new String(Base64.encodeBase64(mac.doFinal(strBuilder.toString().getBytes("UTF-8"))));headerParams.put("X-Ca-Signature", str);no3.a("==HmacSHA256==", str);} catch (UnsupportedEncodingException e2) {e2.printStackTrace();} catch (InvalidKeyException e3) {e3.printStackTrace();} catch (NoSuchAlgorithmException e4) {e4.printStackTrace();}return headerParams;}
public static final String c = "0u94vkvsewic9kkgsp1r3nuq3ir0lv3n";hook 看看要加密 strBuilder 有啥:function main() {Java.perform(function () {var r12 = Java.use("r12");r12["c"].implementation = function (strBuilder, headerParams) {console.log('strBuilder: \n' + strBuilder);var ret = this.c(strBuilder, headerParams);var keyset = ret.keySet();var result = "";var it = keyset.iterator();while (it.hasNext()) {var keystr = it.next().toString();var valuestr = ret.get(keystr).toString();console.log(keystr)console.log(valuestr)result += valuestr;}return ret;};});}setImmediate(main)// frida -FU -l CSDN/csdn.js
strBuilder:POSTapplication/jsonapplication/json; charset=UTF-8X-Ca-Key:203789067X-Ca-Nonce:3339aae3-e295-410c-8345-52c9ebc56b5aX-Ca-Timestamp:1671963564343/v1/api/app/login/doLogin
headerParams.put("X-Ca-Key", y12.b);public static final String b = "203789067";X-Ca-Nonce 为 UUID 值:headerParams.put("X-Ca-Nonce", UUID.randomUUID().toString());X-Ca-Timestamp 为时间戳。
from hashlib import sha256import hmac, base64def get_sign(data, key):key = key.encode('utf-8')message = data.encode('utf-8')sign = base64.b64encode(hmac.new(key, message, digestmod=sha256).digest()).decode()print(sign)return signif __name__ == '__main__':# 待加密的字符串s = "POST" + "\n" + \"application/json" + "\n" + \"\n" + \"application/json; charset=UTF-8" + "\n" + \"\n" + \"X-Ca-Key:203789067" + "\n" + \"X-Ca-Nonce:3339aae3-e295-410c-8345-52c9ebc56b5a" + "\n" + \"X-Ca-Timestamp:1671963564343" + "\n" + \"/v1/api/app/login/doLogin"k = '0u94vkvsewic9kkgsp1r3nuq3ir0lv3n'res = get_sign(s, k)print(res)
抓包结果:QJYeguZxkE+ZojwTP0rIJ+IzjaSHI82uR2y0xOIG35U=static {System.loadLibrary("tiger_tally");}
四
rpc 远程调用
var response = null;Java.enumerateClassLoaders({onMatch: function (loader) {try {if (loader.findClass("com.aliyun.TigerTally.TigerTallyAPI")) {Java.classFactory.loader = loader;response = Java.use("com.aliyun.TigerTally.TigerTallyAPI")} else {}} catch (error) {}}, onComplete: function () {}});function stringToByte (str) {var ch, st, re = [];for (var i = 0; i < str.length; i++ ) {ch = str.charCodeAt(i);st = [];do {st.push( ch & 0xFF );ch = ch >> 8;} while ( ch );re = re.concat(st.reverse());}return re;}function getwwoken(data){var result = response._genericNt3(1, stringToByte(data));return result;}rpc.exports = {getwtoken:getwwoken}
import timeimport hmacimport uuidimport randomimport base64from hashlib import sha256, md5, sha1def get_x_osversion():return "30"def get_x_os():return "android"def get_x_appid():return "CSDN_APP"def get_x_app_theme():return "day"def get_x_connection_type():return "WIFI"def get_x_timestramp():return str(int(time.time() * 1000))def get_x_device_model():return "Redmi M2012K11AC"def get_x_ca_Signature_Headers():return "X-Ca-Timestamp,X-Ca-Key,X-Ca-Nonce"def get_User_Agent():return "Mozilla/5.0 (Linux; Android 11; M2012K11AC Build/RQ3A.211001.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 CSDNApp/5.0.0(Android)wToken/0.0.1"def get_x_ca_nonce():return str(uuid.uuid4())def get_x_device_id():return "aid0f0fef992b53479187546b3c621157f0"def get_access_token():X_Access_Token = "aid0f0fef992b53479187546b3c621157f0AndroidCSDN-APPb85fF96d-7Aa4-4Ec1-bf1D-2133c1A45656"md5_mes = md5(X_Access_Token.encode())return md5_mes.hexdigest()x_timestramp = get_x_timestramp()x_ca_nonce = get_x_ca_nonce()def get_x_randomnum():return str(random.randint(10000, 99999))def get_x_ca_signature():data = "POST" + "\n" + \"application/json" + "\n" + \"\n" + \"application/json; charset=UTF-8" + "\n" + \"\n" + \"X-Ca-Key:203789067" + "\n" + \"X-Ca-Nonce:3339aae3-e295-410c-8345-52c9ebc56b5a" + "\n" + \"X-Ca-Timestamp:1671963564343" + "\n" + \"/v1/api/app/login/doLogin"key = "0u94vkvsewic9kkgsp1r3nuq3ir0lv3n".encode("utf-8")message = data.encode("utf-8")sign = base64.b64encode(hmac.new(key, message, digestmod=sha256).digest())return str(sign, 'utf-8'), x_timestramp, x_ca_noncedef get_xsign():xsign_mes = get_x_device_id() + get_x_randomnum() + x_timestramp + "F403F982CA92F73AC142D50FFA69853D"return sha1(xsign_mes.encode("utf-8")).hexdigest().upper()
import fridafrom login_env import *import requestsdef on_message(message, data):print("[%s] => %s" % (message, data))def inject_hook():session = frida.get_usb_device().attach('net.csdn.csdnplus')with open('CSDN/rpc.js', 'r') as f:js_code = f.read()script = session.create_script(js_code)script.on('message', on_message)script.load()return scriptdef message(message, data):if message["type"] == 'send':print("[*] {0}".format(message['payload']))else:print(message)def req():url = "https://passport.csdn.net/v1/api/app/login/doLogin"headers = {"X-OsVersion": "30","User-Agent": "Mozilla/5.0 (Linux; Android 11; M2012K11AC Build/RQ3A.211001.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/108.0.5359.128 Mobile Safari/537.36 CSDNApp/5.0.0(Android)wToken/0.0.1","X-RandomNum": get_x_randomnum(),"X-Access-Token": get_access_token(),"platform": "android","X-Ca-Signature-Headers": "X-Ca-Timestamp,X-Ca-Key,X-Ca-Nonce","Authorization": "","X-OS": "Android","c_appVersion": "5.0.0","X-App-ID": "CSDN-APP","X-App-Theme": "day","content-type": "application/json; charset=UTF-8","X-Ca-Signature": get_x_ca_signature()[0],"X-ConnectionType": "WIFI","UserToken": "","X-TimeStamp": get_x_ca_signature()[1],"X-Ca-Key": "203789067","Accept": "application/json","X-Device-ID": get_x_device_id(),"wToken": res,"X-DeviceModel": "Redmi M2012K11AC","version": "5.0.0","X-Ca-Nonce": get_x_ca_signature()[2],"X-Ca-Timestamp": get_x_ca_signature()[1],"X-Sign": get_xsign(),"Host": "passport.csdn.net","Connection": "Keep-Alive","Accept-Encoding": "gzip",}data = {"pwdOrVerifyCode":"123456","loginType":"1","userIdentification":"17750659921","checkAli":"true"}response = requests.post(url, headers=headers,json=data)print(response.text)if __name__ == '__main__':rpc_script = inject_hook()res = rpc_script.exports.getwtoken(get_x_ca_signature()[1])req()'''
{"message":"用户名或密码错误","status":false,"code":"1039"}看雪ID:行简
https://bbs.kanxue.com/homepage-945390.htm
# 往期推荐
2、Kernel PWN-开启smap保护的babydrive
球分享
球点赞
球在看
点击“阅读原文”,了解更多!