androidjni反編譯
1. 如何防止 Android App 被反編譯後介面泄露
2. android jni 使用第三方提供的.so庫及所對應的jar包
1.將SO文件直接放到libs/armeabi下,然後代碼中System.loadLibrary("xxx");再public native static int xxx_xxx_xxx();接下來就可以直接調用xxx_xxx_xxx()方法;
2.第二種方案,創建自己的SO文件,在自己的SO文件里調用第三方SO,再在程序中調用自己的SO,這種比較復雜,需要建java類文件,生成.h文件,編寫C源文件include之前生成的.h文件並實現相應方法,最後用android NDK開發包中的ndk-build腳本生成對應的.so共享庫。 http://www.ijiami.cn/newsInfo?id=293&v=3
2. DEX加殼保護,DEX指令動態載入保護和高級源碼混淆保護。其中DEX加殼保護是「愛加密」主推的賣點,該技術通過將DEX文件隱藏,並生成一個類似於虛像的殼文件,阻止黑客利用反編譯工具獲取App源碼。另外,愛加密http://www.ijiami.cn/推出了so庫保護,使得C/C++ 層面的代碼安全也得到防護。加上資源文件保護(圖片、音頻等文件的防查看和防修改)、xml 主配文件保護(對主配文件進行二次簽名)、內存保護等措施,可以基本保證App的動態和靜態安全。
3. 如何定位Android NDK開發中遇到的錯誤
Android NDK是什麼,為什麼我們要用NDK?
Android NDK 是在SDK前面又加上了「原生」二字,即Native Development Kit,因此又被Google稱為「NDK」。眾所周知,Android程序運行在Dalvik虛擬機中,NDK允許用戶使用類似C / C++之類的原生代碼語言執行部分程序。NDK包括了:
從C / C++生成原生代碼庫所需要的工具和build files。
將一致的原生庫嵌入可以在Android設備上部署的應用程序包文件(application packages files,即.apk文件)中。
支持所有未來Android平台的一些列原生系統頭文件和庫
為何要用到NDK?概括來說主要分為以下幾種情況:
代碼的保護,由於apk的java層代碼很容易被反編譯,而C/C++庫反匯難度較大。
在NDK中調用第三方C/C++庫,因為大部分的開源庫都是用C/C++代碼編寫的。
便於移植,用C/C++寫的庫可以方便在其他的嵌入式平台上再次使用。
Android JNI是什麼?和NDK是什麼關系?
Java Native Interface(JNI)標準是java平台的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI是本地編程介面,它使得在 Java 虛擬機(VM) 內部運行的 Java 代碼能夠與用其它編程語言(如 C、C++和匯編語言)編寫的應用程序和庫進行交互操作。
簡單來說,可以認為NDK就是能夠方便快捷開發.so文件的工具。JNI的過程比較復雜,生成.so需要大量操作,而NDK就是簡化了這個過程。
NDK的異常會不會導致程序Crash,NDK的常見的有哪些類型異常?
NDK編譯生成的.so文件作為程序的一部分,在運行發生異常時同樣會造成程序崩潰。不同於Java代碼異常造成的程序崩潰,在NDK的異常發生時,程序在Android設備上都會立即退出,即通常所說的閃退,而不會彈出「程序xxx無響應,是否立即關閉」之類的提示框。
NDK是使用C/C++來進行開發的,熟悉C/C++的程序員都知道,指針和內存管理是最重要也是最容易出問題的地方,稍有不慎就會遇到諸如內存無效訪問、無效對象、內存泄露、堆棧溢出等常見的問題,最後都是同一個結果:程序崩潰。例如我們常說的空指針錯誤,就是當一個內存指針被置為空(NULL)之後再次對其進行訪問;另外一個經常出現的錯誤是,在程序的某個位置釋放了某個內存空間,而後在程序的其他位置試圖訪問該內存地址,這就會產生一個無效地址錯誤。常見的錯誤類型如下:
初始化錯誤
訪問錯誤
數組索引訪問越界
指針對象訪問越界
訪問空指針對象
訪問無效指針對象
迭代器訪問越界
內存泄露
參數錯誤
堆棧溢出
類型轉換錯誤
數字除0錯誤
NDK錯誤發生時,我們能拿到什麼信息?
利用Android NDK開發本地應用的時候,幾乎所有的程序員都遇到過程序崩潰的問題,但它的崩潰會在logcat中列印一堆看起來類似天書的堆棧信息,讓人舉足無措。單靠添加一行行的列印信息來定位錯誤代碼做在的行數,無疑是一件令人崩潰的事情。在網上搜索「Android NDK崩潰」,可以搜索到很多文章來介紹如何通過Android提供的工具來查找和定位NDK的錯誤,但大都晦澀難懂。下面以一個實際的例子來說明,首先生成一個錯誤,然後演示如何通過兩種不同的方法,來定位錯誤的函數名和代碼行。
首先,看我們在hello-jni程序的代碼中做了什麼(有關如何創建或導入工程,此處略),看下圖:在JNI_OnLoad()的函數中,即so載入時,調用willCrash()函數,而在willCrash()函數中, std::string的這種賦值方法會產生一個空指針錯誤。這樣,在hello-jni程序載入時就會閃退。我們記一下這兩個行數:在61行調用了willCrash()函數;在69行發生了崩潰。
下面來看看發生崩潰(閃退)時系統列印的logcat日誌:
[plain] view plain
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'vivo/bbk89_cmcc_jb2/bbk89_cmcc_jb2:4.2.1/JOP40D/1372668680:user/test-keys'
pid: 32607, tid: 32607, name: xample.hellojni >>> com.example.hellojni <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
r0 00000000 r1 beb123a8 r2 80808080 r3 00000000
r4 5d635f68 r5 5cdc3198 r6 41efcb18 r7 5d62df44
r8 4121b0c0 r9 00000001 sl 00000000 fp beb1238c
ip 5d635f7c sp beb12380 lr 5d62ddec pc 400e7438 cpsr 60000010
backtrace:
#00 pc 00023438 /system/lib/libc.so
#01 pc 00004de8 /data/app-lib/com.example.hellojni-2/libhello-jni.so
#02 pc 000056c8 /data/app-lib/com.example.hellojni-2/libhello-jni.so
#03 pc 00004fb4 /data/app-lib/com.example.hellojni-2/libhello-jni.so
#04 pc 00004f58 /data/app-lib/com.example.hellojni-2/libhello-jni.so
#05 pc 000505b9 /system/lib/libdvm.so
#06 pc 00068005 /system/lib/libdvm.so
#07 pc 000278a0 /system/lib/libdvm.so
#08 pc 0002b7fc /system/lib/libdvm.so
#09 pc 00060fe1 /system/lib/libdvm.so
#10 pc 0006100b /system/lib/libdvm.so
#11 pc 0006c6eb /system/lib/libdvm.so
#12 pc 00067a1f /system/lib/libdvm.so
#13 pc 000278a0 /system/lib/libdvm.so
#14 pc 0002b7fc /system/lib/libdvm.so
#15 pc 00061307 /system/lib/libdvm.so
#16 pc 0006912d /system/lib/libdvm.so
#17 pc 000278a0 /system/lib/libdvm.so
#18 pc 0002b7fc /system/lib/libdvm.so
#19 pc 00060fe1 /system/lib/libdvm.so
#20 pc 00049ff9 /system/lib/libdvm.so
#21 pc 0004d419 /system/lib/libandroid_runtime.so
#22 pc 0004e1bd /system/lib/libandroid_runtime.so
#23 pc 00001d37 /system/bin/app_process
#24 pc 0001bd98 /system/lib/libc.so
#25 pc 00001904 /system/bin/app_process
stack:
beb12340 012153f8
beb12344 00054290
beb12348 00000035
beb1234c beb123c0 [stack]
……
如果你看過logcat列印的NDK錯誤時的日誌就會知道,我省略了後面很多的內容,很多人看到這么多密密麻麻的日誌就已經頭暈腦脹了,即使是很多資深的Android開發者,在面對NDK日誌時也大都默默的選擇了無視。
「符號化」NDK錯誤信息的方法
其實,只要你細心的查看,再配合Google 提供的工具,完全可以快速的准確定位出錯的代碼位置,這個工作我們稱之為「符號化」。需要注意的是,如果要對NDK錯誤進行符號化的工作,需要保留編譯過程中產生的包含符號表的so文件,這些文件一般保存在$PROJECT_PATH/obj/local/目錄下。
第一種方法:ndk-stack
這個命令行工具包含在NDK工具的安裝目錄,和ndk-build和其他一些常用的NDK命令放在一起,比如在我的電腦上,其位置是/android-ndk-r9d/ndk-stack。根據Google官方文檔,NDK從r6版本開始提供ndk-stack命令,如果你用的之前的版本,建議還是盡快升級至最新的版本。使用ndk –stack命令也有兩種方式
使用ndk-stack實時分析日誌
在運行程序的同時,使用adb獲取logcat日誌,並通過管道符輸出給ndk-stack,同時需要指定包含符號表的so文件位置;如果你的程序包含了多種CPU架構,在這里需求根據錯誤發生時的手機CPU類型,選擇不同的CPU架構目錄,如:
[plain] view plain
adb shell logcat | ndk-stack -sym $PROJECT_PATH/obj/local/armeabi
當崩潰發生時,會得到如下的信息:
[plain] view plain
********** Crash mp: **********
Build fingerprint: 'vivo/bbk89_cmcc_jb2/bbk89_cmcc_jb2:4.2.1/JOP40D/1372668680:user/test-keys'
pid: 32607, tid: 32607, name: xample.hellojni >>> com.example.hellojni <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
Stack frame #00 pc 00023438 /system/lib/libc.so (strlen+72)
Stack frame #01 pc 00004de8 /data/app-lib/com.example.hellojni-2/libhello-jni.so (std::char_traits<char>::length(char const*)+20): Routine std::char_traits<char>::length(char const*) at /android-ndk-r9d/sources/cxx-stl/stlport/stlport/stl/char_traits.h:229
Stack frame #02 pc 000056c8 /data/app-lib/com.example.hellojni-2/libhello-jni.so (std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)+44): Routine basic_string at /android-ndk-r9d/sources/cxx-stl/stlport/stlport/stl/_string.c:639
Stack frame #03 pc 00004fb4 /data/app-lib/com.example.hellojni-2/libhello-jni.so (willCrash()+68): Routine willCrash() at /home/testin/hello-jni/jni/hello-jni.cpp:69
Stack frame #04 pc 00004f58 /data/app-lib/com.example.hellojni-2/libhello-jni.so (JNI_OnLoad+20): Routine JNI_OnLoad at /home/testin/hello-jni/jni/hello-jni.cpp:61
Stack frame #05 pc 000505b9 /system/lib/libdvm.so (dvmLoadNativeCode(char const*, Object*, char**)+516)
Stack frame #06 pc 00068005 /system/lib/libdvm.so
Stack frame #07 pc 000278a0 /system/lib/libdvm.so
Stack frame #08 pc 0002b7fc /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+180)
Stack frame #09 pc 00060fe1 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
……(後面略)
我們重點看一下#03和#04,這兩行都是在我們自己生成的libhello-jni.so中的報錯信息,那麼會發現如下關鍵信息:
[plain] view plain
#03 (willCrash()+68): Routine willCrash() at /home/testin/hello-jni/jni/hello-jni.cpp:69
#04 (JNI_OnLoad+20): Routine JNI_OnLoad at /home/testin/hello-jni/jni/hello-jni.cpp:61
回想一下我們的代碼,在JNI_OnLoad()函數中(第61行),我們調用了willCrash()函數;在willCrash()函數中(第69行),我們製造了一個錯誤。這些信息都被准確無誤的提取了出來!是不是非常簡單?
先獲取日誌,再使用ndk-stack分析
這種方法其實和上面的方法沒有什麼大的區別,僅僅是logcat日誌獲取的方式不同。可以在程序運行的過程中將logcat日誌保存到一個文件,甚至可以在崩潰發生時,快速的將logcat日誌保存起來,然後再進行分析,比上面的方法稍微靈活一點,而且日誌可以留待以後繼續分析。
[plain] view plain
adb shell logcat > 1.log
ndk-stack -sym $PROJECT_PATH/obj/local/armeabi –mp 1.log
第二種方法:使用addr2line和objmp命令
這個方法適用於那些,不滿足於上述ndk-stack的簡單用法,而喜歡刨根問底的程序員們,這兩個方法可以揭示ndk-stack命令的工作原理是什麼,盡管用起來稍微麻煩一點,但是可以滿足一下程序員的好奇心。
先簡單說一下這兩個命令,在絕大部分的linux發行版本中都能找到他們,如果你的操作系統是linux,而你測試手機使用的是Intel x86系列,那麼你使用系統中自帶的命令就可以了。然而,如果僅僅是這樣,那麼絕大多數人要絕望了,因為恰恰大部分開發者使用的是Windows,而手機很有可能是armeabi系列。
別急,在NDK中自帶了適用於各個操作系統和CPU架構的工具鏈,其中就包含了這兩個命令,只不過名字稍有變化,你可以在NDK目錄的toolchains目錄下找到他們。以我的Mac電腦為例,如果我要找的是適用於armeabi架構的工具,那麼他們分別為arm-linux-androideabi-addr2line和arm-linux-androideabi-objmp;位置在下面目錄中,後續介紹中將省略此位置:
[plain] view plain
/Developer/android_sdk/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/
假設你的電腦是windows, CPU架構為mips,那麼你要的工具可能包含在這個目錄中:
[plain] view plain
D:\ android-ndk-r9d\toolchains\mipsel-linux-android-4.8\prebuilt\windows-x86_64\bin\
好了言歸正傳,如何使用這兩個工具,下面具體介紹:
1. 找到日誌中的關鍵函數指針
其實很簡單,就是找到backtrace信息中,屬於我們自己的so文件報錯的行。
首先要找到backtrace信息,有的手機會明確列印一行backtrace(比如我們這次使用的手機),那麼這一行下面的一系列以「#兩位數字 pc」開頭的行就是backtrace信息了。有時可能有的手機並不會列印一行backtrace,那麼只要找到一段以「#兩位數字 pc 」開頭的行,就可以了。
其次要找到屬於自己的so文件報錯的行,這就比較簡單了。找到這些行之後,記下這些行中的函數地址
2. 使用addr2line查找代碼位置
執行如下的命令,多個指針地址可以在一個命令中帶入,以空格隔開即可
[plain] view plain
arm-linux-androideabi-addr2line –e obj/local/armeabi/libhello-jni.so 00004de8 000056c8 00004fb4 00004f58
結果如下
[plain] view plain
/android-ndk-r9d/sources/cxx-stl/stlport/stlport/stl/char_traits.h:229
/android-ndk-r9d/sources/cxx-stl/stlport/stlport/stl/_string.c:639
/WordSpaces/hello-jni/jni/hello-jni.cpp:69
/WordSpaces hello-jni/jni/hello-jni.cpp:6
從addr2line的結果就能看到,我們拿到了我們自己的錯誤代碼的調用關系和行數,在hello-jni.cpp的69行和61行(另外兩行因為使用的是標准函數,可以忽略掉),結果和ndk-stack是一致的,說明ndk-stack也是通過addr2line來獲取代碼位置的。
3. 使用objmp獲取函數信息
通過addr2line命令,其實我們已經找到了我們代碼中出錯的位置,已經可以幫助程序員定位問題所在了。但是,這個方法只能獲取代碼行數,並沒有顯示函數信息,顯得不那麼「完美」,對於追求極致的程序員來說,這當然是不夠的。下面我們就演示怎麼來定位函數信息。
使用如下命令導出函數表:
[plain] view plain
arm-linux-androideabi-objmp –S obj/local/armeabi/libhello-jni.so > hello.asm
在生成的asm文件中查找剛剛我們定位的兩個關鍵指針00004fb4和00004f58
從這兩張圖可以清楚的看到(要注意的是,在不同的NDK版本和不同的操作系統中,asm文件的格式不是完全相同,但都大同小異,請大家仔細比對),這兩個指針分別屬於willCrash()和JNI_OnLoad()函數,再結合剛才addr2line的結果,那麼這兩個地址分別對應的信息就是:
[plain] view plain
00004fb4: willCrash() /WordSpaces/hello-jni/jni/hello-jni.cpp:69
00004f58: JNI_OnLoad()/WordSpaces/hello-jni/jni/hello-jni.cpp:61
相當完美,和ndk-stack得到的信息完全一致!
使用Testin崩潰分析服務定位NDK錯誤
以上提到的方法,只適合在開發測試期間,如果你的應用或者游戲已經發布上線,而用戶經常反饋說崩潰、閃退,指望用戶幫你收集信息定位問題,幾乎是不可能的。這個時候,我們就需要用其他的手段來捕獲崩潰信息。
目前業界已經有一些公司推出了崩潰信息收集的服務,通過嵌入SDK,在程序發生崩潰時收集堆棧信息,發送到雲服務平台,從而幫助開發者定位錯誤信息。在這方面,處於領先地位的是國內的Testin和國外的crittercism,其中crittercism需要付費,而且沒有專門的中國開發者支持,我們更推薦Testin,其崩潰分析服務是完全免費的。
Testin從1.4版本開始支持NDK的崩潰分析,其最新版本已經升級到1.7。當程序發生NDK錯誤時,其內嵌的SDK會收集程序在用戶手機上發生崩潰時的堆棧信息(主要就是上面我們通過logcat日誌獲取到的函數指針)、設備信息、線程信息等等,SDK將這些信息上報至Testin雲服務平台,只要登陸到Testin平台,就可以看到所有用戶上報的崩潰信息,包括NDK;並且這些崩潰做過歸一化的處理,在不同系統和ROM的版本上列印的信息會略有不同,但是在Testin的網站上這些都做了很好的處理,避免了我們一些重復勞動。
上圖的紅框部分,就是從用戶手機上報的,我們自己的so中報錯的函數指針地址堆棧信息,就和我們開發時從logcat讀到的日誌一樣,是一些晦澀難懂的指針地址,Testin為NDK崩潰提供了符號化的功能,只要將我們編譯過程中產生的包含符號表的so文件上傳(上文我們提到過的obj/local/目錄下的適用於各個CPU架構的so),就可以自動將函數指針地址定位到函數名稱和代碼行數。符號化之後,看起來就和我們前面在本地測試的結果是一樣的了,一目瞭然。
而且使用這個功能還有一個好處:這些包含符號表的so文件,在每次我們自己編譯之後都會改變,很有可能我們剛剛發布一個新版本,這些目錄下的so就已經變了,因為開發者會程序的修改程序;在這樣的情況下,即使我們拿到了崩潰時的堆棧信息,那也無法再進行符號化了。所以我們在編譯打包完成後記得備份我們的so文件。這時我們可以將這些文件上傳到Testin進行符號化的工作,Testin會為我們保存和管理不同版本的so文件,確保信息不會丟失。來看一下符號化之後的顯示:
4. 用jni寫的安卓應用能被反編譯嗎
反編譯是可以的。
但是由於c語言代碼的可讀性本身就很大,反編譯後不可能像java一樣回歸原來的源碼的,反編譯的代碼時沒有數據類型的,所有的數據類型,甚至指針都變成了int類型,c語言的反編譯基本上就可以忽略的功效基本上就可以忽略其功效。
5. android反編譯後怎麼看是不是jni
使用native關鍵字修飾的,很有可能就是
6. Android中可以用C直接開發嗎不用JAVA,JNI也不行,不想被反編譯
可以的,底層原本就是C的,可以直接跨過JAVA層,但是挺麻煩
可以不用JNI,直接從動態連接庫啟動,但是NDK還是要用的,編譯方便
7. 關於Android開發中Java對於.so庫的調用
廠家並沒有欺騙你或者是含糊你的意思,確實是只提供給你jar包以及 so 庫就可以了,做法是這樣子的:
1.比如我現在在用net.sqlcipher.database 這個加密庫(網上能搜得到的,用於資料庫加密)。 那麼我現在就在項目用載入這個jar包(在你的項目單擊右鍵-》屬性-》Java Build Path-》Libraries-》Add Jars,選擇提供給你的jar包,我這里是 sqlcipher.jar,然後在Order and Export勾選你剛剛載入的 jar包。)
2.打開你的workspace目錄,在你的項目目錄下創建一個文件夾libs(如果文件夾不存在的話),然後將提供給你的so庫放入該目錄,基本架構就算是搭建好了。
3.進行開發,這里你需要問一下提供給你jar包的廠家,基本的用法,否則的話是無法進行開發的,因為你都不知道怎麼去用。 sqlcipher的基本用法是:
SQLiteDatabase.loadLibs(this); //載入 so庫文件,你的廠家的方法應該也是類似。
File databaseFile = getDatabasePath(SQLite_toll.DATABASE_NAME);
databaseFile.mkdirs();
databaseFile.delete();
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFile, helper_SharedPreferences.get_str_sp("database_cipher",this), null);
SQLite_toll initToll = new SQLite_toll(this, avaSys);
initToll.onCreate(database);
database.close();
//因為我sqlcipher是用於資料庫加密的,所以你所看到的都是資料庫的一些方法,你廠家提供給你的jar包的用法,你是要去問他們的,或者他們的是否有開源代碼,又或者是網上也有很多人使用,那麼能搜到相關資料。
根據你補充的提問,那麼就是System.loadLibrary(this); ,就可以調用了
8. Android JNI 一般用於做什麼
1.主要是一些演算法的東西吧,因為c/c++比Java效率高,所以應用運行起來速度比較快,特別是一些游戲中的演算法。2.為了保密,我們都知道apk都可以被反編譯,就算有代碼混淆,也只是難看懂,並不是完全看不懂,但用jni編譯成.so就不同了,所以可以達到商業機密不泄露的目的。3.。。。。。還有很多其他好處待研究。
9. 如何防止代碼被反編譯
由於apk是Android虛擬機載入的,它有一定的規范,加密apk後Dalvik無法識別apk了。完全避免是不可能的,總有人能夠破解你的代碼。但是有幾種方式來提高被反編譯取代碼的難度。
1 關鍵代碼使用jni調用本地代碼,用c或者c++編寫,因此相對比較難於反編譯
2 混淆java代碼。混淆是不改變代碼邏輯的情況下,增加無用代碼,或者重命名,使反編譯後的源代碼難於看懂。 網上開源的java代碼混淆工具較多,一般是用ant的方式來編譯的。
1 . 在工程文件project.properties中加入下proguard.config=proguard.cfg , 如下所示:
target=android-8
proguard.config=proguard.cfg
Eclipse會通過此配置在工程目錄生成proguard.cfg文件
2 . 生成keystore (如已有可直接利用)
按照下面的命令行 在D:\Program Files\Java\jdk1.6.0_07\bin>目錄下,輸入keytool -genkey -alias android.keystore -keyalg RSA -validity 100000 -keystore android.keystore
參數意義:-validity主要是證書的有效期,寫100000天;空格,退格鍵 都算密碼。
命令執行後會在D:\Program Files\Java\jdk1.6.0_07\bin>目錄下生成 android.keystore文件。
3. 在Eclipce的操作
File -> Export -> Export Android Application -> Select project -> Using the existing keystore , and input password -> select the destination APK file
經過混淆後的源代碼,原先的類名和方法名會被類似a,b,c。。。的字元所替換,混淆的原理其實也就是類名和方法名的映射。
但4大組件並沒有混淆(所有在清單文件定義的組件不能被混淆),因為系統需要通過清單文件來查找和運行應用程序。
proguard.cfg 文件代碼解讀
-optimizationpasses 5 ->設置混淆的壓縮比率 0 ~ 7
-dontusemixedcaseclassnames -> Aa aA
- ->如果應用程序引入的有jar包,並且想混淆jar包裡面的class
-dontpreverify
-verbose ->混淆後生產映射文件 map 類名->轉化後類名的映射
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* ->混淆採用的演算法.
-keep public class * extends android.app.Activity ->所有activity的子類不要去混淆
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>; -> 所有native的方法不能去混淆.
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
-->某些構造方法不能去混淆
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * { -> 枚舉類不能去混淆.
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable { -> aidl文件不能去混淆.
public static final android.os.Parcelable$Creator *;
}
10. 怎樣防止Android apk被反編譯,用什麼加密方法來保護dex源碼文件不被注入惡意代碼杜絕二次打包的出現
防止Android apk被反編譯的方法:
判斷apk簽名是否與原版簽名是否一致
代碼混淆,將混淆的級別設置高點,混淆出來以後代碼全部變亂
使用NDK編程,將核心演算法用c/c++來編寫,打包成so庫供java層調用