[實踐] Android5.1.1源碼 - 讓某個APP以解釋執行模式運行

[實踐] Android5.1.1源碼 - 讓某個APP以解釋執行模式運行
 
做者:尋禹@阿里聚安全

 

前言

本文的實踐修改了Android5.1.1的源碼。java

本文只簡單的講了一下原理。在「實踐」一節講了具體作法。android

本文的內容涉及Art模式下dex加載的知識,想要詳細瞭解這部分知識能夠去看老羅的文章: 安全

Android運行時ART簡要介紹和學習計劃 函數

Android運行時ART加載OAT文件的過程分析 post

Android運行時ART加載類和方法的過程分析 學習

Android運行時ART執行類方法的過程分析ui

 

本文的內容涉及zygote,若是不知道zygote是什麼,或者好奇zygote如何啓動,能夠去看老羅的文章: 
Android系統進程Zygote啓動過程的源代碼分析spa

 

老羅的文章分析的是Android2.3的源碼,因此下面提到的與zygote有關的函數在老羅的文章裏面可能沒有,若是想要對下面提到的與zygote有關的函數有一個簡單的瞭解能夠看個人文章:Android5.1.1源碼 - zygote fork出的子進程如何權限降級.net

 

原理簡介

怎麼才能讓方法解釋執行

在函數ClassLinker::LinkCode中會連接dex中的方法代碼,這個函數的定義在文件」art/runtime/class_linker.cc」中,下面是它的源碼(這裏只列出了與本文有關的部分):代理

在這個函數中調用了NeedsInterpreter函數判斷當前方法是否要解釋執行,若是返回值爲true,即局部變量enter_interpreter被賦值爲true,那麼調用ArtMethod類中的SetEntryPointFromQuickCompiledCode函數並將GetQuickToInterpreterBridge()的返回值傳入,GetQuickToInterpreterBridge()函數返回用於解釋執行的函數的入口地址,這個入口函數解釋執行dex中的方法。

 

那麼如今來看看NeedsInterpreter函數,這個函數的定義在文件」art/runtime/class_linker.cc」中,下面是它的源碼:

 

當」Runtime::Current()->GetInstrumentation()->InterpretOnly()」返回true且不是本地方法和代理方法,那麼這個函數就會返回true,不然返回false。

 

InterpretOnly函數是Instrumentation類的成員函數,它的函數定義在文件」art/runtime/instrumentation.h」中,下面是它的源碼:

interpret_only_是類Instrumentation的成員變量,是布爾類型。能夠發現InterpretOnly函數僅僅是將」interpret_only_」返回,若是將interpret_only_設置爲true,那麼根據上文分析,全部「非本地且非代理」方法都將被解釋執行。

 

那麼如何將interpret_only_設置爲true哪,在Instrumentation類中有一個ForceInterpretOnly函數,下面是這個函數的源碼:

 

這個函數是Instrumentation類的公有成員函數,因此直接調用這個函數便可將interpret_only_設置爲true。

 

這裏有一個問題,將interpret_only_設置爲true,那麼「非本地且非代理」方法在連接代碼時都將被設置成解釋執行,那麼會不會影響到其餘的APP進程?不會,由於ClassLinker::LinkCode函數對方法的連接是在APP進程的內存中進行的,因此這個操做並不會影響到其餘進程。

這裏進行一個小節,當執行」Runtime::Current()->GetInstrumentation()->ForceInterpretOnly()」語句時,會把Instrumentation對象的interpret_only_成員變量設置爲true。那麼當方法是「非本地且非代理」方法時,NeedsInterpreter函數將返回true,那麼在ClassLinker::LinkCode函數中會將這個方法設置爲解釋執行。

若是要將APP中全部方法都設置爲解釋執行,那麼就須要在連接APP的dex中的方法代碼以前執行」Runtime::Current()->GetInstrumentation()->ForceInterpretOnly()」語句。

調用ForceInterpretOnly函數的時機

個人辦法是在EnableDebugFeatures函數中調用ForceInterpretOnly函數,在這一節中會先說明Android如何執行到EnableDebugFeatures函數,而後會說明在EnableDebugFeatures函數中調用ForceInterpretOnly函數的好處。

全部的Android應用進程都是zygote fork出來的,fork APP進程時的函數調用路徑:

調用完ForkAndSpecializeCommon函數後APP進程就被fork出來了。

 

ForkAndSpecializeCommon函數定義在文件」frameworks/base/core/jni/com_android_internal_os_Zygote.cpp」中,下面它的源碼:

gCallPostForkChildHooks是一個全局變量,它在com_android_internal_os_Zygote.cpp文件的register_com_android_internal_os_Zygote函數中被初始化。

env->CallStaticVoidMethod(…)語句調用了Java方法」Zygote.callPostForkChildHooks」。

 

下面是Zygote.callPostForkChildHooks方法的源碼,這個方法在文件」frameworks/base/core/java/com/android/internal/os/Zygote.java」中:

 

VM_HOOKS是Zygote類的成員變量,下面是它的定義:

 

VM_HOOKS.postForkChild調用的就是ZygoteHooks類中的成員方法postForkChild,這個方法在文件」libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java」中,下面是它的源碼:

 

這個方法中調用了native函數nativePostForkChild,nativePostForkChild函數的C層代碼在文件」/home/sowuy/android/system/art/runtime/native/dalvik_system_ZygoteHooks.cc」中,下面是它的源碼:

 

我將在EnableDebugFeatures函數中調用ForceInterpretOnly函數,緣由有三點:

  1. EnableDebugFeatures函數參數接收的是一個標誌,我能夠設置一個新的標誌位用來表示是否須要調用ForceInterpretOnly函數。
  2. 每次APP啓動的時候都會執行EnableDebugFeatures函數。
  3. EnableDebugFeatures函數被調用的時機好,它運行在fork出的APP進程中,而且在連接APP的dex中的方法前被調用。

 

實踐

修改Zygote.java中的代碼

Zygote.java文件的位置是:frameworks/base/core/java/com/android/internal/os/Zygote.java,在Zygote類中添加一個成員變量:

 

在Zygote類forkAndSpecialize方法的開始部分添加下面的代碼:

 

修改dalvik_system_ZygoteHooks.cc中的代碼

dalvik_system_ZygoteHooks.cc文件的位置是:art/runtime/native/dalvik_system_ZygoteHooks.cc,修改這個文件中的EnableDebugFeatures函數的代碼。

向這個函數中添加下面的代碼:

 

下面是對這個函數修改後的完整代碼:

 

做者:尋禹@阿里聚安全,更多安全技術文章,請訪問阿里聚安全博客

相關文章
相關標籤/搜索