android hook api

android安全可以從三個層面考慮,一次是java虛擬機層,nativec層,還有linux kernel層,本次hook api是屬於nativec層的。
hook api之後就可以使得程序對原有系統函數的調用改為對我們自己編寫的函數的調用,這既可以作為一種攻擊手段,又可以在維持程序運行的情況下更新程序等等。下面談談思路以及實例(以打電話進程com.android.phone為例,項目保密起見,我修改瞭相關函數的名稱,但是思路絕對不假,這事我驗證過的)
           1.向目標進程註入代碼(註入so,並調用該so裡的一個函數)。首先調用ptrace函數,調試com.android.browser進程,在這裡我們需要遍歷該進程加載的libc.so,這裡有我們需要的dlopen,dlsym等函數的地址,我們先中斷com.android.phone,修改其寄存器,壓入參數如我們的so路徑,並將之前找到的dlopen地址壓入寄存器,直接操作blx,就可以讓目標進程調用dlopen加載我們的so,同理dlsym調用我們的so裡的函數。這個已經有大牛寫出來瞭,
           下面就是我做的工作,重定向函數實現hook
2.com.android.phone程序打電話等網絡連接時調用瞭xxx.so,該so維護瞭一個got表和rel.plt表。其中rel.plt表存放瞭外部依賴函數的地址,而got表裡存放的就是本so定義的函數的地址。在上文被註入的so已經和com.android.phone處於一個進程空間,並且可以執行一段我們設定的代碼。我們的代碼應該這麼做。我們也加載xxx.so,這裡不會真正的加載,應該已經加載過瞭,但是我們可以獲得xxx.so的句柄,然後查找到rel.plt表中的dial函數表項。然後加載我們寫的一個myxxx.so,該so裡有我們自己定義的mydial函數,註意兩個函數的簽名必須一致。同理我們找到mydial函數加載後的地址,然後將之前xxx.so的dial表項的函數地址替換為我們的mydial函數的地址。註意在地址替換時需要先調用mprotect函數來突破so內存空間的寫保護。        在mydial函數裡,我們copy瞭dial函數的全部代碼,但是有一個改變。就是將目標電話號碼修改為我們指定的號碼。
        查找函數地址表項代碼為
//handle為目標so的句柄,name為目標函數名
void* getaddr(void *handle,const char *name)

{

if(!handle)
 

return; 

Soinfo *si = (Soinfo*)handle;

Elf32_Sym *symtab = si->symtab; 

const char *strtab = si->strtab; 

Elf32_Rel *rel = si->plt_rel; 

unsigned count = si->plt_rel_count; 

unsigned idx;

 

 

for(idx=0; idx<count; idx++) //外部依賴函數在rel_plt中

       unsigned type = ELF32_R_TYPE(rel->r_info); 

       unsigned sym = ELF32_R_SYM(rel->r_info); 

       unsigned reloc = (unsigned)(rel->r_offset + si->base); 

       char *sym_name = (char *)(strtab + symtab[sym].st_name);

 

 

if(strcmp(sym_name, name)==0)

{

printf("\"plt_rel\" idx:%2d type:%2d sym:%2d sym_name:%-30s addr:%0x\n",idx,type,sym,sym_name,*((unsigned*)reloc));

return (void *)*((unsigned*)reloc);

}

       rel++; 

}

 

 

for(idx=0;idx<si->nchain;idx++) //自定義函數在symtab中

{

unsigned type = ELF32_R_TYPE(symtab[idx].st_info); 

       unsigned sym = ELF32_R_SYM(symtab[idx].st_info);

char *sym_name = (char *)(strtab + symtab[idx].st_name);

 

 

if(strcmp(sym_name, name)==0)

{

printf("\"got\"                idx:%2d sym_name:%-30s st_value:%0x base: %0x\n",idx,sym_name,symtab[idx].st_value,si->base);

return (void *)(symtab[idx].st_value+si->base);

}

};

return NULL;  //not found


至於替換函數執行地址,就是將目標函數地址修改為之前找到的用於代替目標函數執行的函數地址。註意got表中時相對so的base的值,需要加減兩個so的base差值。而rel.plt表中則是絕對地址。
從安全的角度入手,我們可以hook關鍵函數,實現權限操作限制。

You May Also Like