1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
| from typing import Optional
from qiling import * from qiling.const import QL_VERBOSE, QL_INTERCEPT from qiling.extensions import pipe from qiling import * from qiling.os.mapper import *
import threading
class QilingEmulator: def __init__(self, start, end): self.idx = start self.end = end self.idx_oneLoop = 0 self.idx_1 = 0 self.mat = self.generate_matrix() self.proc_name = './challenge'
def generate_matrix(self): matrix = [ 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, ]
def generate_sequence(i): base = 6 digits = [] for _ in range(4): digits.append(i % base) i //= base digits.reverse() sequence = [] for d in digits: start = d * base sequence.append(matrix[start:start + base]) return sequence
mat = [] for i in range(1, 6**4): a = generate_sequence(i) mat.append(a) return mat
def get_Strncmp_rax(self): matx = self.mat[self.idx] ret_v = matx[self.idx_1][self.idx_oneLoop] if ret_v == 0: self.idx_1 += 1 self.idx_oneLoop = -1 return ret_v
def hook_isoc99_scanf(self, ql: Qiling): print("Hit ___isoc99_scanf") ql.os.stdin = pipe.SimpleInStream(0) ql.os.stdin.write(b"1")
def hook_strncmp(self, ql: Qiling, *args): print("Hook strncmp") ql.arch.regs.rax = self.get_Strncmp_rax() self.idx_oneLoop += 1
def try_patch_isa(self, ql: Qiling): pre = bytes.fromhex("8b8a2803000089cf4421c739f9") ins = bytes.fromhex("0f85000b0000") skip = bytes.fromhex("488d50f84839f075c3")
def bypass_isa_check(ql: Qiling) -> None: print("Bypassing ISA Check...") ql.arch.regs.rip += len(ins) + len(skip)
for start, end, perm, label, img in ql.mem.get_mapinfo(): if label != "ld-linux-x86-64.so.2": continue if "x" not in perm: continue
adrs = ql.mem.search(pre + ins + skip, begin=start, end=end) for adr in adrs: ql.hook_address(bypass_isa_check, adr + len(pre))
def hook_puts(self, ql: Qiling): text = ql.mem.string(ql.arch.regs.rdi) print(text) if text == 'Wrong!': self.idx += 1 self.idx_1 = 0 else: raise Exception('Correct found!')
def run_emulator(self): while self.idx < self.end: self.idx_oneLoop = 0 ql = Qiling([self.proc_name], "/", verbose=QL_VERBOSE.DISABLED) base = ql.loader.images[0].base ql._multithread = True self.try_patch_isa(ql) ql.os.set_api('strncmp', self.hook_strncmp) ql.os.set_api('puts', self.hook_puts) ql.hook_address(self.hook_isoc99_scanf, base + 0x10C0) try: ql.run() except Exception as e: print(e) pass
def find(start, end): emulator = QilingEmulator(start, end) emulator.run_emulator()
if __name__ == "__main__": threading.Thread(target=find, args=(0, 100)).start() threading.Thread(target=find, args=(100, 200)).start() threading.Thread(target=find, args=(200, 300)).start() threading.Thread(target=find, args=(300, 500)).start() threading.Thread(target=find, args=(500, 600)).start() threading.Thread(target=find, args=(600, 700)).start() threading.Thread(target=find, args=(700, 800)).start() threading.Thread(target=find, args=(800, 900)).start() threading.Thread(target=find, args=(900, 1000)).start() threading.Thread(target=find, args=(1000, 1100)).start() threading.Thread(target=find, args=(1100, 1200)).start() threading.Thread(target=find, args=(1200, 1296)).start()
|