背景
想實現一個支援多渠道的小說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框架。
dex進行dex2jar
這個步驟可以用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;
}
}
複製程式碼
先記錄這些,後續有進展在繼續