第一次接觸APK【破解紀實】

前言
昨天剛把公司任務弄得差不多。同事想學粵語,下了一款XX粵語手機APP,讓我幫他弄下。之前也沒接觸過APK,這次就當學習好了。
先下個JDK裝好  再把Android SDK NDK統統裝好,配置好環境變量,下載好需要的包,開搞。爲了學習移動端的安全知識,買了一臺安卓系統的手機作爲一個測試環境。


1.下載下來APK解包

百度一下APK,11月20號還更新了。作者還挺勤快嘛。把APK下載下來,先解壓看看裏面是什麼。發現裏面的東西打不開~應該是要解包。從網上找了一下,有個apktool的還是很nice的,用apktool解包後如圖:


2.再把程序安好,看看它裏面到底是賣的什麼藥->是個什麼樣的註冊方法:


從以上兩張圖,可以知道明白了。
1>爆破。根據功能的需求一個地方一個地方的找,找到後再一一修改,但這顯然不是最好的方法,繁瑣而且不完美。
2>從積分入手。
(1)此軟件的積分可以支付寶購買
(2)下載它推薦的“垃圾應用程序”
(3)幫他宣傳。微博分享等等。
當然可以從這3方面的任何一方面入手,我認爲都可以達到需要的刷積分的效果。
我的第一思路就是找到這個積分變量,並修改它。如果能成功,這樣的破解就會是很完美的破解了。


3.定位
找字符串試試,到\res\values裏面的String.xml裏面看了一圈。


這個獲取積分成功是不是很誘人呢?
打開Public.xml。找了對應的ID


0x7f060010。
OK,接下來我們在smali文件夾裏搜索這個的引用。
發現了一個文件引用它  位置在:smali\com\movesky\a\c.smali


4.分析代碼


由於對smali代碼接觸得不多,打開之後,發現完全看不懂。怎麼辦?沒事~本來就是需要今後的學習。~既然看不懂smali代碼,那我們爲什麼不可以換個代碼看呢?
那就用Java decompiler吧  Java我總能看懂吧~


先看看C類裏寫的是什麼東西。




一共有2個函數,成功的函數代碼如下:
代碼:

public final void onSuccess(long paramLong)
  {
    String str = Integer.toString((int)(paramLong / 1L)); //取相應任務的分值
    Log.i("ZRD", "獎勵積分:" + str);///刷新分值顯示
    Toast.makeText(this.d, this.d.getString(2131099664) + str, 0).show();//顯示獲取積分成功
    K.a(this.d, new Handler(), str, "dianjing", "Add");//把積分數據更新下
  }
}
OK.顯然按照我的思路來,最後一句代碼當然更吸引我。那繼續追蹤K類:

public final class K
{
  private static List<NameValuePair> bb;

  private static JSONArray a(String paramString1, String paramString2, String paramString3, String paramString4, String paramString5)
  {
    JSONArray localJSONArray = new JSONArray();
    JSONObject localJSONObject = new JSONObject();
    try
    {
      localJSONObject.put("Fld_Points", paramString1);
      localJSONObject.put("Fld_Action", paramString2);
      localJSONObject.put("Fld_State", paramString3);
      localJSONObject.put("Fld_Source", paramString4);
      localJSONObject.put("Fld_Note", paramString5);
      localJSONArray.put(localJSONObject);
      return localJSONArray;
    }
    catch (JSONException localJSONException)
    {
      while (true)
      {
        localJSONException.printStackTrace();
        ZrdCommon.ZrdLog.Log("Err=" + localJSONException.getMessage());
        localJSONObject = new JSONObject();
      }
    }
  }

  public static void a(Context paramContext, Handler paramHandler)
  {
    a(paramContext, new JSONArray(), paramHandler);
  }
public static void a(Context paramContext, Handler paramHandler, String paramString1, String paramString2, String paramString3)
  {
    a(paramContext, a(paramString1, "1", "1", paramString2, paramString3), paramHandler);
  }

  public static void a(Context paramContext, Handler paramHandler, String paramString1, String paramString2, String paramString3, String paramString4, String paramString5)
  {
    a(paramContext, a(paramString1, paramString2, paramString3, paramString4, paramString5), paramHandler);
  }

  private static void a(Context paramContext, JSONArray paramJSONArray, Handler paramHandler)
  {
    Activity localActivity = (Activity)paramContext;
    ArrayList localArrayList = new ArrayList();
    bb = localArrayList;
    localArrayList.add(new BasicNameValuePair("_VKey", AppJNI.i()));
    bb.add(new BasicNameValuePair("_MaxID", "0"));
    bb.add(new BasicNameValuePair("_DevID", n.a(localActivity)));
    bb.add(new BasicNameValuePair("_BundleID", paramContext.getPackageName()));
    bb.add(newBasicNameValuePair("_BundleVersion", paramContext.getString(2131099661)));
    bb.add(new BasicNameValuePair("_ChannelID", paramContext.getString(2131099662)));
    bb.add(new BasicNameValuePair("_PointsDetail", paramJSONArray.toString()));
    ZrdCommon.ZrdLog.Log("YSpoints Updata PointsDetail=" + paramJSONArray.toString());
    new L(paramContext, paramHandler).start();
  }
}

找到對應的函數,一共套了幾層,稍微需要一點耐心,但並沒有難度。上面的幾個a函數都是對傳進來參數的一切處理,都是字符串游戲。對上述代碼分析後可得 private static void a(Context paramContext, JSONArray paramJSONArray, Handler paramHandler)這個函數是最關鍵的函數。
分析paramJSONArray裏的內容如下:
["Fld_Points":str,              //這裏的str就是完成對應任務的分數.toString()
 "Fld_Action":"1",
 "Fld_State":"1",
 "Fld_Source":"dianjing",        
 "Fld_Note":"Add"]          //方法爲Add




跟到這個時候發現這個函數的作用是客戶端給服務器提交參數的函數。
悲劇了,分析了這麼多~積分卻不在本地。
於是這個時候可能又跳出有幾種思路:
1>劫持這個變量
2>本地化,在本地完成任務達到免費使用
3>騙服務器
又去String.xml翻了翻。發現一個新的東西

URLPoints,那就是服務器存放APP積分的地址了。
進入如下:

看到SumPoints 居然是個負的。
那我們可不可以不讓它訪問服務器而把那個變量改成自己想要的值呢?我覺得這是一種可行的思路。
因爲第一次弄,思路也是天馬行空。當時想,
他這種訪問服務器獲取積分的方法,地址都是一個PHP文件。那肯定要驗證機器碼的,然後我把手機機器碼屏蔽掉了,發現積分溢出了。貼出兩張圖爲證:


這樣這個程序也算是完美破解了~
第一次接觸apk破解,難免有理解得不對的地方和彎路,希望大家能多多指正,多多交流方法,希望把不足之處告訴我,共同進步。
                                                                                    2014.11.22
                                                                                    By Eric 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章