cscg24-license

CSCG 2024 Challenge 'Most unique license checker'
git clone https://git.sinitax.com/sinitax/cscg24-license
Log | Files | Refs | sfeed.txt

solve (3326B)


      1#!/usr/bin/env python3
      2
      3import angr
      4import claripy
      5import logging
      6import subprocess
      7import cle
      8
      9try:
     10    import binaryninja
     11except:
     12    pass
     13
     14check1 = b"A@F01"
     15check2 = b"\xc56i9\xf4j\x0fk\xc4L\xfa\xd3\x8f\x99\xc0\xce"
     16check2_rev = b"00GHK-L1MNS" # from cracked md5 hash
     17
     18def checkpoint(sim, find, text, **kwargs):
     19    while len(sim.active) > 0:
     20        sim.explore(find=find, **kwargs, step_func=step_func)
     21        print(text, sim)
     22    assert(len(sim.found) > 0)
     23    sim.stash(from_stash="found", to_stash="active")
     24
     25def step_func(sim):
     26    if sim.active != [] and bv != None:
     27        for state in sim.active:
     28            for bb in bv.get_basic_blocks_at(state.solver.eval(state.regs.rip)):
     29                bb.set_user_highlight(binaryninja.HighlightStandardColor.MagentaHighlightColor)
     30    sim.drop(stash="avoid")
     31
     32    print(sim.active)
     33
     34
     35def run(_bv=None):
     36    global bv
     37    bv = _bv
     38
     39    logging.getLogger('angr.sim_manager').setLevel(logging.DEBUG)
     40
     41    key = [claripy.BVS(f"key_{i}", 8) for i in range(29)] + [b"\x00"]
     42
     43    cmd = ["gdb", "-ex", "b *0x402030", "-ex", "run",
     44           "-ex", "gcore core.dump", "-ex", "exit", "--batch",
     45           "--args", "./licensecheck", "12345-12345-12345-12345-12345"]
     46    subprocess.run(cmd)
     47
     48    project = angr.Project("core.dump", main_opts={"backend": "elfcore"},
     49        rebase_granularity=0x1000)
     50    binfile = angr.SimFile("licensecheck", open("licensecheck", "rb").read())
     51    state = project.factory.blank_state(fs={"licensecheck": binfile})
     52
     53    elfcore = None
     54    for o in project.loader.all_objects:
     55        if type(o) == cle.backends.elf.elfcore.ELFCore:
     56            elfcore = o
     57            break
     58    assert(elfcore is not None)
     59
     60    for reg in elfcore.initial_register_values():
     61        try:
     62            setattr(state.regs, reg[0], reg[1])
     63        except Exception as e:
     64            print("skip-reg", e)
     65
     66    state.memory.store(state.solver.eval(state.regs.rdi), claripy.Concat(*key))
     67
     68    for i in range(29):
     69        if i >= 18:
     70            state.solver.add(key[i] == check2_rev[i-18])
     71        elif (i + 1) % 6 == 0:
     72            state.solver.add(key[i] == ord(b'-'))
     73        else:
     74            isalpha = claripy.And(key[i] >= ord('A'), key[i] <= ord('Z'))
     75            isnum = claripy.And(key[i] >= ord('0'), key[i] <= ord('9'))
     76            state.solver.add(claripy.Or(isalpha, isnum))
     77
     78    # plt sim hooks
     79    project.hook(0x4010e0, angr.SIM_PROCEDURES["libc"]["strncpy"]())
     80    project.hook(0x4010f0, angr.SIM_PROCEDURES["libc"]["memcmp"]())
     81    project.hook(0x401140, angr.SIM_PROCEDURES["libc"]["strcmp"]())
     82    project.hook(0x401190, angr.SIM_PROCEDURES["libc"]["strlen"]())
     83
     84    # libc hooks
     85    project.hook(0x40ce40, angr.SIM_PROCEDURES["libc"]["fopen"]())
     86    project.hook(0x40cf40, angr.SIM_PROCEDURES["libc"]["fread"]())
     87    project.hook(0x40d040, angr.SIM_PROCEDURES["libc"]["puts"]())
     88
     89    sim = project.factory.simgr(state)
     90    checkpoint(sim, 0x402092, "start of loop", avoid=0x4020cb)
     91
     92    for state in sim.active:
     93        state.regs.rip = 0x4020d0
     94
     95    checkpoint(sim, 0x40245c, "after check1", avoid=0x4020cb)
     96    checkpoint(sim, 0x4024aa, "after check2", avoid=0x4020cb)
     97    checkpoint(sim, 0x4016ed, "final", avoid=0x4016ec)
     98    print(sim.active[0].solver.eval_upto(claripy.Concat(*key), cast_to=bytes, n=2))
     99
    100if __name__ == "__main__":
    101    run()