文章目录 一、系统调用简介 二、进程相关系统调用源码 一、系统调用简介 ---- 在开发应用程序时 , 进行 " 进程创建 " , 调用的 fork() , vfork() , clone() 等函数 , 就是 " 系统调用 " ; " 系统调用 " 是 操作系统 提供的 应用程序 调用 内核功能 的接口 , 如 : 创建进程 , 文件操作 等 ; 系统调用 与 内核 的关系 : 在 应用进程 中调用 fork() 系统调用 函数 , 实际上调用的是 Linux 内核中的 sys_fork() 函数 ; 在 应用进程 中调用 vfork() 系统调用 函数 , 实际上调用的是 Linux 内核中的 sys_vfork() 函数 ; 在 应用进程 中调用 clone() 系统调用 函数 , 实际上调用的是 Linux 内核中的 sys_clone() 函数 ; Linux 内核中的 sys_fork ---- Linux 进程相关 " 系统调用 " 对应的源码在 linux-5.6.18\kernel\fork.c 源码中 ,
strace -o output.txt -T -tt -e trace=all -p 28979
在这篇文章中,我们将通过分析一个使用 Go 语言编写的示例程序来探讨 Go 语言在进行系统调用和进程替换方面的应用。 这是程序安全性和可移植性的重要步骤,确保调用的命令在系统中确实存在。 2. 这个调用实际上将替换当前的进程映像与 ls 命令的进程映像,包括其内存和其他资源。如果这个调用成功,当前的 Go 程序将不会继续存在;如果有错误发生,如无法执行该命令,则会引发 panic。 这种进程替换技术特别适用于需要管理子进程或改变当前执行环境的场景,常见于系统工具和服务器应用中。 此外,它的跨平台支持也有限,主要适用于 Unix-like 系统。 未来展望 通过本文的分析,我们了解到 Go 语言处理系统调用和进程替换的能力,并具体看到了这些功能是如何在实际代码中被利用的。
1、虚拟处理器、虚拟内存:让进程感觉自己拥有所有 image.png 2、进程上限,cat /proc/sys/kernel/pid_max 3、进程的五种状态 image.png set_task_state (task,state); 4、每个进程都有一个父进程 image.png 5、进程的创建:fork() exec() image.png 6、写时拷贝COW image.png 7、线程和进程的区别不大 image.png 8、孤儿进程,父进程先关掉,再设置一个父进程,如果没有,设置init image.png 9、2.6内核后进程调度算法CFS:完全公平调度算法 10、进程分为IO消耗型和处理器消耗型 image.png image.png 13、与调度相关的系统调用 image.png 14、系统调用在用户空间进程和硬件设备之间添加了一个中间层 image.png 15、中断 image.png 21、虚拟文件系统:VFS 22、IO调度 23、页高速缓存和页回写
文章目录 一、系统调用 二、Android NDK 中的系统调用示例 一、系统调用 ---- 在 " 用户层 " , 运行的都是用户应用程序 ; 用户层 下面 是 驱动层 , 驱动层 下面是 系统层 , 最底层是 BIOS ; 系统层 包含 系统内核 ; 层级从上到下 : 用户层 | 驱动层 | 系统层 | BIOS ; 上述 4 层之间 , 不可以直接跨越 , 应用想要读取 驱动 / 内核 的数据是不被允许的 ; 整个应用进程的控制权此时就交给了 驱动层 / 系统层 , 在这些底层具体执行了哪些操作 , 应用层是不知道的 ; arm 架构的 CPU 中软中断指令是 SVC ; x86 架构的 CPU 中软中断指令是 int ; 与 软中断 相对应的是 硬中断 ; 硬中断 是由 硬件产生 ; 二、Android NDK 中的系统调用示例 ---- 系统调用相关的头文件定义在 D:\Microsoft\AndroidNDK64 , 174 对应的 16 进制数为 0xAE ; 进行软中断时 , 执行如下汇编执指令时 , MOV R0, 0xAE SVC 0 会自动执行 #define __NR_getuid 174 对应的系统调用
文章目录 一、进程状态 二、进程创建 三、进程终止 ( 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 ) 一、进程状态 ---- Linux 源码 ) 博客中的 fork() , vfork() , clone() 等系统调用函数 ; 三、进程终止 ( 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 ) ---- 进程终止的方式 : 主动退出 : 主动调用 exit() 系统调用函数 主动退出 ; 自动退出 : 程序的 main 函数返回 , 自动退出 ; 从 main() 函数返回时 , 链接程序 会 为程序 自动添加 exit() 系统调用函数 ; 杀死进程 : 接收到 kill 命令 发出的 SIGKILL 信号 , 进程被杀死 ; 异常退出 : 进程执行出现异常 , 或 收到 自己不能处理的信号 , 被迫终止 ; 前两种是 进程主动退出 , 后两种是 进程被动退出 ; exit() 系统调用 函数 , 定义在 linux-5.6.18\kernel\exit.c 源码中 ,
通过系统调用获取进程标示符(PID) 上一篇文章我们了解了进程的概念,并学会了创建进程和查看进程,在查看进程的时候,我们重点了解了一个属性叫做PID,即进程标识符。 可以的: 我们可以通过一个系统调用来获取,这个系统调用叫做getpid 我们可以通过man手册学习一下 getpid没有参数,直接调用即可获取(返回)当前进程的pid,返回值是pid_t类型 用另一个系统调用——getppid 我们来试一下: 重新make运行 然后我们再多运行几次 我们会发现当前进程的PID每次都是不一样的,但是其父进程的PID是一直不变的 那它的父进程是谁呢 通过系统调用创建进程-fork初识 经过之前的学习我们知道我们可以通过运行一个程序使之变成进程,那有没有其它产生新进程的方法呢? 有的,我们可以通过系统调用来创建进程。 那对于fork来说: 它是一个系统调用,那其实就是操作系统提供的一个函数嘛。 那在fork最后将要return的时候,那它的主体功能即创建子进程当然已经完成了。
是Linux下最基本的一个系统调用。 fork()最大的特点就是一次调用,两次返回,两次返回主要是区分父子进程,因为fork()之后将出现两个进程,所以有两个返回值,父进程返回子进程ID,子进程返回0。 通过复制的方式创建一个进程,被创建的进程称为子进程,调用进程称为父进程,复制的子进程是从父进程fork()调用后面的语句开始执行的。 我们已经知道,fork()系统调用的特点是一次调用两次返回,并且子进程的创建是对父进程的复制,那么是从哪复制开始复制的呢,我们根据程序运行结果分析,程序只打印了一次begin语句,说明不是从头开始复制的 3.2 进程顺序控制 使用fork()创建的进程都是一样的,在操作系统看来没有区别,先后顺序也是不确定的,我们要想控制进程的退出顺序,需要自己去实现这个逻辑。
在Linux系统中,进程与硬件的交互并非直接进行,而是通过系统调用来实现。strace是一个强大的工具,它可以追踪进程执行时的系统调用以及接收到的信号,这对于诊断和调试程序非常有用。 strace简介与原理 strace用于跟踪程序执行时的系统调用和信号。在Linux中,用户态的进程需要通过系统调用来请求内核态的服务,比如文件操作、网络通信等。 执行系统调用:内核函数会执行实际的操作,如读写文件、创建进程等。 返回用户态:系统调用完成后,会将结果返回给用户程序,并从内核态切换回用户态。 系统调用的例子 open():打开一个文件。 系统调用与信号的关联 系统调用和信号都是进程与内核交互的机制,但它们有不同的用途: 系统调用更多用于进程需要内核提供服务的场景,如资源管理、硬件访问等。 跟踪特定进程 如果要跟踪一个已经运行的进程,可以使用-p参数指定进程ID: strace -p <pid> 定位进程异常退出 通过跟踪进程的系统调用,可以观察到进程在异常退出前的最后行为: strace
在Linux系统中,进程与硬件的交互并非直接进行,而是通过系统调用来实现。strace是一个强大的工具,它可以追踪进程执行时的系统调用以及接收到的信号,这对于诊断和调试程序非常有用。 strace简介与原理strace用于跟踪程序执行时的系统调用和信号。在Linux中,用户态的进程需要通过系统调用来请求内核态的服务,比如文件操作、网络通信等。 执行系统调用:内核函数会执行实际的操作,如读写文件、创建进程等。返回用户态:系统调用完成后,会将结果返回给用户程序,并从内核态切换回用户态。系统调用的例子open():打开一个文件。 系统调用与信号的关联系统调用和信号都是进程与内核交互的机制,但它们有不同的用途:系统调用更多用于进程需要内核提供服务的场景,如资源管理、硬件访问等。 跟踪特定进程如果要跟踪一个已经运行的进程,可以使用-p参数指定进程ID:strace -p <pid>定位进程异常退出通过跟踪进程的系统调用,可以观察到进程在异常退出前的最后行为:strace -p <
fork函数的返回值如下: 1、在父进程中,fork返回新创建的子进程的PID号。 2、在子进程中,fork返回0; 3、如果出现错误,fork返回一个负值。 因此可以通过返回值来判断是父进程还是子进程。 fork函数创建子进程的过程: 使用fork函数得到的子进程是父进程的一个复制品,它从父进程继承了进程的所有资源,相当于就是父进程的一个副本。 "退出的子进程的pid=%d\n",pid); } return 0; } 3. exec系列函数 exec系列函数是用于启动一个新的进程,将新的进程启动成功之后会覆盖原进程. 说明这个system函数是阻塞的,必须等待子进程执行完毕之后才会执行父进程的代码。 思路: 父进程扫描目录,得到目录下的文件名称,在传递给子进程,子进程调用eog命令实现图片显示,父进程里2秒钟之后就杀死子进程,再读取目录下下一个文件,再传递给子进程……… #include <stdio.h
文章目录 一、Binder 系统两个核心 二、IPC 进程间通信 三、RPC 远程过程调用 一、Binder 系统两个核心 ---- Binder 系统 最重要的两个核心是 IPC 和 RPC ; IPC Call ) 远程过程调用 : A 进程通过 IPC 发送数据到 B 进程 , B 进程调用自己本地的相关逻辑 , A 进程通过 RPC 调用了 B 进程的代码 ; RPC 是在 IPC 基础上进行的封装 注册服务 , 进程 A 从 ServiceManager 查询进程 B 注册的服务 , 得到一个 Handle , 该 Handle 指向进程 B ; 在 Android 系统中 , 进程 A 就是 驱动 实现 ; 如下图所示 : 三、RPC 远程过程调用 ---- RPC ( Remote Procedure Call ) 远程过程调用 可以理解为 调用其它某个进程的函数 ; RPC 涉及到的函数相关问题 : 这里有涉及到识别问题 , 如何 标识 远程调用目的进程的某个 函数 , 给函数传递哪些 参数 , 该函数如何返回 返回值 ; 标识函数 : 需要 Client 客户端 向 Server 服务端 发送要调用的
操作系统接着通过参数检查找出所需要的调用进程。 然后,它执行系统调用,并把控制返回给系统调用后面跟随着的指令。 在某种意义上,进行系统调用就像进行一个特殊的过程调用,但是只有系统调用可以进入内核,而过程调用不能。 一般把系统调用的编号放在操作系统所期望的地方,如寄存器中。 跟随在 trap 指令后的内核代码开始检查系统调用编号,然后分派给正确的系统调用处理器,这通常是通过一张由系统调用编号所引用的、指向系统调用处理器的指针表来完成。此时,系统调用处理器运行。 为了等待子进程结束,父进程执行 waitpid 系统调用,它只是等待,直至子进程终止(若有多个子进程的话,则直至任何一个子进程终止)。 (实际上,该系统调用是 exec 系统调用,但是若干个不同的库过程使用不同的参数和稍有差别的名称调用该系统调用。
进程主要是执行用户级别程序的环境,进程可以让内核多任务的处理,这样在一个操作系统上可以执行上千个进程。每个进程都有自己独立的进程PID,并且是唯一的。 进程的创建是通过系统调用fork()来创建的,fork()用自己的进程号创建自身进程的一个复制,然后调用系统调用exec()才能开始执行不同的程序。 依据如上图,我们可以得到系统调用fork()可以达到Copy-On-Write,也就是COW的策略来提高性能,这样添加原有地址空间的引用而非所有内容复制,但是一旦任何的进程要被修改,那么此时就会针对修改建立一个独立的副本 如下显示了进程的完整生命周期,具体为: ? on-proc指的是进程运行在CPU上,而ready-to-run指的是进程可以运行,但是还在CPU的运行队列里等待CPU分配资源。 I/O阻塞,让进程进入sleep状态直到I/O完成进程被唤醒。zombie状态发生在进程终止,此时子进程状态等待自己的父进程读取,或者直到被内核清除。
一个进程结束后,调用exit()会发生。 // 进程结束的简化流程 void do_exit(long code) { // 1. 调用调度器,不再被调度 schedule(); // 此时进程已是僵尸,等待父进程wait() } 查看进程 getpid getpid 是 Linux/Unix 系统中获取当前进程 ID(PID) 的系统调用(对应手册页章节 2,即 man 2 getpid),本质是程序向内核发起的请求,返回当前运行进程的唯一标识(PID)。 系统调用:系统调用是用户态程序向操作系统内核请求服务的接口,是用户程序与内核之间的 “桥梁”,用于让应用程序获得内核级别的资源或功能(比如操作硬件、管理进程、访问文件等)。 两次从grep进程的pid不同,第一次查看的时候shell会创建grep进程,每一个新的进程pid都不相同,调用结束后会销毁,第二次重复以上操作导致两次grep的pid不相同。
可在暂存器eip溢出后,塞入一段可让CPU执行的shellcode机器码,让电脑可以执行攻击者的任意指令。 今天讲一下shellcode的调用及内存注入的一个案例。 想必好多新手在玩MSF,CS能生成shellcode的马子,但是shellcode生成后....不会调用,所以来讲一下shellcode的调用。 利用Shellcode注入到进程内存 Shellcode注入到到进程内存发现的概率比较低,因为注入的Shellcode没有保存在磁盘文件。 弊端:当目标应用程序关闭,或者系统重启机就凉凉,还有就是加载器被发现,也凉凉~ OpenProcess(获取进程句柄)--->VirtualAllocEx(在目标进程申请一块内存)-->WriteProcessMemory 拷贝过去-->CreateRemoteThread(在其它进程创建线程) 第一个参数是进程权限//PROCESS_ALL_ACCESS所有能获得的权限, 第三个参数是进程ID HANDLE
一、内存使用方法 二、mmap的系统调用 一、内存使用方法 1.创建内存映射 #include <sys/mman.h> void *mmap(void *addr,size_t length,int 进程把文件映射到进程的虚拟地址空间,可以像访问内存一样访问文件,不需要调用系统调用read()/write()访问文件,从而避免用户模式和内核模式之间的切换,提高读写文件速度。 二、mmap的系统调用 0.查找mmap在内核中的系统调用函数 我现在用的内核版是4.19.40,首先在应用层参考上面解析编写一个mmap使用代码,然后编译成程序,在使用strace工具跟踪其函数调用, 可以发现mmap也是调用底层的mmap系统调用,然后我们寻找一下底层的带6个参数的mmap系统调用有哪些: 可以看到,arm64和X86的系统调用位于不同文件。 下面是mmap系统调用的函数调用以及返回情况说明: SYSCALL_DEFINE6(mmap, offset_in_page(off) //检查偏移是不是页的整数倍, ksys_mmap_pgoff
1、类包含不能序列化的属性时,多进程异步执行失败 import multiprocessing import os import random import sys class A: pool ,因为A中包含了无法序列化的pool(进程池)。 多进程调用self.execute方法时会将类本身的内容,即self全部序列化传给另外一个进程,pool无法序列化,因此多进程执行失败。只需将pool的初始化放入start函数中即可执行。 logging.exception(e) pool.close() pool.join() if __name__ == "__main__": A().start() 2、多进程通信时只能使用一层的 pool.close() pool.join() print (td) 输出为: {'a': {'b': 1, 'c': 1}} 想着可能是因为第二层不是Manager().dict()导致的,
抽象而言的接口是连接两个东西的中间物。接口的好处是屏蔽了连接起来的实际细节。我们只关心接口如何使用。 系统调用:操作系统的接口是连接应用软件与操作系统的中间桥梁。接口在程序设计中表现的形式就是:函数。 操作系统提供的函数就被称为系统调用(system call)。 Linux和Unix等系统遵守这个标准。 系统调用的实现:系统调用的存在给用户提供了接口,阻止了用户恶意访问操作系统的数据。系统调用也给用户访问内核提供了唯一的途径。 系统调用实现的细节是这样的,它在代码中嵌入了一段汇编代码,这段代码中最重要的是int 0x80指令。这将会启动系统调用。当然我们还有系统调用号。 int指令在IDT表中查找系统调用的入口。 这样就实现了系统调用。
可在暂存器eip溢出后,塞入一段可让CPU执行的shellcode机器码,让电脑可以执行攻击者的任意指令。 今天讲一下shellcode的调用及内存注入的一个案例。 想必好多新手在玩MSF,CS能生成shellcode的马子,但是shellcode生成后....不会调用,所以来讲一下shellcode的调用。 利用Shellcode注入到进程内存 Shellcode注入到到进程内存发现的概率比较低,因为注入的Shellcode没有保存在磁盘文件。 弊端:当目标应用程序关闭,或者系统重启机就凉凉,还有就是加载器被发现,也凉凉~ OpenProcess(获取进程句柄)--->VirtualAllocEx(在目标进程申请一块内存)-->WriteProcessMemory 拷贝过去-->CreateRemoteThread(在其它进程创建线程) 第一个参数是进程权限//PROCESS_ALL_ACCESS所有能获得的权限, 第三个参数是进程ID HANDLE