首页
社区
课程
招聘
[原创]Android5.1 Art Hook 技术分享,求加精转正式会员
发表于: 2015-9-16 22:42 31923

[原创]Android5.1 Art Hook 技术分享,求加精转正式会员

2015-9-16 22:42
31923

【原创】Android5.1 Art Hook 技术分享

Hi,大家好,很多次的在各种技术论坛上看到大牛的分享,学到了很多。本着共建社区,共享知识的目的,在这里我和大家分享一下我最近研究到的关于Android5.1的ART HOOK方案。还是demo阶段,请大家多多指正。可以加我QQ 313199058一起探讨。

废话不说,切入正题。
之前看过低端码农关于ART HOOK的思路,有了启发,大家可以先到他的博客上看看他对于ART虚拟机的理解以及他做的hook方案。

http://blog.csdn.net/l173864930/article/details/45035521

他做的是基于android 4.4的hook方案,但是是停留在仅仅打log的阶段,在我后面的测试中发现这其实离真正的hook应用还相去甚远。下面我罗列了一些我需要解决的问题。这些问题,低端码农有解决过一些,有的没有;xposed有解决过一些,有的没有。
我们需要解决如下的几个问题:
1.        如何hook到一个函数
2.        如何回避在输出调用栈时的虚拟机崩溃
3.        如何处理参数
4.        如何处理返回值
5.        如何在不替换libart.so的情况下完成hook
6.        如何在不引用android源码头文件及库的情况下,用NDK直接编译出我们的so

0x00
老调重弹,我先简单介绍一下ART虚拟机关于方法的调用方式。不同于dalvik虚拟机,ART其实包含了两种调用方式——解释执行和机器码执行,首先他没有完全丢弃解释执行的调用方式,因为有些情况下还是需要通过解释执行完成一个函数的运行;接着ART不同于dalvik是因为引入了机器码的运行方式,其实就是在dex opt的时候dex里的一个函数体被优化成了汇编语言编写的机器码,这样运行效率当然高了。
下面看一下oatdump出的某函数片段

4: void com.example.atry.MainActivity.onClick(android.view.View) (dex_method_idx=18)
    DEX CODE:
      0x0000: const/4 v0, #+2
      0x0001: const-wide/16 v2, #+5
      0x0003: invoke-virtual {v4, v0, v2, v3}, void com.example.atry.MainActivity.nativeTest(int, long) // method@17
      0x0006: return-void
    OAT DATA:
      frame_size_in_bytes: 64
      core_spill_mask: 0x00008060 (r5, r6, r15)
      fp_spill_mask: 0x00000000 
      vmap_table: 0xf722d58a (offset=0x0000258a)
      v3/r5, v4/r6, v65535/r15
      mapping_table: 0xf722d584 (offset=0x00002584)
      gc_map: 0xf722d590 (offset=0x00002590)
    CODE: 0xf722d51d (offset=0x0000251d size=104)...
      0xf722d51c: f8d9c010	ldr.w   r12, [r9, #16]  ; stack_end_
      0xf722d520: e92d4060	push    {r5, r6, lr}
      0xf722d524: f2ad0e34	subw    lr, sp, #52
      0xf722d528: 45e6    	cmp     lr, r12
      0xf722d52a: f0c08024	bcc.w   +72 (0xf722d576)
      0xf722d52e: 46f5    	mov     sp, lr
      0xf722d530: 9000    	str     r0, [sp, #0]
      0xf722d532: 1c0e    	mov     r6, r1
      0xf722d534: 9212    	str     r2, [sp, #72]
      0xf722d536: 2202    	movs    r2, #2
      0xf722d538: 9208    	str     r2, [sp, #32]
      0xf722d53a: 2305    	movs    r3, #5
      0xf722d53c: f04f0c00	mov.w   r12, ThumbExpand(0)
      0xf722d540: e9cd3c0a	        
      0xf722d544: 9b0b    	ldr     r3, [sp, #44]
      0xf722d546: 1c31    	mov     r1, r6
      0xf722d548: f8d1e000	ldr.w   lr, [r1, #0]
      0xf722d54c: 9304    	str     r3, [sp, #16]
      0xf722d54e: 9304    	str     r3, [sp, #16]
      0xf722d550: f8dee034	ldr.w   lr, [lr, #52]
      0xf722d554: 9b0a    	ldr     r3, [sp, #40]
      0xf722d556: 2202    	movs    r2, #2
      0xf722d558: f8de0544	ldr.w   r0, [lr, #1348]
      0xf722d55c: f8d0e028	ldr.w   lr, [r0, #40]
      0xf722d560: 47f0    	blx     lr
      suspend point dex PC: 0x0003
      GC map objects:  v4 (r6), v5 ([sp + #72])
      0xf722d562: 3c01    	subs    r4, #1
      0xf722d564: f0008003	beq.w   +6 (0xf722d56e)
      0xf722d568: b00d    	add     sp, sp, #52
      0xf722d56a: e8bd8060	pop     {r5, r6, pc}
      0xf722d56e: f8d9e25c	ldr.w   lr, [r9, #604]  ; pTestSuspend
      0xf722d572: 47f0    	blx     lr
      suspend point dex PC: 0x0006
      0xf722d574: e7f8    	b       -16 (0xf722d568)
      0xf722d576: f8dde008	ldr.w   lr, [sp, #8]
      0xf722d57a: b003    	add     sp, sp, #12
      0xf722d57c: f8d9c274	ldr.w   r12, [r9, #628]  ; pThrowStackOverflow
      0xf722d580: 4760    	bx      r12
      0xf722d582: 0000    	lsls    r0, r0, #0
class MANAGED ArtMethod : public Object {
…
protected:
    Class* declaring_class_;
    uint32_t access_flags_;
    uint32_t code_item_offset_;
    const void* entry_point_from_compiled_code_;
    EntryPointFromInterpreter* entry_point_from_interpreter_;
….
}
ENTRY art_quick_to_interpreter_bridge
    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
    mov     r1, r9                 @ pass Thread::Current
    mov     r2, sp                 @ pass SP
    blx     artQuickToInterpreterBridge    @ (Method* method, Thread*, SP)
    ldr     r2, [r9, #THREAD_EXCEPTION_OFFSET]  @ load Thread::Current()->exception_
    ldr     lr,  [sp, #44]         @ restore lr
    add     sp,  #48               @ pop frame
    .cfi_adjust_cfa_offset -48
    cbnz    r2, 1f                 @ success if no exception is pending
    bx    lr                       @ return on success
1:
    DELIVER_PENDING_EXCEPTION
END art_quick_to_interpreter_bridge
4: void com.example.atry.MainActivity.onClick(android.view.View) (dex_method_idx=18)
    DEX CODE:
      0x0000: const/4 v0, #+2
      0x0001: const-wide/16 v2, #+5
      0x0003: invoke-virtual {v4, v0, v2, v3}, void com.example.atry.MainActivity.nativeTest(int, long) // method@17
      0x0006: return-void
    CODE: 0xf722d51d (offset=0x0000251d size=104)...
      0xf722d51c: f8d9c010	ldr.w   r12, [r9, #16]  ; stack_end_
      0xf722d520: e92d4060	push    {r5, r6, lr}
      0xf722d524: f2ad0e34	subw    lr, sp, #52
      0xf722d528: 45e6    	cmp     lr, r12
      0xf722d52a: f0c08024	bcc.w   +72 (0xf722d576) 
//上面都是检查是否调用函数层数太多,防止栈溢出。
      0xf722d52e: 46f5    	mov     sp, lr
      0xf722d530: 9000    	str     r0, [sp, #0]
      0xf722d532: 1c0e    	mov     r6, r1
      0xf722d534: 9212    	str     r2, [sp, #72]
      0xf722d536: 2202    	movs    r2, #2
      0xf722d538: 9208    	str     r2, [sp, #32]
      0xf722d53a: 2305    	movs    r3, #5
      0xf722d53c: f04f0c00	mov.w   r12, ThumbExpand(0)
      0xf722d540: e9cd3c0a	        
      0xf722d544: 9b0b    	ldr     r3, [sp, #44]
      0xf722d546: 1c31    	mov     r1, r6
      0xf722d548: f8d1e000	ldr.w   lr, [r1, #0]
      0xf722d54c: 9304    	str     r3, [sp, #16]
      0xf722d54e: 9304    	str     r3, [sp, #16]
      0xf722d550: f8dee034	ldr.w   lr, [lr, #52]
      0xf722d554: 9b0a    	ldr     r3, [sp, #40]
      0xf722d556: 2202    	movs    r2, #2//上面都是在构造参数,准备调用下个函数
      0xf722d558: f8de0544	ldr.w   r0, [lr, #1348] //找到了被调用函数nativeTest
      0xf722d55c: f8d0e028	ldr.w   lr, [r0, #40]//取出被调用函数首地址偏移40的地址
      0xf722d560: 47f0    	blx     lr//跳转到偏移40处的地址
      …

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 3
支持
分享
最新回复 (36)
雪    币: 24
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
虽然看不懂,顶一下
2015-9-17 13:44
0
雪    币: 30
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
多谢帮顶,我还会继续更新帖子,尽量不太监
2015-9-18 10:54
0
雪    币: 124
活跃值: (125)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
支持一下,留邮箱发邀!
2015-9-18 11:35
0
雪    币: 6
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
支持楼主,学习一下。
2015-9-20 19:17
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
刚接触安卓安全,感觉有点深了,不过还是学到不少,感谢。
2015-9-20 20:22
0
雪    币: 233
活跃值: (148)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
7
赞,学习了。你的思路跟我的不同,我是替换bridge,而你的是替换地址。我的方法的确不完美,当时也只是想抛砖引玉,现在看来目的已经达到了,赞楼主。
2015-9-20 21:18
0
雪    币: 370
活跃值: (1180)
能力值: ( LV9,RANK:310 )
在线值:
发帖
回帖
粉丝
8
多谢楼主分享
2015-9-20 21:42
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
多谢楼主分享
2015-9-20 22:29
0
雪    币: 30
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
你的文章十分精彩,我也是站在巨人的肩膀上了,向你致敬
2015-9-21 09:08
0
雪    币: 111
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
进来看看。。。。
2015-9-21 12:16
0
雪    币: 1906
活跃值: (712)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
学习了,目前正在学习这一块的东西,欢迎交流
2015-9-21 14:38
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
厉害厉害,不仅技术到家,文章也写得通俗易懂!赞一个
2015-9-21 20:08
0
雪    币: 107
活跃值: (404)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
膜拜学习一下拉....................
2015-9-21 21:04
0
雪    币: 240
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
留着用到来看
2015-9-22 13:17
0
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
留着用到来看
2015-9-22 13:34
0
雪    币: 43
活跃值: (388)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
17
好像和我的做法差不多,楼主看看在hook handler抛一个异常看看,看看进程会不会挂掉。
2015-9-22 23:09
0
雪    币: 30
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
你说的是下图这样的结果吗?
2015-9-23 11:02
0
雪    币: 5
活跃值: (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
真的很不错
2015-9-23 21:24
0
雪    币: 43
活跃值: (388)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
20
[QUOTE=luciya;1393707]你说的是下图这样的结果吗?
[/QUOTE]

图?没看见
2015-9-23 22:06
0
雪    币: 30
活跃值: (36)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
21
你说的问题是我最主要的要解决的问题(见0x01的内容),所以我的解决方案在这个问题上没问题的。我发的图是成功打印了函数调用栈。
2015-9-26 21:33
0
雪    币: 274
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
不错 收藏
2015-10-7 22:15
0
雪    币: 211
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
不错,正好学习一下。谢谢了
2015-10-8 10:17
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
多谢楼主,支持一下。。
2015-10-12 10:20
0
雪    币: 24
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
顶一下
2015-10-12 12:16
0
游客
登录 | 注册 方可回帖
返回
//