zoukankan      html  css  js  c++  java
  • VB 共享软件防破解设计技术初探(二)

    VB 共享软件防破解设计技术初探(二)


    ××××××××××××××××××××××××××××××××××××××××××××××


    其他文章快速链接:

    VB 共享软件防破解设计技术初探(一)
    http://bbs.pediy.com/showthread.php?t=72050

    VB 共享软件防破解设计技术初探(三)
    http://bbs.pediy.com/showthread.php?t=72489



    ××××××××××××××××××××××××××××××××××××××××××××××



    作者:爱琴海[SCG] 2008/09/06 (转载请保留该信息)

      上个篇我粗略的讲了以下几个内容:

    1、  文件完整性,防止被非法修改
    2、  运行时的校验,防止被LOADER
    3、  反调试,防止动态跟踪和挂接
    4、  防静态反汇编分析
    5、  注册码系统(算法部分,核心内容)
    6、  加壳防脱壳
    7、  隐蔽性设计
    8、  另辟蹊径

    列表在这里是为了提醒初学VB发布共享软件的朋友,在设计VB防破解的时候,不要出现“水桶效应”,也就是说,设计如水桶,任何一个角落缺失都将导致无法全部盛满水。

      而这个水桶的捆圈恐怕就是保护文件完整性,防止修改了。
      周末了,今天有点时间。赶快写好,等下吃晚饭,练练琴,然后陪陪女朋友。

      接下去,我们将开始具体至微的讲解第1、2两个内容,剩下的老规矩:日后有空,有时间,有精力,有能力的话接着写。

    1、    文件完整性,可采用CRC32或者MD5或者哈希算法等,计算出文件的加密值,在适当的时候进行对比,判断文件被修改与否。当然那也可以加猛壳来防止文件非法修改。还有简单点的检查文件最后修改时间,看看是否是你自己设置好的时间,如果不是,则很有可能被修改过;也可以检测文件大小,往往压缩壳被脱掉后,文件的大小会增加;保护壳被脱掉后,文件大小会变小,我们可以根据这个设置好临界值来检测有没有被脱壳。常用的还有故意设计好关于算法方面的陷阱,如果是破解者会主动掉进你的陷阱,而事实上,这个跳转除非爆破,不然在算法上是永远也无法到达的,这样就检出破解者在修改程序流程。你可以无声无息的程序死掉,不要直接退出,不然会被追踪到退出函数。

    还有内存镜像校验,是为了防止普通的修改内存和普通断点问题。

    我们就具体演示3种VB程序的完整性校验设计。

    第一种是VB的CRC32自校验设计,包含过程,代码和所有工程文件及演示;
    第二种是VB程序的时间检测法则,包括过程,代码和所有工程文件及演示;
    第三种是VB程序的文件大小检测法则,包括过程,代码和所有工程文件及演示。

    其实还有些检测的办法,但是原理跟我们即将大曝光的三种办法差不多,都是衍生的吧。

    第二章  第一讲

    VB的CRC32自校验设计

    来来来…大家跟我一起做运动,抖抖手啊,抖抖脚啊,做做深呼吸,本讲将会有点长,力求做到简单明了,容易明白,学完马上上手,学会应用的要求,我会具体点讲,不会像某些高人敝帚自珍,当然如果有错误的地方还请大家多多帮忙纠正,谢谢

    首先来简单复习下何谓CRC32

    CRC校验实用程序库 在数据存储和数据通讯领域,为了保证数据的正确,就不得不采用检错的手段。在诸多检错手段中,CRC是最著名的一种。CRC的全称是循环冗余校验,其特点是:检错能力极强,开销小,易于用编码器及检测电路实现。从其检错能力来看,它所不能发现的错误的几率仅为0.0047%以下。

    有查表和计算法,我们可以在程序中自动生成码表来查表计算,方便和快速

    为了快速带过原理笔墨,节省点时间吃饭,我把网路上的一篇介绍《探究CRC32算法实现原理》引述过来,原文地址:

    http://www.diybl.com/course/6_system...1/134331.html#

    以下是引用部分

    基于不重造轮子的原则,本文尽量不涉及网络上遍地都是的资料。
    What's CRC ?
    简而言之,CRC是一个数值。该数值被用于校验数据的正确性。CRC数值简单地说就是通过让你需要做
    处理的数据除以一个常数而得到的余数。当你得到这个数值后你可以将这个数值附加到你的数据后,
    当数据被传送到其他地方后,取出原始数据(可能在传送过程中被破坏)与附加的CRC数值,然后将这里
    的原始数据除以之前那个常数(约定好的)然后得到新的CRC值。比较两个CRC值是否相等即可确认你的
    数据是否在传送过程中出现错误。
    那么,如何让你的数据除以一个常数?方法是对你的数据进行必要的编码处理,逐字节处理成数字。
    那么这个常数是什么?你不必关注它是什么,也不需要关注它是如何获得的。当你真的要动手写一个
    CRC的实现算法时,我可以告诉你,CRC的理论学家会告诉你。不同长度的常数对应着不同的CRC实现算法。
    当这个常数为32位时,也就是这里所说的CRC32。
    以上内容你不必全部理解,因为你需要查阅其他资料来获取CRC完整的理论介绍。
    The mathematics behind CRC ?
    很多教科书会把CRC与多项式关联起来。这里的多项式指的是系数为0或1的式子,例如:
    a0 + a1*x + a2*x^2 + ... + an*x^n。其中a0, a1, ..., an要么为0要么为1。我们并不关注x取什么值。
    (如果你要关注,你可以简单地认为x为2) 这里把a0, a1, ..., an的值取出来排列起来,就可以表示比特
    流。例如 1 + x + x^3所表示的比特流就为:1101。部分资料会将这个顺序颠倒,这个很正常。
    什么是生成多项式?
    所谓的生成多项式,就是上面我所说的常数。注意,在这里,一个多项式就表示了一个比特流,也就是一堆
    1、0,组合起来最终就是一个数值。例如CRC32算法中,这个生成多项式为:
    c(x) = 1 + x + x^2 + x^4 + x^5 + x^7 + x^8 + x^10 + x^11 + x^12 + x^16 + x^22 + x^23 + x^26 + x^32。
    其对应的数字就为:11101101101110001000001100100000(x^32在实际计算时隐含给出,因此这里没有包含它
    的系数),也就是0xEDB88320(多项式对应的数字可能颠倒,颠倒后得到的是0x04C11DB7,其实也是正确的)。
    由此可以看出,CRC值也可以看成我们的数据除以一个生成多项式而得到的余数。
    如何做这个除法?
    套用大部分教科书给出的计算方法,因为任何数据都可以被处理成纯数字,因此,在某种程度上说,我们可以
    直接开始这个除法。尽管事实上这并不是标准的除法。例如,我们的数据为1101011011(方便起见我直接给二进制
    表示了,从这里也可以看出,CRC是按bit进行计算的),给定的生成多项式(对应的值)为10011。通常的教科书
    会告诉我们在进行这个除法前,会把我们的数据左移几位(生成多项式位数-1位),从而可以容纳将来计算得到
    的CRC值(我上面所说的将CRC值附加到原始数据后)。但是为什么要这样做?我也不知道。(不知道的东西不能含糊
    而过)那么,除法就为:
                1100001010
           _______________
    10011 ) 11010110110000 附加了几个零的新数据
            10011......... 这里的减法(希望你不至于忘掉小学算术)是一个异或操作
            -----.........
             10011........
             10011........
             -----........
              00001....... 逐bit计算
              00000.......
              -----.......
               00010......
               00000......
               -----......
                00101.....
                00000.....
                -----.....
                 01011....
                 00000....
                 -----....
                  10110...
                  10011...
                  -----...
                   01010..
                   00000..
                   -----..
                    10100.
                    10011.
                    -----.
                     01110
                     00000
                     -----
                      1110 = 这个余数也就是所谓的CRC值,通常又被称为校验值。
    希望进行到这里,你可以获取更多关于CRC的感性认识。而我们所要做的,也就是实现一个CRC的计算算法。
    说白了,就是提供一个程序,给定一段数据,以及一个生成多项式(对于CRC32算法而言该值固定),然后
    计算得出上面的1110余数。
    The simplest algorithm.
    最简单的实现算法,是一种模拟算法。我们模拟上面的除法过程,遵从网上一份比较全面的资料,我们设定
    一个变量register。我们逐bit地将我们的数据放到register中。然后判断register最高位是否为1,如果是
    则与生成多项式异或操作,否则继续处理。这个过程简单地模拟了上述除法过程:
    引用到此结束




    看来大家选择CRC32作为数据校验是有原因的,速度快,代价小,检错能力比较大。VB软件作者对CRC32有个认识就好了。

    我们编写VB的CRC32自校验程序思路如下:

    1、  计算出目标文件除掉末尾8字节后的所有数据的CRC32值
    2、  将上面计算出来的结果储存在目标程序的末尾8个字节里
    3、  主体程序内置计算自身除掉末尾8字节后的所有数据的CRC32值的功能代码
    4、  主体程序读取末尾8字节内容与计算的CRC32值比较,不一致说明被修改

    由1、2点我们发现,如果手动来添加CRC32值将是件麻烦的事情,所以一般我们都会写一个具备计算要求的CRC32值,及把该值添加到目标程序指定位置的程序,帮我们节省时间和体力。

    为了方便记忆和理解,在这里我将它命名为VB-CRC32 注射器,顾名思义,即将计算出来的CRC32注射到目标程序里。

    那么执行自校验的程序我称它为VB-CRC32 主体程序。大家记住了哦,下面开始先设计VB-CRC32注射程序。

    请跟我一起来:

    打开VB6.0 新建工程

    新建类模块,名字改为“clsCRC”,别告诉我你不会改名,当然是在“属性窗口”改的。

    将如下类模块代码复制到clsCRC类模块里去:(或者直接从我发布的附件来条用该类模块)

    注意:类模块后缀名是CLS,请刚接触VB的同学注意,不要跟模块搞混了。

    我是代码起始线

    Option Explicit

    Public Enum CRCAlgorithms
      CRC16
      CRC32
    End Enum
    Private m_Algorithm As Boolean

    Private m_CRC16 As Long
    Private m_CRC16Asm() As Byte
    Private m_CRC16Init As Boolean
    Private m_CRC16Table(0 To 255) As Long

    Private m_CRC32 As Long
    Private m_CRC32Asm() As Byte
    Private m_CRC32Init As Boolean
    Private m_CRC32Table(0 To 255) As Long

    Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    '此函数作用在这里是内联汇编之用

    Public Function AddBytes(ByteArray() As Byte) As Variant
      Dim ByteSize As Long
        '异常处理
      On Local Error GoTo NoData
      '计算大小
      ByteSize = UBound(ByteArray) - LBound(ByteArray) + 1
        '异常处理
      On Local Error GoTo 0
      '内联汇编提高处理速度
      Select Case m_Algorithm
      Case CRC16
        Call CallWindowProc(VarPtr(m_CRC16Asm(0)), VarPtr(m_CRC16), VarPtr(ByteArray(LBound(ByteArray))), VarPtr(m_CRC16Table(0)), ByteSize)
      Case CRC32
        Call CallWindowProc(VarPtr(m_CRC32Asm(0)), VarPtr(m_CRC32), VarPtr(ByteArray(LBound(ByteArray))), VarPtr(m_CRC32Table(0)), ByteSize)
      End Select
    NoData:
      '返回新值
      AddBytes = Value
    End Function

    Public Function AddString(Text As String) As Variant

      '将字符转为数组,以便套入函数计算CRC
      AddString = AddBytes(StrConv(Text, vbFromUnicode))
      
    End Function
    Public Property Let Algorithm(New_Value As CRCAlgorithms)

      '选择新算法
      m_Algorithm = New_Value

      '确定已经初始化新算法
      Select Case m_Algorithm
      Case CRC16
        If (Not m_CRC16Init) Then Call InitializeCRC16
      Case CRC32
        If (Not m_CRC32Init) Then Call InitializeCRC32
      End Select

      '标记
      Call Clear
      
    End Property
    Public Property Get Algorithm() As CRCAlgorithms

      Algorithm = m_Algorithm
      
    End Property

    Public Function CalculateBytes(ByteArray() As Byte) As Variant

      '重置CRC计算
      Call Clear
      '计算
      CalculateBytes = AddBytes(ByteArray)
      
    End Function

    Public Function CalculateFile(Filename As String) As Variant

      Dim Filenr As Integer
      Dim ByteArray() As Byte
      
      '检测文件是否包换数据
      If (FileLen(Filename) = 0) Then Exit Function
      
      '二进制模式读取文件储存到数组里
      Filenr = FreeFile
      Open Filename For Binary As #Filenr
      ReDim ByteArray(0 To LOF(Filenr) - 9)
      Get #Filenr, , ByteArray()
      Close #Filenr
      
      '将该数组交给处理函数计算出CRC
      CalculateFile = CalculateBytes(ByteArray)

    End Function

    Public Property Get Value() As Variant

      Select Case m_Algorithm
      Case CRC16
        Value = (m_CRC16 And 65535)
      Case CRC32
        Value = (Not m_CRC32)
      End Select
      
    End Property

    Public Property Let Value(New_Value As Variant)

      Select Case m_Algorithm
      Case CRC16
        m_CRC16 = New_Value
      Case CRC32
        m_CRC32 = New_Value
      End Select
      
    End Property

    Private Sub InitializeCRC16()

      Dim i As Long
      Dim j As Long
      Dim k As Long
      Dim CRC As Long
      Dim sASM As String
      
      '创建表格
      For i = 0 To 255
        k = i * 256
        CRC = 0
        For j = 0 To 7
          If (((CRC Xor k) And 32768) = 32768) Then
            CRC = (CRC * 2) Xor &H1021
          Else
            CRC = (CRC * 2)
          End If
          k = k * 2
        Next
        m_CRC16Table(i) = CRC '(CRC And 65535)
      Next
      
      '内联汇编预处理
      sASM = "5589E55756505351528B45088B008B750C8B7D108B4D1431DB8A1E30E3668B149F30C66689D0464975EF25FFFF00008B4D0889015A595B585E5F89EC5DC21000"
      ReDim m_CRC16Asm(0 To Len(sASM)  2 - 1)
      For i = 1 To Len(sASM) Step 2
        m_CRC16Asm(i  2) = Val("&H" & Mid$(sASM, i, 2))
      Next
      
      '标记
      m_CRC16Init = True
      
    End Sub
    Public Sub Clear()

      m_CRC16 = 0
      m_CRC32 = &HFFFFFFFF
      
    End Sub

    Private Sub InitializeCRC32()

      Dim i As Long
      Dim sASM As String
      
      m_CRC32Table(0) = &H0
      m_CRC32Table(1) = &H77073096
      m_CRC32Table(2) = &HEE0E612C
      m_CRC32Table(3) = &H990951BA
      m_CRC32Table(4) = &H76DC419
      m_CRC32Table(5) = &H706AF48F
      m_CRC32Table(6) = &HE963A535
      m_CRC32Table(7) = &H9E6495A3
      m_CRC32Table(8) = &HEDB8832
      m_CRC32Table(9) = &H79DCB8A4
      m_CRC32Table(10) = &HE0D5E91E
      m_CRC32Table(11) = &H97D2D988
      m_CRC32Table(12) = &H9B64C2B
      m_CRC32Table(13) = &H7EB17CBD
      m_CRC32Table(14) = &HE7B82D07
      m_CRC32Table(15) = &H90BF1D91
      m_CRC32Table(16) = &H1DB71064
      m_CRC32Table(17) = &H6AB020F2
      m_CRC32Table(18) = &HF3B97148
      m_CRC32Table(19) = &H84BE41DE
      m_CRC32Table(20) = &H1ADAD47D
      m_CRC32Table(21) = &H6DDDE4EB
      m_CRC32Table(22) = &HF4D4B551
      m_CRC32Table(23) = &H83D385C7
      m_CRC32Table(24) = &H136C9856
      m_CRC32Table(25) = &H646BA8C0
      m_CRC32Table(26) = &HFD62F97A
      m_CRC32Table(27) = &H8A65C9EC
      m_CRC32Table(28) = &H14015C4F
      m_CRC32Table(29) = &H63066CD9
      m_CRC32Table(30) = &HFA0F3D63
      m_CRC32Table(31) = &H8D080DF5
      m_CRC32Table(32) = &H3B6E20C8
      m_CRC32Table(33) = &H4C69105E
      m_CRC32Table(34) = &HD56041E4
      m_CRC32Table(35) = &HA2677172
      m_CRC32Table(36) = &H3C03E4D1
      m_CRC32Table(37) = &H4B04D447
      m_CRC32Table(38) = &HD20D85FD
      m_CRC32Table(39) = &HA50AB56B
      m_CRC32Table(40) = &H35B5A8FA
      m_CRC32Table(41) = &H42B2986C
      m_CRC32Table(42) = &HDBBBC9D6
      m_CRC32Table(43) = &HACBCF940
      m_CRC32Table(44) = &H32D86CE3
      m_CRC32Table(45) = &H45DF5C75
      m_CRC32Table(46) = &HDCD60DCF
      m_CRC32Table(47) = &HABD13D59
      m_CRC32Table(48) = &H26D930AC
      m_CRC32Table(49) = &H51DE003A
      m_CRC32Table(50) = &HC8D75180
      m_CRC32Table(51) = &HBFD06116
      m_CRC32Table(52) = &H21B4F4B5
      m_CRC32Table(53) = &H56B3C423
      m_CRC32Table(54) = &HCFBA9599
      m_CRC32Table(55) = &HB8BDA50F
      m_CRC32Table(56) = &H2802B89E
      m_CRC32Table(57) = &H5F058808
      m_CRC32Table(58) = &HC60CD9B2
      m_CRC32Table(59) = &HB10BE924
      m_CRC32Table(60) = &H2F6F7C87
      m_CRC32Table(61) = &H58684C11
      m_CRC32Table(62) = &HC1611DAB
      m_CRC32Table(63) = &HB6662D3D
      m_CRC32Table(64) = &H76DC4190
      m_CRC32Table(65) = &H1DB7106
      m_CRC32Table(66) = &H98D220BC
      m_CRC32Table(67) = &HEFD5102A
      m_CRC32Table(68) = &H71B18589
      m_CRC32Table(69) = &H6B6B51F
      m_CRC32Table(70) = &H9FBFE4A5
      m_CRC32Table(71) = &HE8B8D433
      m_CRC32Table(72) = &H7807C9A2
      m_CRC32Table(73) = &HF00F934
      m_CRC32Table(74) = &H9609A88E
      m_CRC32Table(75) = &HE10E9818
      m_CRC32Table(76) = &H7F6A0DBB
      m_CRC32Table(77) = &H86D3D2D
      m_CRC32Table(78) = &H91646C97
      m_CRC32Table(79) = &HE6635C01
      m_CRC32Table(80) = &H6B6B51F4
      m_CRC32Table(81) = &H1C6C6162
      m_CRC32Table(82) = &H856530D8
      m_CRC32Table(83) = &HF262004E
      m_CRC32Table(84) = &H6C0695ED
      m_CRC32Table(85) = &H1B01A57B
      m_CRC32Table(86) = &H8208F4C1
      m_CRC32Table(87) = &HF50FC457
      m_CRC32Table(88) = &H65B0D9C6
      m_CRC32Table(89) = &H12B7E950
      m_CRC32Table(90) = &H8BBEB8EA
      m_CRC32Table(91) = &HFCB9887C
      m_CRC32Table(92) = &H62DD1DDF
      m_CRC32Table(93) = &H15DA2D49
      m_CRC32Table(94) = &H8CD37CF3
      m_CRC32Table(95) = &HFBD44C65
      m_CRC32Table(96) = &H4DB26158
      m_CRC32Table(97) = &H3AB551CE
      m_CRC32Table(98) = &HA3BC0074
      m_CRC32Table(99) = &HD4BB30E2
      m_CRC32Table(100) = &H4ADFA541
      m_CRC32Table(101) = &H3DD895D7
      m_CRC32Table(102) = &HA4D1C46D
      m_CRC32Table(103) = &HD3D6F4FB
      m_CRC32Table(104) = &H4369E96A
      m_CRC32Table(105) = &H346ED9FC
      m_CRC32Table(106) = &HAD678846
      m_CRC32Table(107) = &HDA60B8D0
      m_CRC32Table(108) = &H44042D73
      m_CRC32Table(109) = &H33031DE5
      m_CRC32Table(110) = &HAA0A4C5F
      m_CRC32Table(111) = &HDD0D7CC9
      m_CRC32Table(112) = &H5005713C
      m_CRC32Table(113) = &H270241AA
      m_CRC32Table(114) = &HBE0B1010
      m_CRC32Table(115) = &HC90C2086
      m_CRC32Table(116) = &H5768B525
      m_CRC32Table(117) = &H206F85B3
      m_CRC32Table(118) = &HB966D409
      m_CRC32Table(119) = &HCE61E49F
      m_CRC32Table(120) = &H5EDEF90E
      m_CRC32Table(121) = &H29D9C998
      m_CRC32Table(122) = &HB0D09822
      m_CRC32Table(123) = &HC7D7A8B4
      m_CRC32Table(124) = &H59B33D17
      m_CRC32Table(125) = &H2EB40D81
      m_CRC32Table(126) = &HB7BD5C3B
      m_CRC32Table(127) = &HC0BA6CAD
      m_CRC32Table(128) = &HEDB88320
      m_CRC32Table(129) = &H9ABFB3B6
      m_CRC32Table(130) = &H3B6E20C
      m_CRC32Table(131) = &H74B1D29A
      m_CRC32Table(132) = &HEAD54739
      m_CRC32Table(133) = &H9DD277AF
      m_CRC32Table(134) = &H4DB2615
      m_CRC32Table(135) = &H73DC1683
      m_CRC32Table(136) = &HE3630B12
      m_CRC32Table(137) = &H94643B84
      m_CRC32Table(138) = &HD6D6A3E
      m_CRC32Table(139) = &H7A6A5AA8
      m_CRC32Table(140) = &HE40ECF0B
      m_CRC32Table(141) = &H9309FF9D
      m_CRC32Table(142) = &HA00AE27
      m_CRC32Table(143) = &H7D079EB1
      m_CRC32Table(144) = &HF00F9344
      m_CRC32Table(145) = &H8708A3D2
      m_CRC32Table(146) = &H1E01F268
      m_CRC32Table(147) = &H6906C2FE
      m_CRC32Table(148) = &HF762575D
      m_CRC32Table(149) = &H806567CB
      m_CRC32Table(150) = &H196C3671
      m_CRC32Table(151) = &H6E6B06E7
      m_CRC32Table(152) = &HFED41B76
      m_CRC32Table(153) = &H89D32BE0
      m_CRC32Table(154) = &H10DA7A5A
      m_CRC32Table(155) = &H67DD4ACC
      m_CRC32Table(156) = &HF9B9DF6F
      m_CRC32Table(157) = &H8EBEEFF9
      m_CRC32Table(158) = &H17B7BE43
      m_CRC32Table(159) = &H60B08ED5
      m_CRC32Table(160) = &HD6D6A3E8
      m_CRC32Table(161) = &HA1D1937E
      m_CRC32Table(162) = &H38D8C2C4
      m_CRC32Table(163) = &H4FDFF252
      m_CRC32Table(164) = &HD1BB67F1
      m_CRC32Table(165) = &HA6BC5767
      m_CRC32Table(166) = &H3FB506DD
      m_CRC32Table(167) = &H48B2364B
      m_CRC32Table(168) = &HD80D2BDA
      m_CRC32Table(169) = &HAF0A1B4C
      m_CRC32Table(170) = &H36034AF6
      m_CRC32Table(171) = &H41047A60
      m_CRC32Table(172) = &HDF60EFC3
      m_CRC32Table(173) = &HA867DF55
      m_CRC32Table(174) = &H316E8EEF
      m_CRC32Table(175) = &H4669BE79
      m_CRC32Table(176) = &HCB61B38C
      m_CRC32Table(177) = &HBC66831A
      m_CRC32Table(178) = &H256FD2A0
      m_CRC32Table(179) = &H5268E236
      m_CRC32Table(180) = &HCC0C7795
      m_CRC32Table(181) = &HBB0B4703
      m_CRC32Table(182) = &H220216B9
      m_CRC32Table(183) = &H5505262F
      m_CRC32Table(184) = &HC5BA3BBE
      m_CRC32Table(185) = &HB2BD0B28
      m_CRC32Table(186) = &H2BB45A92
      m_CRC32Table(187) = &H5CB36A04
      m_CRC32Table(188) = &HC2D7FFA7
      m_CRC32Table(189) = &HB5D0CF31
      m_CRC32Table(190) = &H2CD99E8B
      m_CRC32Table(191) = &H5BDEAE1D
      m_CRC32Table(192) = &H9B64C2B0
      m_CRC32Table(193) = &HEC63F226
      m_CRC32Table(194) = &H756AA39C
      m_CRC32Table(195) = &H26D930A
      m_CRC32Table(196) = &H9C0906A9
      m_CRC32Table(197) = &HEB0E363F
      m_CRC32Table(198) = &H72076785
      m_CRC32Table(199) = &H5005713
      m_CRC32Table(200) = &H95BF4A82
      m_CRC32Table(201) = &HE2B87A14
      m_CRC32Table(202) = &H7BB12BAE
      m_CRC32Table(203) = &HCB61B38
      m_CRC32Table(204) = &H92D28E9B
      m_CRC32Table(205) = &HE5D5BE0D
      m_CRC32Table(206) = &H7CDCEFB7
      m_CRC32Table(207) = &HBDBDF21
      m_CRC32Table(208) = &H86D3D2D4
      m_CRC32Table(209) = &HF1D4E242
      m_CRC32Table(210) = &H68DDB3F8
      m_CRC32Table(211) = &H1FDA836E
      m_CRC32Table(212) = &H81BE16CD
      m_CRC32Table(213) = &HF6B9265B
      m_CRC32Table(214) = &H6FB077E1
      m_CRC32Table(215) = &H18B74777
      m_CRC32Table(216) = &H88085AE6
      m_CRC32Table(217) = &HFF0F6A70
      m_CRC32Table(218) = &H66063BCA
      m_CRC32Table(219) = &H11010B5C
      m_CRC32Table(220) = &H8F659EFF
      m_CRC32Table(221) = &HF862AE69
      m_CRC32Table(222) = &H616BFFD3
      m_CRC32Table(223) = &H166CCF45
      m_CRC32Table(224) = &HA00AE278
      m_CRC32Table(225) = &HD70DD2EE
      m_CRC32Table(226) = &H4E048354
      m_CRC32Table(227) = &H3903B3C2
      m_CRC32Table(228) = &HA7672661
      m_CRC32Table(229) = &HD06016F7
      m_CRC32Table(230) = &H4969474D
      m_CRC32Table(231) = &H3E6E77DB
      m_CRC32Table(232) = &HAED16A4A
      m_CRC32Table(233) = &HD9D65ADC
      m_CRC32Table(234) = &H40DF0B66
      m_CRC32Table(235) = &H37D83BF0
      m_CRC32Table(236) = &HA9BCAE53
      m_CRC32Table(237) = &HDEBB9EC5
      m_CRC32Table(238) = &H47B2CF7F
      m_CRC32Table(239) = &H30B5FFE9
      m_CRC32Table(240) = &HBDBDF21C
      m_CRC32Table(241) = &HCABAC28A
      m_CRC32Table(242) = &H53B39330
      m_CRC32Table(243) = &H24B4A3A6
      m_CRC32Table(244) = &HBAD03605
      m_CRC32Table(245) = &HCDD70693
      m_CRC32Table(246) = &H54DE5729
      m_CRC32Table(247) = &H23D967BF
      m_CRC32Table(248) = &HB3667A2E
      m_CRC32Table(249) = &HC4614AB8
      m_CRC32Table(250) = &H5D681B02
      m_CRC32Table(251) = &H2A6F2B94
      m_CRC32Table(252) = &HB40BBE37
      m_CRC32Table(253) = &HC30C8EA1
      m_CRC32Table(254) = &H5A05DF1B
      m_CRC32Table(255) = &H2D02EF8D

      '内联汇编预处理
      sASM = "5589E557565053518B45088B008B750C8B7D108B4D1431DB8A1E30C3C1E80833049F464975F28B4D088901595B585E5F89EC5DC21000"
      ReDim m_CRC32Asm(0 To Len(sASM)  2 - 1)
      For i = 1 To Len(sASM) Step 2
        m_CRC32Asm(i  2) = Val("&H" & Mid$(sASM, i, 2))
      Next
      
      '标记CRC32
      m_CRC32Init = True

    End Sub
    Private Sub Class_Initialize()

      '默认为CRC32算法
      Algorithm = CRC32
      
    End Sub

    我是代码终止线

    可以看到该类模块里应用了VB内联汇编的技巧,其核心是利用了CallWindowProcA,将定义好的代码串作为数值编入VB,然后通过CallWindowProcA来指定其为执行的代码进行执行。相关内容请到网上查找。

    该模块是我修改来急速计算文件CRC32或者CRC16的,默认情况下是计算CRC32。

    如图:


     

    然后双击窗体Form1,在工具栏里选择“工程”,指向“部件”,选择“Microsoft Common Dialog Contrll 6.0”,在工具箱中选择它,添加到窗体上。并改其名为“Openfile”。

    注意:细节美观什么的,大家自己弄,我讲的一般不包含如何设置和美化界面什么的。

    如图:


     


    在窗体通用部分添加:
    Private CRC32zhi As String
    '用作储存CRC32的值的
    Private Zhuangtai As Boolean
    '用作标志写入文件是否成功


    在窗体上添加按钮Command1,命名为“打开”,然后设计代码使通过它跟“Openfile”挂钩(别再问我Openfile是什么,也就是刚才我们使用的Common Dialog控件)

    Openfile的Action我们采用1模式,也就是常见的打开对话框;
    Openfile的Dialog Title我们命名为"    请选择需要添加CRC32自校验值的目标程序"
    Openfire的Filter属性我们设置为"*.exe"
    Openfire的其他属性默认即可

    为了计算并自动添加CRC32值到目标程序,并且方便大家复制移植代码,我们有必要给它写个过程,或者函数。这里注射写过程就好了,等下设计主体程序时我们也要写函数的。

    我是代码起始线

    Private Sub SetCRC32(Lujing As String)

    '函数化添加CRC32
    '核心代码

    On Error GoTo CRCerror

     Dim cCRC As New clsCRC, FileCRC$
    '启用类模块


        cCRC.Algorithm = CRC32 '选择算法模式是CRC32
        cCRC.Clear  '算法初始化

        FileCRC = Hex(cCRC.CalculateFile(Lujing))
        '计算出目标程序的CRC32,忽略目标程序末尾8字节数值,末尾8字节是用来储存我们示范的CRC32值的
        
        If Len(FileCRC) < 8 Then FileCRC = Left("00000000", 8 - Len(FileCRC)) & Hex(cCRC.CalculateFile(Lujing))
        '如果CRC32值不足8位,那么要在前面添加零来补足位数
            
        CRC32zhi = FileCRC
           'CRC32值储存

        FileNum = FreeFile
        '获得个文件号(通道)
        
        Open Lujing For Binary As #FileNum
        Seek FileNum, FileLen(Lujing) - 7
        Put #FileNum, , FileCRC
        Close FileNum
        '用二进制模式打开目标程序,通过SEEK定位需要添加CRC32数值的位置,请注意:这个位置以后大家可以自己改
        '通过PUT将我们计算号的CRC32写入指定位置
        '通过CLOSE关闭通道
         
    Zhuangtai = True
     '状态字,表示写入文件成功了

           

    Exit Sub

    CRCerror:
    MsgBox "发生意外错误,请检查目标程序是否正在运行?", , "发生意外错误,代码: " & Err.Number

    End Sub

    我是代码终止线

    SetCRC32就是特意写的直接完成计算CRC32和写入目标程序的功能过程
    调用格式为:SetCRC32(目标程序路径)

    看,多么简单不是吗?

    接下去双击Command1按钮,给它设计功能代码如下:

    我是代码起始线

    Private Sub Command1_Click()

    '示范
    '选择一个待添加CRC32值的自校验程序

    On Error GoTo Qingjiancha

    '初始化CRC32值,主要是为了清空上次的状态
    CRC32zhi = ""
    '初始化写入成功与否的标志
    Zhuangtai = False


    Dim FilenameNo1 As String
    Openfile.DialogTitle = "    请选择需要添加CRC32自校验值的目标程序"
    Openfile.Filter = "*.exe"
    Openfile.Action = 1
    FilenameNo1 = Openfile.Filename

    If FilenameNo1 = "" Then Exit Sub
    '检查是否选择了程序

    If FileLen(FilenameNo1) < 16 Then MsgBox "请检查目标程序是否包含足够数据", , "请检查NO1": Exit Sub
    '检查程序是否包含足够空间和数据,因为储存CRC32需要8个字节的空间,本身计算余量怎么说也要8个字节把?8+8=16

    Big.Caption = "目标程序大小为: " & FileLen(FilenameNo1) & " 字节"

    SetCRC32 (FilenameNo1)

    CRCzhi.Caption = "目标程序CRC32值: " & CRC32zhi

    If Zhuangtai = True Then
    Zhuang.Caption = "CRC32添加状况: 添加成功,你可以启动目标程序的自校验来核实"
    Else
    Zhuang.Caption = "CRC32添加状况: 添加失败,请你检查下目标程序是否正在运行中?"
    End If

    Exit Sub

    FilenameNo1 = ""

    Qingjiancha:
    MsgBox "发生意外错误,请检查输入等情况是否正常,目标程序是否正在运行?", , "发生意外错误,代码: " & Err.Number
    FilenameNo1 = ""
    End Sub

    我是代码终止线


    整个程序还需要:一个名为CRCzhi的Label,一个名为Zhuang的Label
            分别显示计算出来的CRC32值,和显示写入文件是否成功的信息


    这样子,通过编译,生成EXE文件,执行效果如图:


     

    这样我们就完成了VB-CRC32添加校验值到目标程序的注射端。保存工程等文件。

    接下去,我们就来应用该VB-CRC32注射端配合主体程序来完成整个VB-CRC32自校验设计

    下面开始写VB-CRC32自校验主体程序

    打开VB6.0,新建工程

    按照上文一样,建立clsCRC类模块,代码一致,或者直接添加附件里的该类模块也可以。

    如图:



     

    然后设计如下图的程序界面,注意需要一个名为Jieguo的Label,建立一个名为“检测“的Command1

    然后双击窗体,进入代码设计界面

    如图:




    在这个主体自校验部分,大家想一下,大概需要写几个什么样的函数?方便复制和移植?

    我认为是两个函数,分别计算自身的CRC32值,和获取已经写入到末尾8字节的CRC32校验值。

    那么说干就干吧:

    我是代码起始线

    Private Function GetCRC32() As String

    '函数化计算本身的CRC32
    '核心代码

    Dim Lujing As String
    '定义本程序自己的路径变量

    On Error GoTo CRCerror

    Lujing = App.Path & "" & App.EXEName & ".exe"
    '这句语句就获得了程序自己的启动路径,这个技巧VB中必须掌握,用处很多

     Dim cCRC As New clsCRC, FileCRC$
    '启用类模块

        cCRC.Algorithm = CRC32 '选择算法模式是CRC32
        cCRC.Clear  '算法初始化

        FileCRC = Hex(cCRC.CalculateFile(Lujing))
        '计算出目标程序的CRC32,忽略目标程序末尾8字节数值,末尾8字节是用来储存我们示范的CRC32值的
        
        If Len(FileCRC) < 8 Then FileCRC = Left("00000000", 8 - Len(FileCRC)) & Hex(cCRC.CalculateFile(Lujing))
        '如果CRC32值不足8位,那么要在前面添加零来补足位数
            
        GetCRC32 = FileCRC
        
    Exit Function

    CRCerror:
    MsgBox "发生意外错误,程序被破坏?", , "发生意外错误,代码: " & Err.Number

    End Function

    我是代码终止线

    该GetCRC32函数直接当作字符变量来使用即可,可获取自身除末尾8位外其他所有数据的CRC32值,我再强调一遍,这里是做示范,为了方便查看和记忆,特将CRC32校验值储存到目标程序末尾8字节位置,实际应用中,大家可以自己选择一个合理的位置。

    我是代码起始线

    Private Function GetZHI() As String

    '函数化获得末尾标记值
    '这个值是我们用CRC32添加工具添加进去的
    '这个位置你也可以自己修改
    '核心代码

    Dim Lujing As String
    Dim ArrBytes() As Byte
    Dim FilelenNO1
    Dim Xunhuan As Double
    '定义本程序自己的路径变量

    'On Error GoTo ZHIerror

    Lujing = App.Path & "" & App.EXEName & ".exe"
    '这句语句就获得了程序自己的启动路径,这个技巧VB中必须掌握,用处很多

    tfile = FreeFile
        Open Lujing For Binary As #tfile        '利用二进制打开自身
        FilelenNO1 = LOF(tfile)
        ReDim ArrBytes(1 To FilelenNO1) As Byte '将目标末尾8位储存
        Get tfile, , ArrBytes
        Close tfile

    For Xunhuan = FilelenNO1 - 7 To FilelenNO1
    '开始获取这具体的8位
    GetZHI = GetZHI & Chr(ArrBytes(Xunhuan))
    Next Xunhuan


    Exit Function

    ZHIerror:
    MsgBox "怀疑程序被破坏了", , "错误代码: " & Err.Number

    End Function

    我是代码终止线

    该GetZHI函数同样可以当字符形式使用,很方便,从名字上看就知道是为了获取预先储存在本身末尾8字节的CRC32预先计算的值。干什么用?当然是跟上面的GetCRC32函数返回的字符进行比较,看结果是否跟标记的一致,一致就说明程序没有被修改,不一致就说明程序被修改了。

    这个两个关键函数同样可以被大家移植过去使用

    很高兴能给VB共享软件带来点有趣的有用的东西。

    接下去就是在主体中使用这两个函数
    我们的使用代码是:

    我是代码起始线

    '就简单的一句话就交代了 ^_^
    '我们已经写好了GetCRC32函数和GetZHI函数
    '两个函数返回值为字符串,当然,我们只是做测试,如果真的要
    '应用到软件中去,我推荐还是用浮点计算,制造隐藏剧情
    '甚至内联汇编处理,根据CRC32值来跳转,让人难以琢磨
    '使用时,只要使用这两个函数就OK了

    If GetCRC32 = GetZHI Then

    MsgBox "程序未被修改过,恭喜你", , "通过"

    Jieguo.ForeColor = &H80000012 '更改字体颜色为黑色
    Jieguo.Caption = "程序未被修改"

    Else

    MsgBox "程序被修改,请不要非法修改本程序,共享软件云云...", , "被修改"

    Jieguo.ForeColor = &HFF& '更改字体颜色为红色,表示警告
    Jieguo.Caption = "警告:程序被修改"

    End If

    我是代码终止线

    这个使用代码,能看懂的就自己改写,看不懂的就添加到Private Sub Form_Load()事件中去,还有Private Sub Command1_Click()事件中。

    好了,保存工程后,开始编译为EXE文件吧,编译好后,用我们写好的VB-CRC32添加校验值注射工具进行注射一下,这个时候如果有杀毒软件在的话,而且比较好的话,可能会弹出提示问你允不允许修改什么的,我用的微点就会提示和拦截,需要防行。然后运行吧。

    效果如图:


     

    可以看到这里显示的目标程序的CRC32自校验码为:60B04682

    我们用UltraEdit打开注射过了的目标主体程序,在末尾看到:


     

    可见已经添加成功了,运行主体程序:








     

     

    看来校验通过了,那么我们下面来模拟下破解者修改程序的情况:

    在VBExplorer中,我们找到检测按钮事件起始地址:405F90

    代开OD来装载目标主体程序,CTRL+G 直接到 405F90

    00405F90   > 55            PUSH EBP
    00405F91   .  8BEC          MOV EBP,ESP
    00405F93   .  83EC 0C       SUB ESP,0C
    00405F96   .  68 76124000   PUSH <JMP.&MSVBVM60.__vbaExceptHandler>  ;  SE 处理程序安装
    00405F9B   .  64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
    00405FA1   .  50            PUSH EAX
    00405FA2   .  64:8925 00000>MOV DWORD PTR FS:[0],ESP
    00405FA9   .  81EC 9C000000 SUB ESP,9C
    00405FAF   .  53            PUSH EBX
    00405FB0   .  56            PUSH ESI

    0040604D   . /0F84 D1000000 JE VB防破解.00406124
    ‘我们把这句改为必跳实验下,看看CRC32校验的威力

    0040604D     /E9 D2000000   JMP VB防破解.00406124
    00406052     |90            NOP

    然后保存程序,运行修改后的程序如图:






     

    到此我们完成了VB-CRC32自校验程序的设计全部过程,有些问题必须讲以下:

    也许会有人问:“小爱老师,听说CRC32很厉害,防修改。但是我用了你的代码之后,刚发表的共享软件就被人修改了,怎么回事?”

    问到点子上了,确实CRC查错能力很强,但是它本身也有脆弱性,本身防修改,但是事实恰恰相反,你可以问下身边的解密高手,当他们遇到CRC32自校验的时候怎么办?

    一般都是爆破,还有些是替换,替换的话还要重新计算新的CRC32值,比较罗嗦,所以大家都喜欢爆掉CRC32的关键比较点来突破CRC32,而且以此为荣。

    如果你设计VB-CRC32自校验,怎样处理这种情况?首先你要隐蔽你的比较方式,采用浮点计算,套用异常,故意设置隐藏剧情来保护CRC-32的校验,这是个好办法。也有高手说要加壳带CRC32校验。

    前辈们给的办法是把校验值进行变换,分段,分开,分时,不定时,在各种场合和代码角落进行验证,尽量不给检测到非法修改的提示,而是检测到非法修改也不告诉破解者,悄悄变换程序流程,让他迷路去吧

    甚至是报复破解者,这个我是不推荐的,但是我可以给个快速关机的过程,直接调用可以在几秒内关闭对方计算机,让对方来不及保存破解笔记和资料,注:往往破解者用影子系统或者虚拟机

    我是代码起始线

    ‘在通用部分加入如下声明:
    Private Declare Function RtlAdjustPrivilege& Lib "ntdll" (ByVal Privilege&, ByVal NewValue&, ByVal NewThread&, OldValue&)
    Private Declare Function NtShutdownSystem& Lib "ntdll" (ByVal ShutdownAction&)
    Private Const SE_SHUTDOWN_PRIVILEGE& = 19
    Private Const ShutDown& = 0
    Private Const RESTART& = 1
    Private Const POWEROFF& = 2

    ‘在窗体代码部分增加:
    Sub TurboShutdown(Index As Integer)
         RtlAdjustPrivilege SE_SHUTDOWN_PRIVILEGE, 1, 0, 0
        Select Case Index
            Case 1 '关机
                NtShutdownSystem ShutDown
            Case 2 '重启动
                NtShutdownSystem RESTART
            Case 3 '关机
                NtShutdownSystem POWEROFF
        End Select
    End Sub

    我是代码终止线

    调用该快速关机指令为:

    Call TurboShutdown(1)

    希望对你有用,但是不要拿来欺负正常使用你软件的顾客哦,不然把顾客都吓跑了

    注意:以上VB-CRC32全部设计代码和工程文件及程序都发布在附件了,请自行下载




    第二章  第二讲
    VB时间自校验设计

    上一讲我们讲了使用VB进行CRC32自校验的设计,相信是能让部分VB软件作者受益的。下次见到你们发表VB软件的时候,我希望不是随便爆破修改就能破解的了。

    也许你认为VB-CRC32设计有点复杂,你问“小爱老师,有没有简单点的防爆破自校验?”
    当然是有的

    你可以先实验下,随便编译个程序,单击右键查看属性,你会发现它包含了你的最后修改时间,一般的复制,黏贴等都不会修改它的“修改时间”属性。

    然而,当破解者修改了你的软件就会被记录下最新的修改时间,如果破解者不注意,而你的设计又够隐蔽,倒是可以检查这个来判断破解者有没有修改过你的软件。

    来,跟我一起做运动……

    打开VB6.0 新建工程

    添加一个按钮,起名为“检测”

    编写一个检测自身修改时间并作比较的函数:

    我是代码起始线

    Private Function ShiJiancheck() As Boolean
    ShiJiancheck = False
    Dim iFile As String
    Dim FileTime As String
    iFile = App.Path & "" & App.EXEName & ".exe"
    '获取自身启动路径
    FileTime = Format(FileDateTime(iFile), "YYYYMMDDHHMMSS")
    '获得字符串形式的文件最后修改时间
    If FileTime = "20080808080808" Then
    '示范设置为2008年08月08日08时08分08秒,这里大家可以自己定,最好不要太特别
    ShiJiancheck = True
    Else
    ShiJiancheck = False
    End If
    End Function

    我是代码终止线

    调用该函数直接当作布尔变量用即可

    如下调用:

    我是代码起始线

    Private Sub Command1_Click()
    '注意,文件本身的修改时间应该不是我们设定的值,所以编译好EXE文件后,
    '用文件属性修改器来修改文件最后修改时间到指定数值,这个数值不要太特殊了
    '文件属性修改器已经放在同个文件夹下了,请使用
    If ShiJiancheck = False Then
    MsgBox "文件被修改", , "警告"
    Else
    MsgBox "文件正常", , "通过"
    End If
    End Sub

    我是代码终止线

    效果如图:(正常状态)


     

    文件被修改后:

     

    跟CRC32比,此办法短小精悍,但是容易被识破,请隐蔽比较和检测,不要把结果显示出来,知道了吧?给破解制造一次意外事故应该不是难事吧?





    第二章  第三讲
    VB大小自校验设计

    “小爱老师,上面的方法都要修改什么的,太麻烦了,有没有更通用,更普遍的办法,且不用修改程序的呢?”

    “当然有了,那就是VB里面的检测文件大小,但是已经见得多了,已经没什么杀伤力了”

    Vb里常用检测文件大小的函数为FILELEN(路径)

    跟我一起做运动……

    打开VB6.0 新建工程

    先编写个检测自身大小的函数:

    我是代码起始线

    Private Function FileBig() As Long
    '如果文件巨大,那么改LONG为DOUBLE
    Dim FileLujin As String
    filelujing = App.Path & "" & App.EXEName & ".exe"
    FileBig = FileLen(filelujing)
    End Function

    我是代码终止线

    具体使用看下面代码:

    我司代码起始线

    Private Sub Form_Load()
    If FileBig > 27300 Then
    '第一次这个数字随便设置,先编译好
    '用压缩壳将它压缩,查看压缩后文件大小
    '回到这里,修改数值比压缩后的大小大那儿一些就够了
    '如果被脱壳了,程序体积就会膨胀
    '从而被我们检测出来
    '当然要注意了,如果是保护壳的话
    '加壳后反而更大,这个时候,我们的判断
    '语句就要反过来了
    MsgBox "程序被脱壳了", , "警告"
    Else
    MsgBox "程序正常", , "通过"
    End If
    End Sub

    我是代码终止线

    编译,加壳(ASPACK)程序从45056字节压缩为 27136 字节,27300略大于27136,脱壳后应该比45056可能还要大,这样就能实现检测大小来发现脱壳,也就发现修改了。

    如图:

     

    脱壳后:大小71168字节,为什么这么大呢?呵呵,可能是垃圾代码和垃圾段还没清理吧,可以用LORDPE重建,应该会小一点。

    重建PE后,程序大小46261字节
    运行看看:如图



     

    实验成功,但是我还是要提醒一下,这种方法隐蔽点,不要提示的话,也许还能存活,对于VB程序,一旦发现自校验,初学者或者有点基础的人都会想到去断点FILELEN函数,直接捕获你的对比关键点。

    所以自校验的设计最关键在于隐蔽和起到误导作用为好,不知不觉中就到了羊肠小道,永远没有回头路……

    另外要介绍的是同样是检测文件大小以确定是否被脱壳,有些软件作者把数值通过计算好,通过注射方法,写入到主体程序的文件头,这种方法可以比较准确的限定文件大小,而且不容易被发现哦,比方说“超级硬盘搜索正式版”,它就是这么检测的。

    有点作者把VB程序的数据全部加在一起,比较最后的和,这也是种办法,所以大家要学会思考和创新,没有什么是做不到的。


    第二章  第四讲
    VB防LOADER设计金蝉脱壳

    《加密解密技术内幕》一书里提到过两种方法防LOADER

    其指的是防SMARTCHECK,WKTVB DEBUGGER等

    这些技术已经为人所熟知,起不到多么好的作用,我们就了解一下吧,为我们的“金蝉脱壳”做铺垫。
       
    1.  查找特定的窗口标题  就像第一讲里提到的:

    我是引用起始线

    二、反SMARTCHECK加载,SMARTCHECK是调试VB的利器,有必要对其进行防范。小楼前辈在软件加密技术内幕中提到两种检测方法:
    利用VB的AppActivate函数激活SMARTCHECK窗口,然后发送ALT+F4进行关闭该窗口和利用FindWindow发现SMARTCHECK窗口直接将其关闭,其代码基本上是这样:
    winHwnd = FindWindow(vbNullString, "Numega SmartCheck")
    If winHwnd <> 0 Then
    AppActivate "Numega SmartCheck"
    sendkey "%{f4}", True
    sendkey "%y", True
       其实,我觉得直接检测进程SMARTCHK.EXE是否存在也可以,方法跟上面类似,你还可以检测其它比如W32DASM等进程,附件中的Anti-Load就是实例,发现SMARTCHK调用,自动退出:
    …..
     If InStr(LCase(Process.szExeFile), "smartchk.exe") > 0 Then
               smart = Process.th32ProcessID
              TerminateProcess hprocess, 0
              Unload Me
            Exit Do
            End If
    …….
    我是引用终止线

    2.  设置步长和时值计算法

    其原理是软件正常执行的某一块过程是很快的,基本没多少延时;而通过调试器加载,其加载时间往往要多出十几倍。

    这种方法其实应该是反调试反跟踪里用到的,这里就只提下原理,讲到反调试的时候,我再把我知道的写出来。

    目前还有异常SHE处理,使得调试器无碍继续加载。还有其他的办法,但是我涉及较浅,以后有机会都放到反调试一块讲。


    讲完常见的VB反LOADER,你是不是觉得不够好使?如查标题,我改标题你不久查不到了吗? 如步长记时,现在的电脑配置参差不齐,这步长时值该怎么时值好呢?

    左思右想,终于被我想到了个办法金蝉脱壳

    所谓金蝉脱壳指的是核心的东西在你眼皮底下溜走了,抓不到。留下的是一层幻灭的轮回。

    VB金蝉脱壳反LOADER技术基于程序迭代SHELL,第一次运行不会真的开始,而是为了调用本身进行第二次运行,就此结束掉第一次运行,以此类推,知道几百几千次,需要的时间大概在半秒到左右。

    形象点讲就像小孩子走路,故意跌倒,然后爬起来,又故意跌倒,让你永远把握不到他,知道他再起来的时候,你早就离开那里了。

    比如A实例,运行后,重新调用A,然后本次A实例自动结束,第二次A实例启动,再次调用A实例,然后又关闭自己。这样调试器第一跟踪,如果不爆破的话,势必无法继续跟了,到后来,调试器里显示的是父本程序已经结束了,但实际中,经过几百到几千次迭代SHELL后,程序已经打开。

    就像人生一样,调试器跟踪的只是你的上一世,甚至是几百几千世以前的你,而现在的你还好好得活着。这个时候,如果不爆破的话,调试器大概还可以用附加来强行钻入程序空间。

    这样的思路是可行的,但是你有没有想到过如何判断本次运行已经达到要求,可以正常开始?还是继续轮回?

    要求程序依靠自己的标记,而不依靠外界的标记,不然容易被人发现且从外界修改是非常容易攻破的。

    因为程序是同一个程序,凭什么上一辈子要立刻轮回,而这辈子就可以正常存活呢?判断的标准在哪里?同样的程序,同样的标准,为什么会产生不同的轮回结果?

    答案呼之欲出了,对了,就是随机数。

    通过概率,每次轮回的概率是一样的,是同样的标准,但是概率本身又可以导致不同的方向和结果。

    于是我想到设置一个循环取随机数的结构,循环7次,每次产生一个随机数,要么是1,要么是零,然后把这七个数相加来判断是否等于零,如果等于零就不必继续轮回了,如果不等于零,那么SHELL自己,然后马上死掉。因为每次随机数取0活着取1的概率是一样的,都是0.5,所以,7次随机数取值全部为零的概率是0.5^7=0.0078125,倒数为128,即大概需要轮回128次才可以正常运行程序,否则都是SHELL自己,然后父本死掉。

    单单靠解释可能还是有朋友看不明白,没关系,我们先写程序先,慢慢测试调试,你就发现其巧妙的地方了。

    首先写一个7次循环取0或取1的结构,然后把7次结果相加,与0作比较,将轮回金蝉脱克功能嵌入进去。以后程序在运行开头,只要调用一次我的这个SUB过程即可实现防LOADER,等会我们还要测试下效果呢。

    我是代码起始线

    Private Sub JinChan()

    On Error GoTo ANTI
    '只有在被调试的时候才有可能出错,恰好被我们捕获,呵呵

    Dim Lujing As String
    '储存程序自身路径
    Dim Suiji(7) As Byte
    '7个元素数组,用于储存每次随机数
    Dim n As Long
    '循环计数器
    Dim Panduan As Double
    '累加器
    Lujing = App.Path & "" & App.EXEName & ".exe"
    '获得程序自身路径

    For n = 1 To 7
    Randomize
    '每次都初始化随机数生成器
    Suiji(n) = Int(Rnd * 2)
    ‘取随机数0或者1
    Panduan = Panduan + Suiji(n)
    '累加
    Next n


    If Panduan > 0 Then
    '如果累加总结果不为零,那就SHELL自己一次,然后通过END结束自己
    Shell Lujing, 1
    '进入下一个轮回哦
    End
    '结束这一世
    End If

    '如果上面的累加器等于零,则说明达到了0.5^7的概率了,其倒数为128,即我们已经轮'回128是世了。'调试器跟踪的只是我们的第一世。
    '到这里来的话也就是不执行SHELL内容,也不执行END,直接到这里来了
    '正常运行

    Exit sub

    ANTI:
    MsgBox "发现调试器,请关闭调试器", , "警告"
    End

    End Sub

    我是代码终止线

    以后只要把JinChan写入到主窗体LOAD事件中,就实现了金蝉脱壳效果。

    大家跟我来做运动:

    打开VB6.0 新建工程

    在窗体代码里,拷贝上面的代码进去

    然后在Private Sub Form_Load()里输入JinChan,编译生成EXE

    即:
    Private Sub Form_Load()
    JinChan
    End Sub

    先运行一下EXE,看看速度如何,然后再用OD或者SMARTCHECK等测试下,看看是不是无法跟踪到轮回后的这一世,前提是不能爆破。

    效果还是很好的,OD如果开着HIDEOD插件的话,那么在执行SHELL的时候,会自动捕获错误以发现调试器,然后程序自动结束,也相当于起到了防LOADER作用。如果OD关闭HIDEOD插件,那么就可以直接体现出“金蝉脱壳”的效果了。

    如图:通过捕获异常发现调试器

     

    如果没有异常,那么金蝉脱克将发挥作用,轮回百世。调试器里已经结束,但是程序其实轮回转世了。
     
    好了,没想到随便写写可以写这么多,看的我头晕了。

    希望你也别头晕,我们来总结下,《VB 共享软件防破解涉及技术初探(二)》都讲了那些内容:

    1、  设计思想:水桶原理
    2、  完整性校验,包括VB-CRC32注射器和主体的编写;文件修改时间自校验;文件大小自校验等
    3、  防LOADER设计,包括查找标题,经典时值,还有重点的“金蝉脱壳”反LOADER

    这一期就到这里了,熬夜写教程很累,呵呵
    还是老规矩,如果有时间,有精力,有空,有能力,我将接着写《VB 共享软件防破解设计
    技术初探(三)》,感谢大家的支持。

    希望大家能多顶顶,尤其是学习VB写软件的朋友,希望对你有用。

  • 相关阅读:
    C# 串口调试助手源码
    C# 中 textBox 侧面滑条 属性
    C# 中 comboBox 禁止输入
    VS2015 下载 破解
    中国移动OnetNet云平台 GET指令使用
    JSON JsonArray和JsonObject学习资料
    sublime 添加 ConvertToUTF-8
    sublime 添加 颜色插件 colorcoder
    线程池
    爬虫中基本的多线程
  • 原文地址:https://www.cnblogs.com/chenjian/p/3546553.html
Copyright © 2011-2022 走看看