这是在《Crack2007》,分类“矩阵方式”下的一个CM,帖子地址如下
http://bbs.pediy.com/showthread.php?threadid=30368
因为一开始就想错了方向(其实也不算想错了,是往难的方法想了,竟然想到了遍历二叉树之类的方法,结果难的方法也没写得出算法来只好作罢了),已经拖了很多天了,只好在国外发CM的网站搜了搜 果然找到了solution,然后就搞明白了于是有了这篇日志
我自己想的方法 :(可以不看)
正确做法(python写的,for循环没有括号扩住循环体,得靠缩进识别):
先看看代码然后听我稍微解释一下吧,程序有18个多选框,每个多选框有两种选择 checked和unchecked
所以会有2^18(即 262144 )种情况
先设一个大循环使得a=1到262144,然后试探它的每一位,如果是1的话(假设1是checked)就将当前table[j]和table[j-1]参与运算
第八行的 0x328FE就是0xF35466*0x4D
当somme=0xF35466*0x4D 时,i为正确答案(转换为二进制,1代表checked,0代表unchecked),但是程序的多选框和数组table并不是按照顺序排列的,所以需要用资源查看器查看一下多选框对应的序号并将code数组中存放的注册码转换为与多选框排列对应的注册码
for i in range(1, 262144):
http://bbs.pediy.com/showthread.php?threadid=30368
因为一开始就想错了方向(其实也不算想错了,是往难的方法想了,竟然想到了遍历二叉树之类的方法,结果难的方法也没写得出算法来只好作罢了),已经拖了很多天了,只好在国外发CM的网站搜了搜 果然找到了solution,然后就搞明白了于是有了这篇日志
算法很简单的,先拖入OD,找字符串定位到按钮事件代码的地址,然后拉到IDA分析(终于在分析CM算法的时候感到此神器的伟大了)
在开始的地方下断点,运行几次大概分析出以下流程:
注册方法:
程序设有18个多选框,要选中指定的几个就算注册成功
程序内部把这些多选框编号为以下数组(不按顺序的)
intCheckBoxs[18]={0x16,0x49,0x5E,0x15,0x27,0x26,0x21,0x25,0x1D,0x59,0x53,0x37,0x31,0x48,0x5D,0x0C,0x61,0x52};
注册算法:从上面的编号一个一个试
如果unchecked则试下个
如果checked则:
i++
Result=Result+(CheckBoxs[i-1]*CheckBoxs[i]*i)
18个全部试验完之后,如果Result=0xF35466*0x4D则正确。
我自己想的方法 :(可以不看)
生成一个二叉树,每个结点有i个子节点,共i+1层(第一层是头节点,没意义)。节点的数据放入Checkboxs的索引值。
遍历二叉树就可以得出每种情况,但是实际上我们并不一定需要i个单位长度的组合(因为有for循环,子节点数可能不同),或许我们需要10个数字的组合,这就要把后面的7层给剪掉,那现在还能不能保证这些在17个数字里面的“9数字”组合涵盖了全部情况?
经过实验证明是可以保证的。遍历二叉树,每次遍历到叶节点的时候就算出该次选择的n个checkboxs元素对应的Result值,对比是否等于0xF35466*0x4D,等于则成功
正确做法(python写的,for循环没有括号扩住循环体,得靠缩进识别):
先看看代码然后听我稍微解释一下吧,程序有18个多选框,每个多选框有两种选择 checked和unchecked
所以会有2^18(即 262144 )种情况
先设一个大循环使得a=1到262144,然后试探它的每一位,如果是1的话(假设1是checked)就将当前table[j]和table[j-1]参与运算
第八行的 0x328FE就是0xF35466*0x4D
当somme=0xF35466*0x4D 时,i为正确答案(转换为二进制,1代表checked,0代表unchecked),但是程序的多选框和数组table并不是按照顺序排列的,所以需要用资源查看器查看一下多选框对应的序号并将code数组中存放的注册码转换为与多选框排列对应的注册码
for i in range(1, 262144):
somme = 0
a = i
for j in range(1, 19):
if (a & 1):
somme = somme + (j * table[j] * table[j-1])
a = a >> 1
if (somme == 0x328FE):
if (i & 1):
code[3] = '1'
i = i >> 1
if (i & 1):
code[1] = '1'
i = i >> 1
if (i & 1):
code[2] = '1'
i = i >> 1
if (i & 1):
code[9] = '1'
i = i >> 1
if (i & 1):
code[16] = '1'
i = i >> 1
if (i & 1):
code[5] = '1'
i = i >> 1
if (i & 1):
code[6] = '1'
i = i >> 1
if (i & 1):
code[4] = '1'
i = i >> 1
if (i & 1):
code[17] = '1'
i = i >> 1
if (i & 1):
code[7] = '1'
i = i >> 1
if (i & 1):
code[8] = '1'
i = i >> 1
if (i & 1):
code[10] = '1'
i = i >> 1
if (i & 1):
code[11] = '1'
i = i >> 1
if (i & 1):
code[12] = '1'
i = i >> 1
if (i & 1):
code[13] = '1'
i = i >> 1
if (i & 1):
code[14] = '1'
i = i >> 1
if (i & 1):
code[0] = '1'
i = i >> 1
if (i & 1):
code[15] = '1'
i = i >> 1
print(code)
sortir = 1
break
if sortir:
break