Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 如何防止Android應用代碼被竊

如何防止Android應用代碼被竊

編輯:關於Android編程

 

我們知道apk生成後所有的java生成的class文件都被dx命令整合成了一個classes.dex文件,當apk運行時dalvik虛擬機加載classes.dex文件並且用dexopt命令進行進一步的優化成odex文件。我們的方法就是在這個過程中修改dalvik指令來達到我們的目的。

 

 

一、dex文件格式

dex的文件格式通常有7個主要部分和數據區組成,格式如下:

 

header部分記錄了主要的信息其他的部分只是索引,索引的內容存在data區域。

Header部分結構如下:

\

dex與class文件相比的一個優勢,就是將所有的常量字符串集統一管理起來了,這樣就可以減少冗余,最終的dex文件size也能變小一些。詳細的dex文件介紹就不說了,有興趣的可以查看android 源碼dalvik/docs目錄下的dex-format.html文件有詳細介紹。不過我記得在android4.0版本後就沒有了這個文件。

根據上面的dex文件的格式結構,dalvik虛擬機運行dex文件執行的字節碼就存在method_ids區域裡面。我們查看dalvik虛擬機源碼會有一個

struct DexCode {

u2 registersSize;

u2 insSize;

u2 outsSize;

u2 triesSize;

u4 debugInfoOff; /* file offset to debug info stream */

u4 insnsSize; /* size of the insns array, in u2 units */

u2 insns[1];

/* followed by optional u2 padding */

/* followed by try_item[triesSize] */

/* followed by uleb128 handlersSize */

/* followed by catch_handler_item[handlersSize] */

};

這樣一個結構,這裡的insns數組存放的就是dalvik的字節碼。我們只要定位到相關類方法的DexCode數據段,即可通過修改insns數組,從而實現我們的目的。

 

二、odex文件格式

 

apk安裝或啟動時,會通過dexopt來將dex生成優化的odex文件。過程是將apk中的classes.dex解壓後,用dexopt處理並保存為/data/dalvik-cache/data@app @[email protected]文件。

odex文件結構如下:

\

從上圖中我們發現dex文件作為優化後的odex的一部分,我們只需要從odex中找出dex的部分即可以了。

 

三、方法實現

要實現修改字節碼,就需要先定位到想要修改得代碼的位置,這就需要先解析dex文件。dex文件的解析在dalvik源碼的dexDump.cpp給出了我們具體的實現,根據它的實現我們可以查找我們需要的類及方法。具體實現步驟如下:

(1) 找到我們apk生成的odex文件,獲得odex文件在內存中的映射地址和大小。實現代碼如下:

 

  void *base = NULL;
  
  int module_size = 0;
  
  char filename[512];
  
  // simple test code  here!
  
  for(int i=0; i<2; i++){
  
         sprintf(filename,/data/dalvik-cache/data@app@%s-%[email protected], com.android.dex, i+1);
  
base = get_module_base(-1, filename);//獲得odex文件在內存中的映射地址
  
  if(base != NULL){
  
         break;
  
  }
  
  }
  
 module_size = get_module_size(-1, filename); //獲得odex文件大小
(2) 知道dex文件在odex中的偏移,以便解析dex文件。代碼如下:

 

 

// search dex from odex
  
  void *dexBase = searchDexStart(base);
  
  if(checkDexMagic(dexBase) == false){
  
         ALOGE(Error! invalid dex format at: %p, dexBase);
  
         return;
  
  }

(3) 找到dex偏移以後就可以解析dex文件,從而查找我們要進行替換的方法所在的類,然後在該類中找到該方法並返回該方法對應的DexCode結構體。函數實現如下:

 

 

static const DexCode *dexFindClassMethod(DexFile *dexFile, const char *clazz, const char *method)
  
{
  
    DexClassData* classData = dexFindClassData(dexFile, clazz);
  
    if(classData == NULL) return NULL;
  
    const DexCode* code = dexFindMethodInsns(dexFile, classData, method);
  
    if(code != NULL) {
  
        dumpDexCode(code);
  
    }
  
    return code;
  
}
(4) 找到DexCode後就可以進行指令替換了。實現如下:

 

 

const DexCode  *code =
  
    dexFindClassMethod(&gDexFile, Lcom/android/dex/myclass;, setflagHidden);
  
const DexCode*code2 =
  
 dexFindClassMethod(&gDexFile, Lcom/android/dex/myclass;, setflag);
  
    // remap!!!!
  
    if(mprotect(base, module_size, PROT_READ | PROT_WRITE | PROT_EXEC) == 0){
  
    DexCode *pCode = (DexCode *)code2;
  
    // Modify!
  
    pCode->registersSize = code->registersSize;
  
        for(u4 k=0; kinsnsSize; k++){
  
               pCode->insns[k] = code->insns[k];
  
        }
  
      mprotect(base, module_size, PROT_READ | PROT_EXEC);
  
}

 

注意:由於是在運行時修改的dalvik指令,這是進程的內存映射為只讀的,所以需要調用mprotect函數將只讀改為讀寫才能進行指令的修改。

 

根據上面的講述相信大家對運行時修改字節碼的技術有了一定的了解,下一篇我們將講解另一種android apk防止反編譯技術,期待大家的捧場。如果對這篇講的技術有任何疑問及想要獲得這篇文章講的技術的工程源碼

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved