阳光网驿-企业信息化交流平台【DTC零售连锁全渠道解决方案】

 找回密码
 注册

QQ登录

只需一步,快速开始

扫描二维码登录本站

手机号码,快捷登录

老司机
查看: 4009|回复: 20

[讨论] 与其等别人的PJ,不如自己学会弄zcj,能大家一段教程

[复制链接]
  • TA的每日心情
    开心
    2011-5-9 23:55
  • 签到天数: 22 天

    [LV.4]偶尔看看III

    发表于 2009-12-17 19:51:11 | 显示全部楼层 |阅读模式
    zcj编写器是一个很特殊的软件,它可以快速地生成一个zcj,而不需要再过多的了解程序的指令算法。整个程序体实际上只是一个用汇编写的模板,你只要略有汇编基础,就可以轻松方便地写出自己的zcj。此外,你还可以在其中自定义自己的界面和提示信息。可以用VC++或BC++等资源编辑工具自行修改key1.res资源文件,但请不要修改它们对应的ID号。
    zcj编写器的特点
    • 快速高效地生成属于你个人的zcj,且无需了解过多的指令算法
    • 生成的zcj可在各个Windows平台上使用
    • 简单易用,有良好用户界面
    • 可以方便地修改资源,制作个性化的界面
    • 另类zcj功能
    • 文件补丁功能
    • 内存补丁功能
    如何使用zcj编写器
       在目录目录 EXAMPLE 下有一个例子程序,主要用来举例说明这个程序的使用(我先假设自己并不太懂Win32汇编)。
      1. 通过动态调试或反汇编例子程序可以得到以下注册码的计算过程(它不是根据你的序列号来计算注册码):
    xxxx:00401077 CALL GetCommandLineA
    xxxx:0040107C CMP BYTE PTR [EAX],22
    xxxx:0040107F JNZ 401082
    xxxx:00401081 INC EAX
    xxxx:00401082 MOV CX,WORD PTR [EAX]
    xxxx:00401085 MOV WORD PTR [0040306C],CX
    xxxx:0040108C MOV WORD PTR [0040306E],5C
    xxxx:00401095 PUSH 0
    xxxx:00401097 PUSH 0
    xxxx:00401099 PUSH 0
    xxxx:0040109B PUSH 0
    xxxx:0040109D PUSH DWORD 00403058
    xxxx:004010A2 PUSH 0
    xxxx:004010A4 PUSH 0
    xxxx:004010A6 PUSH DWORD 0040306C
    xxxx:004010AB CALL GetVolumeInformationA
    …………    …………
    …………    ………… //上面的指令如果不懂也没有关系,以下是关键
    xxxx:0040111E MOV EAX,1
    xxxx:00401123 CPUID
    xxxx:00401125 MOV ECX,DWORD PTR [00403058]
    xxxx:0040112B XOR EDX,EDX
    xxxx:0040112D MUL ECX
    xxxx:0040112F ADD EAX,EDX
    xxxx:00401131 PUSH EAX????????//从这里开始,说明输出格式
    xxxx:00401132 PUSH DWORD 0040303E    ; 会动态调试的朋友,在这里可以知道内存地址40303E的内容为“%1X”
    xxxx:00401137 PUSH DWORD 0040305C
    xxxx:0040113C CALL wsprintfA
      对于以上的指令并不需要过多的了解它在干什么,只要将其中的每个地址改成一个变量地址的声明,然后再原封不动的抄到zcj编写器的代码窗口中即可。
      这是写好的声明:
    a1 dd 0; 这是一个双字的内存空间,对应于上面的403058。
    ;(因为40109D处的指令是DWORD 403058,所以用dd,如果是WORD就用dw,如果是BYTE就用db)
    a2 dd 0; 对应于上面的40306C
    a3 db "%1X",0; 对应于上面的40303E指向的字符串
    a4 db 20 dup (0)
    ; 这是20个字节的内存空间,用来存放输出的注册码,对应于上面的40305C
      输入如图所示:
    [img=520,400]mkMSITStore:\OEM\工具\Keymake\KEYMAKE.CHM::/5.GIF[/img]
        这是写好的程序代码:
    CALL GetCommandLineA CMP BYTE PTR [EAX],22h; 后面加h表示是十六进制
    JNZ n1
    INC EAX
    n1:
    MOV CX,WORD PTR [EAX];准备生成暗码
    MOV WORD PTR a2,CX
    MOV WORD PTR a2+2,5Ch
    PUSH 0
    PUSH 0
    PUSH 0
    PUSH 0
    LEA EAX,a1; 令EAX指向a1
    PUSH EAX
    PUSH 0
    PUSH 0
    LEA EAX,a2
    PUSH EAX; 令EAX指向a2
    CALL GetVolumeInformationA; 当然这几条语句也可以直接写成
    invoke GetVolumeInformationA,addr a2,0,0,addr a1,0,0,0,0
    的形式
    MOV EAX,1上面的指令如果不懂也没有关系,照抄就行
    CPUID
    MOV ECX,a1
    XOR EDX,EDX
    MUL ECX
    ADD EAX,EDX下面的指令指的是输出格式,除了“%1X”可以修改,其他的请照抄
    PUSH EAX
    LEA EAX,a3; 令EAX指向a3,也就是指向字符“%1X”。“%1X"指的是输出数据的
    PUSH EAX;格式,你会C语言就肯定懂了
    LEA EAX,a4
    PUSH EAX
    CALL wsprintfA
    LEA EAX,a4
    ; 令EAX指向a4。因为程序最后显示的就是EAX寄存器所指向的内存地址的数据。
      输入如下图所示:
    [img=520,400]mkMSITStore:\OEM\工具\Keymake\KEYMAKE.CHM::/6.GIF[/img]
      可以看到这与上面的反汇编代码基本相同。点击编译就可以很容易的得到一个zcj了。
      生成的zcj如下图所示(这只是我写的外观,你也可以自行修改):
    [img=279,238]mkMSITStore:\OEM\工具\Keymake\KEYMAKE.CHM::/4.GIF[/img]
      !!!需要说明的是因为这只是我写的一个模板,所以我也在程序中使用了几个变量。
       请不要再重复声明:hCursorHandle、hInstance、hIcon、hTempEbp、hInput、hMode以免出错。
       还有就是你一定要在指令结束时令EAX指向正确的注册码地址。
      2.这种算注册码的方法不是直接从用户所输入的序列号来计算注册码的,所以并不适用于所有情况。有时我们可能需要根据用户所填入的序列号来计算注册码。考虑到这种情况所以我在程序初使时令EAX指向第一个编辑框(也就是输入序列号的窗口)收到用户输入的数据,令EBX指向第二个编辑框收到用户输入的数据,令ECX指向第三个编辑框收到用户输入的数据。你如果要对用户输入的序列号或用户名等信息进行操作,那么可以就对EAX、EBX、ECX进行操作。
      下面的代码是本例根据用户所填入的序列号来计算注册码的方法:
    MOV ECX,EAX; EAX指向用户输入的八位序列号,现在暂将它移动到ECX寄存器
    XOR EBX,EBX; 以下是一段典型的将内存中的ASCII码转换为十六进制代码。
    n1:
    MOVZX EAX,BYTE PTR [ECX]
    OR AL,AL
    JZ n3
    CMP AL,3Ah
    JC n2
    SUB AL,7
    n2:
    SUB AL,30h
    SHL EBX,4
    ADD EBX,EAX
    INC ECX
    JMP n1
    n3:; 我想以上的一段代码应该懂汇编就能写的出(如果不是很明白,那么你对我编写好的zcj用TRW调试一次就知道了)。
    PUSH EBX; 最后的十六进制结果都保存在寄存器EBX中
    ; 将EBX入栈,这是为了将EBX寄存器的数据保存起来。因为经过CPUID这个指令后EBX的值将被修改。然后后面就和上面一样照抄程序中的指令。以下计算注册码的方法很简短。但在实际的PJ过程中,程序的算法可能会相当复杂。这就需要你通过调试或反汇编将关键的运算指令都找出来,再写进来。
    MOV EAX,1
    CPUID
    POP ECX; 恢复EBX的值到ECX寄存器,开始计算注册码
    XOR EDX,EDX
    MUL ECX
    ADD EAX,EDX; 下面的指令指的是输出格式,除了“%1X”可以修改,其他的请照抄
    PUSH EAX
    LEA EAX,a3; 令EAX指向a3,也就是指向字符“%1X”。%1X"指的是输出数据的格式,你会C语言就肯定懂了
    PUSH EAX
    LEA EAX,a4
    PUSH EAX
    CALL wsprintfA
    LEA EAX,a4
    ; 令EAX指向a4。因为程序最后显示的就是EAX寄存器所指向的内存地址的数据。
    下图分别是采用方案二和方案三编译后的窗口界面:
    [img=279,267]mkMSITStore:\OEM\工具\Keymake\KEYMAKE.CHM::/8.GIF[/img]  [img=279,274]mkMSITStore:\OEM\工具\Keymake\KEYMAKE.CHM::/7.GIF[/img]
      以下几个是进制转换函数和我加入的部分自定义函数,你也可以在编写zcj的过程中调用它们(使用时千万不要把大小写弄错了,对这部分函数以后会不断扩充)。
    atodw    将十进制的内存ASCII数值转换为数据元素
      使用格式:invoke atodw,指向存放内存数值的缓冲区
    htodw    将十六进制的内存ASCII数值转换为数据元素
      使用格式:invoke htodw,指向存放内存数值的缓冲区
    MakeCrypt  对内存缓冲区数据进行加密
      使用格式:invoke MakeCrypt,指向要加密的字符缓冲区,指向接收加密后的字符缓冲区
    UnMakeCrypt 对内存缓冲区数据进行解密
      使用格式:invoke UnMakeCrypt,指向要解密的字符缓冲区,指向接收解密后的字符缓冲区
    wsprintf   使用给定格式格式化数据元素
      使用格式:invoke wsprintf,指向存储输出的字符缓冲区,指向以空值结尾的包含格式化选项的字符串,指向一个数据元素列表
      数据格式化选项:%d,%i  有符号十进制数值
              %ld,%li 长的有符号十进制整数值
              %u    无符号十进制整数值
              %lu   长的无符号十进制整数值
              %x,%X  十六进制整数值,%x输出小写,%X输出大写
              %lx,%lX 长的十六进制整数值,%lx输出小写,%lX输出大写
              #    0x字符串的前缀数据,一般在显示十六进制值时使用
              精度修饰符——小数点后跟一个数,指定复制到输出缓冲区数字的最小数目。如果给定数字位数小于精度指定位数,域中用0填充,默认情况从左边填充。假如给定精度“.10”,数“3.14”复制到输出缓冲区后变为“00000003.14”

    如无特别说明或已经指定了输出位置在Win32程序中所有的结果都返回在eax中。

    使用举例一:比如要将内存中的十进制数值“12345678”转换为十六进制,输出结果以0x为前缀,再进行加密。
    数据区:
    szXor16 db "%#lX",0
    szNum10 db "12345678",0
    szBuffer db 50 dup (0)
    szOutMem db 50 dup (0)
    代码区:
    invoke atodw,addr szNum10  ;这一句是将内存中的数值12345678当做十进制转换为数据元素,返回的结果在eax中,那么eax=bc614e
    invoke wsprintf,addr szBuffer,addr szXor16,eax  ;这一句是将eax中的值以十六进制大写输出到内存szBuffer位置。
    invoke MakeCrypt,addr szBuffer,addr szOutMem  ;这一句是将指向内存szBuffer的数据加密后输出到内存szOutMem的位置。

    使用举例二:比如要将内存中的十六进制数值“ABCDEF”转换为十进制,输出长度为20位数,再进行解密。
    数据区:
    szXor10 db "%1.20u",0
    szNum16 db "ABCDEF",0
    szBuffer db 50 dup (0)
    szOutMem db 50 dup (0)
    代码区:
    invoke htodw,addr szNum16  ;这一句是将内存中的数值ABCDEF当做十六进制转换为数据元素,返回的结果在eax中,那么eax=abcdef
    invoke wsprintf,addr szBuffer,addr szXor10,eax  ;这一句是将eax中的值以十进制输出到内存szBuffer位置。
    invoke UnMakeCrypt,addr szBuffer,addr szOutMem  ;这一句是将指向内存szBuffer的数据解密后输出到内存szOutMem的位置。

      3.如果你不采用这种方法编写那么也可以使用程序中的另一个功能“另类zcj”。它和CrackCode2000一样,也是通过拦截程序指令并显示出注册码。 我之所以再写一个是因为以前的CrackCode2000提供的拦截选项非常有限,而且也不对宽字符串(一般出现在VB程序中用00将ASCII码分隔开)提供支持,还有一个毛病是在有些程序中会出现莫名的非法操作或无法获得注册码的情况(就好比这个例子程序)。 另外它的界面也太简陋了,只是一个消息框。所以我用汇编写了这个另类zcj非常小巧,它最多可以设置99个断点(其实可以更多,但好象没这个必要),以及在每个断点处中断多少次,以key.exe为例,设置如下图所示:
    对于以上界面的说明:
      ⑴、程序名称和中断地址的设置,这个我想用不着多说,会调试的人都懂。中断次数,即指在该位置连续中断多少次。第一字节,就是将当前设置的中断位置处反汇编后的第一个字节(可通过在调试窗口中输入code on看到)。指令长度就是当前中断位置反汇编后的长度。
      ⑵、获取注册码的方式上需要说明一下,我是这样考虑的:寄存器方式-因为注册码可能是会放在寄存器中比较,并且可能经过十进制或十六进制的转换,所以就提供了一个寄存器方式及十进制或十六进制的选项。
      ⑶、内存方式-是指:如设置为EDX,即指注册码保存在EDX所指向的内存地址中(而不是寄存器里)。
      ⑷、偏移地址-这就是说:比如注册码是在eax+64的位置,那么现在就可以在偏移地址处填入64(如果是eax-64,就填入-64)。
      ⑸、宽字符串-一般在VB程序中出现,用00将ASCII码分隔开。
      ⑹、内存单元-比如说注册码你在[EAX]处看到1a,2b,3c,4d,并且它就是注册码,你就可以使用这个选项。
      ⑺、地址指针-但是如果eax+64处的值是123456,而123456里的值又是654321,654321所指向的地址才是注册码所在呢,有位网友向我提出了这个问题,所以加入了一个“地址指针”(不知这种情况该怎么形容,只好用这个词了),现在你就可以根据自己的需要进行设置了。比如说如果你要从654321里取注册码,就不要选择地址指针;如果你要从123456里取注册码就选择地址指针,并将其值设置为1;如果你要从eax+64里取注册码就选择地址指针,并将其值设置为2。有了这个功能以后就可以尽量避免使用直接内存地址。因为Win2000/XP对内存的分配与Win98不同,直接指定内存地址很容易出错。
      ⑻、经过加壳-现在许多程序都用aspack、upx等工具进行了压缩,这个功能就是针对这类程序。
      ⑼、修改内存主要是对于一些需要经过修改内存中的数据后,才会出现注册窗口或才能正常注册的程序。
      ⑽、如果生成的zcj出现错误,你可以在制作前点击全部重置,将所有数据置零。
      ⑾、配置方案是让你可以对每一次的设置进行保存,免得日后不记得了,又得到处找资料。
      ⑿、在左边窗口处也设置保存注册码信息,是因为程序可能对注册码分次进行比较。   可以自定义在弹出的对话框中将显示的主页、邮件、窗口标题和启动提示,还可以自定义图标如下图所示:
      生成的zcj有三个可选界面如下图所示:


      !!!需要说明的一点是这个对话框只在拦截成功的时候出现。
      4.除此之外还有一个制作PJ补丁的附加工具,制作界面如图所示。
      完成后有两个可选界面如下图所示。
      
    最后一个功能就是内存补丁,用于对某些有自校验功能,或经过压缩后很难脱壳的程序。
    假设在内存中或用W32DASM反汇编后看到的代码如下:

    :0049729D 50    PUSH EAX
    :0049729E 6A04   PUSH 4
    :004972A0 FF153810 CALL _vbaFreeVarList
    :004972A6 83C414  ADD ESP,14
    :004972A9 6685F6  TEST SI,SI
    :004972AC 7407   JZ 004972B5

      经过自己的测试后知道如果在004972AC处跳转后就显示为注册版了,也就是说将JZ 004972B5改为JMP 004972B5即可。在程序该处JZ 004972B5对应的机器码是7407,那么JMP 004972B5对应的机器码是什么呢?你如果不知道JMP 004972B5对应的机器码是什么,就请在调试窗口中程序运行到该处时输入a,然后再输入JMP 4972B5,看看左边窗口中的机器码都变成什么了。或者直接使用一个叫机器代码查询器的工具查询一下就可以知道了。
    在这一例中JMP 4972B5对应的机器码是EB07,那么就可以在内存补丁制作窗口中作如下设置:

    修改地址:4972AC
    修改长度:1
    原始指令:74
    修改指令:EB

    你可以用附带的例子程序试试。
    楼主热帖
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    奋斗
    2021-8-1 11:40
  • 签到天数: 510 天

    [LV.9]以坛为家II

    发表于 2015-10-2 17:42:38 | 显示全部楼层
    楼主大爱  但是基础太差看的一头雾水!!!!!!111
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    郁闷
    前天 14:15
  • 签到天数: 2438 天

    [LV.Master]伴坛终老

    发表于 2009-12-17 19:54:39 | 显示全部楼层
    这个没有一定基础的话,是没办法学会的!
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    擦汗
    13 小时前
  • 签到天数: 1291 天

    [LV.10]以坛为家III

    发表于 2009-12-17 20:00:00 | 显示全部楼层
    晕倒.现在那个软件有这么简单.改个跳转就注册成功了....
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    开心
    10 小时前
  • 签到天数: 4850 天

    [LV.Master]伴坛终老

    发表于 2009-12-17 20:07:32 | 显示全部楼层
    看来我到了50岁也学不会,还是买别人现成的吧。
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    开心
    2011-11-24 11:44
  • 签到天数: 20 天

    [LV.4]偶尔看看III

    发表于 2009-12-17 20:10:18 | 显示全部楼层
    这个东西的确不错,有机会和时间学习一下
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    奋斗
    2021-10-12 18:15
  • 签到天数: 849 天

    [LV.10]以坛为家III

    发表于 2009-12-17 20:31:05 | 显示全部楼层
    只要能追到真正的注册码,内存zcj应该也会写了
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    奋斗
    2017-1-27 22:06
  • 签到天数: 342 天

    [LV.8]以坛为家I

    发表于 2009-12-17 21:37:07 | 显示全部楼层
    楼上的现在软件部好真正的追到注册码啊!希望和你能交流下
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    开心
    前天 14:25
  • 签到天数: 3009 天

    [LV.Master]伴坛终老

    发表于 2009-12-17 21:39:05 | 显示全部楼层
    看了老半天还是不能理解,革命尚未成功,还需继续努力
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    开心
    2013-1-1 18:46
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    发表于 2009-12-17 22:05:50 | 显示全部楼层
    图片全是红x,打不开都
    启用邀请码注册,提高发帖质量,建设交流社区
  • TA的每日心情
    开心
    2022-1-14 21:23
  • 签到天数: 1499 天

    [LV.10]以坛为家III

    发表于 2009-12-24 19:46:43 | 显示全部楼层
    的确是博大精深的东西,看得有些头晕呐
    启用邀请码注册,提高发帖质量,建设交流社区
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    快速回复 返回顶部 返回列表