好友
阅读权限 10
听众
最后登录 1970-1-1
qdam
发表于 2019-8-26 10:36
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。
本帖最后由 qdam 于 2019-8-26 10:48 编辑
第一次在比赛中挑战安卓逆向题,神奇地做了出来,在此发帖纪念一下。
附件链接 https://pan.baidu.com/s/173IyPx85Y9aeoJJerfWr3Q , 提取码 ccem
改后缀为zip解压,dex2jar,然后上jd-gui,进行源码分析。
首先看到关键的验证部分,也就是checkFlag函数,然后我们进去看一下函数逻辑。
[Asm] 纯文本查看 复制代码
public static boolean checkFlag(String paramString1, String paramString2)
throws Exception
{
paramString1 = hash(paramString1.getBytes());
paramString1 = hash(new byte[] { paramString1[0], paramString1[(paramString1.length / 2)], paramString1[(paramString1.length - 1)] });
paramString2 = paramString2.getBytes();
int i = 0;
while (i < 10)
{
paramString2 = encrypt(paramString2, paramString1);
paramString1 = hash(paramString1);
i += 1;
}
return toHex(paramString2).equals("74f0b165db8a628716b53a9d4f6405980db2f833afa1ed5eeb4304c5220bdc0b541f857a7348074b2a7775d691e71b490402621e8a53bad4cf7ad4fcc15f20a8066e087fc1b2ffb21c27463b5737e34738a6244e1630d8fa1bf4f38b7e71d707425c8225f240f4bd2b03d6c2471e900b75154eb6f9dfbdf5a4eca9de5163f9b3ee82959f166924e8ad5f1d744c51416a1db89638bb4d1411aa1b1307d88c1fb5");
}
可以看到首先对paramString1进行经行了哈希(MD5),然后是10轮加密,最后paramString2要等于一长串字符。
这里hash()和toHex()函数功能就如名字一样,就不分析了。主要是对encrypt()函数的分析。
再来具体看一下源码。 [Asm] 纯文本查看 复制代码
public static byte[] encrypt(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2)
throws Exception
{
Object localObject = new SecretKeySpec(paramArrayOfByte2, "AES");
paramArrayOfByte2 = Cipher.getInstance("AES/ECB/PKCS5Padding");
paramArrayOfByte2.init(1, (Key)localObject);
localObject = new ByteArrayOutputStream();
paramArrayOfByte2 = new CipherOutputStream((OutputStream)localObject, paramArrayOfByte2);
paramArrayOfByte2.write(paramArrayOfByte1);
paramArrayOfByte2.flush();
paramArrayOfByte2.close();
return (B)((ByteArrayOutputStream)localObject).toByteArray();
}
这里出现了很对没有见到过的函数,但是不要紧,我们可以从函数名字去猜函数的功能,有些不好理解的我们可以去查阅android手册。
我们可以大致猜测出这里是进行了AES加密,而且是把paramArrayOfByte2作为密钥,paramArrayOfByte1作为明文加密。实际的情况也就是这样。
所以总的来说就是经行了10轮AES加密,每次的密钥是上一个密钥的MD5字符串(刚好是16个字符)。问题来了,怎么解密呢,我们知道MD5是单向散列的,不可逆的,只能顺着来。
其实在checkFlag中的前几步操作已经给了我们提示,paramString1 = hash(new byte[] { paramString1[0], paramString1[(paramString1.length / 2)], paramString1[(paramString1.length - 1)] });
这里只对三个字符求哈希值,咦,三个字符,好像很少,可以爆破哎(滑稽)。
然后我们就可以爆破这三个字符,把10个密钥求出来,再反解,看最初的明文有没有“flag”字符即可。
脚本如下,写的有点丑,大家懂意思就行了。
[Python] 纯文本查看 复制代码
# -*- encoding:utf-8 -*-
import hashlib
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
all='74f0b165db8a628716b53a9d4f6405980db2f833afa1ed5eeb4304c5220bdc0b541f857a7348074b2a7775d691e71b490402621e8a53bad4cf7ad4fcc15f20a8066e087fc1b2ffb21c27463b5737e34738a6244e1630d8fa1bf4f38b7e71d707425c8225f240f4bd2b03d6c2471e900b75154eb6f9dfbdf5a4eca9de5163f9b3ee82959f166924e8ad5f1d744c51416a1db89638bb4d1411aa1b1307d88c1fb5'
enc=a2b_hex(all)
for i in range(256):
print(i)
for j in range(256):
for k in range(256):
dec=enc
key=chr(i)+chr(j)+chr(k)
keys=[hashlib.md5(key).digest()]
for x in range(9):
keys.append(hashlib.md5(keys[x]).digest())
for y in range(10):
aes=AES.new(keys[9-y], 1)
dec=aes.decrypt(dec)
if "flag" in dec:
print(b2a_hex(dec))
这里爆破过程中dec有两个值,转一下字符看一下就行了。
免费评分
查看全部评分
发帖前要善用【论坛搜索 】 功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。