| 12
 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()
 
 
 |