# Volcano - Chúng ta có một file binary. Load nó vào IDA ![](https://hackmd.io/_uploads/B13UZKUi3.png) Chương trình sẽ bắt nhật 3 số. Mỗi lần nhập là sẽ có một hàm check xem input hợp lệ. 1. Đoạn check đầu tiên sub_12BB() ![](https://hackmd.io/_uploads/rJJFHY8on.png) Nó chỉ là một vài câu lệnh if. Nếu input 1 thoải mãn hết điều kiện thì return 1 2. Đoạn check thứ 2 sub_13D9() ![](https://hackmd.io/_uploads/SkFxIY8jh.png) Nó sẽ tính số lượng bit 1 nếu `16 < bit_1 <= 26` -> return 1 3. Đoạn check cuối ![](https://hackmd.io/_uploads/ry207YUih.png) Để ý đoạn if này thì thấy có thể `vol = bear` và `secret` sẽ bằng một số lẻ khác 1. Bây giờ ta chỉ việc tìm 1 số thoải mản 2 đoạn check ban đầu là done!! * Script dùng z3 python ``` from z3 import * v7 = Int('v7') s = Solver() s.add(v7 > 0) s.add(v7 % 1 == 0, v7 % 3 == 2, v7 % 5 == 1, v7 % 7 == 3, v7 % 109 == 55) print(s.check()) while s.check() == sat: a1 = s.model()[v7].as_long() print(a1) s.add(v7 != a1) v2 = 0 while a1: v2 += a1 & 1 a1 >>= 1 if v2 > 16 and v2 <= 26: print('Bear = Volcano') break # Result: 1048526 ``` Chọn đại 1 số lẻ và khác 1 làm secret và lấy flag. **Flag**: `amateursCTF{yep_th0se_l00k_th3_s4me_to_m3!_:clueless:}` # rusteze - Đề cho một file binary được viết bằng `Rust`. Load vào ida phân tích. - Chương trình nhập 1 input có độ dài là 38 sao đó sẽ thực hiện một số bitwise operation ![](https://hackmd.io/_uploads/rk7LsK8sh.png) và so sánh với một array có sẵn. ![](https://hackmd.io/_uploads/HJnhjFIo3.png) Nó khá dễ dàng để phân tích và reverse chúng. Và đây là script của tôi. ``` arr_1 = [39, -105, 87, 0, -87, 117, 102, 62, 27, 99, -29, -96, 5, 115, 89, -5, 10, 67, -113, -32, -70, -64, 84, -103, 6, -65, -97, 47, -60, -86, -90, 116, 30, -35, -105, 34, -19, -59] arr_2 = [25, -21, -40, 86, 51, 0, 80, 53, 97, -36, -106, 111, -75, 13, -92, 122, 85, -24, -2, 86, -105, -34, -99, -81, -44, 71, -81, -63, -62, 106, 90, -84, -79, -94, -118, 89, 82, -30] def ror(val, r_bits, max_bits): r_bits %= max_bits mask = (1 << r_bits) - 1 return ((val & mask) << (max_bits - r_bits)) | (val >> r_bits) for i, j in zip(arr_1, arr_2): print(chr((ror(j & 0xff, 2, 8) ^ (i & 0xff)) & 0xff), end = '') ``` **Flag**: `amaeursCTF{h0pe_y0u_w3r3nt_t00_ru5ty}` # trick question - Đề cho 1 file trick-question.pyc. Dùng `pydumpck` lấy được file `trick-question.pyc.cdc.py`. Phân tích file này thì nó sẽ decode 1 đoạn base64 và mình dump base64 đó ra cho dễ nhìn ``` # b64decode = lambda x: id.__self__.__dict__['exec'](id.__self__.__dict__['__import__']('base64').b64decode(x)) import base64 r = [ 0, 0, ... 0] x = [ 'gIHByaW50KCJJbmNvcnJlY3QuIik=', 'gcHJpbnQoIkNvcnJlY3QhIikKZWxzZToKIC', ... 'Y2hlY2sgPSBsYW1iZGE6Tm9uZQpjb2RlID0gdHlwZShjaGVjay5fX2NvZGVfXykoMSwgMCwgMCwgNiwgNSwgNjcsIGInfFx4MDBkXHgwMGRceD'] for i in range(len(r)): if r[i]: x[i] = x[i][::-1] data = base64.b64decode('A'.join(x[::-1])) with open('b64_decode.txt', 'wb') as f: f.write(data) f.close() ``` Và đoạn base64 sẽ như này ``` check = lambda:None code = type(check.__code__)(1, 0, 0, 6, 5, 67, b'|\x00d\x00d\x01\x85\x02\x19\x00d\x02k\x03r\x0et\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x04\x19\x00d\x05k\x03r\x1at\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x01d\x04\x85\x02\x19\x00}\x00t\x00j\x01j\x02d\x06\x19\x00|\x00\x83\x01d\x07k\x03r0t\x00j\x01j\x02d\x03\x19\x00S\x00g\x00}\x01t\x00j\x01j\x02d\x08\x19\x00|\x00\x83\x01D\x00]\r\\\x02}\x02}\x03|\x03d\tk\x02rG|\x01\xa0\x03|\x02\xa1\x01\x01\x00q:|\x01g\x00d\n\xa2\x01k\x03rTt\x00j\x01j\x02d\x03\x19\x00S\x00|\x00\xa0\x04\xa1\x00\xa0\x05d\x0b\xa1\x01}\x00|\x00d\x0c\x19\x00d\x00d\x00d\x04\x85\x03\x19\x00d\rk\x03rlt\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x0e\x19\x00d\x0c\x19\x00|\x00d\x0e\x19\x00d\x0e\x19\x00\x17\x00|\x00d\x0e\x19\x00d\x0f\x19\x00\x18\x00|\x00d\x0e\x19\x00d\x0e\x19\x00|\x00d\x0e\x19\x00d\x0f\x19\x00\x17\x00|\x00d\x0e\x19\x00d\x0c\x19\x00\x18\x00|\x00d\x0e\x19\x00d\x0f\x19\x00|\x00d\x0e\x19\x00d\x0c\x19\x00\x17\x00|\x00d\x0e\x19\x00d\x0e\x19\x00\x18\x00f\x03d\x10k\x03r\xa9t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x11\x19\x00d\x12\x83\x01\xa0\x06|\x00d\x0f\x19\x00\xa1\x01\xa0\x07\xa1\x00d\x13k\x03r\xc0t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x11\x19\x00d\x14\x83\x01}\x04|\x04\xa0\x08|\x00d\x0f\x19\x00\xa1\x01\x01\x00t\x00j\x01j\x02d\x15\x19\x00|\x00d\x16\x19\x00\x83\x01|\x00d\x16<\x00|\x04\xa0\t|\x00d\x16\x19\x00\xa1\x01\x01\x00|\x00d\x16\x19\x00g\x00d\x17\xa2\x01k\x03r\xf0t\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x18\x19\x00d\x19\x17\x00d\x1ak\x03r\xfet\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x1b\x19\x00\xa0\n|\x00d\x1c\x19\x00d\x0cd\x18\x85\x02\x19\x00d\x1d\xa1\x02|\x04\xa0\x0bd\x0cd\x1e\xa1\x02A\x00d\x1fk\x03\x90\x01r\x1dt\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x1b\x19\x00\xa0\n|\x00d\x1c\x19\x00d\x18d \x85\x02\x19\x00d\x1d\xa1\x02|\x04\xa0\x0bd\x0cd\x1e\xa1\x02A\x00d!k\x03\x90\x01r<t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x1b\x19\x00\xa0\n|\x00d\x1c\x19\x00d d\x01\x85\x02\x19\x00d"\x17\x00d\x1d\xa1\x02|\x04\xa0\x0bd\x0cd\x1e\xa1\x02A\x00d#k\x03\x90\x01r]t\x00j\x01j\x02d\x03\x19\x00S\x00d\x0c}\x05|\x00d$\x19\x00D\x00]\x0b}\x02|\x05d%9\x00}\x05|\x05|\x027\x00}\x05\x90\x01qct\x00j\x01j\x02d&\x19\x00|\x05\x83\x01d\'k\x03\x90\x01r\x80t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d(\x19\x00S\x00', (None, 12, 'amateursCTF{', 'False', -1, '}', 'len', 42, 'enumerate', '_', (7, 11, 13, 20, 23, 35), b'_', 0, b'sn0h7YP', 1, 2, (160, 68, 34), '__import__', 'hashlib', '4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a', 'random', 'list', 3, (49, 89, 102, 109, 108, 52), 4, b'freebie', b'0ffreebie', 'int', 5, 'little', 4294967295, 4227810561, 8, 825199122, b'\x00', 4277086886, 6, 128, 'hex', '0x29ee69af2f3', 'True', 'Did you know? pycdc can decompile marshaled code objects. Just make sure you mention the right version!'), ('id', '__self__', '__dict__', 'append', 'encode', 'split', 'sha256', 'hexdigest', 'seed', 'shuffle', 'from_bytes', 'randint'), ('input', 'underscores', 'i', 'x', 'r', 'c'), '', 'check', 3, b'\x10\x01\x0c\x01\x0c\x01\x0c\x01\x0c\x01\x14\x02\x0c\x01\x04\x02\x18\x01\x08\x01\n\x01\x02\x80\x0c\x01\x0c\x01\x0e\x02\x16\x01\x0c\x01n\x03\x0c\x01"\x02\x0c\x01\x10\x02\x0e\x01\x18\x01\x0e\x01\x10\x02\x0c\x01\x10\x02\x0c\x012\x02\x0c\x012\x02\x0c\x016\x02\x0c\x01\x04\x02\x0c\x01\x08\x01\x0c\x01\x16\x02\x0c\x01\x0c\x02', (), ()) check = type(check)(code, {'id': id}) if check(input("Enter the flag: ")): print("Correct!") else: print("Incorrect.") ``` Hint trong `check.code` object:`Did you know? pycdc can decompile marshaled code objects. Just make sure you mention the right version!` lấy marshal code object ghi vào file `.pyc` và decompile lại. ``` import marshal check = lambda:None code = type(check.__code__)(1, 0, 0, 6, 5, 67, b'|\x00d\x00d\x01\x85\x02\x19\x00d\x02k\x03r\x0et\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x04\x19\x00d\x05k\x03r\x1at\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x01d\x04\x85\x02\x19\x00}\x00t\x00j\x01j\x02d\x06\x19\x00|\x00\x83\x01d\x07k\x03r0t\x00j\x01j\x02d\x03\x19\x00S\x00g\x00}\x01t\x00j\x01j\x02d\x08\x19\x00|\x00\x83\x01D\x00]\r\\\x02}\x02}\x03|\x03d\tk\x02rG|\x01\xa0\x03|\x02\xa1\x01\x01\x00q:|\x01g\x00d\n\xa2\x01k\x03rTt\x00j\x01j\x02d\x03\x19\x00S\x00|\x00\xa0\x04\xa1\x00\xa0\x05d\x0b\xa1\x01}\x00|\x00d\x0c\x19\x00d\x00d\x00d\x04\x85\x03\x19\x00d\rk\x03rlt\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x0e\x19\x00d\x0c\x19\x00|\x00d\x0e\x19\x00d\x0e\x19\x00\x17\x00|\x00d\x0e\x19\x00d\x0f\x19\x00\x18\x00|\x00d\x0e\x19\x00d\x0e\x19\x00|\x00d\x0e\x19\x00d\x0f\x19\x00\x17\x00|\x00d\x0e\x19\x00d\x0c\x19\x00\x18\x00|\x00d\x0e\x19\x00d\x0f\x19\x00|\x00d\x0e\x19\x00d\x0c\x19\x00\x17\x00|\x00d\x0e\x19\x00d\x0e\x19\x00\x18\x00f\x03d\x10k\x03r\xa9t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x11\x19\x00d\x12\x83\x01\xa0\x06|\x00d\x0f\x19\x00\xa1\x01\xa0\x07\xa1\x00d\x13k\x03r\xc0t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x11\x19\x00d\x14\x83\x01}\x04|\x04\xa0\x08|\x00d\x0f\x19\x00\xa1\x01\x01\x00t\x00j\x01j\x02d\x15\x19\x00|\x00d\x16\x19\x00\x83\x01|\x00d\x16<\x00|\x04\xa0\t|\x00d\x16\x19\x00\xa1\x01\x01\x00|\x00d\x16\x19\x00g\x00d\x17\xa2\x01k\x03r\xf0t\x00j\x01j\x02d\x03\x19\x00S\x00|\x00d\x18\x19\x00d\x19\x17\x00d\x1ak\x03r\xfet\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x1b\x19\x00\xa0\n|\x00d\x1c\x19\x00d\x0cd\x18\x85\x02\x19\x00d\x1d\xa1\x02|\x04\xa0\x0bd\x0cd\x1e\xa1\x02A\x00d\x1fk\x03\x90\x01r\x1dt\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x1b\x19\x00\xa0\n|\x00d\x1c\x19\x00d\x18d \x85\x02\x19\x00d\x1d\xa1\x02|\x04\xa0\x0bd\x0cd\x1e\xa1\x02A\x00d!k\x03\x90\x01r<t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d\x1b\x19\x00\xa0\n|\x00d\x1c\x19\x00d d\x01\x85\x02\x19\x00d"\x17\x00d\x1d\xa1\x02|\x04\xa0\x0bd\x0cd\x1e\xa1\x02A\x00d#k\x03\x90\x01r]t\x00j\x01j\x02d\x03\x19\x00S\x00d\x0c}\x05|\x00d$\x19\x00D\x00]\x0b}\x02|\x05d%9\x00}\x05|\x05|\x027\x00}\x05\x90\x01qct\x00j\x01j\x02d&\x19\x00|\x05\x83\x01d\'k\x03\x90\x01r\x80t\x00j\x01j\x02d\x03\x19\x00S\x00t\x00j\x01j\x02d(\x19\x00S\x00', (None, 12, 'amateursCTF{', 'False', -1, '}', 'len', 42, 'enumerate', '_', (7, 11, 13, 20, 23, 35), b'_', 0, b'sn0h7YP', 1, 2, (160, 68, 34), '__import__', 'hashlib', '4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a', 'random', 'list', 3, (49, 89, 102, 109, 108, 52), 4, b'freebie', b'0ffreebie', 'int', 5, 'little', 4294967295, 4227810561, 8, 825199122, b'\x00', 4277086886, 6, 128, 'hex', '0x29ee69af2f3', 'True', 'Did you know? pycdc can decompile marshaled code objects. Just make sure you mention the right version!'), ('id', '__self__', '__dict__', 'append', 'encode', 'split', 'sha256', 'hexdigest', 'seed', 'shuffle', 'from_bytes', 'randint'), ('input', 'underscores', 'i', 'x', 'r', 'c'), '', 'check', 3, b'\x10\x01\x0c\x01\x0c\x01\x0c\x01\x0c\x01\x14\x02\x0c\x01\x04\x02\x18\x01\x08\x01\n\x01\x02\x80\x0c\x01\x0c\x01\x0e\x02\x16\x01\x0c\x01n\x03\x0c\x01"\x02\x0c\x01\x10\x02\x0e\x01\x18\x01\x0e\x01\x10\x02\x0c\x01\x10\x02\x0c\x012\x02\x0c\x012\x02\x0c\x016\x02\x0c\x01\x04\x02\x0c\x01\x08\x01\x0c\x01\x16\x02\x0c\x01\x0c\x02', (), ()) bytes = marshal.dumps(code) with open('test.pyc', 'wb') as fw: fw.write(bytes) ``` Dùng `pycdc` để decompile marshal code object `./pycdc -c -v 3.10 <path_file.pyc> -o <path_output.py>` ``` # Source Generated with Decompyle++ # File: test.pyc (Python 3.10) if input[:12] != 'amateursCTF{': return id.__self__.__dict__['False'] if None[-1] != '}': return id.__self__.__dict__['False'] input = None[12:-1] if id.__self__.__dict__['len'](input) != 42: return id.__self__.__dict__['False'] underscores = None for i, x in id.__self__.__dict__['enumerate'](input): if x == '_': underscores.append(i) if underscores != [ 7, 11, 13, 20, 23, 35]: return id.__self__.__dict__['False'] input = None.encode().split(b'_') if input[0][::-1] != b'sn0h7YP': return id.__self__.__dict__['False'] if (None[1][0] + input[1][1] - input[1][2], input[1][1] + input[1][2] - input[1][0], input[1][2] + input[1][0] - input[1][1]) != (160, 68, 34): return id.__self__.__dict__['False'] if None.__self__.__dict__['__import__']('hashlib').sha256(input[2]).hexdigest() != '4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb08b5531fcacdabf8a': return id.__self__.__dict__['False'] r = None.__self__.__dict__['__import__']('random') r.seed(input[2]) input[3] = id.__self__.__dict__['list'](input[3]) r.shuffle(input[3]) if input[3] != [ 49, 89, 102, 109, 108, 52]: return id.__self__.__dict__['False'] if None[4] + b'freebie' != b'0ffreebie': return id.__self__.__dict__['False'] if None.__self__.__dict__['int'].from_bytes(input[5][0:4], 'little') ^ r.randint(0, 0xFFFFFFFF) != 0xFBFF4501: return id.__self__.__dict__['False'] if None.__self__.__dict__['int'].from_bytes(input[5][4:8], 'little') ^ r.randint(0, 0xFFFFFFFF) != 825199122: return id.__self__.__dict__['False'] if None.__self__.__dict__['int'].from_bytes(input[5][8:12] + b'\x00', 'little') ^ r.randint(0, 0xFFFFFFFF) != 0xFEEF2AA6: return id.__self__.__dict__['False'] c = None for i in input[6]: c *= 128 c += i if id.__self__.__dict__['hex'](c) != '0x29ee69af2f3': return id.__self__.__dict__['False'] return None.__self__.__dict__['True'] ``` Đây là đoạn code sau khi decompile. Bây giờ đọc code và reverse nó thôi. Vì nó khá dễ để phân tích nên mình chỉ đưa script giải quyết. ``` from z3 import * import random from Crypto.Util.number import long_to_bytes flag = [0] * 7 flag[0] = 'amateursCTF{' flag[0] += 'sn0h7YP'[::-1] a = [Int('a' + str(i)) for i in range(3)] s = Solver() s.add(a[0] + a[1] - a[2] == 160, a[1] + a[2] - a[0] == 68, a[0] + a[2] - a[1] == 34) tmp = '' if s.check() == sat: m = s.model() for i in a: tmp += chr(m[i].as_long()) flag[1] = tmp flag[2] = '4' r = random r.seed('4') flag[3] = ''.join(map(chr, [49, 89, 102, 109, 108, 52])) # print(flag[3]) -> 1Yfml4 -> f4m1lY flag[3] = 'f4m1lY' r.shuffle(bytearray(b'f4m1lY')) flag[4] = 'of' flag[5] = ''.join([long_to_bytes((0xFBFF4501 ^ r.randint(0, 0xFFFFFFFF)))[::-1].decode(), long_to_bytes((825199122 ^ r.randint(0, 0xFFFFFFFF)))[::-1].decode(), long_to_bytes((0xFEEF2AA6 ^ r.randint(0, 0xFFFFFFFF)))[::-1].decode()]) val_cmp = 0x29ee69af2f3 res = '' while val_cmp != 0: res += chr(val_cmp % 128) val_cmp //= 128 flag[6] = res[::-1] print('_'.join(flag) + '}') ``` **Flag**: `amateursCTF{PY7h0ns_ar3_4_f4m1lY_of_N0Nv3nom0us_Sn4kes}` # rusteze 2 - Đề cho một file PE được viết bằng Rust. Load vào ida và phân tích. Vì file bị strip nên các hàm sẽ bị thay đổi gây khó phân tích hơn bài `rusteze`. Sao một hồi trace vào các hàm để xem thì sẽ nhận ra 2 hàm chính. * sub_1400029C0(v15, v7, v8): sẽ xử lý input và return về v15 ![](https://hackmd.io/_uploads/ryCnGTLjh.png) * sub_140004210(v15, v16): sau khi trace vào các hàm bên trong. Có thể dễ dàng nhận ra đây là hàm so sánh v15, v16 ![](https://hackmd.io/_uploads/r1LAMa8o3.png) - Chương trình này đơn giản chỉ là xử lý qua 1 hàm xor rồi rol 2 bits. Nó giống bài `rusteze` nhưng tricky hơn mà thôi. - Script ``` def ror(val, r_bits, max_bits): r_bits %= max_bits mask = (1 << r_bits) - 1 return ((val & mask) << (max_bits - r_bits)) | (val >> r_bits) a = [-46, -91, -10, -79, 31, 108, 51, 61, -124, 61, 46, -58, -113, -124, 35, 123, -93, -65, 118, -76, -53, -90, 29, 124, 36, -37, -11, 108, -107, 125, 86, 97, -123, 77, 47] xor_val = [192, 167, 229, 183, 3, 70, 53, 38, 174, 26, 55, 212, 152, 218, 57, 23, 136, 227, 125, 143, 242, 174, 25, 73, 14, 220, 233, 54, 130, 95] val_cmp = [-122, 43, 18, 15, -103, -52, 29, 85, -73, 57, -59, -66, -13, -85, 93, -112, 95, 95, 76, -81, -74, 43, -15, 108, -19, -66, 118, 20, -101, -120, -120, 32, -93, -96, 4] for i in range(len(xor_val)): print(chr(ror(val_cmp[i] & 0xff, 2, 8) ^ (xor_val[i] & 0xff)), end = '') ``` **Flag:** `amateursCTF{d0n3_4nd_deRust3d}` # CSCE221-Data Structures and Algorithms Flag nằm trong hex-editer ![](https://hackmd.io/_uploads/Bk0epXwj2.png) **Flag:** `amateursCTF{l1nk3d_bY_4n_xor}` # jvm - Đề cho 1 file .class và 1 file code.jvm. Dùng tool jadx để decompile file .class. - Có thể thấy đây là một bài rev VM. Nên tôi viết đoạn interpreter dịch byte sang asm. ``` fr = open('code.jvm', 'rb').read() vm = [i for i in fr] i = 0 i2 = 0 lst1 = [0] * 1024 lst2 = [0] * 4 fake_flag = 'amateursCTF{aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}' while i < len(fr): op = vm[i] if op in [0,1,2,3]: lst2[vm[i]], lst2[vm[i + 1]] = lst2[vm[i + 1]], lst2[vm[i]] print('op {}: swap lst2[{}] lst2[{}]'.format(op, lst2[i], lst2[i + 1])) i += 2 elif op == 8: lst2[vm[i + 1]] = lst2[vm[i + 1]] + vm[i + 2] print('op {}: add lst2[{}] {}'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 9: lst2[vm[i + 1]] += lst2[vm[i + 2]] print('op {}: add lst2[{}] lst2[{}]'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 12: lst2[vm[i + 1]] -= vm[i + 2] print('op {}: sub lst2[{}] {}'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 13: lst2[vm[i + 1]] -= lst2[vm[i + 2]] print('op {}: sub lst2[{}] lst2[{}]'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 16: lst2[vm[i + 1]] *= vm[i + 2] print('op {}: mul lst2[{}] {}'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 17: lst2[vm[i + 1]] *= lst2[vm[i + 2]] print('op {}: mul lst2[{}] lst2[{}]'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 20: lst2[vm[i + 1]] /= vm[i + 2] print('op {}: div lst2[{}] {}'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 21: lst2[vm[i + 1]] /= lst2[vm[i + 2]] print('op {}: div lst2[{}] lst2[{}]'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 24: lst2[vm[i + 1]] %= vm[i + 2] print('op {}: div_perfect lst2[{}] {}'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 25: lst2[vm[i + 1]] %= lst2[vm[i + 2]] print('op {}: div_perfect lst2[{}] lst2[{}]'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 28: lst2[vm[i + 1]] <<= vm[i + 2] print('op {}: ROL lst2[{}] {}'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 29: lst2[vm[i + 1]] <<= lst2[vm[i + 2]] print('op {}: ROL lst2[{}] lst2[{}]'.format(op, vm[i + 1], vm[i + 2])) i += 3 elif op == 31: lst2[vm[i + 1]] = ord(fake_flag[0]) print('op {}: lst2[{}] = {}'.format(op, vm[i + 1], fake_flag[0])) fake_flag = fake_flag[1:] i += 2 elif op == 32: i4 = i2 i2 += 1 lst1[i4] = ord(fake_flag[0]) print('op {}: lst1[{}] = {}'.format(op, i4, fake_flag[0])) fake_flag = fake_flag[1:] i += 1 elif op == 33: print('op {}: PRINT({})'.format(op, chr(vm[i + 1]))) i += 2 elif op == 34: i2 -= 1 print('op {}: PRINT({})'.format(op, chr(lst1[i2]))) i += 1 elif op == 41: print('op {}: if ls2[{}] = {} == 0: i = vm[{}] = {}'.format(op, vm[i + 1], lst2[vm[i + 1]], i + 2, vm[i + 2])) if lst2[vm[i + 1]] == 0: i = vm[i + 2] else: i += 3 elif op == 42: print('op {}: if ls2[{}] = {} != 0: i = vm[{}] = {}'.format(op, vm[i + 1], lst2[vm[i + 1]], i + 2, vm[i + 2])) if lst2[vm[i + 1]] != 0: i = vm[i + 2] else: i += 3 elif op == 43: print('op {}: i = {}'.format(op, vm[i + 1])) i = vm[i + 1] elif op == 52: i5 = i2 i2 += 1 lst1[i5] = lst2[vm[i + 1]] print('op {}: ls[{}] = ls2[{}] = {}'.format(op, i5, vm[i + 1], lst1[i5])) i += 2 elif op == 53: i2 -= 1 lst2[vm[i + 1]] = lst1[i2] print('op {}: lst2[{}] = lst1[{}] = {}'.format(op, vm[i + 1], i2, lst2[vm[i + 1]])) i += 2 elif op == 54: i6 = i2 i2 += 1 lst1[i6] = vm[i + 1] print('op {}: lst1[{}] = {}'.format(op, i6, vm[i + 1])) i += 2 elif op == 255: break else: b19 = vm[i] b20 = vm[i + 1] b21 = vm[i + 2] vm[i] = ((vm[i] ^ b20) ^ b21) vm[i + 1] = ((vm[i] ^ b19) ^ b21) vm[i + 2] = ((vm[i + 1] ^ b19) ^ b20) print('op {}: XOR ') ``` Result: ![](https://hackmd.io/_uploads/HkMxE4wjn.png) Có thể hiểu chương trình sẽ check flag từ đuôi lên và flag phải thoải mãn `flag[i] - ... == 0` điều này có thể dễ dàng nhận ra khi `ord('}') - 125 = 0`, `flag[i] - 9 - 54 = 34 != 0` Đã hiểu được chương trình thì có thể dễ dàng lấy flag thôi hehe :D **Flag:** `amateursCTF{wh4t_d0_yoU_m34n_j4v4_isnt_A_vm?}`