这次写的是160个CrackMe系列里的Andrénalin系列的第四个,前面三个还是比较容易的,总的说来这个系列的算法都是将用户输入的字符串经过一系列的运算后与一个注册码比较,如果一样则注册成功,所以这个系列直接爆破的话就很容易,直接找到关键字符串—注册成功的语句,然后再合适的位置将判断跳转的语句(je,jne等)nop掉就可以了。
一·目标软件:Andrénalin.4.exe
运行界面:(未注册)
注册后:
二·分析:
首先,我们发现这个软件没有确定键,只有0123456789*#和一个删除键,那么这个软件很有可能输入之后靠Timer控件来自动进行判断的(不排除隐藏按键的可能)。
查壳:
VB编写的,没有加壳。。。
查看事件:
果然有Timer,还不止一个,看来判断的地方不止一个。
OD中跟踪分析:
- 先查看字符串,看有没有什么可以利用的:
居然有这么多的已注册(REGISTRIERT)和一堆看似一样却有微小差别的字符串,我们随便进入到一个字符串所在的位置研究一下:
有一个VB里面的标准比较函数:vbVarTstEq ,那么这个字符串很有可能就是最终用来比较的字符串了(当然不一定是这个字符串,因为还有很多个与这个字符串相像的字符串)
- 跟踪算法:
先不要下断点,随便输入一个数据(我输的147258)后再在Timer1_404650的位置下断点,因为这是第一个Timer的位置,也刚好在那个字符串的上方,这里开始跟踪算法比较容易跟踪
我们发现,在00404982的位置的call函数取了字符串里的第一位字符,然后再00404994的位置上通过rtcAnsiValueBstr函数将字符转化为Unicode,相当与python里ord(a[i]);
然后通过0040499A到004049C8地址的指令将16进制的Unicode转换为10进制的,然后加上一个常数(暂时不知道这个数怎么来的)得到的值再转换为16进制,比如字符‘8’:
‘8’à 0x38 à 56 à 56+常数=Yà Y转换为16进制得到一个数
所以总的算法就是这样把每一个字符转换为一个16进制的字符串,而且在字符串前面还加了一个‘0’;
我们分析了那些相似的字符串,只有这一组全部是16进制数:
0817E747D7A7D7C7F82836D74747A7F7E7B7C7D826D817E7B7C
所以这组应该才是对的比较码
寻找常数产生的算法:
我们分析发现,这个常数是在取字符串里每一位的上面产生的,就是这个call esi里,经过多次输入和单步跟踪发现,这个常数取的是字符串的前两位,比如输入的是‘12345’,那么常数就是12,如果输入的是‘*#1234’,那么常数就是0;
三·写注册机:
知道了验证码后,就可以倒推出key了;
先通过验证码的开头两个字符(除去‘0’)0x81,算出常数是74,那么key的开头两个数字就是74,算出常数后就可以倒退出key了;
算常数的代码:
for i in range(0,10):
a=ord(str(i))
for j in range(0,10):
if(a+i*10+j==0x81):
num=i*10+j
print(num)
break
算key的代码:
key="817E747D7A7D7C7F82836D74747A7F7E7B7C7D826D817E7B7C"
Key=""
id="0123456789*#"
keylen=len(key)
for ecx in range(0,keylen-1):
eax=key[ecx]+key[ecx+1]
ebx=int(eax,16)
for i in id:
a=ord(i)
if(a+num==ebx):
Key=Key+i
eax=""
break
print("Key: %s"%Key)