美文网首页
记录一次tcache调试

记录一次tcache调试

作者: _invincible_ | 来源:发表于2020-05-04 20:17 被阅读0次

说明

根据这篇文章的内容结合glibc-2.27对tcache的分配和释放做了一次调试实验。

测试代码

$ cat t2.c 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){
    
    void *p = malloc(112);
    memset(p, 'A', 112);
    free(p);
    void *p2 = malloc(112);
    free(p2);
}
$ gcc t2.c -o t2 -g

$ ldd --version
ldd (Ubuntu GLIBC 2.27-3ubuntu1) 2.27
...
$ uname -a
Linux ubuntu 5.3.0-51-generic #44~18.04.2-Ubuntu SMP Thu Apr 23 14:27:18 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

实验

1. 获取tcache_perthread_struct 地址

gdb t2
b main
r
b *tcache_init+144
c
p victim
set $tcache_0 = victim

输出:
gdb-peda$ b *tcache_init+144
Breakpoint 2 at 0x7ffff7a7a4f0: file malloc.c, line 3005.
gdb-peda$ c
=> 0x7ffff7a7a4f0 <tcache_init+144>:    mov    rax,QWORD PTR [rip+0x354881]        # 0x7ffff7dced78
...
Breakpoint 2, tcache_init () at malloc.c:3005
3005          tcache = (tcache_perthread_struct *) victim;
gdb-peda$ p victim
$1 = (void *) 0x555555756010
gdb-peda$ set $tcache_0 = victim

tcache分的地址为:0x555555756010


断点说明:
b *tcache_init+144 用于定位tcache指针

=> 0x7ffff7a7a4f0 <tcache_init+144>:    mov    rax,QWORD PTR [rip+0x354881]        # 0x7ffff7dced78
# ...
Breakpoint 2, tcache_init () at malloc.c:3005
3005          tcache = (tcache_perthread_struct *) victim;
# ------------------------------------------------------------------------------------------------

2. 获取第一次分配的内存地址

b *_int_malloc+366
c
reg rax
b *main+26
c
p p
p $rax

输出:
gdb-peda$ reg rax
RAX: 0x555555756260 --> 0x0
gdb-peda$ b *main+26
Breakpoint 4 at 0x5555555546f4: file t2.c, line 8.
gdb-peda$  c
[-------------------------------------code-------------------------------------]
   0x5555555546e7 <main+13>:    call   0x5555555545b0 <malloc@plt>
   0x5555555546ec <main+18>:    mov    QWORD PTR [rbp-0x10],rax
   0x5555555546f0 <main+22>:    mov    rax,QWORD PTR [rbp-0x10]
=> 0x5555555546f4 <main+26>:    mov    edx,0x70
   0x5555555546f9 <main+31>:    mov    esi,0x41
   0x5555555546fe <main+36>:    mov    rdi,rax
   0x555555554701 <main+39>:    call   0x5555555545a0 <memset@plt>
   0x555555554706 <main+44>:    mov    rax,QWORD PTR [rbp-0x10]
[------------------------------------stack-------------------------------------]
...
Breakpoint 4, 0x00005555555546f4 in main () at t2.c:8
8       memset(p, 'A', 112);

gdb-peda$ p p
$2 = (void *) 0x555555756260
gdb-peda$ p $rax
$3 = 0x555555756260

第一次malloc出的地址:0x555555756260


断点说明:
b *_int_malloc+366 定位到_int_malloc的return位置,从rax中获取malloc分配的内存地址

=> 0x7ffff7a7843e <_int_malloc+366>:    ret    

# static void *
# _int_malloc (mstate av, size_t bytes)
# {
# ...
#   checked_request2size (bytes, nb);

#   if (__glibc_unlikely (av == NULL))
#     {
#       void *p = sysmalloc (nb, av);
#       if (p != NULL)
#   alloc_perturb (p, bytes);
#       return p;
#     }
#     ...
# }

b *main+26 回到main函数中查看malloc出的内存地址
# gdb-peda$ disassemble main
# Dump of assembler code for function main:
# ...
   0x00005555555546e7 <+13>:    call   0x5555555545b0 <malloc@plt>
   0x00005555555546ec <+18>:    mov    QWORD PTR [rbp-0x10],rax
   0x00005555555546f0 <+22>:    mov    rax,QWORD PTR [rbp-0x10]
=> 0x00005555555546f4 <+26>:    mov    edx,0x70

3. 查看释放tcache的位置

b * __libc_free+1273
c
p *(tcache_perthread_struct *)$tcache_0
n
p *(tcache_perthread_struct *)$tcache_0
n
p *(tcache_perthread_struct *)$tcache_0

输出:

gdb-peda$ b * __libc_free+1273
Breakpoint 5 at 0x7ffff7a7be49: file malloc.c, line 2931.
gdb-peda$ c

=> 0x7ffff7a7be49 <__GI___libc_free+1273>:  mov    QWORD PTR [rsi+0x40],r12
...
Breakpoint 5, tcache_put (tc_idx=0x6, chunk=0x555555756250) at malloc.c:2931
2931      tcache->entries[tc_idx] = e;
gdb-peda$ p *(tcache_perthread_struct *)$tcache_0
$4 = {
  counts = '\000' <repeats 63 times>, 
  entries = {0x0 <repeats 64 times>}
}

gdb-peda$ n
...
2932      ++(tcache->counts[tc_idx]);
gdb-peda$ p *(tcache_perthread_struct *)$tcache_0
$5 = {
  counts = '\000' <repeats 63 times>, 
  entries = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x555555756260, 0x0 <repeats 57 times>}
}

gdb-peda$ n
gdb-peda$ p *(tcache_perthread_struct *)$tcache_0
$6 = {
  counts = "\000\000\000\000\000\000\001", '\000' <repeats 56 times>, 
  entries = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x555555756260, 0x0 <repeats 57 times>}
}

回收第一次malloc的内存到 tcache.entrise[6]



断点说明:
b * __libc_free+1273 定位到tcache_put函数(内联)
=> 0x7ffff7a7be49 <__GI___libc_free+1273>:  mov    QWORD PTR [rsi+0x40],r12
...
Breakpoint 5, tcache_put (tc_idx=0x6, chunk=0x555555756250) at malloc.c:2931
2931      tcache->entries[tc_idx] = e;

4. 查看tcache第二次被取出

b *main+61
c
delete 1-7
b *__libc_malloc+401
c
p *(tcache_perthread_struct *)$tcache_0
s
s
s
p *(tcache_perthread_struct *)$tcache_0
s
p *(tcache_perthread_struct *)$tcache_0
b *main+74
c
p p2


输出:
gdb-peda$ b *main+61
Breakpoint 6 at 0x555555554717: file t2.c, line 10.
gdb-peda$ c
...
gdb-peda$ b *__libc_malloc+401
Breakpoint 7 at 0x7ffff7a7b201: file malloc.c, line 2941.
gdb-peda$ c
...
3050          return tcache_get (tc_idx);
gdb-peda$ p *(tcache_perthread_struct *)$tcache_0
$7 = {
  counts = "\000\000\000\000\000\000\001", '\000' <repeats 56 times>, 
  entries = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x555555756260, 0x0 <repeats 57 times>}
}

gdb-peda$ s
...
tcache_get (tc_idx=0x6) at malloc.c:2941
2941      assert (tc_idx < TCACHE_MAX_BINS);
gdb-peda$ s
...
2943      tcache->entries[tc_idx] = e->next;
gdb-peda$ s
...
2944      --(tcache->counts[tc_idx]);
gdb-peda$ p *(tcache_perthread_struct *)$tcache_0
$8 = {
  counts = "\000\000\000\000\000\000\001", '\000' <repeats 56 times>, 
  entries = {0x0 <repeats 64 times>}
}
gdb-peda$ s
gdb-peda$ p *(tcache_perthread_struct *)$tcache_0
$9 = {
  counts = '\000' <repeats 63 times>, 
  entries = {0x0 <repeats 64 times>}
}

gdb-peda$ b *main+74
Breakpoint 8 at 0x555555554724: file t2.c, line 11.
gdb-peda$ c
gdb-peda$ p p2
$10 = (void *) 0x555555756260

释放之前的tcache分配给新的指针p2

断点说明:
b *main+61 定位到main函数第二次调用malloc的位置
[-------------------------------------code-------------------------------------]
   0x55555555470a <main+48>:    mov    rdi,rax
   0x55555555470d <main+51>:    call   0x555555554590 <free@plt>
   0x555555554712 <main+56>:    mov    edi,0x70
=> 0x555555554717 <main+61>:    call   0x5555555545b0 <malloc@plt>
   0x55555555471c <main+66>:    mov    QWORD PTR [rbp-0x8],rax
   0x555555554720 <main+70>:    mov    rax,QWORD PTR [rbp-0x8]
   0x555555554724 <main+74>:    mov    rdi,rax
   0x555555554727 <main+77>:    call   0x555555554590 <free@plt>
[------------------------------------stack-------------------------------------]

b *__libc_malloc+401 定位到tcache_get的调用位置
=> 0x7ffff7a7b201 <__GI___libc_malloc+401>: cmp    rax,0x3f
... 
Breakpoint 7, __GI___libc_malloc (bytes=0x70) at malloc.c:3050
3050          return tcache_get (tc_idx);


b *main+61 定位到第二次malloc返回的位置
=> 0x555555554724 <main+74>:    mov    rdi,rax
   0x555555554727 <main+77>:    call   0x555555554590 <free@plt>
   0x55555555472c <main+82>:    mov    eax,0x0
   0x555555554731 <main+87>:    leave  
   0x555555554732 <main+88>:    ret

参考

https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/implementation/tcache/

相关文章

网友评论

      本文标题:记录一次tcache调试

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