ezmac 总共就没几个函数,定位到 sub_10000045C 函数,调用 sub_100000634 ,传入 a6 参数为 57
sub_100000634 只做了异或操作
找到密文 byte_100004022 即可解密
exp
1 2 3 4 5 6 7 8 9 enc = "7D7B687F69784478722174767522267B7C7E787A2E2D7F2D" a = 57 for i in range (len (enc)//2 ): byte = int (enc[2 *i:2 *i+2 ], 16 ) decoded_byte = byte ^ a a = a + 1 print (chr (decoded_byte), end='' )
androidfff 解压在 /lib 里就看到 flutter 特征,Blutter 直接解就好了,app 名字叫 untitled3 ,那就去 asm/untitled3/main.dart 里找,根据 ui 里的 incorrect 去定位关键逻辑
上下翻翻得到关键信息
现在去恢复 libapp.so 里的符号表,搜索 flagcheck 出来也没几个函数
在 untitled3_main__FlagCheckerState::ctor_2f7c1c 里找到密文,记得要除2,原因在第一篇博客里解释过了
在 untitled3_main__FlagCheckerState::_xorEncrypt_29cb18 里找到异或操作
得到 flag:DASCTF{flutter_is_so_easy}
androidfile jeb 打开,在 MainActivity 找到逻辑,注意到 AES 加密标志
仔细看这里的字符串和题目txt中给的公钥私钥是一样的
直接进 i0.a 函数看
看来原来的数据应该是有 enkey 和 eniv 字段的,那看来 AES 是最后一重加密,继续跟进 B
回到了 MainActivity ,发现是调用了个 native 函数,继续跟进看看,在 libandroidfile.so 里定位到 Java_com_dasctf_androidfile_MainActivity_a_1p
可以看出是个 rc4 加密,密钥是 REVERSE ,最后进行 base64 编码
接下来用 RSA 公私钥解 enkey 和 eniv ,再用他们解 AES 即可
exp
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 from Crypto.Cipher import AESfrom Crypto.PublicKey import RSAfrom Crypto.Util.Padding import unpadfrom base64 import b64decodeenkey_b64 = '''QMz2qirA80LJiOs30Efl00JsrIv+ZdrM9iB74P/nCWOrzEemEOaq2lN1/V5/rOAoTgBanJO/AcpookhVIOVdsA==''' eniv_b64 = '''hKH/M/v8zwVICeWlc652BZk2eA/c2g0cLpBwvWBVlphiwBBasdn9HPWk7sb/IaRh8eppZrToUwz6f1eomFJkEQ==''' aes_ct_b64 = '''UBUSWb+1P3Z/aokV67e5xQ7eaHoEj3JAeC0XA1RckTWdWZYCB/+D7qC3Hao74goX''' private_key_pem = '''-----BEGIN PRIVATE KEY----- MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAncB8BH4egqfyJBoV PzGNIuQl/64e5fl1If+CwtICWoiRV4AMfHuiREB+XlTawJ7QD/ZJj2wO6sY4sdNh yYcC4QIDAQABAkEAh81Gdg+kcFHoD9AsbkRX/atuUtcwXkYL4gK2LMThpdEFHIO7 Scr+SYfwqmm/LMtkbojEGEnNoIfmoLvGfhXaAQIhANDWo8OSMSQFnvh129cFiVfY KlS4ec24ixvFD8fUD4SRAiEAwWBuZ3kox1n21AsTAxom+E3z5KUUOSUjPXvG6tZB gVECIDOP2y0tSi6/qIll6BqFxmxG9eSnC4PMfaQkmonXBOHRAiBmJUPsUGmj8/eX xknCp7vSCYs9SZ3HGcDlp05Jmed8IQIhAJnE1PNe9lC5OazgRYhSG6bGCTbfFHT6 OuwCVIxRSx4P -----END PRIVATE KEY-----''' enkey = b64decode(enkey_b64) eniv = b64decode(eniv_b64) aes_ct = b64decode(aes_ct_b64) key = RSA.import_key(private_key_pem) def rsa_raw_decrypt_raw (data ): decrypted_int = pow (int .from_bytes(data, "big" ), key.d, key.n) decrypted = decrypted_int.to_bytes((key.size_in_bits() + 7 ) // 8 , "big" ) return decrypted raw_key = rsa_raw_decrypt_raw(enkey) raw_iv = rsa_raw_decrypt_raw(eniv) aes_key = raw_key[-16 :] aes_iv = raw_iv[-16 :] print ("[+] AES Key =" , aes_key)print ("[+] AES IV =" , aes_iv)cipher = AES.new(aes_key, AES.MODE_CBC, aes_iv) pt_padded = cipher.decrypt(aes_ct) pt = unpad(pt_padded, 16 ) print ("\n[+] Plaintext =" , pt.decode())""" [+] AES Key = b'ElmGJYfKbc2gJh0G' [+] AES IV = b'JZ4tQgwSm3ZZIELJ' [+] Plaintext = DASCTF{android_encrypto_file_and_plains} """
login 先看服务端文件,在 sub_29C0 定位到关键逻辑
服务段先发送 inp u account ,rc4 加密后发送出去
接收到客户端信息,会先解一次 rc4
接着和数组 byte_C1A0 进行比较,错误则提示 back door...
同时还需要验证 key ,逻辑相同,最后比较的数组是 byte_C0A0
这两个数组都是会进行 RSA 解密的,对应的函数都是 sub_73B2
而这里这么多参数,不用去分析程序逻辑,直接计算验证就能分出,谁是n,谁是d
别说d了,甚至p和q都给了
直接解密即可
exp
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 from Crypto.PublicKey import RSAfrom Crypto.Cipher import PKCS1_OAEPimport binasciin = 0x9a49428cadd84b7a81cb80f916e645a6a9dd23c2fe679f93af6a77eff0f0bb1309b77fb7861275f07ab41e98ae5c2ecf933f27d47b9ce0a55a3e06569cacbb4c9183f8ee9a47f2cfbb3a5965c9326f45d2d608cfeabea1a1879eae95b70224d2e7736b9bc4109756f55a3f70f11a9b9c6564fb6456d329c336fbb59859db5fde1f2338294e863c4f05b4a89e6c3b761d52a2081a0af0a320fde831daa741fad77aa7ef2dd30b3e33d1a6e7b44ed44ef40de4557a4fd65b63db63d105386bbd81071739ec3d0fe44b6a0952a2b065bededfecea6e22229fea32adfc9a6e2ccfdf5da437a56ad41d7ef08c2c4635d3a0218aab2a5ed6e9dd42d684bc918efe24d3 d = 0x28c7df24a5798679db2a44979275f5f3179db180d91335702942fb1b70e985de825da90f2eb65d20ddf8be1d9d4e15bc1d84e95795ff8c0c28ce3c33fde054f6e82a4f4cc22597b350c9c62ccc0188bd4152a701a3601558f22aa9fae8b9fdac6c2bc09b1637f71e0511805e04b203c4fdb2b36ad232fe819b06ed4e57c74f39fd9b72623c16ff2100f148f622bf12876260c4859672360dc0da3da6b45c5c8c6215ccda072765840c213fba11a91d6bf598a8a8065797566c8950a34ea0a072a9ed0c38bdc58662f186ec578ca55d5098443fd566cc722ace9c4e89afc4e302c8a4870e11a003b935f4a102695bfd64bb0fa74dcc372682e2b24ff45a1a69 e = 0x10001 c1 = "373A2A27B38FD778C716728EBB95BE89A0A057109119A08D5CE49261EBB0E0776D254A40C4D21BD2463E61608771DE401EED13AC6660D996BEA8C8B82BDD0EAF56C38466776EBA31F7B2219230B654A77EC0AF395A01C31C139A4F6B7B8BA845192096165DD7ACD0331E79DBE434ED8C9A66581D26F69E5FAA295F66010076B91A6DD61DB7ABD325F8BD25D928DEBCC02E5555FF81F7AE3E548E3E4659A37F5D3D3C39FBCAD1B583E42FB04FA328EBB77E7841F45B711E77EE23E11989DB2C0E06B8191A456D56BD1A7D42C47FDFDF1179228B57C6EFCA9B9B6A7D22682E5B67C7C46A877FB677F5F317B4823FCDC812F0362BE27C0F5453037148ED30127B26" c2 = "1638E0EB936140B5527033292CBEFCD73B55CFC7FB79DF51AE3768A0DD9C84AE4580E47A5133B425F4C93EAC97E4B1AA0B4CD30589D004F6D0D19FCBC709E86CC2996B433D29F650B69987A466F05BEF7F69945860DCC44742A511F3621385C89FBD4D73153615789634B25CFC3151A4115BC30C96979E5F965290F36A863E3378B5CFC9BA31438C4BAE22B23EF815EDF7CF1771803BD392A5072B468900B75F5A4377D1DAF3D6F7B7B6850D1A4A4134F2F65840EFAA9B83D31083051DF0FC80A786529159484F62BBB9524F68285F48C7AB8E03BDFECA1A6025AAED9F9728B390689C0C963920C728EB5695FCB9413F9F4E06D3B93DB40E26D6275C84E6126A" key = RSA.construct((n, e, d)) cipher = PKCS1_OAEP.new(key) try : m1 = cipher.decrypt(bytes .fromhex(c1)) print ("[+] m1 解密成功:" , m1) except Exception as err: print ("[-] 解密 m1 出错:" , err) try : m2 = cipher.decrypt(bytes .fromhex(c2)) print ("[+] m2 解密成功:" , m2) except Exception as err: print ("[-] 解密 m2 出错:" , err) """ [+] m1 解密成功: b'qqwweerrttyyuuii' [+] m2 解密成功: b'aassddffgghhjjll' """
得到两个字符串,不知道怎么使用,该去客户端看看了,在关键词 passwd 找到函数 sub_49DD ,各种特征都显示是标准 AES 加密
那两个字符串看来一个是 iv ,一个是 key 了,密文就是 server 里的数组 byte_C2A0
flag :DASCTF{dqmaxfwkm921kr21m;df1m1dqmlk1d12d1}
总结 题目难度还算不大,不过用来给我爽玩一个月之后的复健还是够用了(●’◡’●)