http://blog.csdn.net/stdotleo/archive/2004/10/17/139798.aspx

现在发现很多人关注Dundas Chart For .NET,顺便研究并将
思路及过程分享如下:

1.工具准备
.net Framework SDK 1.1
ASP.NET环境
ILDASM反编译工具
ilasm重新编译工具

2.安装Dundas Chart For .NET,访问示例程序,发现试用版限制仍然是水印,确定打击目标

3.打开ildasm,载入DundasWebChart.dll文件,如果有Reflector 4.0之类更好,看看程序
架构,初步诊断特性如下:
* 控件使用.net控件License模型控制注册信息
* 所有字符串全部加密

使用"转储",导出IL源代码备用.

4.根据惯例,直接找到Dundas.Charting.WebControl.ChartLicenseProvider,分析CheckKey,IsKeyValid
等方法,由于没有License,可以直接将有关的函数返回值从false改为true,例如
.method family hidebysig newslot virtual 
        instance bool  IsKeyValid(string key,
                                  class [mscorlib]System.Type type) cil managed
{
  // 代码大小       151 (0x97)
  .maxstack  4
  .locals init (string V_0,
           class ax V_1,
           string[] V_2,
           string V_3,
           char[] V_4,
           string[] V_5,
           int32 V_6)
  IL_0000:  ldarg.1
  IL_0001:  brfalse    IL_0095
  IL_0006:  ldstr      ""
  IL_000b:  call       string aG::a$PST06000FA9(string)
  IL_0010:  stloc.0
  .try
  {
    IL_0011:  newobj     instance void ax::.ctor()
    IL_0016:  stloc.1
    IL_0017:  ldloc.1
    IL_0018:  ldarg.1
    IL_0019:  callvirt   instance string ax::b(string)
    IL_001e:  stloc.0
    IL_001f:  leave.s    IL_0032
  }  // end .try
  catch [mscorlib]System.Object 
  {
    IL_0021:  pop
    IL_0022:  ldstr      bytearray (16 00 33 00 39 00 3F 00 34 00 29 00 3F 00 7A 00   // ..3.9.?.4.).?.z.
                                    2A 00 28 00 35 00 3E 00 2F 00 39 00 2E 00 7A 00   // *.(.5.>./.9...z.
                                    31 00 3F 00 23 00 7A 00 33 00 29 00 7A 00 33 00   // 1.?.#.z.3.).z.3.
                                    34 00 2C 00 3B 00 36 00 33 00 3E 00 74 00 7A 00   // 4.,.;.6.3.>.t.z.
                                    19 00 35 00 34 00 2E 00 3B 00 39 00 2E 00 7A 00   // ..5.4...;.9...z.
                                    2E 00 32 00 3F 00 7A 00 39 00 35 00 34 00 2E 00   // ..2.?.z.9.5.4...
                                    28 00 35 00 36 00 7A 00 37 00 3B 00 34 00 2F 00   // (.5.6.z.7.;.4./.
                                    3C 00 3B 00 39 00 2E 00 2F 00 28 00 3F 00 7A 00   // <.;.9.../.(.?.z.
                                    3C 00 35 00 28 00 7A 00 37 00 35 00 28 00 3F 00   // <.5.(.z.7.5.(.?.
                                    7A 00 3E 00 3F 00 2E 00 3B 00 33 00 36 00 29 00   // z.>.?...;.3.6.).
                                    74 00 )                                           // t.
    IL_0027:  call       string aG::a$PST06000FA9(string)
    IL_002c:  newobj     instance void [mscorlib]System.InvalidOperationException::.ctor(string)
    IL_0031:  throw
  }  // end handler
  IL_0032:  ldloc.0
  IL_0033:  ldc.i4.1
  IL_0034:  newarr     [mscorlib]System.Char
  IL_0039:  stloc.s    V_4
  IL_003b:  ldloc.s    V_4
  IL_003d:  ldc.i4.0
  IL_003e:  ldc.i4.s   44
  IL_0040:  stelem.i2
  IL_0041:  ldloc.s    V_4
  IL_0043:  callvirt   instance string[] [mscorlib]System.String::Split(char[])
  IL_0048:  stloc.2
  IL_0049:  ldloc.2
  IL_004a:  stloc.s    V_5
  IL_004c:  ldc.i4.0
  IL_004d:  stloc.s    V_6
  IL_004f:  br.s       IL_0064
  IL_0051:  ldloc.s    V_5
  IL_0053:  ldloc.s    V_6
  IL_0055:  ldelem.ref
  IL_0056:  stloc.3
  IL_0057:  ldloc.3
  IL_0058:  callvirt   instance string [mscorlib]System.String::Trim()
  IL_005d:  pop
  IL_005e:  ldloc.s    V_6
  IL_0060:  ldc.i4.1
  IL_0061:  add
  IL_0062:  stloc.s    V_6
  IL_0064:  ldloc.s    V_6
  IL_0066:  ldloc.s    V_5
  IL_0068:  ldlen
  IL_0069:  conv.i4
  IL_006a:  blt.s      IL_0051
  IL_006c:  ldloc.2
  IL_006d:  ldlen
  IL_006e:  conv.i4
  IL_006f:  ldc.i4.2
  IL_0070:  blt.s      IL_0093
  IL_0072:  ldloc.2
  IL_0073:  ldc.i4.0
  IL_0074:  ldelem.ref
  IL_0075:  ldsfld     string Dundas.Charting.WebControl.Chart::b
  IL_007a:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                 string)
  IL_007f:  brfalse.s  IL_0093
  IL_0081:  ldloc.2
  IL_0082:  ldc.i4.1
  IL_0083:  ldelem.ref
  IL_0084:  ldarg.0
  IL_0085:  call       instance string Dundas.Charting.WebControl.ChartLicenseProvider::a()
  IL_008a:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                 string)
  IL_008f:  brfalse.s  IL_0093
  IL_0091:  ldc.i4.1
  IL_0092:  ret
  IL_0093:  ldc.i4.0  <==返回false,改为true
  IL_0094:  ret
  IL_0095:  ldc.i4.0  <==返回false,改为true
  IL_0096:  ret
} // end of method ChartLicenseProvider::IsKeyValid

这样相当于在任何情况下都返回注册码是对的.

修改ldc.i4.0为ldc.i4.1,保存,
去掉组件的public key,在导出的il文件头
  .publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00   // .$..............
                00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00   // .$..RSA1........
                43 D9 8F 8A 90 67 EF 3B CD 44 2A DE 2D D4 8C C6   // C....g.;.D*.-...
                A6 FA CB CE B1 C4 2D E2 84 7B 0A 46 40 96 C0 2E   // ......-..{.F@...
                EB F6 FD 87 E3 88 9B EE D3 2B 9A BD 15 25 A1 1A   // .........+...%..
                28 22 32 CD 4C 46 CC 81 23 F8 CC 08 A1 13 CD 43   // ("2.LF..#......C
                54 29 64 62 20 96 9F F4 44 73 48 D1 C2 18 74 67   // T)db ...DsH...tg
                08 34 C7 A7 E8 9E A8 95 6F C0 0E 0F 84 FD 3D F6   // .4......o.....=.
                FB 3E BF 21 77 44 38 AF 9E 76 04 14 FD E0 6B C2   // .>.!wD8..v....k.
                C3 AF 35 FF 3D D8 75 78 63 0E D1 3F E1 2C BD BC ) // ..5.=.uxc..?.,..

保存,然后运行汇编程序编译
ilasm /dll /RESOURCE=DundasWebChart.res DundasWebChart.il
生成的dll控件覆盖到
C:\Program Files\Dundas Software\Charting\WebControl\Samples\bin
目录下面,为了编译看到效果,需要修改DundasChartSamples.dll的引用public key,
类似方法使用ildasm导出DundasChartSamples.dll的il文件,
找到
.assembly extern DundasWebChart
{
  //去掉.publickey信息,保证不会出现assemblly引用的版本校验错误
  .ver 4:0:0:1652
}
重新使用ilasm汇编生成新的DundasChartSamples.dll
或者可以使用VS.net重新编译测试project,不过我不太喜欢安装这个东东,太大了,还是用
editplus该代码很方便.

很失望,水印依然存在,此路不通!!

5.转向第2种方法,直接找到水印字符串,不就可以很方便的定位水印代码了吗?
由于字符串加密,加密方法来自于
aG.a$PST06000FA9(string A_0){
}
研究发现该加密算法不可逆或者太复杂,转而寻择规律,为了便于研究
写了下面的解密算法il文件,注意到IL文件中的字符串全部是用bytearray表示的,很难处理
-----------------------------------------------------------------------

//  Microsoft (R) .NET Framework IL Disassembler.  Version 1.1.4322.573
//  Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

// PE Header:
// Subsystem:                      00000003
// Native entry point address:     0000231e
// Image base:                     00400000
// Section alignment:              00002000
// File alignment:                 00000200
// Stack reserve size:             00100000
// Stack commit size:              00001000
// Directories:                    00000010
// 0        [0       ] address [size] of Export Directory:          
// 22d0     [4b      ] address [size] of Import Directory:          
// 4000     [328     ] address [size] of Resource Directory:        
// 0        [0       ] address [size] of Exception Directory:       
// 0        [0       ] address [size] of Security Directory:        
// 6000     [c       ] address [size] of Base Relocation Table:     
// 0        [0       ] address [size] of Debug Directory:           
// 0        [0       ] address [size] of Architecture Specific:     
// 0        [0       ] address [size] of Global Pointer:            
// 0        [0       ] address [size] of TLS Directory:             
// 0        [0       ] address [size] of Load Config Directory:     
// 0        [0       ] address [size] of Bound Import Directory:    
// 2000     [8       ] address [size] of Import Address Table:      
// 0        [0       ] address [size] of Delay Load IAT:            
// 2008     [48      ] address [size] of CLR Header:               

// Import Address Table
//     mscoree.dll
//              00002000 Import Address Table
//              0000230e Import Name Table
//              0        time date stamp
//              0        Index of first forwarder reference
//
//                    0  _CorExeMain

// Delay Load Import Address Table
// 没有数据。
// CLR Header:
// 72       Header Size
// 2        Major Runtime Version
// 0        Minor Runtime Version
// 1        Flags
// 6000001  Entrypoint Token
// 2098     [238     ] address [size] of Metadata Directory:        
// 0        [0       ] address [size] of Resources Directory:       
// 0        [0       ] address [size] of Strong Name Signature:     
// 0        [0       ] address [size] of CodeManager Table:         
// 0        [0       ] address [size] of VTableFixups Directory:    
// 0        [0       ] address [size] of Export Address Table:      
// 0        [0       ] address [size] of Precompile Header:         
// Code Manager Table:
//  default
// Export Address Table Jumps:
// 没有数据。

.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 1:0:5000:0
}
.assembly crack
{
  // --- 下列自定义属性会自动添加,不要取消注释 -------
  //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(bool,
  //                                                                                bool) = ( 01 00 00 01 00 00 ) 
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module crack.exe
// MVID: {8D741680-6BD0-4E43-8D74-C76A766CA6B3}
.imagebase 0x00400000
.subsystem 0x00000003
.file alignment 512
.corflags 0x00000001
// Image base: 0x07650000
//
// ============== CLASS STRUCTURE DECLARATION ==================
//
.class public auto ansi beforefieldinit Crack
       extends [mscorlib]System.Object
{
} // end of class Crack


// =============================================================


// =============== GLOBAL FIELDS AND METHODS ===================


// =============================================================


// =============== CLASS MEMBERS DECLARATION ===================
//   note that class flags, 'extends' and 'implements' clauses
//          are provided here for information only

.class public auto ansi beforefieldinit Crack
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  Main(string[] argv) cil managed
  {
    .entrypoint
    // 代码大小       18 (0x12)
    .maxstack  1
    .locals init (string V_0) //这下面就是加密的水印字符串了
    IL_0000:  ldstr      bytearray (1E 00 2F 00 34 00 3E 00 3B 00 29 00 7A 00 19 00   // ../.4.>.;.).z...
                                        32 00 3B 00 28 00 2E 00 7A 00 77 00 7A 00 1B 00   // 2.;.(...z.w.z...
                                        09 00 0A 00 74 00 14 00 1F 00 0E 00 7A 00 1F 00   // ....t.......z...
                                        34 00 2E 00 3F 00 28 00 2A 00 28 00 33 00 29 00   // 4...?.(.*.(.3.).
                                        3F 00 7A 00 1F 00 3E 00 33 00 2E 00 33 00 35 00   // ?.z...>.3...3.5.
                                        34 00 57 00 50 00 1F 00 2C 00 3B 00 36 00 2F 00   // 4.W.P...,.;.6./.
                                        3B 00 2E 00 33 00 35 00 34 00 7A 00 17 00 35 00   // ;...3.5.4.z...5.
                                        3E 00 3F 00 7A 00 1F 00 34 00 3B 00 38 00 36 00   // >.?.z...4.;.8.6.
                                        3F 00 3E 00 76 00 7A 00 3C 00 35 00 28 00 7A 00   // ?.>.v.z.<.5.(.z.
                                        2E 00 3F 00 29 00 2E 00 33 00 34 00 3D 00 7A 00   // ..?.)...3.4.=.z.
                                        2A 00 2F 00 28 00 2A 00 35 00 29 00 3F 00 7A 00   // *./.(.*.5.).?.z.
                                        35 00 34 00 36 00 23 00 57 00 50 00 72 00 19 00   // 5.4.6.#.W.P.r...
                                        73 00 7A 00 68 00 6A 00 6A 00 6E 00 7A 00 1E 00   // s.z.h.j.j.n.z...
                                        2F 00 34 00 3E 00 3B 00 29 00 7A 00 09 00 35 00   // /.4.>.;.).z...5.
                                        3C 00 2E 00 2D 00 3B 00 28 00 3F 00 76 00 7A 00   // <...-.;.(.?.v.z.
                                        2D 00 2D 00 2D 00 74 00 3E 00 2F 00 34 00 3E 00   // -.-.-.t.>./.4.>.
                                        3B 00 29 00 74 00 39 00 35 00 37 00 ) 
    IL_0005:  stloc.0
    IL_0006:  ldloc.0
    IL_0007:  call       string Crack::enc(string)
    IL_000c:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0011:  ret
  } // end of method Crack::Main

  .method private hidebysig static string 
        enc(string A_0) cil managed
{
  // 代码大小       43 (0x2b)
  .maxstack  4
  .locals init (char[] V_0,
           int32 V_1)
  IL_0000:  ldarg.0
  IL_0001:  call       instance char[] [mscorlib]System.String::ToCharArray()
  IL_0006:  dup
  IL_0007:  stloc.0
  IL_0008:  ldlen
  IL_0009:  conv.i4
  IL_000a:  stloc.1
  IL_000b:  ldloc.1
  IL_000c:  dup
  IL_000d:  ldc.i4.m1
  IL_000e:  add
  IL_000f:  stloc.1
  IL_0010:  ldc.i4.0
  IL_0011:  ble.s      IL_001f
  IL_0013:  ldloc.0
  IL_0014:  ldloc.1
  IL_0015:  ldloc.0
  IL_0016:  ldloc.1
  IL_0017:  ldelem.u2
  IL_0018:  ldc.i4.s   90
  IL_001a:  xor
  IL_001b:  conv.u2
  IL_001c:  stelem.i2
  IL_001d:  br.s       IL_000b
  IL_001f:  ldloc.0
  IL_0020:  newobj     instance void [mscorlib]System.String::.ctor(char[])
  IL_0025:  call       string [mscorlib]System.String::Intern(string)
  IL_002a:  ret
} // end of method aG::a


  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // 代码大小       7 (0x7)
    .maxstack  1
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Crack::.ctor

} // end of class Crack


// =============================================================

//*********** 反汇编完成 ***********************
// WARNING: Created Win32 resource file C:\Program Files\Dundas Software\Charting\WebControl\bin\crack\crack.res
-----------------------------------------------------------------------

运行ilasm crack.il就可以调试解密结果了,在这个工具的帮助下,研究发现
加密串和明文是一一对应的,例如
1E 00 2F 00 34 00 3E 00 3B 00 29 00 74 00 解密= Dundas.

从水印中关键字是"Evaluation",多次尝试,发现加密文就是

1F 00 2C 00 3B 00 36 00 2F 00 => Evalu

在导出的IL文件中查找,只发现一个,直接定位到
Dundas.Charting.WebControl.ChartPicture
public void Paint(Graphics graph, bool cursorsOnly, RenderingType renderingType, XmlTextWriter svgTextWriter, Stream flashStream, string documentTitle, bool resizable, bool preserveAspectRatio); 
方法,现在工作完成98%了,研究以下代码,发现处理水印的程序是这样写的
bool ifTrial=true;
if(ifTrial){
  //显示水印代码程序处理
}
原来无论license判断结果如何,都会显示水印!难怪上面方法不可行
太容易了,找到bool ifTrial=true;

    IL_0a7d:  ldc.i4.0
    IL_0a7e:  stfld      bool Dundas.Charting.WebControl.ChartPicture::c
修改为
    IL_0a7d:  ldc.i4.1
    IL_0a7e:  stfld      bool Dundas.Charting.WebControl.ChartPicture::c
保存,重新编译

ilasm /dll /RESOURCE=DundasWebChart.res DundasWebChart.il

覆盖到C:\Program Files\Dundas Software\Charting\WebControl\Samples\bin目录,
效果太明显了,水印没有了

原来所谓....的过程就是这样的,没有你想象中的那么难吧! 


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=139798