2014年12月8日 星期一

[Android] 讓 Log 訊息不出現在Logcat 且隱藏反編譯後之Log字串

Log.d 幾乎是開發過程中的必用函式

而且在debug過程中,會一直反覆更改訊息

不過Log這個函式 也隱藏了安全性風險


  • 風險1:若發佈成apk供使用者下載後,沒有註解掉 Log 訊息, Logcat視窗會輸出開發時的Log訊息 
  • 風險2:apk若被反解譯 ,Log函式訊息會被看到,程式邏輯可能曝光





通常我們為了解決風險1 會使用

private boolean DEBUG = true ;



if(DEBUG)

{

 Log.d(TAG,"this is (DEBUG) msg!") ;

}


當要release apk 時, 會把 DEBUG 改成 false

來防止Log 訊息 輸出到 Logcat 視窗

不過 若apk 被反編譯成 jar 檔案

可以看到反編譯後的原始碼

    if (this.Debug)

      Log.d(this.Tag, "this is (DEBUG) msg!");


若訊息是重要的程式邏輯點資訊  還是有邏輯曝光的風險

因此 我們希望把 Log.d 的訊息 在 反編譯後 不被看見

可以使用 proGuard 混淆器

打開 proguard 設定

[project.properties]

proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt:proguard-project.txt


過濾掉 Log 的函式

[proguard-project.txt]

-assumenosideeffects class android.util.Log { *; }


反編譯後 整個 Log.d 函式消失  被過濾掉了  而且加入了 proGuard 混淆器後 節省了  if (Debug){} 的程式碼

不過目前有個新問題

如果Log 訊息 是經過字串組合的  並非一次印出

例如
String user1 = "peter" ;

Log.d(TAG,"first man is"+user1) ;


反編譯後


new StringBuilder("first man is").append("peter");


Log.d 函式被更改成 new StringBuilder  不過 字串還是會被看出來

最後參考了這篇部落格

裏面提到了可以透過

1.自訂的 Logger函式

2.proGuard 設定


[proguard-project.txt]

-assumenosideeffects class com.example.disablelogtest.Logger { *; }

[Logger.java]


package com.example.disablelogtest;

import android.util.Log;



public final class Logger {



    public static void d(String tag, String message, Object... args) {

        Log.d(tag, String.format(message, args));

    }



    public static void i(String tag, String message, Object... args) {

        Log.i(tag, String.format(message, args));

    }



    public static void e(String tag, Exception e) {

        Log.e(tag, e.getMessage(), e);

    }



    public static void e(String tag, String message, Exception e) {

        Log.e(tag, message, e);

    }



}


Logger 用法


Logger.d(TAG, "Batman goes like %d, %d, %d, \"%s\"", 1, 2, 3, "Pow!");

     * //prints: Batman goes like 1, 2, 3, "Pow!"

反編譯前

String user1 = "tom" ;

String user2= getUserName(0) ;

Logger.d(Tag, "this is (DEBUG) msg! firstOne=%s , secondOne=%s",user1,user2) ;

private String getUserName(int id)
{
    String[] objUser = {"peter" ,"john"} ;
    if (id >(objUser.length-1))
    {
        return "nobody" ;
    }
    return objUser[id] ;
}


反編譯後


String[] arrayOfString = { "peter", "john" };

if (-1 + arrayOfString.length < 0);

for (String str = "nobody"; ; str = arrayOfString[0])
{
  new Object[] { "tom", str };
  return;
}

我們可以看到

"this is (DEBUG) msg! firstOne=%s , secondOne=%s"

的字串已經看不出來

不過這邊要特別注意的是

若組合的字串是寫死的 例如 上面例子寫死的"tom"  還是會出現

不過若是 經過 呼叫 function得到之 字串 則不會直接的顯示出來

總結


最終解決方案為

1.開啟proGuard混淆器


proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt:proguard-project.txt


2.設定proGuard混淆器


-assumenosideeffects class com.example.disablelogtest.Logger { *; }


3.使用 自用 Logger 函式


Logger.d(TAG, "Batman goes like %d, %d, %d, \"%s\"", 1, 2, 3, "Pow!");
以上 就能在程式碼中  保留 Log 訊息

並且 Logcat 不會噴出訊息  , 反解譯之後也不容易被看出邏輯 ^^


參考資料:

沒有留言:

張貼留言