首页 > 其他分享 >android ebpf之uprobe原理和检测方法

android ebpf之uprobe原理和检测方法

时间:2023-11-01 20:55:34浏览次数:35  
标签:调用 ebpf vma hook 指令 xol android uprobe

uprobe通过内核层对用户层进程的指定地址的原指令copy到其他位置,然后写入指定类型中断指令,然后内核中设置对应的中断处理程序,中断处理程序中执行uprobe设置的回调过滤函数,然后设置单步执行copy的原指令后恢复寄存器状态继续执行。ida查看被uprobehook的函数头部,指令被修改为了中断指令BRK #5

uprobe原理源码分析

uprobe注册

分为两种情况:一种是对已经创建的进程,一种是对新创建的进程。对于已经创建的进程而言,当通过ebpf附加回调函数到uprobe时,内核最终会调用__uprobe_register。此函数调用alloc_uprobe申请一个struct uprobe结构体保存hook的目标函数偏移以及设置的uprobe回调函数等信息,接着传给register_for_each_vma

register_for_each_vma中先调用find_vmam_struct mm进程内存描述符中找到需要hook的地址对应的线性内存描述符vm_area_struct *vma,之后valid_vma验证线性内存描述符的权限,含有WRITE可写权限的text段将验证失败。如果验证成功则会调用install_breakpoint将目标hook地址的指令先保存,然后向对应的线性地址(虚拟地址)写入断点指令(AARCH64_BREAK_MON | (UPROBES_BRK_IMM << 5)) = 0xd4200000 | ( 5 << 5)= 0xd42000A0

第二种情况是新创建的进程,当进程的text段被map到进程空间时,会依次调用mmap_region-->vma_merge-->__vma_adjust-->uprobe_mmapuprobe_mmap同样会调用valid_vma验证线性内存描述符的权限,验证成功后调用install_breakpoint将目标hook地址的指令先保存,然后向对应的线性地址(虚拟地址)写入断点指令0xd42000A0(arm64平台)。

uprobe设置中断处理程序

uprobe在内核初始化的时候调用register_user_break_hook注册一个.imm = UPROBES_BRK_IMM = 5 的中断处理程序uprobe_breakpoint_handler和一个单步异常处理函数uprobe_single_step_handler

register_user_break_hook 调用register_debug_hookUPROBES_BRK_IMM中断处理程序加入到user_break_hook链表中

当用户层进程执行到BRK #5指令是会触发中断异常,最后内核中会去执行断点异常处理程序brk_handlerbrk_handler会调用call_break_hookcall_break_hook回去判断是来自用户层还是内核层的异常,如果是用户层的就会获取user_break_hook链表中指定imm对应的中断处理程序,当imm = 5时对应的中断处理程序就是之前设置的uprobe_breakpoint_handler

imm = 5的中断处理程序uprobe_breakpoint_handler会调用uprobe_pre_sstep_notifier,后者会给当前线程设置TIF_UPROBE标志

uprobe触发回调函数

BRK #5中断处理程序执行完之后会调用ret_to_user从内核层返回用户层,此函数进一步调用do_notify_resume

do_notify_resume会检测线程的标志,如果发现TIF_UPROBE的话会去调用uprobe_notify_resume

uprobe_notify_resume第一次调用的时候utask是空的,所以回去调用handle_swbp

handle_swbp先调用handler_chain,此函数会去执行uprobe中保存的回调函数,也就是执行在ebpf附加uprobe时设置的回调函数。执行完回调函数后会调用pre_ssout

pre_ssout会先去调用xol_get_insn_slotarch_uprobe_pre_xol,下面分别看一下这两个函数。

经过如下调用链xol_get_insn_slot-->get_xol_area-->__create_xol_area,查看__create_xol_area函数。

  1. 调用alloc_page(GFP_HIGHUSER)申请4kb物理页
  2. uprobe中保存的hook之前用户层的原始指令copy到这个物理页中
  3. 调用xol_add_vma为此物理页创建名称为[uprobes]用户层map,并将此用户层map的线性地址(虚拟地址)加入到进程内存描述符m_struct mm的线性地址描述符二叉树中(VAD树)。

xol_add_vma 会尝试在较高的用户地址空间创建这个名称为[uprobes]map,然后设置其属性为 VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO,这里注意具有VM_IO属性的内存,通过ptrace是无法访问的,因为ptrace内部有权限判断,如果目标内存具有VM_IO属性操作会被拒绝。

pre_ssout调用完xol_get_insn_slot之后会调用arch_uprobe_pre_xol

  1. arch_uprobe_pre_xol函数会将保存的寄存器环境中的ip设置为[uprobes]中保存原始指令的地址,同时设置单步执行
  2. arch_uprobe_pre_xol函数调用完后,设置uprobe_taskactive_uprobestate

这样在执行完原始指令后会返回到内核中调用单步异常处理函数uprobe_single_step_handleruprobe_single_step_handler会调用uprobe_post_sstep_notifier设置线程标志TIF_UPROBE

因为设置了线程标志TIF_UPROBE,所以在内核返回到用户层之前还会调用ret_to_user-->do_notify_resume-->uprobe_notify_resume,不同的是这次active_uprobeutask都是在设置单步异常之前调用handle_swbp创建好的,因此这次是执行handle_singlestep函数而不是handle_swbp

handle_singlestep调用arch_uprobe_post_xol将单步异常的返回地址设置为之前执行BRK #5指令的返回地址,即hook地址的下一条指令对应的地址。接着进行一些资源的清理并将active_uprobe置空,最后会返回到用户层继续执行BRK #5后面剩余的指令

uprobe检测

检测断点指令

uprobe会将hook地址的指令修改为BRK #5,对应的字节码为A0 00 20 D4,可以对关键的函数进行字节码扫描,或者crc校验。

检测[uprobes]

uprobe会将hook点原始指令放在名称为[uprobes]名称的map中,通过扫描map表查看是否有名称为[uprobes]的虚拟内存。

为text段增加可写属性

因为在注册uprobe的时候其会调用valid_vma判断目标地址所在的代码段是否具有VM_WRITE可写属性,如果有的话就拒绝注册。通过给so的代码段增加可写属性可以阻止uprobe设置hook。

因为在android平台从android 8.0开始就不支持加载具有可写属性的代码段,其是通过linker程序对此增加的限制,在linker调用ElfReader::LoadSegments加载so文件的各个段时,如果判断一个段同时具有PROT_EXEC | PROT_WRITE属性就会拒绝加载。

ElfReader::LoadSegments如果判断段的属性没问题会通过调用mmap64将段加载到内存,可以通过前驱so 去 hook libcmmap64并在加载受保护so加载的时候增加可写属性。

方法二和三都是可以修改内核规避的,修改map名称,去除对WRITE属性的判断。方法一如果crc检测逻辑和扫描逻辑被定位到也是可以绕过,所以应该尽量做的隐蔽点。

以上均为个人观点,仅供参考。
参考:
https://blog.csdn.net/sinat_32960911/article/details/133807486
https://blog.csdn.net/feelabclihu/article/details/105872886

标签:调用,ebpf,vma,hook,指令,xol,android,uprobe
From: https://www.cnblogs.com/revercc/p/17803876.html

相关文章

  • Android GB28181历史视音频远程回放
     作为GB28181安卓客户端,实时视音频点播是必须支持的功能,对于历史视音频回放功能,不支持的话可以从设备上拷贝录像文件再播放,但有些场景没法拷贝,安卓支持回放还是需要的。 历史视音频的回放和实时视音频点播信令上很相似,音视频数据都是通过RTP传输,信令回放要处理SIPINFO消息,解析......
  • Hbuilderx运行uni-app项目到Android Studio模拟器只显示“同步手机端程序文件完成”界
    如图,开发工具也显示同步文件,模拟器也显示同步文件完成,但是就是不展示页面,遇到这种情况,一般是2种情况,一个是项目本身有问题跑不起来,另一个就是创建的模拟器设备参数不支持当前app。一.连接真机调试,排除项目本身问题:如果连接真机都跑不起来,那么看下控制台日志,先解决项目本身的问......
  • 基于eBPF是云原生可观测实践
    eBPF技术是Linux内核3.15版本中引入的全新设计,自从2014年发布以来,一直都备受瞩目。在过去几年中,基于eBPF技术的实践和工程落地层出不穷,出现了爆发式的增长。2015年微软、Google、Facebook、Netflix和Isovalent也共同宣布在Linux基金会下成立了一个新的eBPF基金会,以帮助支持......
  • Android自动化测试框架:UiAutomator和UiAutomator2的区别与示例代码
    UiAutomator和UiAutomator2是两种常用的Android自动化测试框架,它们都是由Google开发的。然而,它们之间存在一些关键的区别:API级别:UiAutomator框架在Android4.3(API级别18)中引入,而UiAutomator2在Android5.0(API级别21)中引入。测试能力:UiAutomator只能测试Android系统应用......
  • 关于Android桌面小组件相关的开发,涉及到的一些点
    你可能用过一些AndroidAPP的小组件,比如:支付宝的小组件:之前疫情期间添加了对应小组件卡片在桌面,可点击小卡片上的查看健康码的按钮,可一键打开健康码。音乐类APP的小组件:添加对应对应小组件后,可在APP的主屏幕中轻松看到当前播放歌曲的相关信息:歌曲封面、歌曲名、歌手名称、所......
  • 19万字Android Framework面试通关秘籍,打破技术壁垒
    2023年已经接近尾声了,疫情的影响也在逐渐减小,市场慢慢复苏。不过最近还是会有一些,“Android市场饱和了”、“大环境还是不好”、“投几十个简历都没有一个约面的”的声音。其实并不是岗位需求量变少了,是越来越多的公司需要【中、高级Android工程师】。企业的用人需求越来越高,面试通......
  • 掌握《Android Framework源码开发揭秘》,成为移动开发领域的领跑者
    前言前两天被一条消息给震惊到了:阿里上半年裁员超1.36万人,今年将新增近6000名应届大学生。差点以为阿里扛不住了。。。。裁员这个事大家应该见怪不怪,这两年,我们已经被一波又一波的裁员浪潮,冲激得可以说是麻木了,但是1.36万这个数字还是挺吓人的。对于企业来说,这是调整经营策略、优化......
  • Android Studio 新项目没有layout
    说明今天安装完新版本的AndroidStudio后,新建项目发现没有layout文件夹,网上搜索得知,原来是官方新增了选项。调整后IntelliJIDEA2023.2.1之前的版本,EmptyActivity是指EmptyViewActivity,而现在EmptyActivity是指EmptyComposeActivity,另外多了一个EmptyViewActiv......
  • android ebpf中的CO-RE学习
    CO-RE原理因为不同的内核版本的系统内部结构体会有差异,例如structuser_arg_ptr,当内核编译配置中存在CONFIG_COMPAT=y的时候,会在native成员之前增加一个布尔变量is_compat,这样native的偏移就发生的变化。如果编写的ebpf内核程序需要访问structuser_arg_ptr类型的变量就需要考......
  • Android之WebView显示PDF文档
    参考:https://blog.csdn.net/Android_Cll/article/details/131641229https://cloud.tencent.com/developer/article/2301730Android项目新增js:/app/src/main/assets/wwwroot/index.js我新建了一个wwwroot放里面了。自己看着办。varurl=location.search.substring(1);PDFJS.......