第二道Crackme做的很爽。
crackmea01
直接打开看看

显示未注册,如果输入正确的name和id应该是有成功的字样的。
先查壳看看基本信息

拿VC写的,无壳。OD

试着定位一下关键字符串

可以看到程序流程还是比较明显的,对我们收入的字符串进行处理后比较,比较决定jnz是否跳转,如果要成功的话应该就是不让他跳。

把他nop掉看看结果。
可以看到成功了

基本上没做任何防爆破的手段。
下面来分析一下代码流程。

最顶上的应该是个mfccall,是把我输入的某些信息接受过去,然后某东西跟0x4比较,我理解为这个应该是比较长度,如果说这里小于4,就算我下面nop掉也没用。试一试

和我猜测的一样,直接失败了。
重新来,进行堆栈窗口跟随,可以看到在那个mfccall之后,

经过这个函数把我们的字符串给倒置了

应该是mfc里自带的一个函数
然后一个给eax,一个给edx,cmp

就是这样了。
crcme1
这道的难度有三星,不晓得咋样。
随便填塞点东西,错误。

查一下信息

KeyFile
感觉没啥有价值的信息,扔到od里面看看

第一个要执行的就是createfileA,这里的access为read,理解为读取文件。而读取的这个ACG.Key就可以理解成一个Keyfile,程序运行的必备文件。
接着往后面看

比较读出来的大小和0xC(12)的大小,jnz为不相等时跳转,意思就是keyfile里面的东西要是十二位。

之后读取文件流,不重要

重要的来了

这里有十二个类似代码块,每一块都是通过inc来遍历我们keyfile里面的东西。一个个看。假设我们keyfile里面是A

可以看到第一个里面,正向逻辑是我们输入的A的ascii为0x41,这个0x41和0x1B进行异或,结果左移两位,然后判断是不是和0x168相同(这里判断分为xor test两步来写,test ebx,ebx 只有当ebx为0的时候jnz才不执行。也就是xor ebx和0x168必须要一样)。
逆向逻辑也很清楚了吧,即我们有的是0x168,然后0x168右移两位,再和0x1B进行异或,得到ascii值,再转成字符输入就可以了。
而后面几个代码块也仅仅是这个0x168不同

所以就可以写成如下脚本
nEnc=[0x168,0x160,0x170,0xEC,0x13c,0x1cc,0x1f8,0xec,0x164,0x1f8,0x1a0,0x1bc]
for i in nEnc:
temp1=i>>2
temp2=temp1^0x1b
print(chr(temp2),end='')
print(chr(0x20))
得到结果 ACG The Best。写进keyfile里面,运行到下面

ok,keyfile就绪了,只要填写name和serial就可以了。
算法逆向
第一次随便输入一串东西,发现他到这里了。

一个非常醒目的跳转吧。看看上面在哪。

可以发现这里已经下面一些就是对name和serial进行处理了。
先浅看一下

先读入两个数据,然后在name里面有cmp eax,0x5和jb连用

意思name长度要大于等于5。接着看

两个关键信息,第一个箭头是根据读入name的ascii判断是不是可以可见字符,如果比0x20小就不是了,读到了就会直接jb出去。
第二个箭头将所有eax的ascii值相加。接着看

将目前的和右移3位,在异或0x515A5,push进栈等会用。接着看

这里应该算是比较核心的区域了。
首先第一个框先给eax,0xA。然后三行代码用来判断什么时候跳出这个循环。
接着两个箭头,是比较0x30和0x39,对应的就是0到9的字符串,意思serial必须要是0到9的数字。然后通过sub获得一个纯数字。然后先将edi和eax相乘,意思就是每轮这里的edi都要乘一个0xA。再在edi本身的基础上加上刚刚的那个纯数字,用作下一轮要成的东西。
接着看

出来之后的edi异或0x87ca,给ebx,然后ebx也就是异或出来的值和之前处理的压在栈里的数据相加,结果比较0x797E7。
不对的话则返回不对的信息。
首先爆破一下

nop掉


就成了。
接下来写一个keygen吧。
keygen的作用就是根据name生成一个serial对吧,现在name的作用知道了,先写

非常正确

一致,一阶段ok。
现在这个0x797E7-329621就是ebx一个的值,168018,再异或0x87ca,0x21798就是上面那个serial处理得到的值。
然后!猛然一惊醒,这里

其实就是这样

就是将字符直接排列了,非常好看懂。
那么keygen其实已经写完了。
sName="cxyyy"
nSum=0
for i in sName:
nSum+=ord(i)
nTmp=nSum<<0x3
nEnd1=nTmp^0x515A5
nEbx=0X797e7-nEnd1
nEdi=nEbx^0x87Ca
print(nEdi)
让他按照10进制直接输出即可,137112

对了,换一个

OK!
NAG
这个据说是什么外国那边的一个说法,意思是每次推出都有一个弹窗,叫我们把他抹去,应该比较好搞。

每次弹窗信息,定位到这,让他跑


根据栈信息找到这个call,直接nop

就没有啦