首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Linux syscall过程分析(万字长文)

一、背景 为了安全,Linux 中分为用户态和内核态两种运行状态。对于普通进程,平时都是运行在用户态下,仅拥有基本的运行能力。...这种机制被称为系统调用,用户态进程发起调用,切换到内核态,内核态完成,返回用户态继续执行,是用户态唯一主动切换到内核态的合法手段(exception 和 interrupt 是被动切换)。...这里先取出系统调用号,系统调用表(ia32_sys_call_table) 中取出对应的处理函数,然后通过先前寄存器中的参数调用之。...否则继续执行下面代码,将内核栈中保存的值保存到相应寄存器中,然后通过 sysexit 返回。...注意这里将原有的 eip 设置到 edx、 esp 设置到 ecx ,这是因为根据 Intel SDM,sysexit 会用 edx 来设置 eip,用 ecx 来设置 esp ,从而指向先前用户空间的代码偏移和栈偏移

13.9K2121

ROP-SROP学习

signal handler 返回后,内核为执行 sigreturn 系统调用,为该进程恢复之前保存的上下文,其中包括将所有压入的寄存器,重新 pop 回对应的寄存器,最后恢复进程的执行。...这一段就是signal frame 在内核sigreturn系统调用处理函数中,会根据当前的栈指针指向的Signal Frame对进程上下文进行恢复,并返回用户态,挂起点恢复执行。...需要注意的有: Signal frame 被保存在用户的地址空间中,所以用户是可以读写的 由于内核与信号处理程序无关,它并不会去记录这个signal对应的signal frame,所以当执行sigreturn...假设可以控制用户进程的栈,那么就可以伪造一个signal frame,当系统执行完sigreturn系统调用之后,会执行一系列pop指令以便恢复相应寄存器的值,当执行到rip时,就会将程序执行流指向syscall...)) syscall的地址 Signal frame的地址(使用SigreturnFrame()伪造) 足够大的空间以便塞下整个sigal frame ?

1.2K10
您找到你想要的搜索结果了吗?
是的
没有找到

内核线程的fork与普通的fork的区别

虚拟地址空间分布 首先,我们先来了解一下进程的虚拟地址空间是怎么分布的: 虚拟地址空间的高地址部分为内核空间,低地址部分为用户空间。各个进程之间的内核空间是共享的,只有用户空间才是独占的。...每个进程都有1个内核栈,这个内核栈位于内核空间。并且,每个进程还有一个用户栈,位于低地址部分。 当进程陷入内核态的时候,将会使用内核栈进行处理,当返回用户态的时候,又会换回去,使用用户栈。...内核栈一般是slab分配器中分配得来的一块内存地址,而且我们也不能仿照对用户进程的操作那样,将每个内核线程的内核栈映射到相同的地址处(这显然是不可行的)。...返回地址指的是,被调用的函数返回时,将会哪个位置开始执行。栈基址寄存器值则指的是当前栈帧的基地址。注意,不是内核栈的基地址,这是很多人的一个误区。...= newVal; // 跳转栈帧 rbp = (uint64_t *)*rbp; } // 设置内核态fork返回到enter_syscall_int

64110

Pwn-Vsyscall滑动爆破绕过PIE

Vsyscall简介 由于一般的系统调用如果想要向内核传递一些参数的话,为了保证用户态和内核态的数据隔离,往往需要把当前寄存器状态先保存好,然后再切换到内核态,当执行完后还需要在会恢复寄存器状态,而这中间就会产生大量的系统开销...因此为了解决这个问题,linux系统会将仅从内核里读取数据的syscall单独列出来进行优化,如 gettimeofday、time、getcpu。...但是却又与普通的syscall系统调用不同,该段代码会再开头进行验证检查,如果不是函数开头执行的话就会出错。...接下来使用gdb调试程序,打印出your input:后断开可以看到此时的栈顶rbp+0x28的地方有一个可以覆盖的地址(也可以直接rsi开始看,这样可以省去考虑ret占用的8bit)。...sh.recvuntil('Your Input :\n') sh.send(payload) sh.interactive() EXP模板 def exp(): global r ''' 获取

1.5K20

深入探索 perf CPU Profiling 实现原理

完成操作后,内核寄存器值恢复到原始状态,并将控制权返回给用户空间的应用程序,同时返回系统调用的结果。...用户空间内核空间的这种分离,确保了用户应用程序不能直接干扰内核,保证了系统的安全稳定性。...当进程执行系统调用时,会用户空间切换到内核空间,进程的当前状态,包括栈指针(rsp 寄存器)、程序计数器(rip,也就是 PC 寄存器)等,会被保存在内核数据结构 struct pt_regs 内,以便在系统调用完成后能够准确地恢复...当系统收到中断请求时,如果不在内核态,先会用户态切换到内核态,并在内核栈中保存当前的状态信息(主要是寄存器信息)。 接着使用中断向量号,在中断向量表中查找对应的处理代码的入口地址。...怎么获取采样发生时刻 CPU 寄存器的内容呢?

1.8K84

Linux系统调用原理

系统调用 是 Linux 内核提供的一段代码(函数),其实现了一些特定的功能,用户可以通过 int 0x80 中断(x86 CPU)或者 syscall 指令(x64 CPU)来调用 系统调用。...而 Linux 进入中断处理程序时,会把这些寄存器的值保存到内核栈中,这样 系统调用 就能通过内核栈来获取到参数。...,那么 系统调用 就可以内核获取到参数的值。...但由于寄存器只能传递 32 位的整型值(x86 CPU),所以参数一般只能传递指针或者整型的数值,如果要获取指针对应结构的数据,就必须通过从用户空间复制到内核空间,如 sys_open() 系统调用获取要打开的文件路径...tmp = getname(filename); ... } getname() 函数就是用于用户空间复制数据到内核空间

4.2K30

C++|并发|libco协程剖析

内核态代码移到用户态其实是常见的思路了,例如驱动的libos,网络的dpdk,乃至于微内核。 对于线程而言,其上下文切换流程如下,需要两次权限等级切换和三次栈切换。上下文存储在内核栈上。...时间角度: 线程的上下文切换必须先进入内核态并切换上下文, 这就造成了严重的调度开销 内核态和用户态存在页表隔离,用于防止meltdown攻击,在ARM中通过ttbr实现 线程的调度算法是通用的,对于内核而言...线程的结构体存在于内核中,在pthread_create时需要进入内核态,频繁创建开销大 空间角度: 线程的栈空间通常在MB级别,而服务器往往只是无状态地转发,并不需要这么大的栈空间 线程利用TCB...*ucp) - ucp获取ucontext并设置上下文 getcontext(ucontext_t*ucp) - 保存当前的ucontext在ucp中 swapcontext(ucontext_t*...rdi) movq %r13, 16(%rdi) movq %r14, 8(%rdi) movq %r15, (%rdi) xorq %rax, %rax 设置上下文 然后目标上下文取出所有通用寄存器

1.1K10

精致全景图 | 系统调用是如何实现的

syscall使执行逻辑用户态切换到内核态,在进入到内核态之后,cpu会 MSR_LSTAR 寄存器中,获取处理系统调用内核代码的起始地址,即上面的 entry_SYSCALL_64。...在执行 entry_SYSCALL_64 函数时,内核代码会根据约定,先从rax寄存器获取想要执行的系统调用的编号,然后根据该编号sys_call_table数组中找到对应的系统调用函数。...接着, rdi, rsi, rdx, r10, r8, r9 寄存器获取该系统调用函数所需的参数,然后调用该函数,把这些参数传入其中。...在系统调用函数执行完毕之后,执行结果会被放到rax寄存器中。 最后,执行sysret汇编指令,内核态切换回用户态,用户程序继续执行。 如果用户程序需要该系统调用的返回结果,则从rax中获取。...最后执行sysret,内核态切换回用户态,继续执行syscall后面逻辑。

1K30

Linux内核之旅张凯捷——系统调用分析(1)

用户在调用系统调用时会向内核传递一个系统调用号,然后系统调用处理程序通过此号系统调用表中找到相应地内核函数执行(系统调用服务例程),最后返回。...3 总结 操作系统内核提供了许多服务,服务在物理表现上为内核空间的函数,系统调用即为在用户空间对这些内核提供服务的请求,即在用户空间程序“调用”内核空间的函数完成相应地服务。...0x3: 描述符特权级(DPL),表示允许用户态进程调用这一异常处理程序。 __KERNEL_CS: 由于系统调用处理程序处于内核当中,所以应选择__KERNEL_CS填充段寄存器。...syscall_badsys:将-ENOSYS存放到eax寄存器所在栈中位置,再跳转到resume_userspace返回用户空间,返回后EAX中产生负的ENOSYS。...2.1 vsyscalls vsyscalls的工作原理即为:Linux内核将第一个页面映射到用户空间,该页面包含一些变量和一些系统调用的实现,被映射到用户空间的系统调用即可以在用户空间执行,不需要进行上下文切换

1.6K30

X86如何实现函数调用?

(32位系统)程序的虚拟内存空间提供了 2^{32} 的空间保存数据,用户地址空间3G0x0000000到0xC0000000,内核空间1G0xC0000000到0xFFFFFFFF。...(64位系统)程序的虚拟内存空间提供了 2^{64} 的空间保存数据,用户地址空间128T0x0000 0000 0000 0000到0x0000 7FFF FFFF F0000,内核空间128T0xFFFF...二、寄存器 寄存器提供了额外的存储空间,每个寄存器可以存一个字(4字节)。 和函数调用相关的寄存器(e表示扩展的意思): eip:指令指针,存储当前正在执行的机器指令的地址。也叫PC(程序计数器)。...两个寄存器都需要更新为 指向callee的新栈帧的顶部和底部。 当函数返回时,需要恢复寄存器中的旧值,才可以返回caller。...step11:堆栈中删除参数 继续讲堆栈上的参数弹出到寄存器,然后删除esp栈顶以下的元素。栈顶以下的元素已经不在栈中,没有意义。

2.7K20

从一道 CTF 题看 SROP | PWN

内核接口使用的寄存器有rdi、rsi、rdx、r10、r8和r9。...系统调用通过syscall指令完成。除了rcx、r11和rax,其他的寄存器都被保留。系统调用的编号必须在寄存器rax中传递。系统调用的参数限制为6个,不直接堆栈上传递任何参数。...返回时,rax中包含了系统调用的结果,而且只有INTEGER或者MEMORY类型的值才会被传递给内核用户接口 x86-64下通过寄存器传递参数,这样做比通过栈具有更高的效率。...获取到栈地址后,可以使用 sigreturn 来获取shell了,但是目标程序中没有 gadget: syscall;retn ,我们需要使用将 rax 设置为 15 ,之后 syscall 的方式来进行...获取到栈地址后,可以使用 sigreturn 来获取shell了,但是目标程序中没有 gadget: syscall;retn ,我们需要使用将 rax 设置为 15 ,之后 syscall 的方式来进行

89020

为什么 Linux 系统调用会消耗较多资源

; Linux 中的每一个系统调用都有特定的序号,函数会将系统调用的编号拷贝到 eax 寄存器; 函数执行 INT 0x80 指令,处理器会用户态切换到内核态并执行预先定义好的处理器; 执行中断处理器...eax 寄存器中; 内核栈中恢复寄存器的值并将返回值放到栈上; 系统调用会返回 C 函数,包装函数会将结果返回给应用程序; 如果系统调用服务在执行过程中出现了错误,C 语言函数会将错误存储在全局变量...、用户态切换至内核态,还需要完成验证参数的合法性,与函数调用的过程相比确实会带来很多的额外开销[^10]。...vDSO 虚拟动态共享对象(virtual dynamic shared object、vDSO)是 Linux 内核用户空间暴露内核空间部分函数的一种机制[^16],简单来说,我们将 Linux 内核中不涉及安全的系统调用直接映射到用户空间...,这样用户空间中的应用程序在调用这些函数时就不需要切换到内核态以减少性能上的损失。

1.9K40

汇编和栈

而 Linux 中 栈是在堆的上面,所以 Linux 中的内存是 两边向中间分布 。 很迷惑吗?通过下面这个图片你可以看出栈的移动方式。 栈从高位地址开始。确切地说,它的高度取决于操作系统的内核。...内核为每个正在运行的程序(每个线程)提供栈空间。 栈的大小是有限的,并且随着内存地址空间的向下增长而增加。当栈上的空间用完时,指向栈 “顶部” 的指针最高地址向下移动到最低地址。...一旦栈达到内核给定的有限大小,或者如果栈越过了堆的边界,则称栈溢出。这是一个致命错误,通常称为栈溢出。 # 栈指针和基本指针寄存器 您尚未了解的两个非常重要的寄存器是 RSP 和 RBP。...这是可以肯定的,因为函数的局部变量是由 RBP 的偏移量来获取的,如果 RBP 不变,则您将无法向该函数打印局部变量,甚至可能导致程序崩溃。...pop RSP 寄存器获取值并将其存储到目的地。

3.3K20

C语言 | C++ 基础栈溢出及保护机制

,64位的寄存器有rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp, rip等,对应32位的eax, ebx, ecx, edx, esi, edi, esp, ebp, eip...毕竟没人的姓名会有64个字母,毕竟我们的内存空间也是有限的。但是,往坏处想一想,没人能阻止用户在终端输入100甚至1000个的字符,当那种情况发生时,会发生什么事情?...64的空间,main函数中只有name一个局部变量,显然这段空间就是name数组,即name的起始地址为rbp-0x40。...当main函数执行完leave命令,执行到ret命令时:上一个函数的rbp数值已重新取回至rbp寄存器,栈顶指针rsp已经指向了保存这个返回地址的单元。...),由此获取对cpu的控制,从而执行任何他想执行的动作。

4.6K88

MIT 6.S081 (BOOK-RISCV-REV1)教材第四章内容 --Trap -- 上

---- 用户空间陷入 我们紧接上一part的流程继续往下分析,当我们在swtch函数中通过ret指令跳转到forkret函数时,forkret内核会干什么呢?...下一个userret陷阱帧中恢复保存的用户寄存器,做a0与sscratch的最后一次交换来恢复用户a0并为下一个陷阱保存TRAPFRAME,并使用sret返回用户空间。...在进入用户空间之前,内核先前将sscratch设置为指向一个每个进程的陷阱帧,该帧(除此之外)具有保存所有用户寄存器空间(kernel/proc.h:44)。...其次,xv6内核页表映射与用户页表映射不同,因此内核不能使用普通指令用户提供的地址加载或存储。 内核实现了安全地将数据传输到用户提供的地址和用户提供的地址传输数据的功能。...fetchstr是一个例子(kernel/syscall.c:25)。 文件系统调用,如exec,使用fetchstr用户空间检索字符串文件名参数。

37620

Linux内核之旅张凯捷——系统调用分析(2)

并且在linux-4.20内核,glibc-2.23版本环境下编写了用户态系统调用程序并对程序运行追踪分析。...int __init sysenter_setup(void) sysenter_setup()函数的主要工作: (1)调用get_zeroed_page()获得一个被填充为0的物理页,返回该页在内核地址空间的线性地址...sysenter_start: 即将vdso32-sysenter.so拷贝到对应的页中,在《系统调用分析(1)》的vDSO介绍中提到的arch_setup_additional_pages函数便是把拷贝到的页的内容映射到用户空间...(3)调用do_fast_syscall_32 -> do_syscall_32_irqs_on() 系统调用表中找到相应处理函数进行调用。...MSR寄存器进行初始化: (1)向MSR_STAR的32 ~ 47位写入内核态的cs,向48 ~ 64位设置用户态的cs。

1.9K20

手把手教你|拦截系统调用

一、什么是系统调用 系统调用 是内核提供给应用程序使用的功能函数,由于应用程序一般运行在 用户态,处于用户态的进程有诸多限制(如不能进行 I/O 操作),所以有些功能必须由内核代劳完成。...而内核就是通过向应用层提供 系统调用,来完成一些在用户态不能完成的工作。 说白了,系统调用其实就是函数调用,只不过调用的是内核态的函数。...获取 sys_call_table 数组的地址 要修改 sys_call_table 数组元素的值,一般需要通过内核模块来完成。因为用户态程序由于内存保护机制,不能改写内核态的数据。...要获取 sys_call_table 数组的虚拟内存地址有两种方法: 第一种方法: System.map 文件中读取 System.map 是一份内核符号表,包含了内核中的变量名和函数名地址,在每次编译内核时...第二种方法:通过 kallsyms_lookup_name() 函数来获取 System.map 文件中读取的方法不是很优雅,所以内核提供了一个名为 kallsyms_lookup_name() 的函数来获取内核变量和内核函数的虚拟内存地址

1.7K10

入侵检测之syscall监控

监控 6️⃣linux入侵检测之应急响应 0x01:Syscall简介 内核提供用户空间程序与内核空间进行交互的一套标准接口,这些接口让用户态程序能受限访问硬件设备,比如申请系统资源,操作设备读写,创建新进程等...用户空间发生请求,内核空间负责执行,这些接口便是用户空间内核空间共同识别的桥梁,这里提到两个字“受限”,是由于为了保证内核稳定性,而不能让用户空间程序随意更改系统,必须是内核对外开放的且满足权限的程序才能调用相应接口...在用户空间内核空间之间,有一个叫做Syscall(系统调用, system call)的中间层,是连接用户态和内核态的桥梁。这样即提高了内核的安全型,也便于移植,只需实现同一套接口即可。...Linux系统,用户空间通过向内核空间发出Syscall,产生软中断,从而让程序陷入内核态,执行相应的操作。对于每个系统调用都会有一个对应的系统调用号,比很多操作系统要少很多。...系统调用前,linux在eax寄存器中写入子功能号,中断处理程序根据eax寄存器的值来判断用户进程申请哪种系统调用。

2.5K10

Linux内核跟踪:ftrace hook入门手册(下)

其中较为关键的一个差异点,就是Linux内核4.17版本开始修改了系统调用过程中的函数签名,这对ftrace hook的实现造成了较大的困扰。...首先是参数值的获取。Linux系统调用的大致过程是,用户程序将系统调用的实际参数设置到特定的寄存器中,然后通过中断指令(int 30)切换到内核空间并实际执行系统调用过程。...此时,用户空间寄存器会以pt_regs结构体的形式,存储在当前内核空间的最高地址处。...: current) + THREAD_SIZE) - 1; } 获取用户寄存器内容后,即可从中读取出系统调用的参数了。...五、 后记 实际上,相比于eBPF等用户空间的终端监控方法,ftrace hook这样的内核模块实现终究属于比较沉重的方案,尤其是开发过程中需要进行大量的系统适配处理和测试。

1.8K20
领券