您的位置:首页 > 运维架构 > Linux

[pwn基础]Linux内核装载ELF过程简介

2022-06-11 12:12 4319 查看

[toc]

[pwn基础]Linux内核装载ELF过程简介

用户层:

用户层bash进程会调用

fork
系统调用创建一个新的进程,然后新的进程调用
execve()
系统调用执行指定的
ELF文件
,原先的bash进程继续返回等待刚才启动的新进程结束,然后继续等待用户输入命令。

扩展学习:https://blog.csdn.net/qq_41453285/article/details/89006116

int execve(const char *filename,char *const argv[], char *const envp[]);

//filename  = 被执行的程序文件名
//argv[]    = 执行的参数
//envp[]    = 环境变量

利用fork()、execlp()实现minibash:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
char buf[1024]={0};
pid_t pid;
while(1)
{
printf("minibash$");
scanf("%s",buf);
pid = fork();
if(pid == 0)//子进程
{
if(execlp(buf,0) < 0){
printf("exec error\n");
}
}else if(pid > 0)//父进程
{
int status;
waitpid(pid,&status,0);//等待子进程返回
printf("子进程执行完毕!\n");
}else{
//返回-1 创建进程失败!
printf("创建进程失败!\n");
}
}
return 0;
}

## 内核层

在用户层调用

execve
函数后,进入到内核层,Linux内核开始进行真正的装载工作。

execve() 系统调用相应的入口是sys_execve()
,在源码
arch\i386\kernel\Process.c
中被定义。

最终sys_execve会调用

do_execve()
函数,do_execve函数会首先查找被执行的文件,如果找到文件,读取文件的前
128
字节,用来判断文件
Magic(魔数)

确定是ELF文件后,最后会调用

load_elf_binary()
函数来进行ELF文件的装载,该文件被定义在
fs\Binfmt_elf.c
中。(函数的主要实现步骤):

(1) 检查ELF可执行文件格式的有效性,比如Magic(魔数)、程序头表(段表)的数量。
(2) 寻找动态链接的 ".interp"段,设置动态链接器的路径。
(3) 根据ELF可执行文件的程序头表(段表),对ELF文件进行映射,代码段、数据段、只读数据段。
(4) 初始化ELF进程环境,比如进程启动时EDX寄存器的地址应该是"DT_FINI"地址。
(5) 将系统调用的返回地址修改成"ELF可执行文件入口点",(如果是静态链接,那么入口点是"e_entry"),(如果是动态链接,那么入口点是"动态链接器")
(6) laod_elf_binary() ret -> do_execve() ret -> sys_execve() ret[返回已被修改] -> eip =(ELF入口) 开始执行ELF程序,装载完毕,进程执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: