首页 > 代码库 > Cydia Substrate框架Android so hook分析

Cydia Substrate框架Android so hook分析

         最近需要用到Android so hook,于是分析了一下比较流行的Cydia Substrate框架

         CydiaSubstrate框架的核心函数是MSHOOKFunction,官方使用说明如下:

技术分享

         现在Android 默认编译出来的都是thumb指令集的,就分析一下这个模式下的HOOK吧。

         在使用MSHOOKFunction HOOK前,先用IDA attach到进程先看下准备HOOK的函数,前面18个字节的二进制指令如下:

52ABF480 30 B5       PUSH            {R4,R5,LR}

52ABF482 8D B0       SUB             SP, SP, #0x34

52ABF484 05 1E       SUBS            R5, R0, #0

52ABF486 10 D1       BNE             loc_52ABF4AA

52ABF488 0C 1E       SUBS            R4, R1, #0

52ABF48A 28 D0       BEQ             loc_52ABF4DE

52ABF48C 15 49       LDR             R1, =(aSign - 0x52ABF496)

52ABF48E 02 23       MOVS            R3, #2

52ABF490 5B 42       NEGS            R3, R3

HOOK后的指令如下:

52ABF480 78 47       BX              PC

52ABF480             ;---------------------------------------------------------------------------

52ABF482 C0          DCB 0xC0 ;

52ABF483 46          DCB 0x46 ; F

52ABF484             ; ---------------------------------------------------------------------------

52ABF484             CODE32

52ABF484

52ABF484             loc_52ABF484                            ; CODE XREF:_F14700dj

52ABF484 04 F0 1F E5 LDR             PC, =(sub_58F7C000+1)

52ABF484             ; ---------------------------------------------------------------------------

52ABF488 01 C0 F7 58 off_52ABF488 DCDsub_58F7C000+1         ; DATA XREF:_F14700d:loc_52ABF484r

52ABF488             ; End of function _F14700d

52ABF488

52ABF48C             ; ---------------------------------------------------------------------------

52ABF48C             ; START OF FUNCTION CHUNK FORsub_58F7D000

52ABF48C             CODE16

52ABF48C

52ABF48C             loc_52ABF48C       ;CODE XREF: sub_58F7D000:loc_58F7D010j

52ABF48C                                                 ; DATA XREF: sub_58F7D000:loc_58F7D010o ...

52ABF48C 15 49       LDR             R1, =(aSign - 0x52ABF496)

52ABF48E 02 23       MOVS            R3, #2

52ABF490 5B 42       NEGS            R3, R3

 

       HOOK前后对比,发现函数的前面12个字节的指令被替换了,这12个字节指令就是实现了一个跳转功能,跳转到过滤函数sub_58F7C000。仔细看一下,还是觉得有点奇怪的地方,LDR     PC,=(sub_58F7C000+1)这个指令比较明显就是跳转的功能,那为前面的BX PC只是为了跳转到这条指令,为什么要这样用?而不是直接使用LDR     PC,=(sub_58F7C000+1)进行跳转呢,BX PC是不是多此一举呢?

      后来经过手动patch测试后发现,这条指令不可缺少的,因为LDR     PC,=(sub_58F7C000+1)指令是arm指令集的,而我们的原始函数使用的是thumb指令集,直接在函数开头放上arm指令集的指令,CPU不会把它识别为arm指令,仍然把它做为thumb指令,这样就会执行出错了。这里的BX PC可进行指令集切换,这样就可以正常执行了。

      另外这里的LDR     PC,=(sub_58F7C000+1)指令使用sub_58F7C000+1做为跳转地址,而不是sub_58F7C000,也是因为指令集的原因,尾巴上带1的指令告诉CPUsub_58F7C000函数是thumb指令集的,不带1的话,就被认为是arm指令集了

     MSHookFunction会返回一个old地址,old地址指向的函数,需要实现原函数相同的功能,但是这里的前面12个字节已经被覆盖掉了,是不是old可以直接执行原来的12个字节后跳转回0x52ABF48C就可以了呢?

我们直接来看下old指向的地址(在IDA里转成CODE的时候有的时候会失败,是因为它默认把指令当成arm指令集来识别,按Alt+Gvalue设为1改成thumb模式再转就可以)

debug141:58F7D000 30 B5       PUSH            {R4,R5,LR}

debug141:58F7D002 8D B0       SUB             SP, SP, #0x34

debug141:58F7D004 05 1E       SUBS            R5, R0, #0

debug141:58F7D006 0D D1       BNE             sub_58F7D024

debug141:58F7D008 0C 1E       SUBS            R4, R1, #0

debug141:58F7D00A 05 D0       BEQ             sub_58F7D018

debug141:58F7D00C 78 47       BX              PC

debug141:58F7D00C             ;---------------------------------------------------------------------------

debug141:58F7D00E C0          DCB 0xC0 ;

debug141:58F7D00F 46          DCB 0x46 ; F

debug141:58F7D010             ;---------------------------------------------------------------------------

debug141:58F7D010             CODE32

debug141:58F7D010

debug141:58F7D010             loc_58F7D010                            ; CODE XREF:sub_58F7D000+Cj

debug141:58F7D010 04 F0 1F E5 LDR             PC, =(loc_52ABF48C+1)

debug141:58F7D010             ; End of function sub_58F7D000

debug141:58F7D010

debug141:58F7D010             ;---------------------------------------------------------------------------

debug141:58F7D014 8D F4 AB 52 off_58F7D014 DCDloc_52ABF48C+1         ; DATA XREF:sub_58F7D000:loc_58F7D010r

debug141:58F7D018             CODE16

debug141:58F7D018

debug141:58F7D018             ; =============== S U B R O U T IN E =======================================

debug141:58F7D018

debug141:58F7D018             ; Attributes: thunk

debug141:58F7D018

debug141:58F7D018             sub_58F7D018                            ; CODE XREF: sub_58F7D000+Aj

debug141:58F7D018 78 47       BX              PC

debug141:58F7D018             ;---------------------------------------------------------------------------

debug141:58F7D01A C0          DCB 0xC0 ;

debug141:58F7D01B 46          DCB 0x46 ; F

debug141:58F7D01C             ;---------------------------------------------------------------------------

debug141:58F7D01C             CODE32

debug141:58F7D01C

debug141:58F7D01C             loc_58F7D01C                            ; CODE XREF:sub_58F7D018j

debug141:58F7D01C 04 F0 1F E5 LDR             PC, =(loc_52ABF4DE+1)

debug141:58F7D01C             ;---------------------------------------------------------------------------

debug141:58F7D020 DF F4 AB 52 off_58F7D020 DCD loc_52ABF4DE+1         ; DATA XREF:sub_58F7D018:loc_58F7D01Cr

debug141:58F7D020             ; End of function sub_58F7D018

debug141:58F7D020

debug141:58F7D024             CODE16

debug141:58F7D024

debug141:58F7D024             ; =============== S U B R O U T IN E =======================================

debug141:58F7D024

debug141:58F7D024             ; Attributes: thunk

debug141:58F7D024

debug141:58F7D024             sub_58F7D024                            ; CODE XREF:sub_58F7D000+6j

debug141:58F7D024 78 47       BX              PC

debug141:58F7D024             ;---------------------------------------------------------------------------

debug141:58F7D026 C0          DCB 0xC0 ;

debug141:58F7D027 46          DCB 0x46 ; F

debug141:58F7D028             ; ---------------------------------------------------------------------------

debug141:58F7D028             CODE32

debug141:58F7D028

debug141:58F7D028             loc_58F7D028                            ; CODE XREF:sub_58F7D024j

debug141:58F7D028 04 F0 1F E5 LDR             PC, =(sub_52ABF4AA+1)

debug141:58F7D028             ;---------------------------------------------------------------------------

debug141:58F7D02C AB F4 AB 52 off_58F7D02C DCDsub_52ABF4AA+1         ; DATA XREF:sub_58F7D024:loc_58F7D028r

debug141:58F7D02C             ; End of function sub_58F7D024

 

    这段内存是新分配的内存,整个指令比原来长很多,除了后面增加了很多指令,第4条指令和第6条指令也跟原来不一样了。

   分析可知,第4和第6条指令都为条件短跳指令,这里要从0x58F7D006跳到0x52ABF4AA仅通过一个字节的偏移已经跳不回去了,所以需要把这里的短跳转换为长跳,这里先跳转到0x58F7D024近处的指令,再使用远跳指令跳到0x52ABF4AA除了跳转指令,BL,BLX这样的CALL指令,还有涉及到PC值的指令,也需要经过类似的转换才行。如果前面12个字节不需要转换的话,直接使用原来的12字节指令就可以了。

 

总结:

Cydia Substrate框架的

优点:

相比调用不停重写函数前面一些指令的框架,更为稳定,支持多线程并发运行。old函数处理较好,基本上需要替换的指令都能比较好的支持

缺点:

arm代码编译后比较紧凑,函数之间不留有空隙,thumb指令集在不影响其它寄存器的条件下,12个字节的跳转指令长度已经到达极限,太短的函数是无法做inline hook的。

即使长度够的话,也并不是完美的,举个会发生异常的例子:如果12个字节之后的指令有往最前面12字节内回跳的话,这样就会挂掉

 

 


本文出自 “燕十二” 博客,请务必保留此出处http://chenjava.blog.51cto.com/374566/1591735

Cydia Substrate框架Android so hook分析