【移動應(yīng)用開發(fā)技術(shù)】Android中安全地打印日志的示例_第1頁
【移動應(yīng)用開發(fā)技術(shù)】Android中安全地打印日志的示例_第2頁
【移動應(yīng)用開發(fā)技術(shù)】Android中安全地打印日志的示例_第3頁
【移動應(yīng)用開發(fā)技術(shù)】Android中安全地打印日志的示例_第4頁
【移動應(yīng)用開發(fā)技術(shù)】Android中安全地打印日志的示例_第5頁
已閱讀5頁,還剩4頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

【移動應(yīng)用開發(fā)技術(shù)】Android中安全地打印日志的示例

這篇文章主要介紹了Android中安全地打印日志的示例,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓在下帶著大家一起了解一下。在Android開發(fā)過程中,不管是寫Demo還是實戰(zhàn)項目中,都會打印一些日志用于記錄數(shù)據(jù),調(diào)試來著,Android中的日志工具類是Log,這個類提供了一些方法來打印日志。五個級別,v、d、i、w、e,各有不同的重載。當(dāng)談到如何打印日志?很多人會想這不是很簡單,直接使用android.util.Log這個類不就行了?然而,日志屬于非常敏感的信息;逆向工程師在逆向你的程序的時候,本來需要捕捉你程序的各種輸出,然后進(jìn)行推測,順藤摸瓜然后得到需要的信息;一旦你的日志泄漏,無異于門戶洞開,破解你的程序如入無人之境。安全的概念本來就是相對的,如果破解你程序的代價遠(yuǎn)遠(yuǎn)大于破解得到的價值,那么就可以認(rèn)為程序是“安全的”;這里就分析一下,為了提高程序的安全性,在打印日志的時候應(yīng)該注意什么。首先看看絕大部分公司以及開發(fā)者的做法:日志開關(guān)+日志類為了在release版本里面沒有日志輸出,一個最簡單的想法是:把所有打印日志的語句放在一個if(DEBUG)的語句里面;在日常開發(fā)的時候,DEBUG開關(guān)打開,發(fā)布正式版本的時候關(guān)閉這個開關(guān)即可,大致思路如下://

LogUtil.java

public

class

LogUtil

{

private

static

boolean

DEBUG

=

true;//

發(fā)布的時候修改為false

public

static

void

d(String

tag,

String

msg)

{

if

(DEBUG)

android.util.Log.d(TAG,

msg);

}

//

其他debug方法

}接下來看一個真實的例子,國外的一個apk,名字叫做powerclean;包名:com.lionmobi.powerclean;我們安裝這個包;發(fā)現(xiàn)很正常,沒有任何日志輸出;然后我們逆向這個apk;隨便翻看幾個類,發(fā)現(xiàn)很多地方有類似日志輸出:日志輸出圖片我們打開這個叫做x的類,雖然被混淆過了,但是意思很明白,跟我們上面的思路一樣:package

com.lionmobi.util;

import

android.util.Log;

public

class

x

{

private

static

boolean

a;

static

{

x.a

=

false;

}

public

static

void

d(String

arg1,

String

arg2)

{

if(x.a)

{

Log.d(arg1,

arg2);

}

}

public

static

void

e(String

arg1,

String

arg2)

{

if(x.a)

{

Log.e(arg1,

arg2);

}

}

public

static

void

i(String

arg1,

String

arg2)

{

if(x.a)

{

Log.i(arg1,

arg2);

}

}

}這是一個真實的例子,而且這個app的用戶還不少;接下來我們看看這種方式有什么問題。靜態(tài)反編譯打開日志開關(guān)上面的那種方式有一個問題:雖然在release版本里面,確實沒有日志輸出;但是輸出日志的代碼依然存在,只是沒有執(zhí)行到!(if條件不成立)所以,有沒有辦法讓這些代碼執(zhí)行到呢?簡單來說,就是能不能在release版本里面把這個DEBUG變量弄成true呢?當(dāng)然可以!而且做法還非常簡單。我們使用apktool反編譯得到這個apk的smali代碼;然后上面的反編譯告訴我們,這個日志類的位置是:com.lionmobi.util.x我們打開這個x.smali文件,內(nèi)容如下:.class

public

Lcom/lionmobi/util/x;

.super

Ljava/lang/Object;

#

static

fields

.field

private

static

a:Z

#

direct

methods

.method

static

constructor

<clinit>()V

.locals

1

const/4

v0,

0x0

#

修改為0x1

(True)

sput-boolean

v0,

Lcom/lionmobi/util/x;->a:Z

#初始化位置

return-void

.end

method

.method

public

static

d(Ljava/lang/String;Ljava/lang/String;)V

.locals

1

sget-boolean

v0,

Lcom/lionmobi/util/x;->a:Z

if-eqz

v0,

:cond_0

invoke-static

{p0,

p1},

Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

:cond_0

return-void

.end

method

.method

public

static

e(Ljava/lang/String;Ljava/lang/String;)V

.locals

1

sget-boolean

v0,

Lcom/lionmobi/util/x;->a:Z

if-eqz

v0,

:cond_0

invoke-static

{p0,

p1},

Landroid/util/Log;->e(Ljava/lang/String;Ljava/lang/String;)I

:cond_0

return-void

.end

method

.method

public

static

i(Ljava/lang/String;Ljava/lang/String;)V

.locals

1

sget-boolean

v0,

Lcom/lionmobi/util/x;->a:Z

if-eqz

v0,

:cond_0

invoke-static

{p0,

p1},

Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

:cond_0

return-void

.end

method很明白,那個叫做a的靜態(tài)變量就是我們的開關(guān),它的初始化在哪個靜態(tài)代碼塊里面;新建了一個局部變量0x0然后賦值給了a;因此,我們把這個0x0修改為0x1就打開了這個開關(guān)。很簡單吧,接下來我們把修改好的smali打包回去,然后簽名得到一個新的可以運行的apk;運行一下看看結(jié)果。果然,一大堆的日志輸出了出來,你的程序每一步在干什么都自己告訴別人了,都不需要去猜;我就隨便截個圖,感受下:泄漏的日志信息讓release版本里面不包含日志代碼從上面的分析我們得到一個結(jié)論:如果需要程序是“日志安全的”,那么release版本里面不應(yīng)該存在輸出日志的代碼。如何做到這一點呢?我們可以做一個工具,開發(fā)的時候,正常打印日志;一旦需要發(fā)布版本,把所有打印日志的語句代碼,全部刪除掉。代碼很簡單,用一些正則表達(dá)式就可以做到。事實上,我們也可以使用一些別的工具,來實現(xiàn)這個類似的功能;那就是proguard;提到這個工具,很多認(rèn)只是覺得他是一個代碼混淆的工具,實際上,它還可以幫你剔除無用代碼!什么樣的代碼是無用代碼呢?if

(true)

{

//

statement;

}類似于這樣,靜態(tài)編譯的時候被認(rèn)為“永遠(yuǎn)不會執(zhí)行的代碼”,就被認(rèn)為是無用代碼,會被這個工具直接優(yōu)化掉,生成的class文件里面,這個if語句直接就沒有了。這個功能,完美符合我們的需求;我們只需要把輸出日志的代碼用這樣的if語句包圍起來,然后release的時候肯定會用這個工具混淆;然后,在release版本里面,所有的輸出日志的代碼全部都沒有了!不會像以前一樣,留下一個影子,只是不做事。正確的做法最終,我們所有打印日志的語句應(yīng)該如下:private

static

final

boolean

DEBUG

=

true;

//

必須是static

final

也就是常量,這樣才能在編譯器優(yōu)化;刪除if塊

if

(DEBUG)

{

android.util.Log.d(TAG,

"msg

to

print");

}然后,使用proguard優(yōu)化代碼即可??雌饋砗唵?,好像也與最初的“日志開關(guān)”沒有什么區(qū)別,仔細(xì)分析一下:日志開關(guān)必須是靜態(tài)常量對比一下正確的做法與最開始的日志開關(guān),一個是一個靜態(tài)變量,一個是靜態(tài)常量;如果是常量的話,那么就是永遠(yuǎn)不變的,那么當(dāng)DEBUG變量為False的時候proguard可以理所當(dāng)然地認(rèn)為,這一部分代碼時絕對不會被執(zhí)行的,這樣,打印日志的語句就會被優(yōu)化(刪除)掉;如果是一個變量,那么在運行期間就有可能改變它的值(private僅僅是對于程序員的改變,對于編譯器以及運行時,沒有什么改不了),這樣proguard就會置之不理,這樣你的日志代碼就暴露出來了,一字之差,失之千里。拋棄日志類假設(shè)我們使用了靜態(tài)常量代碼塊以及proguard優(yōu)化代碼的技術(shù);但是依然采用上面的日志類的技術(shù),會發(fā)生什么呢?public

class

LogUtil

{

private

static

final

boolean

DEBUG

=

false;

public

static

void

d(String

tag,

String

msg)

{

if

(DEBUG)

android.util.Log.d(tag,

msg);

}

}我寫了一個demo,自己打包然后反編譯,得到這個日志類如下(為了方便看,沒有混淆):package

com.example.test.app;

public

class

LogUtil

{

private

static

final

boolean

DEBUG;

public

LogUtil()

{

super();

}

public

static

void

d(String

tag,

String

msg)

{

}

}我們看到,if代碼塊已經(jīng)沒有了,確實不會輸出任何日志;但是,我們看看調(diào)用這個類的地方!掩耳盜鈴的日志這個LogUtil.d的調(diào)用,無異于掩耳盜鈴;雖然破解者沒辦法讓android.util.Log這個類輸出任何日志,但是你這里的這個調(diào)用還是告訴了別人你在干什么;所以,要屏蔽日志的輸出,必須使用if代碼塊直接包含要被剔除的日志。上面的那個日志類,要被優(yōu)化掉,那就是:if

(DEBUG)

{

LogUtil.d(TAG,

"msg");

}這里,不是多此一舉嗎,寫一個日志類就是想不想重復(fù)地寫if(DEBUG),這里為了使這一句隱藏,還是逃不掉;但是很抱歉,逃得了和尚逃不了廟,這種方法沒辦法做到完全隱藏信息;必須拋棄日志類包裹日志代碼的做法!解放雙手的補充也許有人說,為了這個所謂的日志安全,每次輸出日志都的寫一個if語句,那不麻煩死;簡直反人類,我懶!實際上,要少寫幾行代碼,我們可以選擇復(fù)用(代碼級別,比如上面的日志類),也可以選擇生成(

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論