---
# System prepended metadata

title: AmateursCTF
tags: [reverse, Write-up]

---

# 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?}`



