winxp總管破解筆記(一) (8千字)

看雪資料發表於2002-10-07

好久沒寫東西了,找不到好的題材,現在有了,一個.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把源程式載入,很快我們得到了反編譯的程式碼,你看到的是一種樹狀的結構圖:

winxp總管破解筆記(一) (8千字)

很清晰的結構,完全採用類的結構,透過名字我們判斷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

完成了,等我的下一篇文章研究一下注冊演算法:)

相關文章