分享的内容
这次,作为CTF菜鸡,我将分享一下与以下“搞笑”代码偶然相遇的情况。
(上图[1],下图[4],但实际上到处都是类似的代码,看来你公司的代码仓库也已经被“占领”了)
References:
[1].
[2].
[3].
[4].
[5]。
[6]。
[7]。
开始讲暴躁的偶然故事
作为CTF菜鸡,遇到app外卖问题时有多高兴,但是因为食物,有这么简单的乐趣,ta不给你!
标题想法:
l使用专用Base64算法(代码:PBase64)处理flag的密语(代码:PBa(flag)),但专用Base64算法实际上只替换了标准Base64算法的table。
l密码短语(flag)对flag使用固定密钥,并使用AES算法加密。//其中,AES实现与[4]一致~
l为了获得PBa(flag),需要反向运算一些代码,处理逻辑主要是或、反向运算、还是。//幸福吧?
解决问题的想法:
1.反编译APK获得代码。
2.简单地写Java程序,用Java(FLAG);
3.根据私有Base64算法的table和标准Base64算法table的字符对应关系,从PBa(flag)还原到Ba(flag),并使用标准Base64库decode计算aes.en (flag)
4.APK抠出AES的实现,本地写程序调用AES的decrypt方法使用固定密钥解密获得flag、分数!
123都很顺利,但是Too Young Too Simple!你就是无法破解:such issues can arise if a bad key is used during decryption。
晕,蔬菜鸡误解主题了吗?请公布答案,看大师们的Writeup学习。
晕,那不是我的主意!Ba(flag)都和我算的一样,为什么我不能解密?(闹了半天)
原来SecureRandom因为Windows平台和Android平台不一致而出现密钥不一致,没有仔细看分析问题(需要反思),密钥就是这样生成的!上帝啊,这可能就是这个主题的精髓。
小某为什么说这个代码“搞笑”?
这位仁兄给出了完美的答案[7]:
密码实践表明,Java的SecureRandom不应用于派生原始密钥,PBKDF2应该使用更专业的密钥推导算法,如。由于SecureRandom的具体表示,根据默认随机数生成器的实现情况,如果随机数生成器不匹配,set的种子种子种子([1]中称为种子,[4]中称为密码)可能会有所不同,平台加密密文也会出现。使用同样的pasword,在其他平台上无法破解铭文的异常,即CTF料理鸡的这次情况。(阿尔伯特爱因斯坦)。
理论上正确的实践(使用PBKDF2或类似算法导出密钥)必须出现在各大企业的安全编码规范、安全设计规范、加密应用规范等文档中。
但是随便搜索一下,就会发现使用相似逻辑派生密钥的AES包及相关帖子[1]~[7]随处可见,不良代码的扩散力和代码一样强。甚至在Windows和Linux上分析跨平台解密异常,提出了“解决方案[6]”,可惜把SecureRandom变成了对PBKDF2等专业算法的满分答案。
再扯一个容易被忽略的SecureRandom使用惯例。
Java的SecureRandom是一个伪随机数生成器,可用于高效地生成密码学中的安全随机数,它不是真正的随机数发生器,而是常用于需要密码学含义的安全随机数场景,例如AES的IV值。
但是,在这样的场景中,千万不要手动给SecureRandom实例setSeed。和上面提到的“搞笑”代码一样。
这是因为,如果Set设置固定或不安全种子种子种子,Java的SecureRandom将退化为纯伪随机数发生器,无法生成密码学的安全随机数。