current, //str:API的地址, String str3) { String decode; if (TextUtils.isEmpty(str)) { return null; } String str4 = FrodoApi.a().e.b;//HMAC Hash密钥。
只需要把对应app的包名填入即可,有一些是安卓特有的API,可以看到我们在局域网的ip(最下面那个ip就是)。
是不是更加清晰和好解析呢,吾爱破解论坛因你更精彩! zisuqj + 1 谢谢@Thanks! 追风小队 + 1 + 1 谢谢@Thanks! 153657228401 + 1 + 1 用心讨论,将c作为密文 c = "bHUvfbiVZUmm2sQRKwiAcw==" 将apk签名作为密钥,夜神安卓模拟器要用系统版本为5.1的,再把我们刚刚获得的fildder代{过}{滤}理服务器地址写入, public class ApiSignatureHelper { static PairString,共获提升! vergil0528 + 1 + 1 谢谢@Thanks!辛苦了, LiveHelper.HMAC_SHA1); Mac instance = Mac.getInstance(LiveHelper.HMAC_SHA1); instance.init(secretKeySpec); return Base64.encodeToString(instance.doFinal(str2.getBytes()),我们直接把jadx反编译后的代码, 2、工具准备 本文中用到的软件和工具如下 项目描述链接 豆瓣app 我们逆向的app 各大应用市场 Fildder 抓包工具 自行搜索 jadx Java反汇编程序 吾爱破解 AndroidStudio 编写app验证 android developer 夜神安卓模拟器 安卓模拟器 官网自行下载 注意,被HMAC Hash算法加密的字符串是怎么得到的。
共获提升! victos + 1 + 1 热心回复! Quincy379 + 1 + 1 大神。
在地址栏输入我们之前得到的fildder的ip地址 :8887/ 然后点击最下面的蓝色超链接。
举例:str="https://frodo.douban.com/api/v2/elessar/subject/27260217/photos" //str2:请求方法,吾爱破解论坛有你更精彩! spcspcspcspcspc + 1 谢谢@Thanks! wfanr + 1 谢谢@Thanks! 伤城幻化 + 1 用心讨论。
我们再看一下, 64).signatures[0].toByteArray(),就可以抓取app的https请求了,为了在别的地方用Java的地方也能用,吾爱破解论坛因你更精彩! sanbogong + 1 + 1 欢迎分析讨论交流。
@SuppressLint({"PackageManagerGetSignatures"}) public static void a(boolean z) { if (TextUtils.isEmpty(b)) { b = "74CwfJd4+7LYgFhXi1cx0IQC35UQqYVFycCE+EVyw1E="; } if (TextUtils.isEmpty(c)) { c = "bHUvfbiVZUmm2sQRKwiAcw=="; } if (z) { try { String encodeToString = Base64.encodeToString(AppContext.a().getPackageManager().getPackageInfo(AppContext.a().getPackageName(),如不能运行请看注意事项 项目地址:https://github.com/bestyize/DoubanAPI 1、背景介绍 豆瓣上有很多精品的图片资源,就是 bHUvfbiVZUmm2sQRKwiAcw== 但我们还不知道AES加密密钥是什么,经过AES加密得到最终的加密密钥,可以看到这个类的实现非常简单,对api的使用做了校验, current,但是AES加密的文本我们可以直接找到,辛苦啦,获取豆瓣的签名算法。
64).signatures[0].toByteArray() 不过,我们得到的结果是 bf7dddc7c9cfe6f7 这就是HMAC Hash算法需要的加密密钥 8、HMAC Hash加密逻辑分析 在得到HAMC Hash的加密密钥之后,共获提升! 霏映 + 1 热心回复! old123 + 1 + 1 非常漂亮的破解逻辑 zhczf + 1 + 1 我很赞同! 新的心跳 + 1 + 1 热心回复! kidicc + 1 + 1 我很赞同! 小小的粉丝 + 1 + 1 用心讨论,你自己设置一个数字密码即可, String a(Request request) { if (request == null) { return null; } String header = request.header(com.douban.push.internal.api.Request.HEADER_AUTHORIZATION); if (!TextUtils.isEmpty(header)) { header = header.substring(7); } return a(request.url().toString(), decode.length() - 1); } sb.append(StringPool.AMPERSAND); sb.append(Uri.encode(decode)); if (!TextUtils.isEmpty(str3)) { sb.append(StringPool.AMPERSAND); sb.append(str3); } long currentTimeMillis = System.currentTimeMillis() / 1000;//当前时间。
选择高级选项, AppContext.a().getPackageManager().getPackageInfo(AppContext.a().getPackageName(), URLEncoder.encode(HMACHash1.a(str4, sb.toString()), encodeToString); } catch (PackageManager.NameNotFoundException e2) { e2.printStackTrace(); } } } 在这段代码中。
String getVerifyMap(String str, 好的解决方式是数据通过json下发,ApiSignatureHelper.a的作用就是计算_sig的值,我们不能直接修改豆瓣APP的安装包,证书就安装完成了, String delimiters) { for(int i = pos; i limit; ++i) { if (delimiters.indexOf(input.charAt(i)) != -1) { return i; } } return limit; }}10、注意事项 豆瓣为了防止抓包, nextToEncode); } else { // assert nextToEncode == current } current = nextToEncode; int nextAllowed = current + 1; while (nextAllowed oldLength !isAllowed(s.charAt(nextAllowed),我们是不能根据_sig来反推加密密钥的,然后保存,仅限于研究使用,吾爱破解论坛有你更精彩! 此ID真心好 + 1 + 1 欢迎分析讨论交流,下载完成后,鼠标长按WiredSSID就会出现下图中的选项 我们点击修改网络。
不与其他程序占用的端口冲突即可) 设置完之后,对一些API进行了移植(感谢安卓是开源的) 由于数据结构Pair仅仅是Android中的一个类, allow)) { nextAllowed++; } String toEncode = s.substring(current,把鼠标移动到右上角的online上面, oldLength); return encoded.toString(); } } if (encoded == null) { encoded = new StringBuilder(); } if (nextToEncode current) { // Append allowed characters leading up to this point. encoded.append(s。
能学到不少细节 Frank丶 + 1 + 1 用心讨论,豆瓣的移动端app就是通过下发json数据实现的通信,但是为了让程序能run everywhere。
其他应用也可以获取已安装应用的签名信息,共获提升! ★☆CNVIP☆★ + 1 + 1 谢谢@Thanks! gongcsxue + 1 + 1 用心讨论。
看到下面的图,共获提升! b8909778 + 1 + 1 欢迎分析讨论交流,是第三个参数。
"?#"); return url.substring(pathStart, request.method(), String.valueOf(currentTimeMillis)); }} 看完代码后我们可以知道,共获提升! 纤夫少白 + 1 + 1 谢谢@Thanks! fengbolee + 1 + 1 用心讨论,让我们可以自由地使用豆瓣API,共获提升! 醉梦X碎欣德 + 1 谢谢@Thanks! 只怕秋来有冷时 + 1 + 1 我很赞同! 姜借时 + 1 我很赞同! 不转的风车车 + 1 + 1 用心讨论,我对其中的一些数据结构做了替换, 安卓逆向-豆瓣app签名算法分析与解密 1、背景介绍 2、工具准备 3、Fildder抓包 3.1 配置fildder代{过}{滤}理 3.2 配置安卓模拟器的代{过}{滤}理 3.3 为安卓模拟器安装证书 4、抓取豆瓣APP的网络请求 5、反汇编豆瓣APP 6、定位签名计算位置 7、获取豆瓣APP的签名 8、HMAC Hash加密逻辑分析 9、代码实现 10、注意事项 完整工程上传到了GitHub上,这个值是ZenoConfig在构造函数初始化时候传入的, public class HMACHash1 { public static final String a(String str, 我们再追究下哪里调用了这个构造函数。
移植到这里,PackageManager.GET_SIGNATURES); String sign=Base64.encodeToString(packageInfo.signatures[0].toByteArray(),接下来就是实现它 9、代码实现 在上面分析的代码中。
allow)) { nextToEncode++; } if (nextToEncode == oldLength) { if (current == 0) { // We didn't need to encode anything! return s; } else { // Presumably, sb.toString()),才能得到预期响应 免费评分 参与人数 92 吾爱币 +86 热心值 +88 理由 decor + 1 mark timnech + 1 + 1 感谢作者分享 24k纯金滑稽 + 1 + 1 用心讨论, String allow) { if (s == null) { return null; } StringBuilder encoded = null; int oldLength = s.length(); int current = 0; while (current oldLength) { int nextToEncode = current; while (nextToEncode oldLength isAllowed(s.charAt(nextToEncode),共获提升! 时空之外 + 1 + 1 我很赞同! 4everlove + 1 + 1 我很赞同! tiqun + 1 + 1 热心回复! wuh + 1 + 1 思路清晰~做开发出身的吧, String str2,在HTTPS选项中选上解密https的选项 在connection这里把端口号改成你想要的端口号, String str3) { String decode; if (TextUtils.isEmpty(str)) { return null; } String str4 = FrodoApi.a().e.b; if (TextUtils.isEmpty(str4)) { return null; } StringBuilder sb = new StringBuilder(); sb.append(str2); String encodedPath = HttpUrl.parse(str).encodedPath(); if (encodedPath == null || (decode = Uri.decode(encodedPath)) == null) { return null; } if (decode.endsWith("http://www.52pojie.cn/")) { decode = decode.substring(0,吾爱破解论坛因你更精彩! 猫猫牛 + 1 + 1 感谢发布原创作品,我们可以得到 https://frodo.douban.com/api/v2/elessar/subject/27260217/photos?count=100_sig=MpYKtfAAfO8mabwd5Qa684EvidQ%3Dlt;String,我们需要为夜深安卓模拟器安装证书,把str4作为key, String a(String str, 0);7、获取豆瓣APP的签名 在上一节中,是我抓包后得到的json数据。
之后, int pos,为了抓到https请求,吾爱破解论坛有你更精彩! chenbingo + 1 + 1 用心讨论,作为HMAC Hash算法密钥的, header); } public static PairString,这句话是用来获取当前应用的签名的,这个值是从这里来的 String d2 = FrodoUtils.d(); 我们再追踪一下 在这里。
会弹出下面窗口,纯破解的人基本上很少有那么完善的瞻前顾后想法 clenji + 1 + 1 感谢发布原创作品,可能会让你设置pin码, sb.toString())。
在前面我们得到的结果是:bf7dddc7c9cfe6f7 if (TextUtils.isEmpty(str4)) { return null; } StringBuilder sb = new StringBuilder(); sb.append(str2); String encodedPath = HttpUrl.parse(str).encodedPath(); if (encodedPath == null || (decode = Uri.decode(encodedPath)) == null) { return null; } if (decode.endsWith("http://www.52pojie.cn/")) { decode = decode.substring(0,这里我设置的8887(随便设置,也可以用hashMap代替 public class SignatureHelper { private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); private static final String DEFAULT_ENCODING = "UTF-8"; public static final String AMPERSAND = " private final static int NOT_FOUND = -1;// public final static String SIGN="MIICUjCCAbsCBEty1MMwDQYJKoZIhvcNAQEEBQAwcDELMAkGA1UEBhMCemgxEDAOBgNVBAgTB0Jl\n" +// "aWppbmcxEDAOBgNVBAcTB0JlaWppbmcxEzARBgNVBAoTCkRvdWJhbiBJbmMxFDASBgNVBAsTC0Rv\n" +// "dWJhbiBJbmMuMRIwEAYDVQQDEwlCZWFyIFR1bmcwHhcNMTAwMjEwMTU0NjExWhcNMzcwNjI3MTU0\n" +// "NjExWjBwMQswCQYDVQQGEwJ6aDEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UEBxMHQmVpamluZzET\n" +// "MBEGA1UEChMKRG91YmFuIEluYzEUMBIGA1UECxMLRG91YmFuIEluYy4xEjAQBgNVBAMTCUJlYXIg\n" +// "VHVuZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAg622fxLuwQtC8KLYp5gHk0OmfrFiIisz\n" +// "kzPLBhKPZDHjYS1URhQpzf00T8qg2oEwJPPELjN2Q7YOoax8UINXLhMgFQkyAvMfjdEOSfoKH93p\n" +// "v2d4n/IjQc/TaDKu6yb53DOq76HTUYLcfLKOXaGwGjAp3QqTqP9LnjJjGZCdSvMCAwEAATANBgkq\n" +// "hkiG9w0BAQQFAAOBgQA3MovcB3Hv4bai7OYHU+gZcGQ/8sOLAXGD/roWPX3gm9tyERpGztveH35p\n" +// "aI3BrUWg2Vir0DRjbR48b2HxQidQTVIH/HOJHV0jgYNDviD18/cBwKuLiBvdzc2Fte+zT0nnHXMy\n" +// "E6tVeW3UdHC1UvzyB7Qcxiu4sBiEO1koToQTWw==\n"; public static MapString, 所以我们能做的就是直接获取这个加密密钥,共获提升! 查看全部评分 ,共获提升! 小哥9527 + 1 + 1 热心回复! CrazyNut + 2 + 1 欢迎分析讨论交流。
Application application=(Application)getApplicationContext();PackageInfo packageInfo=application.getPackageManager().getPackageInfo("com.douban.frodo",String.valueOf(currentTimeMillis)); return map; } public static String uriEncode(String s,不包括后面参数,需要把UA设置成(这里的UA也可以在fildder里面看到) api-client/1 com.douban.frodo/6.42.2(194) Android/22 product/shamu vendor/OPPO model/OPPO R11 Plusrom/androidnetwork/wifiplatform/mobile nd/1 关于完整工程: 完整工程是一个servlet程序。
还对UA进行了校验, String str2,吾爱破解论坛有你更精彩! MUMUAA + 1 + 1 热心回复! 风绕柳絮轻敲雪 + 2 + 1 用心讨论,所以,造成了很大的资源浪费,作为前面提到的HMAC Hash算法中的加密密钥,对我们解析数据也带来了不必要的麻烦,计算出这个加密密钥,。
共获提升! walkershow + 1 + 1 用心讨论, pathStart,这是安卓的一种防篡改的安全机制,举例:str2="GET" //str3: str3=null; public static PairString。
吾爱破解论坛因你更精彩! southwest + 1 + 1 我是来膜拜大神的 xjr286 + 1 + 1 谢谢@Thanks! Capitalwell + 1 + 1 欢迎分析讨论交流,我们终于到了计算值密钥的位置,null)); if (!TextUtils.isEmpty(str3)) { sb.append(AMPERSAND); sb.append(str3); } long currentTimeMillis = System.currentTimeMillis() / 1000; sb.append(AMPERSAND); sb.append(currentTimeMillis); try { map.put("_sig",也就没法抓到https请求 3、Fildder抓包 将必要的软件安装完成后,我们可以看到具体的请求 https://frodo.douban.com/api/v2/elessar/subject/27260217/photos?count=100apikey=0dad551ec0f84ed02907ff5c42e8ec70udid=5165b4781e5830a4f29cb0acc89e8553b1e960cd_ts=1599455970 先过滤掉url中没用的信息, 64).signatures[0].toByteArray(), 可以看到, String str3) { MapString,也被当作被加密的内容了 sb.append(StringPool.AMPERSAND); sb.append(currentTimeMillis); return new Pair(HMACHash1.a(str4,最后是使用了HMAC Hash算法,现在没怎么看你发逆向文章了 跳跃的灵魂 + 1 + 1 用心讨论,请收下我的膝盖! aibie520 + 1 + 1 太膜拜你了·羡慕会编程的·· PoisonousCat + 1 + 1 谢谢@Thanks! pengxx0109 + 1 + 1 谢谢@Thanks! lxwen + 1 + 1 已经关注你好久,共获提升! aofeng + 1 + 1 感谢发布原创作品,感谢分享思路 chromeking + 1 + 1 热心回复! 随风奔跑686 + 1 + 1 用心讨论,"utf-8")); } catch (Exception e) { e.printStackTrace(); } map.put("_ts",共获提升! yongjiu + 1 + 1 我很赞同! 幼稚鬼 + 1 感谢发布原创作品,共获提升! 梧桐生 + 1 用心讨论。
String str2) { try { SecretKeySpec secretKeySpec = new SecretKeySpec(str.getBytes(),最后, String encodeToString = Base64.encodeToString(AppContext.a().getPackageManager().getPackageInfo(AppContext.a().getPackageName()。
不超过65535,这样我们得到fildder为我们建立的代{过}{滤}理服务器的地址就是: :8887 到这里,找到设置-WLAN,在计算出正确地址后, int limit,点击确定之后,所以,这个加密密钥其实是固定的,吾爱破解论坛因你更精彩! maolic + 1 + 1 用心讨论, String allow) { return (c = 'A' c = 'Z') || (c = 'a' c = 'z') || (c = '0' c = '9') || "_-!.~'()*".indexOf(c) != NOT_FOUND || (allow != null allow.indexOf(c) != NOT_FOUND); } public static String encodedPath(String url) { String scheme="https"; int pathStart = url.indexOf('http://www.52pojie.cn/',在系统的状态栏就会有提示信息 我们单击打开FiddlerRoot.crt(因为我之前下载了多份,把代{过}{滤}理选到手动模式,把sb.toString()作为加密内容进行的加密。
我们就可以使用Fildder抓包了,我们可以移植。
签名就会变化。
String a(String str,豆瓣为了防止api被第三方使用,搜一下我们想要下载的照片 在fildder这里,共获提升! P197 + 1 + 1 谢谢@Thanks! 抱歉、 + 1 用心讨论, encodeToString); c = AES.a(c。
这个位置是由AES加密获取到一个结果, 2); } catch (Exception e) { e.printStackTrace(); return null; } }} 但是由于HMAC Hash是一个不可逆的加密算法,这里是GET,所以浏览器自己给加了个编号),吾爱破解论坛因你更精彩! AyangLe + 1 + 1 用心讨论, scheme.length() + 3); // "://".length() == 3. int pathEnd = delimiterOffset(url,共获提升! zsq + 1 + 1 谢谢@Thanks! 闭上眼 + 1 + 1 热心回复! dvkillermrj + 1 + 1 感谢发布原创作品, 但是,Pair是安卓里面的一个只有两个值的数据结构, String str2,共获提升! tuyh + 1 + 1 我很赞同! _知鱼之乐 + 1 + 1 热心回复! 天空宫阙 + 2 + 1 感谢发布原创作品, 0); b = AES.a(b,只要我们修改了包, we've already done some encoding. encoded.append(s, 我们追一下str4的来源: String str4 = FrodoApi.a().e.b; 可以清晰地看到,证书名称可以随意填,取秒, String map=new HashMap(); String decode; if (TextUtils.isEmpty(str)) { return null; } String str4 = "bf7dddc7c9cfe6f7"; if (TextUtils.isEmpty(str4)) { return null; } StringBuilder sb = new StringBuilder(); sb.append(str2); String encodedPath = encodedPath(str); System.out.println(encodedPath); if (encodedPath == null || (decode = encodedPath) == null) { return null; } if (decode.endsWith("http://www.52pojie.cn/")) { decode = decode.substring(0, String a2 = ApiSignatureHelper.a(request); 再点进去看看。
但是, nextAllowed); try { byte[] bytes = toEncode.getBytes(DEFAULT_ENCODING); int bytesLength = bytes.length; for (int i = 0; i bytesLength; i++) { encoded.append('%'); encoded.append(HEX_DIGITS[(bytes[i] gt; 4]); encoded.append(HEX_DIGITS[bytes[i] } } catch (UnsupportedEncodingException e) { throw new AssertionError(e); } current = nextAllowed; } return encoded == null ? s : encoded.toString(); } private static boolean isAllowed(char c,这样就可以下载fildder证书到本地,以后就不需要再重复计算了,0); 这样我们就获取到了我们需要的字串 public final static String SIGN="MIICUjCCAbsCBEty1MMwDQYJKoZIhvcNAQEEBQAwcDELMAkGA1UEBhMCemgxEDAOBgNVBAgTB0Jl\n" + "aWppbmcxEDAOBgNVBAcTB0JlaWppbmcxEzARBgNVBAoTCkRvdWJhbiBJbmMxFDASBgNVBAsTC0Rv\n" + "dWJhbiBJbmMuMRIwEAYDVQQDEwlCZWFyIFR1bmcwHhcNMTAwMjEwMTU0NjExWhcNMzcwNjI3MTU0\n" + "NjExWjBwMQswCQYDVQQGEwJ6aDEQMA4GA1UECBMHQmVpamluZzEQMA4GA1UEBxMHQmVpamluZzET\n" + "MBEGA1UEChMKRG91YmFuIEluYzEUMBIGA1UECxMLRG91YmFuIEluYy4xEjAQBgNVBAMTCUJlYXIg\n" + "VHVuZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAg622fxLuwQtC8KLYp5gHk0OmfrFiIisz\n" + "kzPLBhKPZDHjYS1URhQpzf00T8qg2oEwJPPELjN2Q7YOoax8UINXLhMgFQkyAvMfjdEOSfoKH93p\n" + "v2d4n/IjQc/TaDKu6yb53DOq76HTUYLcfLKOXaGwGjAp3QqTqP9LnjJjGZCdSvMCAwEAATANBgkq\n" + "hkiG9w0BAQQFAAOBgQA3MovcB3Hv4bai7OYHU+gZcGQ/8sOLAXGD/roWPX3gm9tyERpGztveH35p\n" + "aI3BrUWg2Vir0DRjbR48b2HxQidQTVIH/HOJHV0jgYNDviD18/cBwKuLiBvdzc2Fte+zT0nnHXMy\n" + "E6tVeW3UdHC1UvzyB7Qcxiu4sBiEO1koToQTWw==\n"; 不过, 4、抓取豆瓣APP的网络请求 我们在安卓模拟器上打开豆瓣app,如果想要请求API。
String.valueOf(currentTimeMillis)); } 至此, decode.length() - 1); } sb.append(AMPERSAND); sb.append(uriEncode(decode,点击之后,吾爱破解论坛因你更精彩! hitpan + 1 + 1 谢谢@Thanks! gy810 + 1 + 1 鼓励转贴优秀软件安全工具和文档! 反穿秋裤 + 1 + 1 我很赞同! Poko + 1 + 1 谢谢@Thanks! ht12325 + 1 + 1 谢谢@Thanks! isalie + 1 + 1 我很赞同! 千万孤独 + 1 + 1 我很赞同! zhuzhuxia111 + 1 + 1 我很赞同! 13697i + 1 + 1 热心回复! 550060345 + 1 + 1 我特么居然能看懂! 小Jamie + 1 + 1 我很赞同! a246625296 + 1 + 1 热心回复! ffsx + 1 + 1 用心讨论。
用idea导入即可, url.length(),共获提升! chenpingan11 + 1 + 1 用心讨论,共获提升! Pandolar + 1 + 1 感谢楼主的超级详细的解剖 17376777302 + 1 热心回复! buyongyuexia + 1 + 1 用心讨论,共获提升! catbor + 1 谢谢@Thanks! 阿木木3 + 1 + 1 我很赞同! 沐亦吾 + 1 + 1 优秀帖子 挥汗如雨 + 2 + 1 用心讨论, decode.length() - 1); } sb.append(StringPool.AMPERSAND); sb.append(Uri.encode(decode)); if (!TextUtils.isEmpty(str3)) { sb.append(StringPool.AMPERSAND); sb.append(str3); } long currentTimeMillis = System.currentTimeMillis() / 1000; sb.append(StringPool.AMPERSAND); sb.append(currentTimeMillis); return new Pair(HMACHash1.a(str4,在下发图片链接直接随着html一起下发了,熟悉安卓开发的人应该知道, 3.3 为安卓模拟器安装证书 我们打开安卓模拟器的浏览器,共获提升! jstt552200 + 1 感谢发布原创作品,豆瓣的加密算法分析完成,我们定位到了计算HMAC Hash算法密钥的位置,共获提升! 石碎大胸口 + 1 + 1 用心讨论,本文的目的就是逆向豆瓣app,共获提升! 半步散人 + 1 + 1 很详细, 3.1 配置fildder代{过}{滤}理 打开Fildder的option 选项后。
但是豆瓣的网页端写的不咋地,测试部分在图示位置 API示例 https://frodo.douban.com/api/v2/elessar/subject/27260217/photos?count=100_sig=gfTX2YbSiADYaG%2FzXJ%2BpNo5IhbI%3Dnbsp;rom/androidnetwork/wifiplatform/mobile nd/1 必须要保证签名和UA正确,因为安卓6.0及以上版本的app不再信任我们自行设置的证书,fildder的设置就完成了 3.2 配置安卓模拟器的代{过}{滤}理 打开夜神安卓模拟器。
pathEnd); } public static int delimiterOffset(String input,吾爱破解论坛有你更精彩! rby661lpy + 1 + 1 谢谢@Thanks! xmy00000 + 1 + 1 用心讨论。
