压在透明的玻璃上c-国产精品国产一级A片精品免费-国产精品视频网-成人黄网站18秘 免费看|www.tcsft.com

改造 Cydia Substrate 框架用于函數內代碼的HOOK

  上一次分析了Cydia Substrate so hook 框架的實現,實際使用中,發現這樣的框架并不能滿足我的一些需求,比如我要知道一個函數內部某處代碼的運行時的寄存器值,用原始的框架就無法做到。

  想實現的功能是只要指定一個地址,就可以打印該處代碼執行時的寄存器環境、HOOK的地址以及線程的TID,同時支持多個地址的添加。

  先實現一個通用的消息打印函數

  void printAllReg(int Reg_R0,int Reg_R1,int Reg_R2,int Reg_R3,int Stack_SP,int Stack_SP2)

  {

  int *pSP2 = &Stack_SP2;

  int Reg_R12 = *(pSP2+1);

  int Reg_R11 = *(pSP2+2);

  int Reg_R10 = *(pSP2+3);

  int Reg_R9 = *(pSP2+4);

  int Reg_R8 = *(pSP2+5);

  int Reg_R7 = *(pSP2+13);

  int Reg_R6 = *(pSP2+12);

  int Reg_R5 = *(pSP2+11);

  int Reg_R4 = *(pSP2+10);

  char *pFormat="Hookaddr:0x%08x tid=%x R0:0x%08x R1:0x%08x R2:0x%08x R3:0x%08x
R4:0x%08xR5:0x%08x R6:0x%08x R7:0x%08x R8:0x%08x R9:0x%08x R10:0x%08x R11:0x%08xR12:0x%08x ";

  LOGD(pFormat,(Stack_SP2-1-(int)pSSELibBase),gettid(),Reg_R0,Reg_R1,Reg_R2,Reg_R3,Reg_R4,Reg_R5,Reg_R6,Reg_R7,Reg_R8,Reg_R9,Reg_R10,Reg_R11,Reg_R12);

  }

  里面具體的參數意義后面再講。

  printAllReg要由一個中轉函數來調用,這個函數必須滿足如下要求:

  1.調用前后不能改變R0-R12,LR寄存器的值

  2.調用完打印函數后,跳到old函數

  3.把監控地址入棧,這個要求比較關鍵,不然打印出來不知道是哪處代碼在打印,也就沒有意義了。

  根本滿足這三點要求,C語言函數肯定是不行的,只有用arm匯編來實現了

  void HookAddr()

  {

  __asm__(

  "PUSH    {R0-R7}
"//保存可能會改變的寄存器

  "mov r4,r8 
"

  "PUSH  {R4}
"

  "mov r4,r9 
"

  "PUSH  {R4}
"

  "mov r4,r10 
"

  "PUSH  {R4}
"

  "mov r4,r11 
"

  "PUSH  {R4}
"

  "mov r4,r12 
"

  "PUSH  {R4}
"//將r8-r12入棧,直接push {R8}這樣的指令是不支持的

  "ldr r7,=0x1a2b3001
"//0x1a2b3001是什么意思?

  "PUSH  {R7}
"

  "PUSH  {LR}
"//將返回地址入棧,printAllReg執行完后,lr寄存器會變掉

  "ldr r7, =printAllReg 
"//將兩個地址入棧后,調用打印函數

  "BLX r7 
"

  "POP   {R7} 
"

  "mov lr,r7 
"//恢復lr

  "POP   {R7} 
"

  "POP   {R4} 
"

  "mov r12,r4 
"//r12經過rlx后,會變掉,這里專門恢復一下

  "POP    {R0-R3} 
" //平衡堆棧

  "POP    {R0-R7} 
" //恢復r0-r7

  "MOV R0,R0
"   //讓下面的bx pc指令4字節對齊

  "BX PC
"//轉到arm模式,以進行跳轉

  "MOV R0,R0
"//占位

  "MOV R0,R0
"//占位,這里后面會被patch掉

  "MOV R0,R0
"//占位,這里后面會被patch掉

  "MOV R0,R0
"//占位,這里后面會被patch掉

  "BX  LR
"

  );

  這段函數經過編譯后,用IDA反匯編的結果如下:

改造 Cydia Substrate 框架用于函數內代碼的HOOK

  紅框里的指令都是我們需要patch的指令

  0x1A2B3001為這值占用了四個字節,這個值是要入棧給printAllReg的,我們在這里寫入HOOK的地址,就能被printAllReg函數所用了。

  再回頭來看下printAllReg里int Reg_R12 =*(pSP2+1);這樣指令的作用,從中轉函數我們知道,調用printAllReg時,堆棧里值是這樣排列的LR,HOOK Addr,R12,R11,R10,R9,R8,R7,R6,R5,R4,

  Stack_SP2指向的就是HookAddr,向后遞推,就可以把R12-R4的地址讀出來了,當然也可以把改下printAllReg的調用界面,把這些值全放參數里傳過來。

  第一個紅框,patch成跳轉指令,0x16e0放把下四個字節內容加載到PC的指令,0x16e4放跳轉地址

  使用如下函數進行patch

  經過這個函數patch后的中轉函數,如下圖所示

改造 Cydia Substrate 框架用于函數內代碼的HOOK

  每個hook都會分配一段代碼內存用于保存這樣的中轉函數,以后需要監控一個指定函數時,只需要調用setAddrHook,輸入地址就可以了。限于Cydia Substrate框架的限制,輸入的hook地址指向的前面12個字節最好不要被跳轉所分割。

  也可以按此方法對HOOK函數的過濾函數進行通用化改造,實現輸入函數地址即可打印函數調用信息的界面。

    文章來源:http://chenjava.blog.51cto.com/374566/1591851

 

上一篇:安卓防火墻 PS DroidWall

下一篇:Ossim系統常見測試方法