PWN

PWN

快速入门

前言

首先我觉得要学习PWN还是要有一定基础的,因为PWN毕竟是和系统底层知识打交道,所以我觉得应该具备如下的一些技能,并且我推荐了一些不错的书籍。

概述

PWN我觉得最开始的时候应该是没有这门学科和系统化的资料教程的,PWN本身属于高阶技能,个人感觉都是以前那些逆向大佬、编程大佬开始玩点高级的东西,然后就开始挖漏洞,结果就挖出了各种二进制漏洞,并且把二进制漏洞也完美的利用起来了,后面就归纳总结出一套体系供后人学习,在此真的膜拜那些前辈的共享精神。

PWN为什么叫PWN呢?其实只是一种声音,pwn!你的电脑爆炸了,你的电脑被攻破了,因为用二进制漏洞挖掘与利用这词来形容pwn未免也太长了,所以就用了简洁的叫法。

术语

这里介绍一些简单的PWN术语:

  • Exploit(exp) : 用于攻击的脚本与方案
  • Payload : 攻击载荷,是对目标进程劫持控制流的数据
  • Shellcode : 调用攻击目标的shell的代码

比赛

详见:ctftime.org

PWN环境搭建

学习PWN知识我们先需要一个指定的环境来进行PWN,这里首选的操作系统为Ubuntu、Kali然后安装必要的PWN环境软件来进行搭建,当然如果你想省力气的话也可以用docker直接部署别人封装好的pwn环境。

具体搭建步骤请看下一章

常见漏洞

  • 整数安全
  • 格式化字符串
  • 栈溢出与ROP
  • 堆利用

常见的保护

RELRO

Relocation Read-Onl(RELRO)此项技术主要针对GOT改写的攻击方式,它分成两种,Partial RELRO和FULL RELRO
Partial (部分)RELRO容易受到攻击,例如攻击者可以atoi.got为system.plt进而输入/bin/sh\x00获得shell,完全RELRO使整个GOT只读,从而无法被覆盖,但这样会大大增加程序的启动时间,因为程序在启动之前需要解析所有的符号。

1
2
3
4
gcc -o hello test.c //默认情况下,是Partial RELRO
gcc -z norelro -o hello test.c // 关闭,即No RELRO
gcc -z lazy -o hello test.c // 部分开启,即Partial RELRO
gcc -z now -o hello test.c // 全部开启,即Full RELRO

Canary

栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞是,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行,当启用栈保护后,函数开始执行的时候先会往栈里插入类似cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行,攻击者在覆盖返回地址的时候往往会将cookie信息给覆盖掉,导致栈保护检车失败而阻止shellcode的执行,在linux中我们将cookie信息称为canary。

1
2
3
gcc -fno-stack-protector -o hello test.c   //禁用栈保护
gcc -fstack-protector -o hello test.c //启用堆栈保护,不过只为局部变量中含有 char 数组的函数插入保护代码
gcc -fstack-protector-all -o hello test.c //启用堆栈保护,为所有函数插入保护代码

NX(DEP)

NX enabled如果这个保护开启就是意味着栈中数据没有执行权限,如此一来,当攻击者在堆栈上部署自己的shellcode并触发时,就会直接造成程序的崩溃,但是可以利用rop这种方法绕过。

1
2
3
gcc -o  hello test.c // 默认情况下,开启NX保护
gcc -z execstack -o hello test.c // 禁用NX保护
gcc -z noexecstack -o hello test.c // 开启NX保护

ASLR

ASLR 是 Linux操作系统的功能选项,作用于程序(ELF)装入内存运行时。是一种针对缓冲区溢出安全保护技术,通过对堆、栈、共享库映射等线性区布局的随机化,防止攻击者直接定位攻击代码位置,到达阻止溢出攻击的一种技术。

在传统的操作系统里,用户程序的地址空间布局是固定的,自低向高依次为代码区, BSS区,堆栈区,攻击者通过分析能轻易得出各区域的基地址,在此情况下,只要攻击者的注入代码被执行,攻击者就能随意跳转到想到达的区域,终取得计算机的控制权,试想如果一个程序在执行时,系统分配给此进程三个区域的基地址是随机产生的,每次该程序执行都不一样,那么攻击者注入的代码即使被执行,也终会因为无法找到合法的返回地址而产生错误,终进程停止,攻击者无法入侵,这就是地址空间布局随机化的基本思想。

查看并修改当前系统的ASLR设定:

1
2
3
4
5
6
7
8
sudo cat /proc/sys/kernel/randomize_va_space

# ASLR 有三个安全等级:
# 0:ASLR 关闭
# 1:随机化栈基地址(stack)、共享库(.so\libraries)、mmap 基地址
# 2:在1基础上,增加随机化堆基地址(chunk)

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

PIE

PIE 是 gcc 编译器的功能选项,作用于程序(ELF)编译过程中。是一个针对代码段( .text )、数据段( .data )、未初始化全局变量段( .bss )等固定地址的一个防护技术。程序运行时各个段加载的虚拟地址也是在装载时才确定,这就意味着,在PIE开启的情况下,攻击者将对程序的内存布局一无所知。这也防止了通过 ROPgadget 等一些工具来帮助解题。

1
2
3
4
gcc -o hello test.c  // 默认情况下,不开启PIE
gcc -no-pie -o hello test.c
gcc -fpie -pie -o hello test.c // 开启PIE,此时强度为1
gcc -fPIE -pie -o hello test.c // 开启PIE,此时为最高强度2

内存地址随机化机制,有三种情况

  • 0 - 表示关闭进程地址空间随机化
  • 1 - 表示将mmap的机制,stack和vdso页面随机化
  • 2 - 表示在1的基础上增加堆(heap)的随机化

总结

作用位置 归属 作用时间
ASLR 1:栈基地址(stack)、共享库(.so\libraries)、mmap 基地址
2:在1基础上,增加随机化堆基地址(chunk)
系统功能 作用于程序(ELF)装入内存运行时
PIE 代码段( .text )、初始化数据段( .data )、未初始化数据段( .bss ) 编译器功能 作用于程序(ELF)编译过程中

img

PWN技巧

  • One-gadget
  • 通用dadget及Return-to-csu
  • 劫持hook函数
  • 利用DynELF泄露函数地址
  • SSP Leak
  • 利用environ泄露栈地址
  • 利用_IO_FILE结构
  • 利用vsyscall

神奇的小知识

如何检查文件的保护情况

checksec 文件名(要以root权限执行)

image.png

编译时如何关闭这些保护呢

1
gcc -o hello hello.c -m32 -fno-stack-protector -z execstack -mpreferred-stack-boundary=2 -no-pie -g

查看程序使用了哪些函数

objdump命令是用查看目标文件或者可执行的目标文件的构成的gcc工具

-j hello 仅仅显示指定名称为hello的section的信息

-t 显示文件的符号表入口

objdump -t -j .text hello

查看hello程序的.text段有哪些函数

image.png

环境搭建

一、Ubuntu 环境搭建

虚拟机安装

当初尝试搭建ubuntu16.04的环境,但是搭建了大半天pwntools还是不行。所以这次尝试ubuntu20.04,选择20.04是因为现在很多打比赛的题目大部分都是libc2.27以上的了。

官方镜像下载:https://releases.ubuntu.com/focal/

下载好镜像之后就可以在VMware上安装了。

安装完后打开终端更新软件列表:

1
2
sudo apt-get update
sudo apt-get upgrade -y

虚拟机挂起恢复后,无法联网

1
sudo service network-manager restart

系统自动登入root账户

Ubuntu20.04安装完成之后,默认是没有root账户登录权限的,这样在操作系统时有诸多不便,比如新建一个文件都提示权限不够!不过可以通过创建的普通用户获取管理员权限,然后修改配置和root账户的密码,最后实现系统自动登录root账户,具体操作步骤如下:

  1. 设置密码

    1
    sudo passwd root

    然后按照提示,先输入当前账户的密码,然后是root账户密码,最后再确认密码。

  2. 修改系统配置文件 (先安装vim编辑器)

    1
    sudo vim /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf

    进入50-ubuntu.conf的文件中,并在文件中最后添加两行:

    1
    2
    3
    4
    [Seat:*]
    user-session=ubuntu
    greeter-show-manual-login=true //手工输入登录系统的用户名和密码
    all-guest=false //不允许guest登入
  3. 修改autologin和password文件

    1
    sudo vim /etc/pam.d/gdm-autologin

    注释掉第三行

    1
    2
    3
    4
    5
    6
    #%PAM-1.0
    auth requisite pam_nologin.so
    #auth required pam_succeed_if.so user != root quiet_success //注释掉此行
    auth optional pam_gdm.so
    auth optional pam_gnome_keyring.so
    auth required pam_permit.so

    保存退出后执行:

    1
    sudo vim /etc/pam.d/gdm-password

    注释掉第三行然后保存退出

    1
    2
    3
    4
    5
    6
    #%PAM-1.0
    auth requisite pam_nologin.so
    #auth required pam_succeed_if.so user != root quiet_success //注释掉此行
    @include common-auth
    auth optional pam_gnome_keyring.so
    @include common-account
  4. 修改profile文件

    1
    sudo vim /root/.profile

    在文件中修改配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # ~/.profile: executed by Bourne-compatible login shells.

    if [ "$BASH" ]; then
    if [ -f ~/.bashrc ]; then
    . ~/.bashrc
    fi
    fi
    tty -s && mesg n || true //添加此行
    mesg n 2> /dev/null || true
  5. 修改custom.conf文件

    1
    sudo vim /etc/gdm3/custom.conf

    修改如下:

    1
    2
    3
    4
    5
    6
    7
    8
    # Enabling automatic login
    AutomaticLoginEnable=true #是否自动登录系统,设为ture时每次会自动进入系统,而不用输密码
    AutomaticLogin=root #自动登录系统时的默认用户名

    # Enabling timed login
    TimedLoginEnable=true #是否开启超时自动登录
    TimedLogin=root #超时自动登录的用户
    TimedLoginDelay=10 #超时时间
  6. 重启系统就会自动登录到root账户了

    1
    sudo reboot

安装 vim

vim 是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面。 vi使用于文本编辑,但是vim更适用于coding。

1
2
sudo apt install vim
vim -v

安装 git

后续会经常在github上拽工具,所以git必装

1
2
sudo apt install git
git --version

安装 gcc

GCC(GNU Compiler Collection)是由GNU开发的编程语言译器,必装啦,这个不用说了,自己想要编写一些demo的时候需要gcc进行编译,后续ARM交叉编译环境也需要gcc支持

1
2
sudo apt install gcc
gcc -v

安装 python3-pip

pip 是一个现代的,通用的 Python 包管理工具。提供了对 Python 包的查找、下载、安装、卸载的功能。

因为python2已经不再维护了,所以后续很多工具所需的依赖python2会出错,python3不会有什么问题。

1
2
sudo apt install python3-pip
pip -V

创建 PWN目录

建议在主目录下创建一个tools目录,这样我们所有git下来的工具就有统一存放的位置,也方便后续查找

1
2
cd ~
mkdir tools

安装 pwntools

Pwntools是一个CTF框架和开发库。它是用Python编写的,由rapid设计,旨在让使用者简单快速的编写exploit。

Pwntools有两种安装方法,一种是git项目后安装,另一种是pip直接安装。这里我们把pwntools git下来,但是用pip安装,因为后续的工具需要pwntools项目包里的脚本,pip安装不会出错。

1
2
3
4
5
cd tools
git clone https://github.com/Gallopsled/pwntools.git
sudo apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntools

检验以下,如果导包后没报错安装成功:

1
2
python3
>>> from pwn import *

安装 pwndbg

pwndbg是gdb的插件,帮助我们在做题时进行调试。当然你喜欢gef,或者peda也随意。

1
2
3
4
cd tools
git clone https://github.com/pwndbg/pwndbg.git
cd pwndbg
./setup.sh

安装后在命令行输入gdb回车,如果左下角出现pwndbg代表安装成功。

安装 checksec

一个辅助工具,可以用来检测二进制文件格式和安全防护情况。安装完pwntools后,checksec也会自动被安装上。可以在目录/usr/bin下找到checksec的脚本。

除了pwntools自带的,我们也可以选择在线安装:

1
sudo apt install checksec

安装 32位的库

gcc-multilib可用于交叉编译(cross compiling),即编译程序以在不同的处理器架构上运行。例如可以在x86_64位处理器上编译出x86_32位程序,运行在32位处理器上,或者在x86平台上编译出可以在ARM处理器上运行的程序。

1
sudo apt install gcc-multilib

其他网站

https://hollk.blog.csdn.net/article/details/118188924

https://blog.csdn.net/qq_54218833/article/details/125241618

https://blog.csdn.net/Y_peak/article/details/120712904

二、Kali 环境搭建

虚拟机安装

Ubuntu的界面和命令行不够优雅,所以这次尝试Kali 2021.1,选择这个版本是因为系统相对稳定流程,并且zsh的颜色配置相对完善。

官方镜像下载:https://old.kali.org/kali-images/

下载好镜像之后就可以在VMware上安装了。

安装完后打开终端更新软件列表:

1
sudo apt-get update

系统自动登入账户

安装完成之后,默认是没有root账户登录权限的,这样在操作系统时有诸多不便,比如新建一个文件都提示权限不够!不过可以通过创建的普通用户获取管理员权限,然后修改配置和root账户的密码,最后实现系统自动登录用户账户,具体操作步骤如下:

  1. 设置密码

    1
    sudo passwd root

    然后按照提示,先输入当前账户的密码,然后是root账户密码,最后再确认密码。

  2. 修改系统配置文件

    1
    sudo vim /etc/lightdm/lightdm.conf

    进入lightdm.conf的文件中,把这两行的注释删除然后修改参数保存:

    1
    2
    3
    [Seat:*]
    autologin-user=jacckx
    autologin-user-timeout=0
  3. 修改autologin文件,实现自动登入账户

    1
    sudo vim /etc/pam.d/lightdm-autologin

    注释掉这一行

    1
    #auth   required        pam_succeed_if.so user != root quiet_success	//注释掉此行
  4. 重启系统就会自动登录到账户,不需要输入密码了

    1
    sudo reboot

创建 PWN目录

建议在主目录下创建一个tools目录,这样我们所有git下来的工具就有统一存放的位置,也方便后续查找

1
2
cd ~
mkdir tools

安装 pwntools

Pwntools是一个CTF框架和开发库。它是用Python编写的,由rapid设计,旨在让使用者简单快速的编写exploit。

Pwntools有两种安装方法,一种是git项目后安装,另一种是pip直接安装。这里我们把pwntools git下来,但是用pip安装,因为后续的工具需要pwntools项目包里的脚本,pip安装不会出错。

pip 是一个现代的,通用的 Python 包管理工具。提供了对 Python 包的查找、下载、安装、卸载的功能。

因为python2已经不再维护了,所以后续很多工具所需的依赖python2会出错,python3不会有什么问题。

1
2
3
4
5
6
cd tools
git clone https://github.com/Gallopsled/pwntools.git
sudo apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntools

检验以下,如果导包后没报错安装成功:

1
2
python3
>>> from pwn import *

安装 gdb

kali系统里没有安装gdb

1
sudo apt install gdb

安装 pwndbg

pwndbg是gdb的插件,帮助我们在做题时进行调试。当然你喜欢gef,或者peda也随意。

1
2
3
4
cd tools
git clone https://github.com/pwndbg/pwndbg.git
cd pwndbg
./setup.sh

安装后在命令行输入gdb回车,如果左下角出现红色(pwndbg)代表安装成功。

安装 checksec

一个辅助工具,可以用来检测二进制文件格式和安全防护情况。安装完pwntools后,checksec也会自动被安装上,可以在目录~/.local/bin下找到checksec的脚本。最后就是把这个路径加到环境变量里,首先打开:

1
sudo vim ~/.zshrc

在最后一行添加:

1
export PATH="$HOME/.local/bin:$PATH"

保存退出后运行这个命令来更新:

1
source ~/.zshrc

除了pwntools自带的,我们也可以选择在线安装:

1
sudo apt install checksec

安装 32位的库

gcc-multilib可用于交叉编译(cross compiling),即编译程序以在不同的处理器架构上运行。例如可以在x86_64位处理器上编译出x86_32位程序,运行在32位处理器上,或者在x86平台上编译出可以在ARM处理器上运行的程序。

1
sudo apt install gcc-multilib

三、其他选装工具

安装 sublime-text

1
2
3
4
5
6
7
8
9
# Install the GPG key:
wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/sublimehq-archive.gpg > /dev/null

# Select the channel to use:
echo "deb https://download.sublimetext.com/ apt/stable/" | sudo tee /etc/apt/sources.list.d/sublime-text.list

# Update apt sources and install Sublime Text:
sudo apt-get update
sudo apt-get install sublime-text

安装 aptitude

1
sudo apt install aptitude

安装 gdebi

gdebi是一个用于安装你自己手动下载的包的GUI程序。

1
sudo apt install gdebi 

用gdebi安装deb包,它将会自动安装deb包所需要的依赖包:

1
sudo gdebi nautilus_nutstore_amd64.deb

逆向工程基础

内存管理

在操作系统中,为了防止直接分配和使用物理内存造成的诸如内存不足、安全性不足、内存碎片化等问题,采用了虚拟内存空间技术。利用这一手段,只有在进程真正需要访问内存资源时才产生缺页中断,建立虚拟内存地址和物理地址的映射,从而避免了内存浪费。虚拟内存的主要作用是:

  1. 为每个进程提供了一致的地址空间。
  2. 保护每个进程的空间不被其他进程破坏。
  3. 程序运行时只在内存中保存需要的数据,并根据需要在磁盘和内存之间来回传送数据(缺页中断)。

x86-32位虚拟地址空间

在Linux中,系统为每个进程维持了一个单独的虚拟地址空间,包括了 .text、.data、.bss、stack、heap,共享库等内容。

image-20221130040818432

在这个单独的虚拟地址空间中,空间被划分为内核空间用户空间。访问内核空间需要程序有ring0的权限,尽管存在特权分离,但它们都共享相同的虚拟地址空间

在Linux x86-32位中,4GB地址空间被划分成:

  • 3GB的用户空间,地址从0x08048000 ~ 0xBFFFFFFF

  • 1GB的内核空间,地址从0xC0000000 ~ 0xFFFFFFFF

而Windows对空间的划分不同于Linux,4G 地址空间中低2G,0x00000000 ~ 0x7FFFFFFF 是用户地址空间。高2G,0x80000000 ~ 0xFFFFFFFF 是系统地址空间。

glibc

glibc 即 GNU C Library,是为 GNU 操作系统开发的一个 C 标准库。glibc 主要由两部分组成,一部分是头文件,位于 /usr/include;另一部分是库的二进制文件。二进制文件部分主要是 C 语言标准库,有动态和静态两个版本,动态版本位于 /lib/libc.so.6,静态版本位于 /usr/lib/libc.a