想实现一个支持多渠道的小说App,因此对该小说App进行分析获取它的接口调用方式 该App详情页截图:
Charles抓取飞卢详情页面的接口
该小说App的域名是一个固定IP(试过几次退出登陆发现每次IP不一样,猜测是客户端写死的或者服务端下发,应该是防止域名被劫持吧)
上传的参数是一堆乱码,token也是乱码,
一般末尾是‘=’,应该是base64编码, 解密失败
返回内容居然是XML,author_name居然也是乱码,猜测是base64编码,使用站长工具Base64解密
感觉该App对数据加密做的很严谨,怪不得市场没有破解版
现在模拟它的请求只要破解它的token和参数就可以了
使用Android Studio打开该App,看到tencent_stub,应该是做个乐固加固了。
Mac上使用 Android CrackTool 进行反编译处理
反编译结果的确是乐固加固
那开始对这个加固包进行反编译 参照这个文档 Android APK脱壳--腾讯乐固、360加固一键脱壳
使用脱壳工具FDex2
VirtualXposed:无需root手机即可使用xp框架。
这个步骤可以用Android Crack Tool上执行,执行成功之后,使用jdgui打开 搜索关键字 Xml4Android_relevantPage
,获取详情页
刷新详情页发现Logcat中有日志
日志中有contetn 原文
进行搜索,发现token和参数加密都是native实现的RSA加密,
public <T extends BaseModel> T a(Object paramObject, String paramString1, UserInfoDto paramUserInfoDto, String paramString2, b<T> paramb) { try { paramString1 = paramString1.split("//?"); String str2 = paramString1[1]; String str1 = a(paramString1[0]); paramString1 = new java/lang/StringBuilder; paramString1.<init>(); paramString1.append(str1); paramString1.append("?appversion="); paramString1.append(AppUtils.getAppversion()); paramString1.append("&Type=Android"); paramString1 = paramString1.toString(); str1 = paramString1; if (!TextUtils.isEmpty(paramString1)) { str1 = paramString1; if (paramString1.contains("http://client4ip")) { str1 = paramString1.replace("http://client4ip", "https://client4ip"); } } if (!TextUtils.isEmpty(paramString2)) { paramString1 = paramb.d(paramString2); } else { if (!TextUtils.isEmpty(paramUserInfoDto.getUsername())) { paramUserInfoDto.setUsername(paramUserInfoDto.getUsername().toLowerCase()); } if (!TextUtils.isEmpty(paramUserInfoDto.getPassword())) { paramUserInfoDto.setPassword(paramUserInfoDto.getPassword().toLowerCase()); } if (!TextUtils.isEmpty(paramUserInfoDto.getVerifyCode())) { paramUserInfoDto.setVerifyCode(paramUserInfoDto.getVerifyCode().toLowerCase()); } if (!TextUtils.isEmpty(paramUserInfoDto.getUsername())) { paramString2 = paramb.a(paramUserInfoDto); paramString1 = paramb.d(paramString2); } else { paramString1 = new java/lang/StringBuilder; paramString1.<init>(); paramString1.append(System.currentTimeMillis()); paramString1.append(""); paramString2 = MD5.MD5(paramString1.toString()); paramString1 = paramb.d(paramString2); } } paramUserInfoDto = m.a().b("SP_UID"); if (!TextUtils.isEmpty(m.a().b("username"))) { paramUserInfoDto = m.a().b("username"); } Object localObject = paramUserInfoDto; if (TextUtils.isEmpty(paramUserInfoDto)) { localObject = j.a(); m.a().a("SP_UID", (String)localObject); } paramUserInfoDto = new java/lang/StringBuilder; paramUserInfoDto.<init>(); paramUserInfoDto.append(str2); paramUserInfoDto.append("&uuid="); paramUserInfoDto.append((String)localObject); localObject = paramUserInfoDto.toString(); paramUserInfoDto = (UserInfoDto)localObject; if (!TextUtils.isEmpty((CharSequence)localObject)) { paramUserInfoDto = (UserInfoDto)localObject; if (!((String)localObject).contains("time=")) { paramUserInfoDto = new java/lang/StringBuilder; paramUserInfoDto.<init>(); paramUserInfoDto.append((String)localObject); paramUserInfoDto.append("&time="); paramUserInfoDto.append(URLEncoder.encode(TimeUtils.getNowString(), "gb2312")); paramUserInfoDto = paramUserInfoDto.toString(); } } localObject = paramUserInfoDto; if (!TextUtils.isEmpty(paramUserInfoDto)) { localObject = paramUserInfoDto; if (!paramUserInfoDto.contains("appversion=")) { localObject = new java/lang/StringBuilder; ((StringBuilder)localObject).<init>(); ((StringBuilder)localObject).append(paramUserInfoDto); ((StringBuilder)localObject).append("&appversion="); ((StringBuilder)localObject).append(AppUtils.getAppversion()); ((StringBuilder)localObject).append("&Type=Android"); localObject = ((StringBuilder)localObject).toString(); } } paramUserInfoDto = new java/lang/StringBuilder; paramUserInfoDto.<init>(); paramUserInfoDto.append("content 原文 "); paramUserInfoDto.append((String)localObject); g.a(new Object[] { paramUserInfoDto.toString() }); paramUserInfoDto = paramb.a((String)localObject, paramString2); paramString2 = new com/lzy/okgo/model/HttpParams; paramString2.<init>(); paramString2.put("", paramUserInfoDto, new boolean[0]); paramObject = ((PostRequest)((PostRequest)((PostRequest)((PostRequest)((PostRequest)com.lzy.okgo.a.b(str1).tag(paramObject)).headers("token", paramString1)).headers("mobileType", "Android")).headers("appversion", AppUtils.getAppversion())).params(paramString2)).execute(); if (paramObject == null) { return null; } if (((Response)paramObject).isSuccessful()) { paramUserInfoDto = ((Response)paramObject).body().byteStream(); paramObject = new java/io/BufferedReader; paramString1 = new java/io/InputStreamReader; paramString1.<init>(paramUserInfoDto, "gb2312"); ((BufferedReader)paramObject).<init>(paramString1); paramUserInfoDto = new java/lang/StringBuffer; paramUserInfoDto.<init>(); for (;;) { paramString1 = ((BufferedReader)paramObject).readLine(); if (paramString1 == null) { break; } paramUserInfoDto.append(paramString1); } paramObject = (BaseModel)paramb.b(paramUserInfoDto.toString()); return (T)paramObject; } } 复制代码
先记录这些,后续有进展在继续