Linux 2.6版内核中通过模块获取sys_call_table地址的方法

Linux 抓取sys_call_table地址 本文主要介绍三种方法抓取sys_call_table的地址 方法一:以sys_close为参考,遍历内存 方法二:直接抓/proc/kallsyms 方法三:调用函数kallsyms_lookup_name(“sys_call_table”) #include <linux/module.h> #include <linux/fs.h> #include <linux/syscalls.h> #include <linux/kallsyms.h> MODULE 阅读详情
朱熹之2007-1-4 09:09
Linux 2.6版内核中通过模块获取sys_call_table地址的方法

转自我的blog:
http://blog.chinaunix.net/u/27624/showart_226262.html

本文主要介绍在Linux 2.6版的内核中实现基地址修改的方法。所有代码我都在基于2.6.19版内核的Fedora Core 6上进行了测试。

Linux 2.6版的内核出于安全的考虑没有将系统调用列表基地址的符号sys_call_table导出,但要对系统调用进行替换,却必须要获取该地址,于是就有了这篇文章。

我在这里采用的基本思路是这样的,因为系统调用都是通过0x80中断来进行的,故可以通过查找0x80中断的处理程序来获得sys_call_table的地址。其基本步骤是,首先获取中断描述符表的地址,再从中查找0x80中断的服务例程,再搜索该例程的内存空间,以从其中获取sys_call_table的地址。其代码如下:

#include <linux/module.h>
#include <linux/kernel.h>

// 中断描述符表寄存器结构
struct {
    unsigned short limit;
    unsigned int base;
} __attribute__((packed)) idtr;


// 中断描述符表结构
struct {
    unsigned short off1;
    unsigned short sel;
    unsigned char none, flags;
    unsigned short off2;
} __attribute__((packed)) idt;

// 查找sys_call_table的地址
void disp_sys_call_table(void)
{
    unsigned int sys_call_off;
    unsigned int sys_call_table;
    char* p;
    int i;

    // 获取中断描述符表寄存器的地址
    asm("sidt %0":"=m"(idtr));
    printk("addr of idtr: %x/n", &idtr);

    // 获取0x80中断处理程序的地址
    memcpy(&idt, idtr.base+8*0x80, sizeof(idt));
    sys_call_off=((idt.off2<<16)|idt.off1);
    printk("addr of idt 0x80: %x/n", sys_call_off);

    // 从0x80中断服务例程中搜索sys_call_table的地址
    p=sys_call_off;
    for (i=0; i<100; i++)
    {
        if (p[i]=='/xff' && p[i+1]=='/x14' && p[i+2]=='/x85')
        {
            sys_call_table=*(unsigned int*)(p+i+3);
            printk("addr of sys_call_table: %x/n", sys_call_table);
            return ;
        }
    }
}

// 模块载入时被调用
static int __init init_get_sys_call_table(void)
{
    disp_sys_call_table();
    return 0;
}

module_init(init_get_sys_call_table);

// 模块卸载时被调用
static void __exit exit_get_sys_call_table(void)
{
}

module_exit(exit_get_sys_call_table);

// 模块信息
MODULE_LICENSE("GPL2.0");
MODULE_AUTHOR("Xizhi Zhu");

在编译并载入该模块后,可以通过dmesg命令看到如下的输出:
addr of idtr: d0af4680
addr of idt 0x80: c0103e04
addr of sys_call_table: c03094c0

可见,上面的程序能够获取sys_call_table的地址。

在上面的代码中,最复杂的应该就是从0x80中断的服务例程中搜索sys_call_table的一段了,现解释如下。

首先,我们使用命令“gdb -q /usr/src/kernels/2.6.19/vmlinux”来反编译内核,再使用“disass system_call”和“disass syscall_call”两条gdb命令来查看内核的汇编代码,其结果如下:

(gdb) disass system_call
Dump of assembler code for function system_call:
0xc0103e04 <system_call+0>: push %eax
0xc0103e05 <system_call+1>: cld
0xc0103e06 <system_call+2>: push %es
0xc0103e07 <system_call+3>: push %ds
0xc0103e08 <system_call+4>: push %eax
0xc0103e09 <system_call+5>: push %ebp
0xc0103e0a <system_call+6>: push %edi
0xc0103e0b <system_call+7>: push %esi
0xc0103e0c <system_call+8>: push %edx
0xc0103e0d <system_call+9>: push %ecx
0xc0103e0e <system_call+10>: push %ebx
0xc0103e0f <system_call+11>: mov $0x7b,%edx
0xc0103e14 <system_call+16>: movl %edx,%ds
0xc0103e16 <system_call+18>: movl %edx,%es
0xc0103e18 <system_call+20>: mov $0xfffff000,%ebp
0xc0103e1d <system_call+25>: and %esp,%ebp
0xc0103e1f <system_call+27>: testl $0x100,0x30(%esp)
0xc0103e27 <system_call+35>: je 0xc0103e2d <no_singlestep>
0xc0103e29 <system_call+37>: orl $0x10,0x8(%ebp)
End of assembler dump.
(gdb) disass syscall_call
Dump of assembler code for function syscall_call:
0xc0103e44 <syscall_call+0>: call *0xc03094c0(,%eax,4)
0xc0103e4b <syscall_call+7>: mov %eax,0x18(%esp)
End of assembler dump.

其中,system_call是0x80中断的服务例程的入口,而syscall_call是调用指定系统调用的部分。在得到的反汇编代码中可以看到,地址0xc03094c0就是我们需要搜索的sys_call_table的地址。

p.s. 如果不考虑可移植性,我们当然可以直接使用这个地址进行操作。但是,为了获取更好的兼容性,我们应该通过对代码段进行搜索来查找该值。

通过进一步的反汇编,我们可以发现,从system_call开始,到syscall_call结束的汇编代码如下:

0xc0103e04 <system_call+0>: push %eax
0xc0103e05 <system_call+1>: cld
0xc0103e06 <system_call+2>: push %es
0xc0103e07 <system_call+3>: push %ds
0xc0103e08 <system_call+4>: push %eax
0xc0103e09 <system_call+5>: push %ebp
0xc0103e0a <system_call+6>: push %edi
0xc0103e0b <system_call+7>: push %esi
0xc0103e0c <system_call+8>: push %edx
0xc0103e0d <system_call+9>: push %ecx
0xc0103e0e <system_call+10>: push %ebx
0xc0103e0f <system_call+11>: mov $0x7b,%edx
0xc0103e14 <system_call+16>: movl %edx,%ds
0xc0103e16 <system_call+18>: movl %edx,%es
0xc0103e18 <system_call+20>: mov $0xfffff000,%ebp
0xc0103e1d <system_call+25>: and %esp,%ebp
0xc0103e1f <system_call+27>: testl $0x100,0x30(%esp)
0xc0103e27 <system_call+35>: je 0xc0103e2d <no_singlestep>
0xc0103e29 <system_call+37>: orl $0x10,0x8(%ebp)

0xc0103e2d <no_singlestep+0>: testw $0x1c1,0x8(%ebp)
0xc0103e33 <no_singlestep+6>: jne 0xc0103ef8 <syscall_trace_entry>
0xc0103e39 <no_singlestep+12>: cmp $0x140,%eax
0xc0103e3e <no_singlestep+17>: jae 0xc0103f6b <syscall_badsys>

0xc0103e44 <syscall_call+0>: call *0xc03094c0(,%eax,4)
0xc0103e4b <syscall_call+7>: mov %eax,0x18(%esp)

我们不用关心这段代码具体执行了什么操作,值得我们注意的只有一点,就是从 system_call开始,直到正式发生系统调用时才出现了第一个call语句。我们可以利用这一点来进行搜索。再通过“x/xw (syscall_call)”命令来查看call语句的指令码为0xc03094c08514ff。这样,我们就可以利用程序中给出的代码进行查找了。
 
Linux进程地址图文详解 内核空间(Kernel space): 内核空间中存放的是内核代码和数据,而进程的用户空间中存放的是用户程序的代码和数据。不管是内核空间还是用户空间,它们都处于虚拟空间中。 处于用户态的程序只能访问用户空间,而处于内核态的程序可以访问用户空间和内核空间。 用户态和内核态有什么区别呢? 区别: 当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时... 阅读详情

相关推荐

2024年Linux x86平台获取sys_call_table(1),2024年最新面试Linux运维岗

最全的Linux教程,Linux从入门到精通第一份《Linux从入门到精通》466页内容简介====本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。

2401_83947353的博客 1058

获取Linux 2.6.x sys_call_table

网上搜索了一下, 发现此代码主要原理是通过搜索 int 0x80的中断服务程序中的sys_call_table来实现.  在linux中所有的syscall都是调用int 0x80, int 0x80的中断服务程序为system_call(arch/x86/kernel/traps_32.c:set_system_gate(SYSCALL_VECTOR,&system_call).  sy

奋斗中拥有 5643

Linux内核模块编程-系统调用拦截

系统调用拦截本文实验基于Centos6.5 内核版本2.6.32-431.el6.x86_64,系统调用拦截的目的其实就是把系统真正要执行的系统调用替换为我们自己写的内核函数。系统调用拦截的实现那么如何去实现系统调用拦截呢,通过学习系统调用的内核实现我们发现其实系统调用的地址是放在sys_call_table中通过系统调用号定位到具体的系统调用地址,然后开始调用,那么通过编写内核模块来修改sys_c

zyfforlinux 5051

Linux x86平台获取sys_call_table(2),转疯了

Linux 3.10.0 – x86_64最简单获取sys_call_table符号的方法:ffffffff816beee0 R sys_call_table内核模块使用 kallsyms_lookup_name(推荐) 或者 kprobe:unsigned long * __sys_call_table = (unsigned long *)kallsyms_lookup_name(“sys_call_table”);下面举例说明一下x86_64平台下其他获取sys_call_table的方案。(1)//

2401_84139587的博客 959

保姆级教程:用Protege 5.5.0从零构建你的第一个知识图谱(附实战案例文件)

本文提供了一份详细的Protege 5.5.0使用指南,从零开始构建知识图谱。涵盖环境配置、本体结构设计、实例填充到可视化展示的全流程,特别适合初学者快速掌握知识建模技术。通过实战案例演示,帮助读者理解如何定义类、属性及建立实例关系,是学习知识图谱构建的实用教程。

weixin_42548816的博客 554

保姆级教程:手把手调试PX4Ctrl的油门映射与姿态控制(附ROS节点配置)

本文提供PX4Ctrl的深度调参指南,涵盖油门映射、姿态控制及ROS节点配置等关键环节。通过详细解析PX4控制器的核心逻辑、递归最小二乘法(RLS)参数估计及状态机设计,帮助开发者优化无人机飞控性能。附实战案例与安全调试建议,适合PX4开发者进阶学习。

weixin_30363981的博客 382

linux模块句柄和基址,获取内存加载的dll的句柄或基址

通过TEB遍历dllnt!_TEB+0x000 NtTib : _NT_TIB+0x01c EnvironmentPointer : Ptr32 Void+0x020 ClientId : _CLIENT_ID+0x028 ActiveRpcHandle : Ptr32 Void+0x02c ThreadLocalStoragePointer : Ptr32...

weixin_29118723的博客 310

UE5网络模块实战:属性复制、RPC与联机开发踩坑指南

多人联机开发中,网络同步是核心难题。UE5网络模块以服务器权威为基础,通过Actor复制、RPC和所有权机制实现多端状态一致。理解属性复制与OnRep回调、区分Server/Client/Multicast RPC的适用场景,是构建稳定联机架构的关键。本文结合数字孪生与多端协作场景,探讨如何将渲染与逻辑分离,并针对打包后网络失效、端口防火墙、崩溃排查等工程实践问题给出解决方案。通过蓝图接口解耦表现层,利用C++创建StaticMesh组件实现服务器逻辑与客户端表现分离,同时注意专用服务器不加载渲染依赖(如D

weixin_29010003的博客 273

Linux x86平台获取sys_call_table

Linux 3.10.0 -- x86_64 获取sys_call_table的几种方式

小立仔 1664

Bellhop水声信道模型的仿真

Bellhop是一种基于射线追踪的水声信道模型,广泛用于预测水下环境中的声压场。它通过模拟声波在水中的传播路径,计算声场分布,适用于复杂的水下通信场景。

yt94832的博客 1315

Python实战:逐笔高频因子构建与回测全流程解析

本文详细解析了使用Python构建与回测逐笔高频因子的全流程。从逐笔数据的价值与清洗入手,通过实战代码演示了‘大买成交金额占比’因子的计算逻辑,并重点阐述了因子正交化处理的重要性以剔除风格影响。最后,提供了一个经典的分位数回测框架来验证因子有效性,并分享了数据质量、计算效率与过拟合等核心避坑指南。

grass的博客 391

linux 命令 sys_call_table地址,Linux2.6内核模块获取sys call table地址

在上面的代码中,最复杂的应该就是从0x80中断的服务例程中搜索sys_call_table的一段了,现解释如下。首先,我们使用命令“gdb -q /usr/src/kernels/2.6.19/vmlinux”来反编译内核,再使用“disass system_call”和“disass syscall_call”两条gdb命令来查看内核的汇编代码,其结果如下:(gdb) disass system...

weixin_42524165的博客 447

如何使用freesurfer对T1w结构像进行分区指标的提取?——皮层面积,灰质体积,平均厚度,厚度标准差,平均曲率、高斯曲率、曲率指数、折叠指数

如何使用freesurfer对T1w结构像进行分区指标的提取?——皮层面积,灰质体积,平均厚度,厚度标准差,平均曲率、高斯曲率、曲率指数、折叠指数

从事脑科学核磁共振方法学研究,在Nature communications等权威期刊发表研究论文,熟练掌握磁共振处理方法和统计学方法,欢迎大家和我交流。 3788

Linux 2.6 中导出sys_call_table表修改系统调用函数

Linux中实现系统调用

清水 4641

2026年软考信息安全工程师备考指南

信息安全工程师是信息产业部和人事部举办的软考中新增开的一门考试。软考全称全国计算机技术与软件专业技术资格(水平)考试,这门新开的信息安全工程师分属该考试“信息系统”专业,位处中级资格,是信息产业部和人事部在最新的“国人厅发[2007]139号文件中新增的专业。2016年下半年,第一次开考信息安全工程师(中级)考试。 考试科目: 1.信息安全基础知识,考试时间为150分钟,笔试,选择题; ...

鹿鸣天涯 7397

C#上位机通信层封装:西门子S7NetPlus库的优雅使用

支持S7-1200/1500(机架号0,槽号1)、S7-300/400(机架号/槽号需根据实际配置);支持位(Bit)、字节(Byte)、字(Word)、双字(DWord)、浮点数(Float/Double)等数据类型的读写;支持DB块、输入寄存器(I)、输出寄存器(Q)、内存寄存器(M)、定时器(T)、计数器(C)的操作;轻量无依赖,兼容.NET 5+。首先定义核心枚举和常量,统一规范参数类型,避免硬编码。/// 西门子PLC型号(对应不同的机架/槽号默认配置)

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1085

linux 系统调用表 sys_call_table 获取方法

一.方法一:常用方式,也是一google一堆的方式 我们首先需要找到call table-with-offset的特征,先看下面的代码 syscall_call: call *sys_call_table(,%eax,4) 假设我们没有vmlinux可供gdb反汇编,那也只有采用模拟的方式了,模拟出一个call *sys_call_table(,%eax,4),然后看其机器...

whatday的专栏 5139

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

抓取sys_call_table 地址 x86_64

在网上看到很多文章是通过驱动内联汇编拿到idt地址,但是在x86_64上确跑不起来,还宕机,来一起唠唠。 先说说网上同行说自己使用以下代码去解析sys_call_table 地址 lkm.c //lkm.c #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/types.h&

qq_42931917的博客 2200

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

获取sys_call_table地址

关于劫持系统调用时的sys_call_table地址,在上篇文章中提到了手动获取系统调用表地址的方法,本文采用 kallsyms_lookup_name() 来获得sys_call_table的符号地址。 文章指路:https://blog.csdn.net/ShirokoYae/article/details/119036040 主要参考文章:https://blog.csdn.net/zzzpany/article/details/94308431,获取方法 次要参考文章:https://blog

ShirokoYae的博客 974

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

linux内核hook技术之函数地址替换

前言 函数地址替换是一种更为简单、常见的hook方式,比如对security_ops、sys_call_table等结构中的函数进行替换,来完成自己的安全权限控制。 其中security_ops是LSM框架中所使用的,sys_call_table是系统调用表结构。当然了,这些结构目前在内核中都已经是只读数据结构了,如果想直接进行函数替换的话,首先就是考虑解决关闭写保护的问题。在下面的模块例子中,演示了重置cr0寄存器写保护位及其 修改内存页表项属性值两种关闭写保护方式,有兴趣的朋友可对...

快乐时光 2600

Linux x86平台获取sys_call_table,网络安全开发面试技能介绍

还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!【完整版领取方式在文末!!

2401_84139587的博客 1080

Linux Rootkit 系列二:基于修改 sys_call_table 的系统调用挂钩

与第一篇文章作者所想象的不同,本文不打算给大家介绍三种不同的系统调用挂钩技术,相反,本文仅详细讲解最简单的系统调用挂钩方案,并且基于这个方案实现最基本的文件监视工具。这样,既可以让读者轻松上手进行实际应用, 又可以加深、巩固读者对LKM的理解,同时还免去了一次学习多种挂钩方案的理论知识压力。 所以,本文力求以实验为核心,每一个步骤都可能有对应的实验代码。代码仓库:https://github...

whatday的专栏 2123

Linux4.19-通过IDT获取sys_call_table实现系统调用劫持

上一篇博客写了如何获取IDT地址,这里将接着上一篇博客继续写,如果还不清楚如何获取IDT可以看一下我的上一篇博客:Linux4.19-获取IDT地址:https://blog.csdn.net/qq_41208289/article/details/106012230 这里再次声明一下,博主的系统为目前最新版本的Debian10,Linux4.19内核(32位x86机器) 前言 网上的绝大部分博客对于获取sys_call_table的方法在目前的内核中都已经失效,Linux大概从4.8开始加入了保

CalvinXu 2266

Linux系统中获取系统调用表(system call table)地址的几种方法

上回讲到如何编写简单的内核模块,那么内核模块可以用来做什么呢?一个例子就是可以hook系统调用,替换为自己的接口函数;还有就是设备驱动的开发。 本文将就hook系统底层调用技术展开讨论。下图是应用层的一个系统调用在linux系统中的调用流程: 在应用层调用getpid系统调用,为glibc中封装,此调用会引发int 80中断,调用切换到内核空间,然后根据system_call数组及其_NR_getpid下标找到系统调用sys_getpid接口的地址,之后将会返回系统调用结果到应用层。 ..

weixin_42915431的博客 8502
上一篇: LKM 注射
下一篇: ubuntu下压缩和解压缩的命令用法
ender049
博客等级 码龄20年 7粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值