简单写下做题的步骤和心路历程
题目使用方案二也就是需要我们找到对应用户名KCTF的注册码:
首先用IDA打开,根据字符串定位关键位置, 也就是程序的main函数:
其中sub_401380是程序的关键加解密部分,关键部分如下图所示:
其中base16其实就是把输入的字符串作为16进制存放在内存里,所以我们输入的sn是一段64字节的16进制字符串,然后AES和Tea算法是根据IDA的findCrypto插件找到的,插件可以根据算法的特征来定位关键位置,方便我们快速确定题目算法类型,该脚本插件在Github上的地址:
https://github.com/polymorf/findcrypt-yara
题目的AES部分有加密和解密的功能,由于a6参数传入0,所以这里使用了解密。加解密的区别很大,但是对于我这种不熟悉AES的来说,还是去看初始化密钥的T表,和现成的加解密脚本做对比就可以知道了。
RSA算法是根据常见的e=65537来判断的,通过动态调试直接从内存里取出n,然后刚才AES解密的结果就是明文m,通过pow(m,e,n)得到最后字符串,和用户名Tea加密生成字符串做比较,题目只比较了后16个字节,导致有多解。
静态分析流程图如下所示:
使用提供的正确sn来正向验证程序流程是否和猜想一致,输入为:
key: F27689EC6EDDD9E3
sn:eaa209cf68dfd48b77e1cddd00a4a48abef8decfc1df630e242548c364503eff
然后跟着上面的流程,用OD动态调试下:
AES函数结束后,在0019FDCC的位置写入解密结果,密钥为480B62C3ACD6C8A36B18D9E906CD90D2,之后反推sn的时候需要用密钥加密rsa解密出的字符串。
这部分的正向代码用python来写就是:
from Crypto.Cipher import AES s='eaa209cf68dfd48b77e1cddd00a4a48abef8decfc1df630e242548c364503eff'.decode('hex') key = '480B62C3ACD6C8A36B18D9E906CD90D2'.decode('hex') cipher = AES.new(key, AES.MODE_ECB) encrypted = cipher.decrypt(s).encode('hex') print (encrypted)
RSA部分结束后,n,e,m,c都可以在内存找到,比如n的值为0x69823028577465AB3991DF045146F91D556DEE8870845D8EE1CD3CF77E4A0C39
n的长度明显小,可以直接通过网站分解qp出来
http://factordb.com/
然后找到c的值,用python正向实现,结果一致。
import gmpy2 n = 0x69823028577465AB3991DF045146F91D556DEE8870845D8EE1CD3CF77E4A0C39 e = 0x10001 m = phi_n = (p - 1) * (q - 1) d = gmpy2.invert(e, phi_n) print (hex(m,e,n))
最后到Tea,直接比较后16位,由于用的是官方提供的正确sn,所以二者一致:
逻辑有了,那么逆向就是反着来,先得到Tea加密KCTF的结果,再RSA解密,最后AES加密即可得到正确sn
import gmpy2 from Crypto.Cipher import AES n = 0x69823028577465AB3991DF045146F91D556DEE8870845D8EE1CD3CF77E4A0C39 q = 201522792635114097998567775554303915819 p = 236811285547763449711675622888914229291 e = 0x10001 c = 0x2888888888888888888888888880014AF58AD4D76D59D8D2171FFB4CA2231 phi_n= (p - 1) * (q - 1) d = gmpy2.invert(e, phi_n) print(hex(pow(c,d,n))) s='2d5f4c9d567c43399312b8898d6c7f2ec799c64bde4fe39eb01771be1e7f4795'.decode('hex') key = '480B62C3ACD6C8A36B18D9E906CD90D2'.decode('hex') cipher = AES.new(key, AES.MODE_ECB) encrypted = cipher.encrypt(s).encode('hex') print("name = KCTF") print("sn = "+encrypted)
结果如下图所示:
最后于 1天前 被Mirge编辑 ,原因: