好久没写东西了,找不到好的题材,现在有了,一个.NET的程序----WINXP总管,让我们有幸目睹微软的杰作.NET框架程序的破解:)
目标软件:WINXP总管
编程语言:VB.NET
破解工具:ILDASM,WINHEX
作者:GREENLEMON(菩提!)[FCG]
背景知识介绍:首先,我们遇到的是一个全新的东西,.NET框架,这个东西是什么呢,他怎么工作的,如果你用WIN32DASM反汇编一下这个程序,你会看到莫名其妙的代码,因为它不再是我们传统意义上的汇编代码了,它是.NET的核心也就是MSIL语言,IL全称是INTERMEDIATE
LANGUAGE,也就是一种中间语言,类似PCODE,但这回所有的编程语言包括VB,VC,C#全都编译成MSIL然后再利用.NET框架的JIT实时转译成本地机的可执行代码,从而实现了平台无关性,于是我们要破解这类程序就要找到一种类似PCODE反编译器的东西,很幸运的是微软大叔为我们提供了全套超强绿色套装:)对我们最有用的就是ILDASM(这些东西在.NET
FRAMEWORK SDK中提供)
好了基本的东西知道了一点,现在开始就要了解这种语言了,当然微软的MSDN有所有你想知道的东西,所以我这里就不罗索了,你可以去看看他的教程,我就来讲讲具体的破解,这才是我等感兴趣的:)
首先用ILDASM把源程序载入,很快我们得到了反编译的代码,你看到的是一种树状的结构图:
很清晰的结构,完全采用类的结构,通过名字我们判断MyClsRegister这个类就是关键所在,而他的几个方法也是一看就明白做什么用的,关键就在它们里面代码的含义,就是msil语言究竟是怎么样的。我们从Registered入手,这个最象那么回事:)
所有的misl语言都基于CLR(公共语言运行库),CLR 是.NET 框架应用程序的执行引擎,它有别于传统的CPU结构,传统的CPU执行依赖于寄存器和堆栈,而CLR只使用堆栈,所以你所看到的MSIL语言都是下面的形式:
ld....
ld....
语句(call,比较。。)
实际上类似于
push
push
call
也就是说全都是这样的函数,方法调用
.method public
static void Registered() cil managed //方法的名称
{
//
Code size 90 (0x5a) //代码的大小
.maxstack
4 //最大的堆栈数
.locals init (string V_0, //参数
string V_1)
IL_0000: nop
IL_0001:
call string WinXP_Manager.MyClsOther/MyClsRegister::GetRegCodeValue()//这个方法在前面有描述是注册表"date"键值
IL_0006: stloc.0 //st=store这句是要保存上面返回值到loc.0,loc.0是本地的一个参数
IL_0007: call string WinXP_Manager.MyClsOther/MyClsRegister::GetRegCodeWord()//这个方法在前面有描述是注册表"name"键值
IL_000c: stloc.1 //类似上面,存到loc.1里面
IL_000d:
ldloc.0 //取出loc.0,推到堆栈里
IL_000e: ldstr
"" //取字符串,这里是空串
IL_0013: ldc.i4.0 //取一个0,推入堆栈
IL_0014: call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StringType::StrCmp(string,
string,
bool)//可以看出上面三个参数是用来给这个比较call的,目的显然是判断是不是空串,返回值入栈
IL_0019: ldc.i4.0 //推一个0入栈
IL_001a:
ceq //比较看是不是空的啦,是推送 1,否则推送 0
IL_001c:
ldloc.1 //和上面类似来判断另一个是不是空
IL_001d: ldstr
""
IL_0022: ldc.i4.0
IL_0023:
call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StringType::StrCmp(string,
string,
bool)
IL_0028: ldc.i4.0
IL_0029: ceq
IL_002b:
or //把ceq后的两个堆栈的值或一下
IL_002c: brfalse.s
IL_0036 //如果是0,则跳到36行继续
IL_002e: ldc.i4.0 //否则推一个0
<----------将来修改这里推1进去
IL_002f: stsfld bool WinXP_Manager.publicVarFun::IsRegistered//存到这个参数里(这个参数就是用来判断注册与否的)
IL_0034: br.s IL_0057//跳出去
IL_0036:
nop
IL_0037: ldloc.0 //取出date
IL_0038:
ldloc.1 //取出name
IL_0039: call
string WinXP_Manager.MyClsOther/MyClsRegister::FromHDSNGetRegisterCode(string)//另一方法里用于算注册码
IL_003e: ldc.i4.0
IL_003f: call
int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StringType::StrCmp(string,
string,
bool)//比较拉
IL_0044: ldc.i4.0
IL_0045: beq.s IL_004f //判断相等就说明注册了
IL_0047: ldc.i4.0 //不等就推0 <-----------------这里改成1:)
IL_0048: stsfld bool WinXP_Manager.publicVarFun::IsRegistered
IL_004d: br.s IL_0056
IL_004f:
nop
IL_0050: ldc.i4.1 //相等推1
IL_0051:
stsfld bool WinXP_Manager.publicVarFun::IsRegistered
IL_0056: nop
IL_0057: nop
IL_0058: nop
IL_0059: ret
} // end of method MyClsRegister::Registered
很简单把,接下来我们就要改了,怎么做,首先要知道这些代码怎么用16进制表示在文件里的,把显示字节打开,再来看看这段代码
.method public static void Registered() cil managed
// SIG: 00
00 01
{
// Method begins at RVA 0x9370c
// Code size
90 (0x5a)
.maxstack 4
.locals init
(string V_0,
string V_1)
IL_0000:
/* 00 | */
nop
IL_0001: /* 28 | (06)000056 */
call string WinXP_Manager.MyClsOther/MyClsRegister::GetRegCodeValue()
IL_0006: /* 0A |
*/ stloc.0
IL_0007: /* 28 | (06)000057
*/ call string WinXP_Manager.MyClsOther/MyClsRegister::GetRegCodeWord()
IL_000c: /* 0B |
*/ stloc.1
IL_000d: /* 06 |
*/ ldloc.0
IL_000e: /* 72 | (70)000B80 */ ldstr
""
IL_0013: /* 16 |
*/ ldc.i4.0
IL_0014: /* 28
| (0A)000083 */ call
来看看这段,他的16进制表示是这样的
00
28 56 00 00 06 0a 28 57 00 00 06 0b 06 72 80 0b 00 70 16 28 83 00 00 0a
看出来了吧:)
IL_0019: /* 16 |
*/ ldc.i4.0
IL_001a:
/* FE01 | */ ceq
IL_001c: /* 07 |
*/ ldloc.1
IL_001d: /* 72 | (70)000B80
*/ ldstr ""
IL_0022: /* 16
| */ ldc.i4.0
IL_0023: /* 28 | (0A)000083 */ call
int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StringType::StrCmp(string,
string,
bool)
IL_0028: /* 16 |
*/ ldc.i4.0
IL_0029: /* FE01 |
*/ ceq
IL_002b:
/* 60 | */
or
IL_002c: /* 2C | 08
*/ brfalse.s IL_0036
IL_002e: /* 16
| */ ldc.i4.0
//这里改成17
IL_002f: /* 80 | (04)000007
*/ stsfld bool WinXP_Manager.publicVarFun::IsRegistered
IL_0034: /* 2B | 21
*/ br.s IL_0057
IL_0036: /* 00 |
*/ nop
IL_0037:
/* 06 | */
ldloc.0
IL_0038: /* 07 |
*/ ldloc.1
IL_0039: /* 28
| (06)000059 */ call string WinXP_Manager.MyClsOther/MyClsRegister::FromHDSNGetRegisterCode(string)
IL_003e: /* 16 |
*/ ldc.i4.0
IL_003f: /* 28 | (0A)000083
*/ call int32 [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.StringType::StrCmp(string,
string,
bool)
IL_0044: /* 16 |
*/ ldc.i4.0
IL_0045: /* 2E
| 08 */ beq.s
IL_004f
IL_0047: /* 16 |
*/ ldc.i4.0 //这里改成17
IL_0048:
/* 80 | (04)000007 */ stsfld bool WinXP_Manager.publicVarFun::IsRegistered
IL_004d: /* 2B | 07
*/ br.s IL_0056
IL_004f: /*
00 | */ nop
IL_0050: /* 17 |
*/ ldc.i4.1
IL_0051: /* 80 | (04)000007
*/ stsfld bool WinXP_Manager.publicVarFun::IsRegistered
IL_0056: /* 00 |
*/ nop
IL_0057: /* 00 |
*/ nop
IL_0058:
/* 00 | */
nop
IL_0059: /* 2A |
*/ ret
} // end of method MyClsRegister::Registered
完成了,等我的下一篇文章研究一下注册算法:)