当我们在聊Getshell,我们本质上在聊什么?
字数 2572 2025-08-22 12:23:30
Shell与Getshell技术深度解析
一、Shell的本质与功能
1.1 Shell的定义
Shell是一个命令行解释器,作为用户与Linux内核交互的接口。它接收用户输入的命令,解释这些命令,然后调用相应的程序来执行。Shell扮演着用户和操作系统内核之间的"翻译者"角色。
1.2 /bin/sh的演变
- 最初指向Bourne Shell(sh),Unix系统最早的Shell之一
- 现代Linux系统中通常是符号链接,可能指向:
- bash
- dash
- 其他Shell实现
- 设计为POSIX标准的最小实现,确保脚本可移植性
1.3 Shell的核心功能
- 命令解释:解析用户输入的命令
- 程序执行:启动和管理其他程序的运行
- 环境控制:管理环境变量
- 脚本执行:运行Shell脚本
- 管道和重定向:处理输入输出流
二、POSIX标准详解
2.1 POSIX定义
POSIX (Portable Operating System Interface) 是一套标准化的操作系统接口规范,旨在确保不同操作系统间的兼容性和软件可移植性。
2.2 POSIX规范的主要内容
-
系统调用和库函数:
- 文件操作
- 进程控制
- 线程管理
- 网络通信
- 用户和组管理
-
命令行和工具:
- Shell命令语法
- 常用工具行为规范(如ls, grep, awk等)
- 程序返回值规范
-
线程模型:
- pthread库接口规范
- 线程同步机制
- 线程调度
2.3 主要系统的POSIX兼容性
- Linux:基本完全兼容
- macOS:获得POSIX认证
- BSD系列:大部分遵循POSIX标准
三、ELF程序执行全流程
3.1 程序执行前的准备
- Shell解析命令行,获取文件路径"./elf"
- 检查文件权限(读取和执行权限)
- 确认文件存在且可执行
3.2 fork()过程详解
- 系统调用clone()(fork的底层实现)
- 复制进程描述符(task_struct)
- 创建新的内存管理结构(mm_struct)
- 复制页表
- 设置子进程返回值为0,父进程获取子进程PID
- 子进程继承父进程的文件描述符表
3.3 execve()详细过程
- 释放原进程空间
- 读取ELF文件头(前128字节)
- 验证ELF魔数:0x7F 'E' 'L' 'F'
- 检查ELF文件类型(ET_EXEC或ET_DYN)
- 检查目标架构是否匹配
3.4 ELF加载过程
- 解析程序头表(Program Header Table)
- PT_LOAD段的加载
- PT_DYNAMIC段的处理
- PT_INTERP段识别动态链接器
3.5 内存映射详细步骤
- 建立虚拟内存布局:
- 代码段(text):映射到固定地址,设置为只读和可执行
- 数据段(data):映射可读写数据,包含已初始化的全局变量
- BSS段:分配零页,映射未初始化的全局变量
- 堆区:从数据段末尾开始,初始化brk指针
- 栈区:在虚拟地址空间高地址处,设置栈指针(sp)
3.6 动态链接过程(动态链接ELF)
- 加载动态链接器(ld.so)
- 解析依赖关系
- 加载所需的共享库
- 重定位和符号解析
3.7 执行环境设置
- 设置程序入口地址(entry point)
- 初始化寄存器状态
- 设置argc、argv和环境变量
- 准备辅助向量(auxiliary vector)
3.8 进程状态转换
- 从TASK_RUNNING状态开始执行
- 父进程(Shell)进入TASK_INTERRUPTIBLE等待子进程结束
3.9 错误处理机制
- execve失败时返回到子进程
- 出错处理(文件不存在、权限不足等)
- 资源清理
3.10 进程终止
- 程序执行完毕或异常终止
- 发送SIGCHLD信号给父进程
- 资源回收
- 退出码传递给父进程
四、GetShell技术本质
4.1 GetShell的定义
获取目标系统的Shell解释器的交互权限,具体包括:
- 获得一个交互式的Shell会话
- 能够执行命令并获取结果
- 通常是/bin/sh或/bin/bash的解释器环境
4.2 反弹Shell的技术原理
4.2.1 网络连接建立阶段
- 创建socket文件描述符
- TCP三次握手过程
- 建立网络缓冲区
- 设置TCP状态机
4.2.2 文件描述符重定向
- 标准输入(stdin)重定向到网络连接
- 标准输出(stdout)重定向到网络连接
- 标准错误(stderr)重定向到网络连接
4.2.3 进程创建和替换
- 创建新的task_struct结构
- 复制文件描述符表
- 设置进程上下文
- 调度新进程
4.2.4 内核层面发生的关键操作
a) 网络子系统:
- 创建socket文件描述符
- TCP三次握手过程
- 建立网络缓冲区
- 设置TCP状态机
b) 进程管理:
- 创建新的task_struct结构
- 复制文件描述符表
- 设置进程上下文
- 调度新进程
c) 内存管理:
- 为新进程分配虚拟内存空间
- 建立页表映射
- 复制父进程的地址空间
- 加载shell程序到内存
d) 文件系统:
- 打开/bin/sh文件
- 读取程序代码
- 处理文件描述符继承
4.2.5 Shell环境建立
- 初始化Shell环境变量
- 设置工作目录
- 建立命令历史记录机制
4.2.6 I/O重定向后的数据流
- 本地输入通过网络传输到远程Shell
- 远程Shell输出通过网络传输回本地
- 错误信息同样通过网络传输
4.2.7 系统调用链路
完整的系统调用序列包括:
- socket()
- connect()
- dup2() (用于文件描述符重定向)
- fork()
- execve()
五、技术总结与关联
-
Shell本质:用户与操作系统内核交互的接口,作为命令解释器将用户指令转化为系统操作
-
POSIX角色:确保接口标准化的规范,定义操作系统应提供的接口,保证不同系统间的操作可预测和可移植
-
ELF执行机制:展示了进程创建和程序执行的基本机制,包括:
- fork()创建新进程
- execve()加载新程序
- 内存映射
- 动态链接
- 一系列系统调用操作
-
GetShell本质:获取目标系统的命令解释器权限,涉及:
- 文件描述符重定向
- 网络套接字操作
- 进程控制
- 底层机制操纵
-
技术层次关联:从基本系统接口到复杂程序执行机制,再到高级攻击技术,展示了操作系统各层面的紧密联系和相互作用