add de1ctf code_runner
This commit is contained in:
parent
b9492db703
commit
08c20c817f
BIN
2020/de1ctf/code_runner/code_runner
Normal file
BIN
2020/de1ctf/code_runner/code_runner
Normal file
Binary file not shown.
259
2020/de1ctf/code_runner/code_runner.py
Normal file
259
2020/de1ctf/code_runner/code_runner.py
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
from capstone import *
|
||||||
|
from z3 import *
|
||||||
|
from elftools.elf.elffile import ELFFile
|
||||||
|
|
||||||
|
def get_insn_list(bytecode, first_addr):
|
||||||
|
insn_list = {}
|
||||||
|
md = Cs(CS_ARCH_MIPS, CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN)
|
||||||
|
for insn in md.disasm(bytecode, first_addr):
|
||||||
|
insn_list[insn.address] = (hex(insn.address), insn.mnemonic, insn.op_str, insn.size)
|
||||||
|
return insn_list
|
||||||
|
|
||||||
|
def dump_func(insn_list, func_addr):
|
||||||
|
(addr, i, op, size) = insn_list[func_addr]
|
||||||
|
if i != "jr":
|
||||||
|
return [(addr, i, op)] + dump_func(insn_list, func_addr + size)
|
||||||
|
return [(addr, i, op)]
|
||||||
|
|
||||||
|
def iter_func(insn_list, func_addr, hook_code):
|
||||||
|
(addr, i, op, size) = insn_list[func_addr]
|
||||||
|
hook_code(addr, i, op)
|
||||||
|
if i != "jr":
|
||||||
|
dump_func(insn_list, func_addr + size)
|
||||||
|
|
||||||
|
f = ELFFile(open('code_runner', 'rb'))
|
||||||
|
symbols = f.get_section_by_name('.dynsym')
|
||||||
|
[main] = symbols.get_symbol_by_name('main')
|
||||||
|
text = f.get_section_by_name('.text')
|
||||||
|
|
||||||
|
first_addr = text['sh_addr']
|
||||||
|
start_addr = main.entry.st_value
|
||||||
|
check_start = 0x00401994
|
||||||
|
bytecode = text.data()
|
||||||
|
|
||||||
|
insn_list = get_insn_list(bytecode, first_addr)
|
||||||
|
|
||||||
|
class Node:
|
||||||
|
def __init__(self, insn, next_func = None):
|
||||||
|
self.insn = insn
|
||||||
|
self.addr = insn[0][0]
|
||||||
|
self.next_func = next_func
|
||||||
|
(_, i, op) = insn[-1]
|
||||||
|
if i == "b":
|
||||||
|
self.branch = "branch"
|
||||||
|
self.to = int(op, 16)
|
||||||
|
elif i == "beq":
|
||||||
|
self.branch = "equal"
|
||||||
|
self.to = int(op.split(', ')[-1], 16)
|
||||||
|
elif i == "bne":
|
||||||
|
self.branch = "non_equal"
|
||||||
|
self.to = int(op.split(', ')[-1], 16)
|
||||||
|
else:
|
||||||
|
self.branch = "return"
|
||||||
|
self.to = None
|
||||||
|
self.mustbe = None
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
next_func = f"call {hex(self.next_func)}" if self.next_func is not None else ""
|
||||||
|
return f"{self.addr}, {self.branch}, {self.to}, {self.mustbe}, {next_func}" # , {self.insn}"
|
||||||
|
|
||||||
|
def condition(self, z, param):
|
||||||
|
class PIndex:
|
||||||
|
def __init__(self, v = 0):
|
||||||
|
self.v = v
|
||||||
|
def __add__(self, s):
|
||||||
|
return PIndex(self.v + s)
|
||||||
|
def __sub__(self, s):
|
||||||
|
return PIndex(self.v - s)
|
||||||
|
def __repr__(self):
|
||||||
|
return f"param[{self.v}]"
|
||||||
|
|
||||||
|
if self.mustbe is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
reg = {}
|
||||||
|
reg["$zero"] = 0
|
||||||
|
reg["$sp"] = 0
|
||||||
|
for (_, i, op) in self.insn:
|
||||||
|
# print(i, op)
|
||||||
|
if i in ["sw", "nop", "jal", "negu", "b"]:
|
||||||
|
pass
|
||||||
|
elif i == "move":
|
||||||
|
[out, x] = op.split(', ')
|
||||||
|
reg[out] = reg[x]
|
||||||
|
elif i == "lw":
|
||||||
|
[out, x] = op.split(', ')
|
||||||
|
if x == "0x20($fp)":
|
||||||
|
reg[out] = PIndex()
|
||||||
|
elif i == "lbu":
|
||||||
|
[out, x] = op.replace(')', '').replace('(', '').split(', ')
|
||||||
|
reg[out] = param[reg[x].v]
|
||||||
|
elif i == "addiu":
|
||||||
|
[a, b, c] = op.split(', ')
|
||||||
|
reg[a] = reg[b] + int(c, 16)
|
||||||
|
elif i == "addu":
|
||||||
|
[a, b, c] = op.split(', ')
|
||||||
|
reg[a] = reg[b] + reg[c]
|
||||||
|
elif i == "subu":
|
||||||
|
[a, b, c] = op.split(', ')
|
||||||
|
reg[a] = reg[b] - reg[c]
|
||||||
|
elif i == "xor":
|
||||||
|
[a, b, c] = op.split(', ')
|
||||||
|
reg[a] = reg[b] ^ reg[c]
|
||||||
|
elif i == "andi":
|
||||||
|
[a, b, c] = op.split(', ')
|
||||||
|
# if int(c, 16) != 255:
|
||||||
|
reg[a] = reg[b] & int(c, 16)
|
||||||
|
# else:
|
||||||
|
# reg[a] = reg[b]
|
||||||
|
elif i == "sll":
|
||||||
|
[a, b, c] = op.split(', ')
|
||||||
|
reg[a] = reg[b] << int(c, 16)
|
||||||
|
elif i == "mult":
|
||||||
|
[a, b] = op.split(', ')
|
||||||
|
reg["hi"] = reg[a] * reg[b]
|
||||||
|
reg["lo"] = reg[a] * reg[b]
|
||||||
|
elif i == "mflo":
|
||||||
|
reg[op] = reg["hi"]
|
||||||
|
elif i == "bgez":
|
||||||
|
[a, _] = op.split(', ')
|
||||||
|
reg[a] = If(reg[a] > 0, reg[a], -reg[a])
|
||||||
|
elif i == "slt":
|
||||||
|
[a, b, c] = op.split(', ')
|
||||||
|
reg[a] = If(reg[b] <= reg[c], 1, 0)
|
||||||
|
elif i == "bnez":
|
||||||
|
[a, _] = op.split(', ')
|
||||||
|
if self.mustbe == True:
|
||||||
|
z.add(reg[a] == 0)
|
||||||
|
elif self.mustbe == False:
|
||||||
|
z.add(reg[a] != 0)
|
||||||
|
print(z)
|
||||||
|
elif i == "bne" or i == "beq":
|
||||||
|
[a, b, c] = op.split(', ')
|
||||||
|
if self.mustbe == True:
|
||||||
|
z.add(reg[a] == reg[b])
|
||||||
|
elif self.mustbe == False:
|
||||||
|
z.add(reg[a] != reg[b])
|
||||||
|
print(z)
|
||||||
|
else:
|
||||||
|
input("unknown instruction")
|
||||||
|
# exit()
|
||||||
|
# print(reg)
|
||||||
|
# input()
|
||||||
|
print()
|
||||||
|
|
||||||
|
def split_to_nodes(func):
|
||||||
|
nodes = []
|
||||||
|
insn = []
|
||||||
|
next_func = None
|
||||||
|
for (addr, i, op) in func:
|
||||||
|
insn += [(addr, i, op)]
|
||||||
|
if i == "jal":
|
||||||
|
next_func = int(op, 16)
|
||||||
|
if i == "b" or i == "beq" or i == "bne" or i == "jr":
|
||||||
|
nodes += [Node(insn, next_func)]
|
||||||
|
next_func = None
|
||||||
|
insn = []
|
||||||
|
return nodes
|
||||||
|
|
||||||
|
def inspect_badjump(nodes):
|
||||||
|
badjump = []
|
||||||
|
for n in nodes:
|
||||||
|
if n.to is None:
|
||||||
|
continue
|
||||||
|
(_, i, op, _) = insn_list[n.to]
|
||||||
|
if i == "move" and op == "$v0, $zero":
|
||||||
|
if n.to not in badjump: badjump += [n.to]
|
||||||
|
if n.branch == "equal":
|
||||||
|
n.mustbe = False
|
||||||
|
elif n.branch == "non_equal":
|
||||||
|
n.mustbe = True
|
||||||
|
return badjump
|
||||||
|
|
||||||
|
def do_next(insn_list, start = check_start):
|
||||||
|
print(hex(start))
|
||||||
|
nodes = split_to_nodes(dump_func(insn_list, start))
|
||||||
|
inspect_badjump(nodes)
|
||||||
|
next_func = None
|
||||||
|
z = Solver()
|
||||||
|
param = [BitVec(f"param_{i}", 8) for i in range(4)]
|
||||||
|
for n in nodes:
|
||||||
|
# print(n)
|
||||||
|
if n.next_func:
|
||||||
|
next_func = n.next_func
|
||||||
|
if hex(start) == "0x4013c8":
|
||||||
|
n.mustbe = False
|
||||||
|
n.condition(z, param)
|
||||||
|
else:
|
||||||
|
n.condition(z, param)
|
||||||
|
z.check()
|
||||||
|
m = z.model()
|
||||||
|
r = sorted([(d, m[d]) for d in m], key = lambda x: str(x[0]))
|
||||||
|
flag = list(map(lambda x: int(str(x[1])), r))
|
||||||
|
print(flag)
|
||||||
|
print()
|
||||||
|
if next_func:
|
||||||
|
return flag + do_next(insn_list, next_func)
|
||||||
|
return flag
|
||||||
|
|
||||||
|
first_check = do_next(insn_list)
|
||||||
|
print(first_check)
|
||||||
|
first_check = bytes(first_check)
|
||||||
|
print(first_check)
|
||||||
|
exit()
|
||||||
|
from pwn import *
|
||||||
|
|
||||||
|
def pass_pow(target):
|
||||||
|
# from itertools import combinations_with_replacement
|
||||||
|
from string import printable
|
||||||
|
import hashlib
|
||||||
|
print(f"pow target: {target}")
|
||||||
|
# for p in combinations_with_replacement(''.join([chr(i) for i in range(256)]), 3):
|
||||||
|
# p = ''.join(list(p)).encode()
|
||||||
|
for i in range(256):
|
||||||
|
for j in range(256):
|
||||||
|
for k in range(256):
|
||||||
|
p = bytes([i, j, k])
|
||||||
|
h = hashlib.sha256(p).hexdigest()
|
||||||
|
# if p[0] == b'a':
|
||||||
|
# input(f"{p}, {h}, {target}, {h == target}")
|
||||||
|
if h == target:
|
||||||
|
print(f"pow solved: {p}")
|
||||||
|
return p
|
||||||
|
print('pow not found!')
|
||||||
|
exit()
|
||||||
|
|
||||||
|
|
||||||
|
# first_check = do_next(insn_list)
|
||||||
|
# first_check = bytes(first_check)
|
||||||
|
|
||||||
|
# open('code_runner.input', 'wb').write(first_check)
|
||||||
|
# print(f"faster: {first_check}")
|
||||||
|
|
||||||
|
r = remote("106.53.114.216", 9999)
|
||||||
|
|
||||||
|
r.recvline()
|
||||||
|
r.recvuntil('hashlib.sha256(s).hexdigest() == "')
|
||||||
|
target = r.recvuntil('"')[:-1]
|
||||||
|
r.recvline()
|
||||||
|
r.recvline()
|
||||||
|
|
||||||
|
r.sendline(pass_pow(target.decode()))
|
||||||
|
|
||||||
|
r.recvuntil("===============")
|
||||||
|
# binary
|
||||||
|
r.recvuntil("===============")
|
||||||
|
|
||||||
|
print(r.recvuntil("Faster > \n").decode())
|
||||||
|
first_check = open('./code_runner.input', 'rb').read()
|
||||||
|
first_check += b' ' * (0x100 - len(first_check))
|
||||||
|
r.send(first_check)
|
||||||
|
|
||||||
|
print(r.recvline())
|
||||||
|
print(r.recvline())
|
||||||
|
print(r.recvline())
|
||||||
|
print(r.recvline())
|
||||||
|
print(r.recvline())
|
||||||
|
print(r.recvline())
|
||||||
|
print(r.recvline())
|
||||||
|
# r.interactive()
|
Loading…
Reference in New Issue
Block a user