当我们在聊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的核心功能

  1. 命令解释:解析用户输入的命令
  2. 程序执行:启动和管理其他程序的运行
  3. 环境控制:管理环境变量
  4. 脚本执行:运行Shell脚本
  5. 管道和重定向:处理输入输出流

二、POSIX标准详解

2.1 POSIX定义

POSIX (Portable Operating System Interface) 是一套标准化的操作系统接口规范,旨在确保不同操作系统间的兼容性和软件可移植性。

2.2 POSIX规范的主要内容

  1. 系统调用和库函数

    • 文件操作
    • 进程控制
    • 线程管理
    • 网络通信
    • 用户和组管理
  2. 命令行和工具

    • Shell命令语法
    • 常用工具行为规范(如ls, grep, awk等)
    • 程序返回值规范
  3. 线程模型

    • pthread库接口规范
    • 线程同步机制
    • 线程调度

2.3 主要系统的POSIX兼容性

  • Linux:基本完全兼容
  • macOS:获得POSIX认证
  • BSD系列:大部分遵循POSIX标准

三、ELF程序执行全流程

3.1 程序执行前的准备

  1. Shell解析命令行,获取文件路径"./elf"
  2. 检查文件权限(读取和执行权限)
  3. 确认文件存在且可执行

3.2 fork()过程详解

  1. 系统调用clone()(fork的底层实现)
  2. 复制进程描述符(task_struct)
  3. 创建新的内存管理结构(mm_struct)
  4. 复制页表
  5. 设置子进程返回值为0,父进程获取子进程PID
  6. 子进程继承父进程的文件描述符表

3.3 execve()详细过程

  1. 释放原进程空间
  2. 读取ELF文件头(前128字节)
  3. 验证ELF魔数:0x7F 'E' 'L' 'F'
  4. 检查ELF文件类型(ET_EXEC或ET_DYN)
  5. 检查目标架构是否匹配

3.4 ELF加载过程

  1. 解析程序头表(Program Header Table)
  2. PT_LOAD段的加载
  3. PT_DYNAMIC段的处理
  4. PT_INTERP段识别动态链接器

3.5 内存映射详细步骤

  1. 建立虚拟内存布局
    • 代码段(text):映射到固定地址,设置为只读和可执行
    • 数据段(data):映射可读写数据,包含已初始化的全局变量
    • BSS段:分配零页,映射未初始化的全局变量
    • 堆区:从数据段末尾开始,初始化brk指针
    • 栈区:在虚拟地址空间高地址处,设置栈指针(sp)

3.6 动态链接过程(动态链接ELF)

  1. 加载动态链接器(ld.so)
  2. 解析依赖关系
  3. 加载所需的共享库
  4. 重定位和符号解析

3.7 执行环境设置

  1. 设置程序入口地址(entry point)
  2. 初始化寄存器状态
  3. 设置argc、argv和环境变量
  4. 准备辅助向量(auxiliary vector)

3.8 进程状态转换

  1. 从TASK_RUNNING状态开始执行
  2. 父进程(Shell)进入TASK_INTERRUPTIBLE等待子进程结束

3.9 错误处理机制

  1. execve失败时返回到子进程
  2. 出错处理(文件不存在、权限不足等)
  3. 资源清理

3.10 进程终止

  1. 程序执行完毕或异常终止
  2. 发送SIGCHLD信号给父进程
  3. 资源回收
  4. 退出码传递给父进程

四、GetShell技术本质

4.1 GetShell的定义

获取目标系统的Shell解释器的交互权限,具体包括:

  1. 获得一个交互式的Shell会话
  2. 能够执行命令并获取结果
  3. 通常是/bin/sh或/bin/bash的解释器环境

4.2 反弹Shell的技术原理

4.2.1 网络连接建立阶段

  1. 创建socket文件描述符
  2. TCP三次握手过程
  3. 建立网络缓冲区
  4. 设置TCP状态机

4.2.2 文件描述符重定向

  1. 标准输入(stdin)重定向到网络连接
  2. 标准输出(stdout)重定向到网络连接
  3. 标准错误(stderr)重定向到网络连接

4.2.3 进程创建和替换

  1. 创建新的task_struct结构
  2. 复制文件描述符表
  3. 设置进程上下文
  4. 调度新进程

4.2.4 内核层面发生的关键操作

a) 网络子系统

  • 创建socket文件描述符
  • TCP三次握手过程
  • 建立网络缓冲区
  • 设置TCP状态机

b) 进程管理

  • 创建新的task_struct结构
  • 复制文件描述符表
  • 设置进程上下文
  • 调度新进程

c) 内存管理

  • 为新进程分配虚拟内存空间
  • 建立页表映射
  • 复制父进程的地址空间
  • 加载shell程序到内存

d) 文件系统

  • 打开/bin/sh文件
  • 读取程序代码
  • 处理文件描述符继承

4.2.5 Shell环境建立

  1. 初始化Shell环境变量
  2. 设置工作目录
  3. 建立命令历史记录机制

4.2.6 I/O重定向后的数据流

  1. 本地输入通过网络传输到远程Shell
  2. 远程Shell输出通过网络传输回本地
  3. 错误信息同样通过网络传输

4.2.7 系统调用链路

完整的系统调用序列包括:

  1. socket()
  2. connect()
  3. dup2() (用于文件描述符重定向)
  4. fork()
  5. execve()

五、技术总结与关联

  1. Shell本质:用户与操作系统内核交互的接口,作为命令解释器将用户指令转化为系统操作

  2. POSIX角色:确保接口标准化的规范,定义操作系统应提供的接口,保证不同系统间的操作可预测和可移植

  3. ELF执行机制:展示了进程创建和程序执行的基本机制,包括:

    • fork()创建新进程
    • execve()加载新程序
    • 内存映射
    • 动态链接
    • 一系列系统调用操作
  4. GetShell本质:获取目标系统的命令解释器权限,涉及:

    • 文件描述符重定向
    • 网络套接字操作
    • 进程控制
    • 底层机制操纵
  5. 技术层次关联:从基本系统接口到复杂程序执行机制,再到高级攻击技术,展示了操作系统各层面的紧密联系和相互作用

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本质 :获取目标系统的命令解释器权限,涉及: 文件描述符重定向 网络套接字操作 进程控制 底层机制操纵 技术层次关联 :从基本系统接口到复杂程序执行机制,再到高级攻击技术,展示了操作系统各层面的紧密联系和相互作用