主頁 > 移動端開發 > 018 Android加固之實作dex加載器

018 Android加固之實作dex加載器

2021-08-10 08:03:17 移動端開發

文章目錄

    • Android APK加固-安全人員角度
    • 關于類加載器
      • 類加載器
      • 類加載器的種類和個數
      • 創建類加載實體
      • 類加載器DexClassLoader和PathClassLoader
    • 使用類加載器動態加載dex檔案
      • 制作dex檔案
      • 動態加載dex檔案
      • 完整步驟回顧

Android APK加固-安全人員角度

Android安全人員對APK加固采取的角度大概分為以下幾個方面:

  1. 將可執行代碼dex檔案加密,能夠動態解密并執行
  2. 能夠檢測當前狀態是被除錯,想盡一切辦法反除錯

那如果繼續再細分一下,實作一個初級的APK加固:

  1. 使用類加載器動態加載dex檔案
  2. 設計傀儡dex替換原dex,動態加載dex
  3. 在傀儡dex中的各種地方增加反除錯代碼

接下來就是從類加載器開始一步步完成APK加固

關于類加載器

類加載器

在JAVA開發中動態加載的技術主要用于加載jar包,使軟體具備動態添加插件的功能,Java代碼都是寫在Class里的,程式運行在虛擬機上時,虛擬機需要把需要的Class加載進來才能創建實體物件并作業,而完成這一加載作業的角色就是ClassLoader,

Android的Dalvik/ART虛擬機如同標準JAVA的JVM虛擬機一樣,在運行程式時首先需要將對應的類加載到記憶體中,因此我們可以利用這一點,在程式運行時手動加載Class,從而達到代碼動態加載可執行檔案的目的,

Android的Dalvik/ART虛擬機雖然與標準Java的JVM虛擬機不一樣,ClassLoader具體的加載細節不一樣,但是作業機制是類似的,也就是說在Android中同樣可以采取類似的動態加載jar或者dex的功能,只是在Android應用中動態加載一個jar或者dex的作業要比Eclipse加載一個插件復雜許多

類加載器的種類和個數

動態加載的基礎是ClassLoader,從名字可以看出ClassLoader就是專門用來處理類加載作業的,所以這個類也叫類加載器,而且一個運行中的APP不僅有一個類加載器,

其實在Android系統啟動的時候會創建一個Boot型別的ClassLoader實體,用于加載一些系統Framework層級需要的類,我們的Android應用里也需要用到一些系統的類,所以APP啟動的時候也會把Boot型別的ClassLoader傳進來,此外,APP也有自己的類,

這些類保存在APK的dex檔案里面,所以APP啟動的時候,也會創建一個自己的ClassLoader實體,用于加載自己dex檔案中的類,下面我們在專案里驗證看看,

 public void enmuClassLoader()
    {
        int count=0;
        //獲取當前包的ClassLoader
        ClassLoader classLoader=getClassLoader();
        if (classLoader!=null)
        {
            Log.d("GuiShou","[onCreate] classLoader"+count++ +":"+classLoader.toString());
        }

        while (classLoader.getParent()!=null)
        {
            classLoader=classLoader.getParent();
            Log.d("GuiShou","[onCreate] classLoader"+count++ +":"+classLoader.toString());
        }
    }

在這里插入圖片描述

可以看見有兩個ClassLoader實體,一個是BootClassLoader,系統啟動時候創建的,一個是PathClassLoader,應用啟動時創建的,由此也可以看出,一個運行的Android應用至少有兩個ClassLoader,

創建類加載實體

動態加載外部Dex檔案的時候,我們也可以使用自己創建的ClassLoader實體來加載dex里面的class,不過ClassLoader的創建方式有點特殊,我們先來看看它的構造方法

private ClassLoader(Void unused,ClassLoader parent){
       this.parent=parent;
}

創建一個ClassLoader的時候,需要使用一個現有的ClassLoader的實體作為新創建的實體的Parent,這樣一來,一個Android應用,甚至整個Android系統里所有的ClassLoader實體都會被一棵樹關聯起來,這也是ClassLoader的雙親代理模型(Parent-Delegation Model)的特點

類加載器DexClassLoader和PathClassLoader

在Android中,ClassLoader是一個抽象類,在實際開發程序中,我們一般是使用其子類DexClassLoader和PathClassLoader來加載類的,

它們的不同之處是:

  • DexClassLoader可以加載jar/dex/apk,可以從SD卡中加載未安裝的APK
  • PathClassLoader只能加載系統中已經安裝過的APK

根據功能,我們更加傾向于使用DexClassLoader,所以接下來先使用DexClassLoader來加載一個簡單的dex檔案

使用類加載器動態加載dex檔案

制作dex檔案

為了能與Android的類有互動,先寫這樣一段代碼

public class TestActivity {
    public void CreateVew(Activity ac){
        //創建一個TextView
        TextView tv=new TextView(ac);

        //創建布局 設定引數
        FrameLayout.LayoutParams params=new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.WRAP_CONTENT,
                FrameLayout.LayoutParams.WRAP_CONTENT
        );

        //設定控制元件到頂端的距離
        params.topMargin=0;
        //設定控制元件的位置
        params.gravity= Gravity.TOP|Gravity.CENTER_HORIZONTAL;
        tv.setText("TestActivity View");

        //添加TextView到Avtivity中
        ac.addContentView(tv,params);
    }
}

在這里插入圖片描述

這段代碼的效果就是顯示一段TextView到Activity中

在這里插入圖片描述

這次代碼直接在Android專案中編譯,然后在app的目錄中查找class檔案復制到自己的目錄中即可,類所在的目錄是app/build/intermediates/classes/debug/包名

接下來把當前的這個Activity進行反編譯得到的smali檔案轉成一個dex檔案放到這個工程的資源檔案里

在這里插入圖片描述

將apk用AndroidKiller打開,分析完成后打開smali檔案路徑,復制出一份副本

在這里插入圖片描述

洗掉其余的smali檔案,只保留我們自己寫的TestActivity類的smali,然后通過smali.jar將其轉成dex檔案

在這里插入圖片描述

然后在main檔案夾下新建一個assets檔案夾,將dex檔案復制到里面,并且洗掉TestActivity類

動態加載dex檔案

現在我們已經有了一個制作好的dex檔案,接著就需要將這個dex檔案動態加載進來,想要動態加載dex,需要下面幾個步驟,

  1. 將dex檔案從自定義資源檔案夾拷貝到程式目錄下
  2. 創建一個DexClassLoader,加載dex
  3. 呼叫加載的dex中的class方法

首先拷貝dex檔案

public String CopyDex(String dexName){
        //獲取Asserts目錄管理器
        AssetManager as=getAssets();

        //合成路徑 data/data/包名/files/dex名稱
        String path=getFilesDir()+ File.separator+dexName;

        Log.d("GuiShou",path);

        //創建檔案流
        try {
            FileOutputStream out=new FileOutputStream(path);
            //打開檔案
            InputStream is=as.open(dexName);
            //回圈讀取檔案,拷貝到目標路徑
            byte[] buffer=new byte[1024];
            int len=0;
            while ((len=is.read(buffer))!=-1){
                out.write(buffer,0,len);
            }
            //關閉檔案
            out.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


        return path;
    }

接著創建DexClassLoader

 public DexClassLoader GetLoader(String path){
        //創建dex的類加載器,回傳DexClassLoader物件
        DexClassLoader dexClassLoader=new DexClassLoader(path,  //dex檔案路徑
                getCacheDir().toString(),          //優化后的dex檔案路徑
                null,       //原生庫路徑
                getClassLoader()    //父類加載器
                );
        return dexClassLoader;
    }

最后呼叫加載的dex中的class方法

public void  execClassMethod(DexClassLoader dex,String ClassName, String MethodName){

        try {
            //獲取加載的類資訊
            Class TestDex=dex.loadClass(ClassName);

            //獲取構造方法 無參構造
            Constructor localConstructor=TestDex.getConstructor(new Class[]{});

            //呼叫構造方法 創建物件
            Object instance=localConstructor.newInstance(new Object[]{});

            //獲取成員方法
            Method methodTest=TestDex.getDeclaredMethod(MethodName,new Class[]{Activity.class});

            //取消java訪問檢查,提高反射速度
            methodTest.setAccessible(true);

            //呼叫方法 this指標傳進去
            methodTest.invoke(instance,new Object[]{this});


        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

最后呼叫以上三個函式

    //加載dex
    public void loadDex(){
        //拷貝自定義資源中的dex到程式目錄下
        String dexPath=CopyDex("test.dex");

        //創建一個DexClassLoader,加載dex
        DexClassLoader dexClassLoader=GetLoader(dexPath);

        //呼叫加載dex中的class方法
        execClassMethod(dexClassLoader,"com.example.classloaderdemo.TestActivity","CreateVew");
    }

到這里,代碼就已經全部完成了,

接著運行程式,

在這里插入圖片描述

效果和之前寫的dex檔案代碼一致,那么就說明我們已經完成了動態加載dex檔案的程序,

完整步驟回顧

  1. 新建一個工程,創建TestActivity類,實作一個創建view的方法
  2. 編譯生成apk,使用AndroidKiller反編譯,將除了TestActivity.smali代碼外的全部smali檔案洗掉,編譯生成dex檔案
  3. 在專案main檔案夾創建asserts檔案夾,將生成的dex拷貝到這個目錄下
  4. 在代碼中完成以下步驟
    1. 拷貝自定義資源中的dex到程式目錄下
    2. 創建一個dexClassLoader加載dex
    3. 呼叫加載dex中的class方法

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/292759.html

標籤:其他

上一篇:android學習 之 內容提供器

下一篇:Android FFmpeg集成

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more