Linux下pwn从入门到放弃
字数 2092 2025-08-25 22:58:56

Linux下PWN从入门到精通

0x00 简介

PWN在安全领域中指的是通过二进制/系统调用等方式获得目标主机的shell。随着移动端和IoT设备的流行,传统的缓冲区溢出技术再次变得重要。

0x01 必备工具

  1. gdb:Linux下必备的调试工具
  2. gdb增强插件
    • gdb-peda
    • gef
    • gdbinit
  3. pwntools:编写exp和poc的利器
  4. checksec:检测ELF程序的安全性和运行平台
  5. objdump和readelf:查看ELF程序关键信息
  6. IDA Pro:强大的反编译工具
  7. ROPgadget:ROP利用工具
  8. one_gadget:快速寻找libc中exec('bin/sh')的位置
  9. libc-database:通过泄露的函数地址查询libc版本

0x02 ELF安全机制检测

使用checksec检测ELF程序的安全措施:

  1. RELRO

    • Partial RELRO:部分保护
    • FULL RELRO:完全保护,无法修改GOT表
  2. Stack Canary

    • 开启后不能直接覆盖返回地址
    • 需要绕过方法:改写指针、泄露canary、覆盖canary
  3. NX(DEP)

    • 栈中数据无执行权限
    • 无法使用call esp/jmp esp
    • 需使用ROP技术绕过
  4. PIE(ASLR)

    • 地址随机化
    • 未开启时基地址固定(如0x400000)
  5. FORTIFY

    • 限制格式化字符串漏洞利用
    • 包含%n的格式化字符串不能位于可写地址
    • 使用位置参数时必须使用范围内的所有参数

0x03 调试技巧

GDB常用命令

  • n:执行一行源代码但不进入函数
  • ni:执行一行汇编代码但不进入函数
  • s:执行一行源代码并进入函数
  • si:执行一行汇编代码并进入函数
  • c:继续执行到下一个断点
  • b *地址:下断点
  • directory:加载源码目录
  • set follow-fork-mode parent:只调试主进程
  • stack:显示栈信息
  • x:十六进制显示内存数据

调试脚本

未开启ASLR

def debug(addr):
    raw_input('debug:')
    gdb.attach(r, "b *" + addr)

开启ASLR

wordSz = 4
hwordSz = 2
bits = 32
PIE = 0
mypid=0

def leak(address, size):
    with open('/proc/%s/mem' % mypid) as mem:
        mem.seek(address)
        return mem.read(size)

def findModuleBase(pid, mem):
    name = os.readlink('/proc/%s/exe' % pid)
    with open('/proc/%s/maps' % pid) as maps:
        for line in maps:
            if name in line:
                addr = int(line.split('-')[0], 16)
                mem.seek(addr)
                if mem.read(4) == "\x7fELF":
                    bitFormat = u8(leak(addr + 4, 1))
                    if bitFormat == 2:
                        global wordSz
                        global hwordSz
                        global bits
                        wordSz = 8
                        hwordSz = 4
                        bits = 64
                    return addr
    log.failure("Module's base address not found.")
    sys.exit(1)

def debug(addr = 0):
    global mypid
    mypid = proc.pidof(r)[0]
    raw_input('debug:')
    with open('/proc/%s/mem' % mypid) as mem:
        moduleBase = findModuleBase(mypid, mem)
        gdb.attach(r, "set follow-fork-mode parent\nb *" + hex(moduleBase+addr))

0x04 泄露libc地址和版本

  1. 格式化字符串漏洞

    • 泄露栈数据找到libc函数地址
    • 使用libc-database判断版本
    • 常用目标:__libc_start_main
  2. write函数

    • 使用pwntools的DynELF计算各种地址
  3. printf函数

    • 利用遇到0x00停止输出的特性
    • 泄露栈中重要数据

0x05 栈溢出利用技术

无保护程序

  1. 传统方法

    • 将shellcode写入栈中
    • 查找call esp/jmp esp指令
  2. 现代方法

    • 寻找程序中的system函数
    • 布局栈空间调用gets(.bss)
    • 调用system('/bin/sh')
  3. 虚表覆盖

    • 通过覆盖虚表利用漏洞

开启NX保护

  • 使用ROP技术绕过
  • ROPgadget工具生成利用链
  • 复杂程序需手动分析

开启Canary保护

  1. 利用canary泄露flag

    • 覆盖libc_argv[0]为flag地址
    • stack_check_fail时会打印程序名称
  2. 子进程泄露

    • 在一个子进程中泄露Canary
    • 在另一个子进程中伪造Canary

开启PIE保护

  1. printf泄露

    • 多打印栈中数据
    • 计算程序基地址、libc基地址
  2. write泄露

    • 使用DynELF函数

0x06 格式化字符串漏洞

  1. pwntools自动化

    • FmtStr和fmtstr_payload函数
    • 自动计算利用点并生成payload
  2. 信息泄露

    • 制造格式化字符串漏洞泄露数据

0x07 UAF漏洞

  • 释放堆后未清空指针
  • 导致use-after-free漏洞

0x08 任意地址写

  1. 单字节写

    • 即使只能写一个字节也可控制程序
  2. GOT表修改

    • 控制GOT表写入
    • 改变程序执行流程
  3. top_chunk控制

    • 计算libc基地址
    • 控制top_chunk指针

0x09 综合技巧

  • 即使所有保护全开,完全控制栈仍可攻破
  • 组合多种技术:信息泄露+ROP+任意地址写
  • 灵活运用工具链提高效率

0x0A 学习资源

  1. 工具安装指南:

    • gdb插件安装:http://blog.csdn.net/gatieme/article/details/63254211
  2. 示例题目分析:

    • 虚表覆盖:http://blog.csdn.net/niexinming/article/details/78144301
    • ROP利用:http://blog.csdn.net/niexinming/article/details/78259866
    • Canary绕过:http://blog.csdn.net/niexinming/article/details/78681846
    • 格式化字符串:http://blog.csdn.net/niexinming/article/details/78699413
    • UAF漏洞:http://blog.csdn.net/niexinming/article/details/78598635
Linux下PWN从入门到精通 0x00 简介 PWN在安全领域中指的是通过二进制/系统调用等方式获得目标主机的shell。随着移动端和IoT设备的流行,传统的缓冲区溢出技术再次变得重要。 0x01 必备工具 gdb :Linux下必备的调试工具 gdb增强插件 : gdb-peda gef gdbinit pwntools :编写exp和poc的利器 checksec :检测ELF程序的安全性和运行平台 objdump和readelf :查看ELF程序关键信息 IDA Pro :强大的反编译工具 ROPgadget :ROP利用工具 one_ gadget :快速寻找libc中exec('bin/sh')的位置 libc-database :通过泄露的函数地址查询libc版本 0x02 ELF安全机制检测 使用checksec检测ELF程序的安全措施: RELRO : Partial RELRO:部分保护 FULL RELRO:完全保护,无法修改GOT表 Stack Canary : 开启后不能直接覆盖返回地址 需要绕过方法:改写指针、泄露canary、覆盖canary NX(DEP) : 栈中数据无执行权限 无法使用call esp/jmp esp 需使用ROP技术绕过 PIE(ASLR) : 地址随机化 未开启时基地址固定(如0x400000) FORTIFY : 限制格式化字符串漏洞利用 包含%n的格式化字符串不能位于可写地址 使用位置参数时必须使用范围内的所有参数 0x03 调试技巧 GDB常用命令 n :执行一行源代码但不进入函数 ni :执行一行汇编代码但不进入函数 s :执行一行源代码并进入函数 si :执行一行汇编代码并进入函数 c :继续执行到下一个断点 b *地址 :下断点 directory :加载源码目录 set follow-fork-mode parent :只调试主进程 stack :显示栈信息 x :十六进制显示内存数据 调试脚本 未开启ASLR 开启ASLR 0x04 泄露libc地址和版本 格式化字符串漏洞 : 泄露栈数据找到libc函数地址 使用libc-database判断版本 常用目标: __libc_start_main write函数 : 使用pwntools的DynELF计算各种地址 printf函数 : 利用遇到0x00停止输出的特性 泄露栈中重要数据 0x05 栈溢出利用技术 无保护程序 传统方法 : 将shellcode写入栈中 查找call esp/jmp esp指令 现代方法 : 寻找程序中的system函数 布局栈空间调用gets(.bss) 调用system('/bin/sh') 虚表覆盖 : 通过覆盖虚表利用漏洞 开启NX保护 使用ROP技术绕过 ROPgadget工具生成利用链 复杂程序需手动分析 开启Canary保护 利用canary泄露flag : 覆盖libc_ argv[ 0 ]为flag地址 stack_ check_ fail时会打印程序名称 子进程泄露 : 在一个子进程中泄露Canary 在另一个子进程中伪造Canary 开启PIE保护 printf泄露 : 多打印栈中数据 计算程序基地址、libc基地址 write泄露 : 使用DynELF函数 0x06 格式化字符串漏洞 pwntools自动化 : FmtStr和fmtstr_ payload函数 自动计算利用点并生成payload 信息泄露 : 制造格式化字符串漏洞泄露数据 0x07 UAF漏洞 释放堆后未清空指针 导致use-after-free漏洞 0x08 任意地址写 单字节写 : 即使只能写一个字节也可控制程序 GOT表修改 : 控制GOT表写入 改变程序执行流程 top_ chunk控制 : 计算libc基地址 控制top_ chunk指针 0x09 综合技巧 即使所有保护全开,完全控制栈仍可攻破 组合多种技术:信息泄露+ROP+任意地址写 灵活运用工具链提高效率 0x0A 学习资源 工具安装指南: gdb插件安装:http://blog.csdn.net/gatieme/article/details/63254211 示例题目分析: 虚表覆盖:http://blog.csdn.net/niexinming/article/details/78144301 ROP利用:http://blog.csdn.net/niexinming/article/details/78259866 Canary绕过:http://blog.csdn.net/niexinming/article/details/78681846 格式化字符串:http://blog.csdn.net/niexinming/article/details/78699413 UAF漏洞:http://blog.csdn.net/niexinming/article/details/78598635