• 标 题:闲话破解
  • 作 者:softworm
  • 时 间:2003/08/24 05:22pm
  • 链 接:http://bbs.pediy.com

Think like a cracker

  以前在E文的破文中,经常可以见到一句话:“Think like a cracker”。随着破解的东西多了,慢慢积累一些经验,觉得这话大有深意。

  以我的理解,大概是指要善于揣摩保护者的想法。我也没法描述清楚,只是有点感觉,在破解的时候,要多从具体的代码中跳出来想想,把握大局,判断形势,决定正确的方向。能把这方面的东西表现在破文里,我想会更有意思。

  以下是以前破解的一个软件,比较旧了(整理以前的笔记得来的,做不到总用刚破解的东西来写文章)。

  是个股票分析类的软件,叫StockNT吧。背景如下:
  
  用户可从Internet下载,功能有限制(好象是数据不能更新)。用户向作者付款后,可从其网站下载一个叫formal.ini的文件,拷入安装目录,然后再联机注册,成功后即为正版用户。不能从别的机器拷贝,只能用以上方式成为正式用户。只能在一台机器上注册,若要把软件安装到别的机器上,必须先“联机注销”,安装后重新注册。


1.先来研究一下formal.ini。断在CreateFileA,很快就可以找到访问该文件的代码。简单  的分析之后,可得到以下结论:

  文件长度仅18个字符,只使用了前16个,为16进制数字。可以用UltraEdit自己做一  
   个,便于分析。假设文件内容为0123456789abcdef01,

   将前16字符转换为数字,结果为:
  
  76543210,fedcba98两个dword。

  其使用方式为:

  42A939  push 2
           push eax           //指向包含上述2个dword的buffer
           call f_Compute     //我取的名字:-)
           mov eax,[ebp-28h]  //还是放在那个buffer中的第一个值(计算结果)
           pop ecx
           cmp eax,[ebp-24h]//与第2个值比较
           pop ecx
           jnz l_TrialVersion

   即经过call的处理后得到的2个dword必须相等。

  现在来推测一下:虽然这个文件是付款之后才可获得,但还未“联机注册”,不会含有与用户相关的真正信息。也许,只是一个简单的计数,表示“第XXX个用户”。做的保护,只为避免谁都可以做一个formal.ini去注册。这个函数内的计算比较复杂,难以迅速弄清其算法。
   如何做出一个这样的文件?很容易想到暴力穷举。根据以上的推测,可以相信:我们只需给出一个dword的值,计算另一个dword即可。

   在上述地址设断点,断下后在SoftIce中手工输入代码:初始化一个dword为0x76543210,另一个为1。在循环中递增第2个值,找到符合条件的值或到达0xFFFFFFFF后,调用int 3。按F5开始计算,等待一段时间后,SoftIce弹出,得到的结果为0xEA0D4CAD。所以,可做出一个正确的formal.ini文件,内容为:

   01234567DAC4D0AE01//最后的"01"未用

2.首先,我不打算真的去“联机注册”(破解时,是在不能上网的机器上做的)。很快可以发现,有了formal.ini之后,运行时程序会访问安装目录下的Reg\Register.ini文件,这才是真正的keyfile。同样,从访问文件的代码可以看到,这个文件长度为36字符,格式与formal.ini相似,有2行。将文件内容读出后经过变换,与正确值对比。正确值是由用户机器的一些特征数据计算而来的,包括硬盘信息(与分区相关的数据),一些系统文件的时间戳,系统时间等等)。这就是所谓的只能安装在一台机器上的由来。

  结合静态分析,对代码稍加跟踪,可得到全部用于比较的正确值。问题是,这里做的是密文比较。Register.ini的数据经过与formal.ini一样的处理(每次取一行的16字符转换为数字),经上述的f_Compute的计算后才用于对比。拿到正确的结果,如何得到被f_Compute处理以前的数据?此函数计算太复杂,层层调用子函数,难以看清其计算方式,更不要说写出个反函数。

   利用前面formal.ini的数据做个测试,把结果作为参数放入buffer,f_Compute得到的结果并非是原来的参数,即此函数不是既可加密又可解密的双向函数,没有捷径可走。

   现在该怎么办?再来猜一猜,Think like a cracker呵呵。既然用户在获取formal.ini后,可以通过联机注册成为正式用户,那么,注册成功后,程序自己必定会有创建Reg目录,生成Register.ini的动作,也就是说,f_Compute的反函数必定已存在于代码之中。我们只要找到这个函数,把用于比较的正确值作为参数输入,经该函数处理的结果就是Register.ini的正确内容。

   如何找到该函数?有很多线索:与WinSock相关的函数调用,对CreateDirectoryA的调用,对"Register.ini"字符串的使用等等。总之,找到了,在这个过程中随时可用formal.ini的数据来测试。要注意的是,要手动修改WinSock相关函数调用的返回值,否则我们的目标函数执行不到(实际上,只要执行了该函数,破解也就成功了:-)。

  最后得到Register,ini的正确数据为:

  37BC43727C4B3BA801
  E10226146C01741601//每行最后2个字符未用

  多说两句,我不太喜欢列出大段的代码,我觉得对阅读者没什么用。尽量说明破解过程中的一些思路想法可能更有意思。各位大虾以为如何?