Todd

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            65 隨筆 :: 0 文章 :: 24 評論 :: 0 Trackbacks

          有矛就有盾。
          所以我們要討論加密技術。

          我們知道,所有的編譯型語 言,例如VC、BCB、Delphi和Win32ASM……最終都會把源代碼編譯成機器能識別的0和1——因此也能夠反過來把這些0和1反編譯成匯編代 碼。反編譯有什么用呢?試想想,你辛辛苦苦寫了一個perfect的軟件出來,正準備把它賣上100萬份,忽然!在市面上出現了很多仿制你的東 西……hoho,不知道你會怎么想呢?反正我是會欲哭無淚的。還有另外一種情況,你的軟件是用注冊碼的形式來授權的,每份license要賣30個美刀。 呵呵,正當你在考慮著一年后是去加利福尼亞還是夏威夷度假的時候,你的軟件被Crack了——也就是說,你一分錢都不會得到……(啊!我想跳樓啦!!)

          所以我們要討論如何給自己的程序加密。這次就先說說最簡單的花指令。

          在解釋這個“花指令”之前,不妨先做幾個小小的實驗。

          我們先來寫一個程序,命名為hua.asm,內容如下:

          ;***************************************************************
          ;花指令實驗1
          ;作者:羅聰
          ;日期:2002-8-21
          ;***************************************************************
          .386
          .model flat, stdcall
          option casemap:none

          include "masm32"include"windows.inc
          include "masm32"include"kernel32.inc
          include "masm32"include"user32.inc
          includelib "masm32"lib"kernel32.lib
          includelib "masm32"lib"user32.lib

          .data
          szText        db    "嘿嘿,這是一個花指令程序……", 0
          szCaption    db    "花指令演示 by LC 2002-8-21", 0

          .code
          main:
              jmp Do_It
          Do_It:
              invoke MessageBox, NULL, addr szText, addr szCaption, MB_OK
              invoke ExitProcess, 0
          end main


          然后用W32Dasm v10來反編譯它,得到的結果如下:(由于篇幅所限,這里只列出關鍵部分)


          +++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
          //********************** Start of Code in Object .text **************
          Program Entry Point = 00401000 (hua.exe File Offset:00001600)



          //******************** Program Entry Point ********
          :00401000 EB00                    jmp 00401002

          * Referenced by a (U)nconditional or ?onditional Jump at Address:
          |:00401000(U)
          |
          :00401002 6A00                    push 00000000

          * Possible StringData Ref from Data Obj ->"花指令演示 by LC 2002-8-21"
                                            |
          :00401004 681F304000              push 0040301F

          * Possible StringData Ref from Data Obj ->"嘿嘿,這是一個花指令程序……"
                                            |
          :00401009 6800304000              push 00403000
          :0040100E 6A00                    push 00000000

          * Reference To: USER32.MessageBoxA, Ord:01BBh
                                            |
          :00401010 E80D000000              Call 00401022
          :00401015 6A00                    push 00000000

          * Reference To: KERNEL32.ExitProcess, Ord:0075h
                                            |
          :00401017 E800000000              Call 0040101C


          哇,好夸張啊!你可能會說。反編譯出來的代碼幾乎是跟源代碼一一對應的,這樣一來?我們的程序還有什么秘密可言呢?完全可以從反編譯的結果中理解程序的功能。

          而且我們還可以在W32Dasm的“String Data References”中得到:
          "嘿嘿,這個是一個花指令程序……"
          "花指令演示 by LC 2002-8-21"


          把剛才的源程序稍做修改,來做第二個實驗:


          ;***************************************************************
          ;花指令實驗2
          ;作者:羅聰
          ;日期:2002-8-21
          ;***************************************************************
          .386
          .model flat, stdcall
          option casemap:none

          include "masm32"include"windows.inc
          include "masm32"include"kernel32.inc
          include "masm32"include"user32.inc
          includelib "masm32"lib"kernel32.lib
          includelib "masm32"lib"user32.lib

          .data
          szText        db    "嘿嘿,這是一個花指令程序……", 0
          szCaption    db    "花指令演示 by LC 2002-8-21", 0

          .code
          main:
              jz Do_It    ;注意這里和第一個實驗中的源程序的區別
              jnz Do_It    ;注意這里和第一個實驗中的源程序的區別
          Do_It:
              invoke MessageBox, NULL, addr szText, addr szCaption, MB_OK
          end main


          用W32Dasm反編譯一下:

          +++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
          //********************** Start of Code in Object .text **************
          Program Entry Point = 00401000 (hua.exe File Offset:00001600)



          //******************** Program Entry Point ********
          :00401000 7402                    je 00401004
          :00401002 7500                    jne 00401004

          * Referenced by a (U)nconditional or ?onditional Jump at Addresses:
          |:00401000?, :00401002?
          |
          :00401004 6A00                    push 00000000

          * Possible StringData Ref from Data Obj ->"花指令演示 by LC 2002-8-21"
                                            |
          :00401006 681F304000              push 0040301F

          * Possible StringData Ref from Data Obj ->"嘿嘿,這是一個花指令程序……"
                                            |
          :0040100B 6800304000              push 00403000
          :00401010 6A00                    push 00000000

          * Reference To: USER32.MessageBoxA, Ord:01BBh
                                            |
          :00401012 E801000000              Call 00401018


          可以看出,這時的W32Dasm反編譯出來的匯編指令還是正確的。但是W32Dasm其實已經逐漸落入我們設下的“陷阱”了。

          下面我們來做第三個實驗,把源程序改成:

          ;***************************************************************
          ;花指令實驗3
          ;作者:羅聰
          ;日期:2002-8-21
          ;***************************************************************
          .386
          .model flat, stdcall
          option casemap:none

          include "masm32"include"windows.inc
          include "masm32"include"kernel32.inc
          include "masm32"include"user32.inc
          includelib "masm32"lib"kernel32.lib
          includelib "masm32"lib"user32.lib

          .data
          szText        db    "嘿嘿,這是一個花指令程序……", 0
          szCaption    db    "花指令演示 by LC 2002-8-21", 0

          .code
          main:
              jz Do_It    ;注意這里和第一個實驗中的源程序的區別
              jnz Do_It    ;注意這里和第一個實驗中的源程序的區別
              db 0E8h        ;注意這里和第二個實驗中的源程序的區別
          Do_It:
              invoke MessageBox, NULL, addr szText, addr szCaption, MB_OK
              invoke ExitProcess, 0
          end main


          我們來看看W32Dasm中反編譯出來的東西:

          +++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
          //********************** Start of Code in Object .text **************
          Program Entry Point = 00401000 (hua.exe File Offset:00001600)



          //******************** Program Entry Point ********
          :00401000 7403                    je 00401005
          :00401002 7501                    jne 00401005
          :00401004 E86A00681D              call 1DA81073
          :00401009 304000                  xor byte ptr [eax+00], al

          * Possible StringData Ref from Data Obj ->"嘿嘿,這是一個花指令程序……"
                                            |
          :0040100C 6800304000              push 00403000
          :00401011 6A00                    push 00000000

          * Reference To: USER32.MessageBoxA, Ord:01BBh
                                            |
          :00401013 E80E000000              Call 00401026
          :00401018 6A00                    push 00000000

          * Reference To: KERNEL32.ExitProcess, Ord:0075h
                                            |
          :0040101A E801000000              Call 00401020


          呵呵,很明顯了,這時的 00401004 到 00401009 行出錯了,而且這時查看“String Data References”,也只剩下了:
          "嘿嘿,這是一個花指令程序……"


          讓我們進一步隱藏信息,做第四個實驗:

          ;***************************************************************
          ;花指令實驗4
          ;作者:羅聰
          ;日期:2002-8-21
          ;***************************************************************
          .386
          .model flat, stdcall
          option casemap:none

          include "masm32"include"windows.inc
          include "masm32"include"kernel32.inc
          include "masm32"include"user32.inc
          includelib "masm32"lib"kernel32.lib
          includelib "masm32"lib"user32.lib

          .data
          szText        db    "嘿嘿,這是一個花指令程序……", 0
          szCaption    db    "花指令演示 by LC 2002-8-21", 0

          .code
          main:
              jz Do_It    ;注意這里和第一個實驗中的源程序的區別
              jnz Do_It    ;注意這里和第一個實驗中的源程序的區別
              db 0E8h        ;注意這里和第二個實驗中的源程序的區別
          Do_It:
              lea eax, szText        ;注意這里和第三個實驗中的源程序的區別
              lea ebx, szCaption    ;注意這里和第三個實驗中的源程序的區別
              invoke MessageBox, NULL, eax, ebx, MB_OK    ;注意這里和第三個實驗中的源程序的區別
              invoke ExitProcess, 0
          end main


          編譯,再用W32Dasm反編譯,得到的是:

          +++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
          //********************** Start of Code in Object .text **************
          Program Entry Point = 00401000 (hua.exe File Offset:00001600)



          //******************** Program Entry Point ********
          :00401000 7403                    je 00401005
          :00401002 7501                    jne 00401005
          :00401004 E88D050030              call 30401596
          :00401009 40                      inc eax
          :0040100A 008D1D1D3040            add byte ptr [ebp+40301D1D], cl
          :00401010 006A00                  add byte ptr [edx+00], ch
          :00401013 53                      push ebx
          :00401014 50                      push eax
          :00401015 6A00                    push 00000000

          * Reference To: USER32.MessageBoxA, Ord:01BBh
                                            |
          :00401017 E80E000000              Call 0040102A
          :0040101C 6A00                    push 00000000

          * Reference To: KERNEL32.ExitProcess, Ord:0075h
                                            |
          :0040101E E801000000              Call 00401024


          呵呵,這次不但面目全非了,而且“String Data References”按鈕已經變成了灰色。什么蛛絲馬跡都沒有了。

          各位看官看到這里明白了嗎?其實花指令就是人為地構造一些“陷阱”和一些無用的字節。例如第二個實驗中的:

          jz Do_It
          jnz Do_It

          其實這個跟 jmp Do_It 還不是一樣嗎?(呵呵,如果在大學的期末考試里這樣寫,一定會被判不及格……)

          是的,其實程序原有的功能和邏輯還是一樣的,我們只不過是換了一種表現形式而已。然而,反編譯工具是沒有人腦那么智能的,它們往往就會把這些指令理解錯,從而錯誤地確定了指令的起始位置。

          要實現這種絕對跳轉的功能,還可以用很多的方法,例如:

          Push Do_It
          ret


          花指令是很容易理解的,不過大家要注意適時而用,不要濫用啊,能起到迷惑破解者和隱藏信息的作用就行了,不然將來要維護代碼時,我怕被迷惑的反而是你自己哦,呵呵……

          posted on 2010-05-20 01:44 Todd 閱讀(545) 評論(0)  編輯  收藏 所屬分類: 攻防c++
          主站蜘蛛池模板: 永城市| 崇明县| 梅州市| 满洲里市| 靖远县| 叶城县| 正阳县| 宁强县| 通辽市| 利津县| 新邵县| 石棉县| 商洛市| 理塘县| 革吉县| 定日县| 桐柏县| 宜丰县| 顺平县| 克拉玛依市| 乌拉特后旗| 博爱县| 驻马店市| 南阳市| 尚义县| 通江县| 怀宁县| 临泽县| 余姚市| 阿拉尔市| 当阳市| 斗六市| 浙江省| 渝北区| 新河县| 弋阳县| 湄潭县| 甘泉县| 怀仁县| 拜泉县| 襄汾县|