内核系统调用openat Hook(Android10)

2024-06-07 23:38

本文主要是介绍内核系统调用openat Hook(Android10),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

以下操作基于安卓10系统lineageOs 17.1源码研究,手机型号oneplus3 镜像研究测试。

一、安卓内核模块开发编译

    安卓系统如何开发内核可加载模块参考以下文章:
 "安卓10源码学习开发定制(11)内核篇之安卓内核可加载模块开发编译"

二、内核系统调用hook原理

    内核系统调用hook主要是在内核模块加载的时候,通过修改替换内核系统调用表sys_call_table的系统调用号地址来实现目的。

三、内核源码默认配置修改支持系统调用挂钩功能

  • 为了通过insmod命令加载内核模块,需要增加Android内核可加载内核模块配置的支持。

  • 为了获取sys_call_table导出全局内核符号表的地址需要增加内核符号表导出配置功能。

  • 为了向内核内存空间读写数据,需要禁用Android内核的内存保护。需要关闭CONFIG_STRICT_MEMORY_RWX这个选项来编译内核。

   如下是所有相关的配置修改:

# ///ADD START
# 允许通过insmod命令加载模块
CONFIG_MODULES=y
# 允许通过命令rmmod命令卸载内核模块
CONFIG_MODULE_UNLOAD=y
# 关闭内核内存读写保护
CONFIG_STRICT_MEMORY_RWX=n# 打开该配置使符号表中包含所有的函数地址
CONFIG_KALLSYMS=y# 打开该配置方便通过adb shell cat /proc/kallsyms查看内核导出的符号地址
CONFIG_KALLSYMS_ALL=y
# ///ADD END

  将以上配置追加到安卓源码内核源文件中,文件路径如下:

home/qiang/lineageOs/kernel/oneplus/msm8996/arch/arm64/configs/lineageos_oneplus3_defconfig

   配置好之后编译一次源码,产生内核的编译输出文件。后续编写内核模块需要依赖这些文件来进行编译。

四、获取内核符号表地址

     将以上内核源码配置修改之后,编译安卓系统。lineageOs源码编译过程中会自动编译内核源码。内核编译输出目录如下:

/home/qiang/lineageOs/out/target/product/oneplus3/obj/KERNEL_OBJ

   在内核编译输出目录找到System.map文件。打开该文件找到system_call_table符号表的地址。如下所示:

qiang@ubuntu:~/lineageOs/out/target/product/oneplus3/obj/KERNEL_OBJ$qiang@ubuntu:~/lineageOs/out/target/product/oneplus3/obj/KERNEL_OBJ$ pwd
/home/qiang/lineageOs/out/target/product/oneplus3/obj/KERNEL_OBJqiang@ubuntu:~/lineageOs/out/target/product/oneplus3/obj/KERNEL_OBJ$ ls -la System.map 
-rw-rw-r-- 1 qiang qiang 4946646 2月   3 22:46 System.mapqiang@ubuntu:~/lineageOs/out/target/product/oneplus3/obj/KERNEL_OBJ$ cat System.map  |grep "sys_call_table"ffffffc000093000 T compat_sys_call_table
ffffffc001057000 R sys_call_table

从以上System.map文件可以知道sys_call_table符号地址为:0xffffffc001057000

五、挂钩openat函数模块开发

     可加载模块openat hook核心关键代码如下:

//保存内核系统原有的openat函数地址
asmlinkage int (*real_openat)(int, const char __user*,int,umode_t);//保存系统调用表地址
void **sys_call_table;// 替换内核系统调用openat新的new_openat函数
int new_openat(int dirfd, const char __user* pathname, int flags,umode_t modex)
{int ret=-1;//cred 中保存了当前进程的uid pid等信息const struct cred *cred = current_cred();kuid_t uid=cred->uid;int pid=current->pid;int myuid=uid.val;if(myuid>10000){char bufname[256]={0};strncpy_from_user(bufname,pathname,255);//打印日志输出测试printk("openat pathname:%s  uid:%d pid:%d\n",bufname,myuid,pid);}ret= real_openat(dirfd, pathname, flags,modex);return ret;
}//模块加载的时候调用
static int __init hook_init(void){printk("load module success\n");//sys_call_table符号地址sys_call_table=(void*)0xffffffc001057000;printk("sys_call_table %p",(void*)sys_call_table);// 获取openat函数的调用地址real_openat = (void*)(sys_call_table[__NR_openat]);printk("11111111  real_openat %p\n",(void*)real_openat);//替换系统调用表openat函数地址sys_call_table[__NR_openat]=(unsigned long*)new_openat;printk("replace openat finish");return 0;
}

六、测试模块

    1. 编译内核模块,本人编译的模块为kernel_hook_openat.ko

        安卓系统如何开发内核可加载模块参考以下文章:
        "安卓10源码学习开发定制(11)内核篇之安卓内核可加载模块开发编译"

    2. 将内核模块adb push到手机,并用insmod命令加载模块,如下图所示:

图片


    3. 打印内核日志验证,日志如下:

4,3927,3837282014,-;load module success
4,3928,3837282027,-;sys_call_table ffffffc00105700011111111  real_openat ffffffc0001db1f8
4,3929,3837282031,-;replace openat finish4,3974,3850163171,-;openat pathname:/system/lib64/libselinux.so  uid:10129 pid:5822
4,3975,3850163867,-;openat pathname:/system/lib64/libcutils.so  uid:10129 pid:5822
4,3976,3850164538,-;openat pathname:/system/lib64/libprocessgroup.so  uid:10129 pid:5822
4,3977,3850164870,-;openat pathname:/system/lib64/libcrypto.so  uid:10129 pid:5822
4,3978,3850165322,-;openat pathname:/system/lib64/libz.so  uid:10129 pid:5822
4,3979,3850165703,-;openat pathname:/system/lib64/libc.so  uid:10129 pid:5822
4,3980,3850167419,-;openat pathname:/system/lib64/libm.so  uid:10129 pid:5822
4,3981,3850167877,-;openat pathname:/system/lib64/libdl.so  uid:10129 pid:5822
4,3982,3850168240,-;openat pathname:/system/lib64/libc++.so  uid:10129 pid:5822
4,3983,3850168565,-;openat pathname:/system/lib64/libpcre2.so  uid:10129 pid:5822
4,3984,3850168795,-;openat pathname:/system/lib64/libpackagelistparser.so  uid:10129 pid:5822
4,3985,3850169027,-;openat pathname:/system/lib64/libbase.so  uid:10129 pid:5822
4,3986,3850169780,-;openat pathname:/system/lib64/libcgrouprc.so  uid:10129 pid:5822
4,3987,3850179680,-;openat pathname:/sys/kernel/mm/transparent_hugepage/enabled  uid:10129 pid:5822
4,3988,3850180250,-;openat pathname:/dev/__properties__/property_info  uid:10129 pid:5822
4,3989,3850180348,-;openat pathname:/dev/__properties__/properties_serial  uid:10129 pid:5822
4,3990,3850180448,-;openat pathname:/dev/__properties__/u:object_r:default_prop:s0  uid:10129 pid:5822
4,3991,3850180496,-;openat pathname:/dev/__properties__/u:object_r:debug_prop:s0  uid:10129 pid:5822
4,3992,3850180572,-;openat pathname:/dev/__properties__/u:object_r:heapprofd_prop:s0  uid:10129 pid:5822
4,3993,3850180722,-;openat pathname:/system/lib64/libnetd_client.so  uid:10129 pid:5822

参考文章:

  • Hooking Android System Calls for Pleasure and Benefit

    https://www.cnblogs.com/lanrenxinxin/p/6289436.html

图片

这篇关于内核系统调用openat Hook(Android10)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1040627

相关文章

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

在C#中调用Python代码的两种实现方式

《在C#中调用Python代码的两种实现方式》:本文主要介绍在C#中调用Python代码的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#调用python代码的方式1. 使用 Python.NET2. 使用外部进程调用 Python 脚本总结C#调

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置

SpringCloud之LoadBalancer负载均衡服务调用过程

《SpringCloud之LoadBalancer负载均衡服务调用过程》:本文主要介绍SpringCloud之LoadBalancer负载均衡服务调用过程,具有很好的参考价值,希望对大家有所帮助,... 目录前言一、LoadBalancer是什么?二、使用步骤1、启动consul2、客户端加入依赖3、以服务

Vue 调用摄像头扫描条码功能实现代码

《Vue调用摄像头扫描条码功能实现代码》本文介绍了如何使用Vue.js和jsQR库来实现调用摄像头并扫描条码的功能,通过安装依赖、获取摄像头视频流、解析条码等步骤,实现了从开始扫描到停止扫描的完整流... 目录实现步骤:代码实现1. 安装依赖2. vue 页面代码功能说明注意事项以下是一个基于 Vue.js

Linux系统中配置静态IP地址的详细步骤

《Linux系统中配置静态IP地址的详细步骤》本文详细介绍了在Linux系统中配置静态IP地址的五个步骤,包括打开终端、编辑网络配置文件、配置IP地址、保存并重启网络服务,这对于系统管理员和新手都极具... 目录步骤一:打开终端步骤二:编辑网络配置文件步骤三:配置静态IP地址步骤四:保存并关闭文件步骤五:重