当前版本: 0.1
完成日期: 2007-6-15
作者: Dajie Tan <jiankemeng@gmail.com>
系统调用是用户态进程切入内核态的唯一入口,是内核为用户态进程提供服务的
接口。Linux Kernel 提供了大约300个左右的系统调用,作为用户空间进程访问
内核的 API。
C 语言环境下,经常使用的(如getpid)是系统基础库 libc 封装过的。在其
后面究竟隐藏着什么样的秘密呢?
1. 先看一个例子:
#include <stdio.h>
int main()
{
long ID1;
ID1 = getpid();
printf("pid=%d/n", ID1);
return 0;
}
存为 sc.c,如下命令编译之:
gcc sc.c -o sc -static
看看它的汇编码:
objdump -d sc > sc.S
查看 sc.S 我们发现 getpid 被 libc 替换成 __getpid,而这个函数只有下面
的 3 行指令:
0804e0d0 <__getpid>:
804e0d0: b8 14 00 00 00 mov $0x14,%eax
804e0d5: cd 80 int $0x80
804e0d7: c3 ret
将 0x14 置于 eax 后,触发 0x80 号软件中断。
这个 0x80 号软件中断服务程序,就是内核系统调用的统一入口。
至于如何区分具体的是哪个系统调用,则通过 eax 传过来的整型值来区分。内
核定义了一个系统调用表,表的每项是一个函数指针,指向具体的实现函数,
每个系统调用函数在表中的位置固定,其序号 (从 0 开始计数)就是该系统
调用的系统调用号。实际上就是一个元素固定的数组。如 i386 内核,系统调
用表名为 sys_call_table,则 sys_call_table[20] 就是 getpid 的函数指针:
[arch/i386/kernel/syscall_table.S]
ENTRY(sys_call_table)
.long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
.long sys_exit
.long sys_fork
.long sys_read
.long sys_write
.long sys_open /* 5 */
.long sys_close
.long sys_waitpid
.long sys_creat
.long sys_link
.long sys_unlink /* 10 */
.long sys_execve
.long sys_chdir
.long sys_time
.long sys_mknod
.long sys_chmod /* 15 */
.long sys_lchown16
.long sys_ni_syscall /* old break syscall holder */
.long sys_stat
.long sys_lseek
.long sys_getpid /* 20 */
.long sys_mount
...
int 0x80 触发,使内核进入相应的处理程序,在保存了寄存器后,就使用 eax
的值索引 sys_call_table,得到地址后,跳转过去就进入了实质的服务函数。
因此,我们可以改写上面的程序为:
#include <stdio.h>
int main()
{
long ID1;
//ID1 = getpid();
asm volatile(
"int $0x80/n/t"
: "=a" (ID1) /* eax 亦是返回值所在,因此要与ID1 对应 */
: "0" (20) /* 20 置入 eax */
);
printf("pid=%d/n", ID1);
return 0;
}
编译 gcc sc.c -o sc,执行之,结果是一样的。
上面简单的系统调用不需要传递参数,当需要传递 3 个参数时,那么如何处理呢?
2. 参数传递
i386 内核实现系统调用时有一个参数传递约定:
ebx --- 置第一个参数
ecx --- 置第二个参数
edx --- 置第三个参数
esi --- 置第四个参数
edi --- 置第五个参数
ebp --- 置第六个参数 (系统调用最大参数个数为6)
特别注意,使用 ebp 前要先将其进栈, int 0x80 返回后,要恢复之。
3. 使用标准宏
上面使用嵌入式汇编不是很方便,可以使用 POSIX 标准约定的一系列宏:
#include <linux/unistd.h>
_syscallX(type, name, type1, arg1, type2, arg2, ...)
其中 X 取值 0~5 表示系统调用的参数个数
name 为系统调用的名字,如 getpid, read 等
type1 为第一个参数类型
arg1 为第一个参数值
type2 为第二个参数类型
arg2 为第二个参数值
...
很显然,使用这些宏,要对所用之系统调用的参数个数和类型有清晰的了解。
如上面的程序改写为:
#include <stdio.h>
#include <linux/unistd.h>
_syscall0(int, getpid);
int main()
{
long id = getpid();
printf("id = %d/n", id);
return 0;
}
就绕过了 libc。可以使用 gcc -E sc.c > sc.C 看看预处理后的结果,就知道
这个_syscall 宏做了什么事了。
这些宏定义于内核源码目录的 include/asm-i386/unistd.h 下,抑或
/usr/include/asm-i486/unistd.h 下。
4. 查看系统调用号
可以查看内核源码目录的 include/asm-i386/unistd.h,该文件中定义了一系列以
__NR_ 开头的常量,紧随其后的即为系统调用名,相应的即为系统调用号。
更多的参考: http://people.openrays.org/~comcat/mydoc/syscall_ref.html
相关推荐
第十二节:C#工业控制编程基础--输出正弦波实验
第十二节:基于c#使用开发板输出正弦波实验 文章目录第十二节:基于c#使用开发板输出正弦波实验一、实验目的:了解采集卡DA相关函数的使用。二、实验内容:利用C#生成正弦波,然后用采集卡DA输出。三、实验步骤:1.打开Visual Studio 2013,新建窗体应用程序项目,配置好板卡dll文件。2.在窗体中放入控件,对控件进行布局排版,并修改他们的Name属性和Text属性。3.在Chart控件内选择Spline型图表,如图2。4.进入编程区域,在public partial class Form1 :
keil mdk b __main不进入C语言main函数入口
在调试的时候发现,从startup.s中逐步运行到b __main,但下一步就是不跳转到main函数,后来发现问题出现在以下两个函数: 1、void _mutex_acquire(void *m) 2、void _mutex_release(void *m) 为了保证malloc是线程安全的,必须重写这两个方法,保证开关中断,但千万不能在函数里加printf打印,因为这时候还没有初始化串口...
线性回归做糖尿病分析(diabetes数据集),并分析单个特征值与病情的关系
1.diabetes数据集 共442个样本,每个样本有十个特征,分别是 [‘age’, ‘sex’, ‘bmi’, ‘bp’, ‘s1’, ‘s2’, ‘s3’, ‘s4’, ‘s5’, ‘s6’],对应年龄、性别、体质指数、平均血压、S1~S6一年后疾病级数指标。 Targets为一年后患疾病的定量指标,值在25到346之间。 ...
应用程序如何直接调用一个系统调用, 不经过C库?
通常应用程序是怎么访问系统调用的? 应用程序通常不会直接访问系统调用, 一般都是通过C库来访问系统调用. 我们通常说的, 写个应用程序, 调某个系统调用, 其实也不是真的直接调用系统调用, 而是调用C库(一般是glbic)封装的函数, 而这个封装的函数的函数名跟系统调用名称相同, 比如写个程序,打开某个文件, 将其内容输出来, 这里面我们看似调用了open(), read(), write()这些"系统调用", 实际也是glibc封装过的, 跟Linux相应的系统调用, 同名的函数, 而非真的系统调用本
超声波 vs 红外 vs 激光雷达:扫地机器人避障传感器选型指南(实测对比)
本文深入对比了扫地机器人三种主流避障传感器——超声波、红外与激光雷达的核心原理与实测表现。文章基于成本、精度、环境适应性等关键指标,提供了清晰的选型决策树和典型场景配置方案,旨在帮助开发者与爱好者根据项目需求与预算,构建高效可靠的机器人避障系统。
AT89C52单片机+LCD屏:手把手教你做一个能算小数和负数的计算器(附完整代码)
本文详细介绍了如何使用AT89C52单片机和LCD1602显示屏构建一个支持小数和负数运算的高精度计算器。从硬件选型、系统架构设计到核心算法实现,提供了完整的代码示例和优化技巧,特别适合51单片机初学者和课程设计参考。
Linux几种检测rootkit隐藏进程的方法
Rootkit通常会隐藏进程,隐藏文件和网络连接。这里主要记录几种对隐藏进程的检测方法 一. 隐藏进程的方法 1.1 用户级Rootkit 通过LD_PRELOADER来hook libc库实现,从而过滤/proc/pid目录 1.2 内核级rootkit 通过hook系统调用getdents/getdents64或者hook 文件file_operation的iterate 1.3 内核...
二次开发vba_CATIA VBA(VBS)二次开发:使用Search批量选择元素
在CATIA二次开发中很多在程序中进行自动交互的方法或函数都需要使用选择集作为参数,将几何元素按照要求批量添加到选择集中也是实现程序自动运行的有效方法。在前面的文章《CATIA使用VBA(VBS)二次开发时用户的交互选择》和《CATIA使用VBA(VBS)二次开发时工程图和草图位置的交互选择函数Indicate2D》中介绍了在CATIA VBA(VBS)二次开发中用户和选择集之间的交互操...
Android应用方法隐藏及反调试技术浅析
原文地址: http://www.freebuf.com/articles/terminal/75944.html 0x00 前言 Android应用的加固和对抗不断升级,单纯的静态加固效果已无法满足需求,所以出现了隐藏方法加固,运行时动态恢复和反调试等方法来对抗,本文通过实例来分析有哪些对抗和反调试手段。 0x01 对抗反编译 首先使用apktool进行反
【STM32】433MHz OOK信号软解码实战:从EV1527协议到嵌入式实现
本文详细介绍了基于STM32微控制器实现433MHz OOK信号软解码的完整实战过程。文章从EV1527协议解析入手,重点阐述了利用STM32的GPIO和定时器进行信号采样、脉宽还原、同步头识别以及数据位判决的核心算法,并提供了对抗无线干扰的容错优化策略,帮助开发者深入理解并掌握低成本无线通信的嵌入式实现方案。
Unity之OpenXR+XR Interaction Toolkit实现 VR控制第一人称角色模型动画
我们在开发VR项目时,有时会有第一人称视角的需求,即我们自己带上VR头显,能够看到自己的身体,如果模拟一些人物触电死亡,使用工具动画之类的需求,那么VR控制第一人称视角就比较实用了。我们今天就来介绍一下如何实现VR设备控制第一人称:1.角色手部跟随手柄移动和旋转2.角色头部跟随VR头显转动和移动3.角色腿部跟随角色头显移动和下蹲。
android 系统内存检查
1. Introduction Android对内存的使用包括内存泄漏和内存越界,内存泄漏会导致系统内存减少,最终分配不到内存,这样大的程序就不能运行,甚至系统没有内存而崩溃。Android中kernel和应用程序都可能会有内存泄漏和越界。对于Java代码,在越界的时候虚拟机会加以检查并抛出异常。而对于C/C++代码,越界的时候就悄无声息地让程序出错或crash 2.
OpenClaw人人养虾:接入Matrix
Matrix 是一个开放的去中心化通讯协议(Decentralized Communication Protocol),任何人都可以搭建自己的 Homeserver(家服务器)并与全球 Matrix 网络互联。OpenClaw 通过 Matrix Client-Server API 实现接入。
glibc和系统调用的关系
glibc是gnu提供的一个C函数库,其特点是大而全涵盖了ANSC C标准接口和POSIX接口等。其中POSIX接口大部分是对linux系统调用的直接导出,所以完全可以绕开libc库而直接引用系统调用。 具体方法:http://bbs.nankai.edu.cn/cgi-bin/bbs/bbsanc?path=/PersonalCorpus/J/jasonduan/D595ABB25/M.118
IDEA的使用指南
IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.
假人有限元模型
假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用
系统调用1
write系统调用,往标准输出打印字符串用strace。
TMS_WebGMaps_1.9.8.0_Full_Source
TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder
避免无限递归:syscall_no_intercept 的 5 个关键使用场景,深入理解系统调用拦截库
在 Linux 系统调用拦截领域,syscall_intercept 是一款通过热补丁(hotpatch)libc 机器码来实现用户态系统调用拦截的开源库。使用它的开发者都知道一个"潜规则":一旦钩子生效,任何通过 libc 发起的系统调用都会再次被拦截,稍不留神就会陷入**无限递归**导致程序崩溃。而 `syscall_no_intercept` 正是打破这个死循环的"逃生通道"。本文面向新手和
大中型超市收银系统(可直接运行)
光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开
各种小巧的Hello World
在Reddit看到这篇文章:Hello from a libc-free world!,觉得挺有趣,然后又想起以前看过的各种相关资料,在此做一个整理。注意所有实验环境都为Linux。版本一:实际上是用汇编重写_start入口,具体说明请看文章开头提供的连接,汇编代码如下,命名为stubstart.S _start: call main movl $1, %eax
2603,系统调用
2603,系统调用
栈溢出漏洞利用技术:ROP、ret2syscall与ret2libc详解
栈溢出是二进制安全领域的经典漏洞类型,其核心原理是通过覆盖栈上的返回地址来控制程序执行流程。随着ASLR、NX等现代防护机制的普及,传统的shellcode注入方式逐渐失效,催生了ROP(面向返回编程)等高级利用技术。ROP通过串联程序中现有的代码片段(gadget)来构造攻击链,能够绕过数据执行保护。ret2syscall和ret2libc是两种典型的ROP变体:前者直接通过系统调用实现攻击,后者则利用libc库函数突破防护。这些技术在CTF竞赛和渗透测试中具有重要应用价值,理解其原理有助于开发更安全的软
Linux libc.so.6误删修复:动态链接器直连自救指南
libc.so.6是GNU C Library(glibc)的核心动态链接库,为几乎所有用户态程序提供内存管理、系统调用封装等基础能力。其本质是运行时依赖,删除后shell虽可输入但无法执行外部命令,传统恢复手段如yum重装或拷贝文件极易因版本不匹配、符号链接丢失或权限异常而失败。真正可靠的修复路径是绕过libc依赖,直接调用独立于libc的动态链接器ld-linux-x86-64.so.2,加载本地存在的libc-*.so实体文件并重建符号链接。该方法无需重启、不依赖网络或外部介质,适用于CentOS 7
DetectFrida源码深度解析:Android应用安全的3种Frida检测与3种原生代码加固技术
DetectFrida是一个专门用于Android应用安全防护的开源项目,它提供了**3种Frida动态分析工具检测方法**和**3种原生代码加固技术**。这个项目对于Android开发者和安全研究人员来说是一个宝贵的资源,能够帮助理解如何保护应用免受逆向工程和动态分析的攻击。💪 ## 🔍 DetectFrida项目概述与核心功能 DetectFrida项目的核心目标是检测和防御Frida
x86-64汇编递归阶乘:栈帧、调用约定与系统调用实战
阶乘是理解函数调用机制的经典入口,其背后涉及栈帧布局、寄存器保存规则和调用约定等底层核心概念。在x86-64 Linux环境下,通过纯汇编实现递归阶乘,可直观展现CPU如何管理函数调用链、%rbp/%rsp如何协同构建栈空间,以及sys_write等系统调用如何绕过libc直接与内核交互。该实践不仅揭示递归易致栈溢出的本质原因,更强化对ABI规范、栈对齐要求和数字转字符串等工程细节的掌握,是打通《深入理解计算机系统》理论与真实机器行为的关键桥梁。
裸调linux write()接口
背景 我们知道linux提供了很多系统调用给应用程序使用,但linux并没有将这些系统调用封装成C语言接口,而是提供一个软中断,然后应用程序需要通过软中断带上系统调用编号和参数去调用接口,这对于应用程序相当的不友好。这时候libc库便登上了历史舞台,它将这些系统调用封装成一个个函数,形象生动地提供给应用程序使用,从此之后,应用程序只需要调用那些write(), read(), exit()等便能达到目的,而不是通过软中断去使用这些接口。。 然后,当我们熟悉了这些符号接口的时候,却不知道背后是怎么工作
系统调用libc详解
好的,这是一个非常深入的话题。我将从原理、本质到实现细节,为您全面解析系统调用、libc以及如何实现自定义系统调用。第一部分:系统调用的调用方式(Beyond libc)系统调用是用户程序请求内核服务的唯一正式途径。虽然最常用的方式是通过标准库(如glibc),但还存在其他方式。• 角色:libc作为系统调用的封装器(Wrapper),提供了符合POSIX标准的友好API。• 原理:绕过libc,直接使用汇编指令触发软中断或执行syscall指令。
结合libc手册描述libc与Linux的爱恨情仇
libc是标准C库,包含了一系列标准函数,这些函数可以被所有C程序以及其他语言的程序使用。提供基础函数:如字符串处理、内存管理、输入输出操作等。封装系统调用:为程序提供一致的接口,使得开发者不必直接处理复杂的系统调用。libc作为Linux系统的标准C库,在程序开发中扮演着基础且关键的角色。它不仅为C语言提供了标准化的函数库和系统调用封装,还通过其高度优化的实现和广泛的功能支持,为高级编程语言提供了可靠的基础。
2294



被折叠的 条评论
为什么被折叠?



