前两天同学给我发了个.net编写的cpu优化的程序,由于注册机制无法正常使用,他寻思看我能不能有什么解决办法。以前搞过一些简单的crackme,但对.net程序的机制还很陌生。破解过程当中遇到了很多问题,发个帖子叙述一下具体情况,当中一些遗留问题也希望能得到达人们的指点~
  
 
    解压后就这些文件,DLLInject是主程序,HID是机器码文件生成用的,那个dll文件至今不知道做什么用的(猜测可能是优化CPU时用到)。直接运行DLLInject会弹出需要注册的对话框。
  
 
    这种对话框乍看来只有许可证文件存在程序才能正常运行,点击OK程序就退出了。后来才查到这样的验证机制是.net本身提供的System.ComponentModel.LicenseXXX。.net许可证机制提供了框架,具体的许可证校验算法肯定还是作者自己实现的,以配合硬件机器码完成验证。
  
 
    用Reflector无法正常载入,看来文件还被特意修改过啊,解决方法:http://hi.baidu.com/dreamzgj/blog/item/3c0bc18e243592f0513d928a.html。不过马上又出现了新的错误:Reflector Error:Module '…' contains zero or multiple module definitions。解决方法:http://hi.baidu.com/dreamzgj/blog/item/5cd5f1456fedc388b2b7dc8a.html。都是同一个人写的文章。这回Reflector载入虽然还是提示数组越界的错误(看来还有其他被修改的小地方),名称也都被混淆过(另外用StrongNameRemove根本不能正常载入该程序),但起码可以看个大致结构了,entrypoint函数(S9oGE4FMD)还是无法显示。
  
 
    其他很多函数内容都是形如下式,都是一些看起来毫无作用的垃圾信息。估计是干扰函数或者是运行时动态修复吧。
  
 
    用ILDASM把代码导成il形式看入口函数终于能正常查看了,也是为数不多的能看到一些语句的函数(其他函数都是返回个null值就没了)。

代码:
.method assembly static void  S9oGE4FMD(string[] A_0) cil managed noinlining
{
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) 
  .custom instance void [System]System.ComponentModel.EditorBrowsableAttribute::.ctor(valuetype [System]System.ComponentModel.EditorBrowsableState) = ( 01 00 02 00 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       50 (0x32)
  .maxstack  3
  IL_0000:  br         IL_0007
  IL_0005:  pop
  IL_0006:  ldc.i4.0
  .try
  {
    IL_0007:  call       bool [Microsoft.VisualBasic]Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase::get_UseCompatibleTextRendering()
    IL_000c:  call       void [System.Windows.Forms]System.Windows.Forms.Application::SetCompatibleTextRenderingDefault(bool)
    IL_0011:  ldtoken    EIOtYCk427B2j46XCZ.aC4npiTU1ygUa7KS3q
    IL_0016:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
    IL_001b:  call       void [System]System.ComponentModel.LicenseManager::Validate(class [mscorlib]System.Type)
    IL_0020:  leave      IL_0026
  }  // end .try
  finally
  {
    IL_0025:  endfinally
  }  // end handler
  IL_0026:  call       class EIOtYCk427B2j46XCZ.aC4npiTU1ygUa7KS3q usJHEvC4iTtNdZDPye.bhVRye8yqVI1niw4o6::vaCk4npiU()
  IL_002b:  ldarg.0
  IL_002c:  callvirt   instance void [Microsoft.VisualBasic]Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase::Run(string[])
  IL_0031:  ret
} // end of method aC4npiTU1ygUa7KS3q::S9oGE4FMD
    Validate应该就是许可证验证函数了吧,不过网上说这种.net许可证机制好像不能直接跳过去,因为后面会用其中的一些信息数据,这里一直没有弄明白,哪位了解这种许可证机制的给解释一下能不能直接跳过吧。用PEBrowsePro跟入Validate并没有直接跳到System.dll空间,这点倒是和纯粹PE文件的函数调用大不相同啊,并且执行中总是提示各种执行异常。
    无奈还是直接把validate函数去掉试试吧,不过得直接在二进制文件上改(ILDASM导出的xx.il文件用ILASM虽然编译成功但执行时会弹出错误)。用IDA打开exe文件,找到两个函数的调用字节码的文件偏移,再用ultraedit打开exe填写0x00(nop)覆盖对应位置。不过执行后还是会弹出许可证那个窗口,看来程序在运行中还多次调用了Validate函数,静态找不到其他的调用迹象,动态又不太顺利。
    用DotNet_Id的查了一下壳,天啊,原来是加过壳啊,难怪分析起来这么费劲呢。
  
 
    http://jithook.blogspot.com上面提供了各个版本的MaxToCode的脱壳工具,最新版本是RE-MaxV3.40。MaxToCode加壳后,会生成一个dll文件随着exe文件一起在运行时提供支持,脱壳工具要载入dll后才能脱壳。不过这个DLLInject.exe配的pe.dll看来并不是这个MaxToCode壳用的dll(删了该dll,DLLInject.exe也能正常运行)。MaxToCode支持把dll融入到exe中,如果它真的是加了MaxToCode的话那一定是融合了,但没有找到提取方法。看来之前载入错误,编译后不能运行都是这个壳导致的。
    突发奇想,我寻思想改掉System.ComponentModel.LicenseManager下验证函数本身应该就能绕过了吧。
  
 
    先从Validate函数开始改起吧,两个版本的都要处理一下。ret字节码0x2a。在C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\system.dll文件的相应偏移位置找到对应字节码修理一下。
  改前:
   
  
 
  改后:
  
   
 
    由于第二个版本的Validate有返回值(类型为License)所以在返回前要在把一个license放到堆栈上,再ret。
    执行程序仍旧弹框框,可问题是删掉system.dll还是弹框框!难道程序没有依赖system.dll吗!用Filemon监视了一下程序执行时访问文件的情况才发现,原来程序加载用的system.dll并不是c:\windows\Microsoft.net\...目录下的system.dll而是C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\ system.dll。
    这样就把改好的dll替换一下,再运行程序,发现其他函数isvalid等已经不用改了,程序已经不会被那个许可证困扰了。
  
 
    这回算是正常运行了吧(这点还真不敢确认,程序没发现有什么功能,该不会是和许可证有关吧),还有那个pe.dll的谜团都有待解开~希望哪位知道的话提示一下~总觉得改了系统的system.dll好像很不妥的方法,似乎绕过了验证。
上传的附件 CPU优化终身版.rar