首页
社区
课程
招聘
利用程序原来的代码写注册机
发表于: 2006-8-30 16:21 16120

利用程序原来的代码写注册机

2006-8-30 16:21
16120

【文章标题】: 利用程序原来的代码写注册机
【文章作者】: laomms
【软件名称】: serial
【下载地址】: 看附件
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  有时候,懒得写注册机,就想把原来的程序中的部分汇编代码套用到高级语言中,于是找了KANXUE老大写的一个最简单的程序做了测试。事实证明,这也是非常繁琐的事情。这

个程序用高级语言写可能就一会儿,可是我用嵌入汇编的方式,却花了不少时间。既然已经做了,也就把步骤贴出来分享一下。
  算法核心部分:
  00401228   .  68 8E214000   PUSH 0040218E                            ;  用户名
  0040122D   .  E8 4C010000   CALL 0040137E                            ;  用户名算法
  00401232   .  50            PUSH EAX                                 ;  返回结果
  00401233   .  68 7E214000   PUSH 0040217E                            ;  注册码
  00401238   .  E8 9B010000   CALL 004013D8                            ;  注册码算法
  0040123D   .  83C4 04       ADD ESP,4                                ;  返回结果在EBX
  00401240   .  58            POP EAX                                  ;  弹出用户名计算结果
  00401241   .  3BC3          CMP EAX,EBX                              ;  比较是否相等,相等就成功
  00401243   .  74 07         JE SHORT 0040124C
  
  找到关键算法后我用Asm2Clipboard插件将CALL 0040137E里的汇编代码全部复制出来:
  
  用户名的算法CALL,它的过程是将每位注册码的ASCII码异或5678后相加,也就是注册码的ASCII的和异或5678。Asm2Clipboard复制的结果(附算法分析)。
  
   MOV ESI,DWORD PTR SS:[ESP+4]           //这里的ESP+4我们准备放入自己的用户名name
    PUSH ESI                               //压入注册码
  @002:
    MOV AL,BYTE PTR DS:[ESI]               //逐个取用户名ASCII
    TEST AL,AL                             //判断AL是否为0,即注册码是否取完,这个把它去掉
    JE @014                                //如果取完就跳到@014,去@014处看看
    CMP AL,41                              //是否大于41H,即大于“A”,要改为CMP AL,$41
    JB @019                                //没有就跳到@019提示,去@019处看看
    CMP AL,5A                              //是否大于5AH,即大于“Z”,这个要改成16进制形式:CMP AL,$5A
    JNB @011                               //如果大于就跳到@011进行变化,减20H转大写,去@011处看看
    INC ESI                                //取下一个注册码
    JMP @002                               //循环执行
  @011:
    CALL @035                              //呼叫@035处的代码,即将每位注册码的ASCII减20H,即小写转大写,我们直接把@035处的代码移过来放这里
    INC ESI                                //取下一个注册码
    JMP @002                               //重新跳到判断注册码的地方
  @014:
    POP ESI                                //注册码出栈
    CALL @026                              //执行@026处代码,是个寄存器清空操作,我们直接把@026处的代码移上来
    XOR EDI,5678                           //EDI=EDI XOR 5678
    MOV EAX,EDI                            //将结果存入EAX,这个EAX就是算法CALL的最终返回值,也就是我们要的结果
    JMP @025                               //跳到@025处,@025是个返回操作,就是退出整个算法CALL,我们去@025看看
  @019:
    POP ESI
    PUSH 30                                  //对话框样式。
    PUSH 00402160                            //对话框标题,改为自定义的标题,MOV EAX,DWORD PTR SS:[title],  PUSH EAX
    PUSH 00402169                            //对话框内容,改为自定义的内容,MOV EAX,DWORD PTR SS:[text],  PUSH EAX
    PUSH DWORD PTR SS:[EBP+8]                //对话框句柄,改为PUSH 0
    CALL <JMP.&USER32.MessageBoxA>           //MessageBox函数,改为CALL MessageBoxA
  @025:
    RETN                                     //这个返回就是整个算法过程完成后退出整个算法CALL。我们可以利用它,把结果转移到我们要的变量上,比如改为:MOV SN,

EAX
  @026:
    XOR EDI,EDI                              //EDI清空
    XOR EBX,EBX                              //EBX清空,EBX不能用,改用为:XOR ECX,ECX
  @028:
    MOV BL,BYTE PTR DS:[ESI]                 //逐个取注册码ASCII放入BL,BL改CL。
    TEST BL,BL                               //判断BL是否为0,即所有的注册码是否运算完毕,这个把它去掉,BL改CL
    JE @034                                  //如果取完了就跳到@034,@034只是一个返回操作,就是退出这个循环
    ADD EDI,EBX                              //EDI=EDI+EBX,EDI放着最终的结果,EBX改ECX
    INC ESI                                  //取下一位注册码
    JMP @028                                 //循环操作
  @034:
    RETN                                     //就是CALL @026返回操作,原程序是返回到@014中的XOR EDI,5678。所以我们可以把XOR EDI,5678划一个段落为@034,并把这

个删除掉
  @035:
    SUB AL,20                                //AL-20,AL放的是大于5A的字符
    MOV BYTE PTR DS:[ESI],AL                 //将结果放回段寄存器DS:[ESI]
    RETN                                     //这个返回,就是CALL @035的返回,原程序是返回到@002中INC ESI处。
  
  
  注册码的算法CALL,将注册码转成16进制值后异或1234:
  
    XOR EAX,EAX                       //EAX清空
    XOR EDI,EDI                       //EDI清空
    XOR EBX,EBX                       //EBX清空
    MOV ESI,DWORD PTR SS:[ESP+4]      //逐个取注册码ASCII
  @004:
    MOV AL,0A                         //0A赋值给AL,这句要改为MOV AL,$0A
    MOV BL,BYTE PTR DS:[ESI]          //逐个取出注册码ASCII放入BL
    TEST BL,BL                        //判断注册码是否取完      
    JE @013                           //取完就跳到@013
    SUB BL,30                         //注册码减30H,改SUB BL,30H
    IMUL EDI,EAX                      //EDI=EDI*EAX,EAX=0A
    ADD EDI,EBX                       //EDI=EDI+EBX,EDI为结果
    INC ESI                           //取下一位注册码
    JMP @004                          //循环
  @013:
    XOR EDI,1234                      //EDI异或1234
    MOV EBX,EDI                       //EDI的值送入EBX,EBX为最终的结果
    RETN
  
  程序要求这个两个值相等,也就是SUM(NAME)XOR 5678=HEX(serial)XOR 1234,异或是可以逆的,这个用高级语言来写非常简单serial=NAME XOR 5678 XOR 1234,也可以将

原来的程序改装成注册机。我这里想利用原来的代码做出注册机,所以只要将用户名的计算过程再加个异或1234即可,所以我在原先的代码中加入XOR EDI,$1234即可。将代码稍微

改了下,并加入一个对话框以便没有输入用户名时提示一下:
  
  其中NAME是用户名,SN是算法CALL的计算结果
  
    MOV ESI,DWORD PTR SS:[name]
    PUSH ESI
    JE @1                       //这里加入没有输入注册码时提示的对话框
    XOR EAX,EAX
  @002:
    MOV AL,BYTE PTR DS:[ESI]
    TEST AL,AL
    JE @014
    CMP AL,$41
    JB @019
    CMP AL,$5A
    JNB @011
    INC ESI
    JMP @002
  @011:
    SUB AL,$20                //这里提前了
    MOV BYTE PTR DS:[ESI],AL
    INC ESI
    JMP @002
  @014:
    POP ESI
    XOR EDI,EDI              //这里提前了
    XOR ECX,ECX
  @028:
    MOV CL,BYTE PTR DS:[ESI]
    TEST CL,CL
    JE @034
    ADD EDI,ECX
    INC ESI
    JMP @028
  @034:
    XOR EDI,$5678
    XOR EDI,$1234
    MOV EAX,EDI                           
    JMP @025     
  @019:                       //这里是提示用户名不能为数字
    push 0
    MOV EAX,DWORD PTR SS:[title]
    PUSH EAX
    MOV EAX,DWORD PTR SS:[text]
    PUSH EAX
    PUSH 0
    CALL MessageBox
    POP ESI
    JMP @2
  @1:                         //这是没有输入用户名的对话框提示
    push 0
    MOV EAX,DWORD PTR SS:[title]
    PUSH EAX
    MOV EAX,DWORD PTR SS:[text1]
    PUSH EAX
    PUSH 0
    CALL MessageBox
    POP ESI
    JMP @2
  @025:
    MOV SN,EAX
  @2:
  
  简直就是个汇编注册机了,呵呵。
  我这里套在DELPHI中,具体看附件。
  我觉得有时候拿程序的部分代码套在汇编中还是有一定的好处,特别是大数计算和位操作。
  我也希望有大虾出一篇专门介绍高级语言嵌入汇编的文章。
  
--------------------------------------------------------------------------------
【版权声明】: 没有任何技术, 大家见笑了, 谢谢!

                                                       2006年08月30日 16:19:32


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (19)
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
2
这文要支持啊。。。。。顶

用 C 写了一下;

#include<stdio.h>
#include<string.h>
main()
{
    int len,i,sum=0,sum1;
    char name[20];
    gets(name);
    len=strlen(name);
    for(i=0;i<len;i++)
    {
        sum1=name[i];
        sum1-=32;
        sum+=sum1;

    }
    sum=sum^0x5678^0x1234;
    printf("%d\n",sum);
}
2006-8-30 21:01
0
雪    币: 3689
活跃值: (4247)
能力值: (RANK:215 )
在线值:
发帖
回帖
粉丝
3
加精
2006-8-30 21:17
0
雪    币: 2871
活跃值: (2340)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
顶。
看不懂keymake当中是如何用汇编写的注册机。这个先学习。
2006-8-30 21:30
0
雪    币: 47147
活跃值: (20460)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
5
最初由 laomms 发布
于是找了KANXUE老大写的一个最简单的程序做了测试


laomms 文章思路清晰,这方法也很精彩
有一个笔误,这个CrackMe不是我的,是Cruehead/MiB写的。;)
2006-8-31 08:51
0
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
6
我发表一下自己的观点:
如果注册算法本身是用汇编写的,有很多类似异或,移位和取反等基本汇编指令那么用汇编做注册机很合适
如果用高级语言写的注册算法,算法是比较有逻辑性的,还是喜欢弄清作者原来的思路,这样对提高自己看算法的能力有提高

汗...感觉说了一堆废话
2006-8-31 10:28
0
雪    币: 1829
活跃值: (1377)
能力值: (RANK:50 )
在线值:
发帖
回帖
粉丝
7
我试过用IDA把代码提出来做dll,或者用Asm写注册机,把反汇编代码修改一下就可以用了,嵌入到高级语言修改量太大。难易程度还是要看加密的方式。
2006-8-31 11:55
0
雪    币: 249
活跃值: (10)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
8
以前写C、汇编对应的keygen都是利用原来的代码复制、修改而成的。

但如果是VB-Native程序,还能这么利用原来代码写吗?反正我没有尝试过
2006-8-31 13:16
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
9
最初由 学习 发布
顶。
看不懂keymake当中是如何用汇编写的注册机。这个先学习。


如果利用KEYMAKE就更简单了.
在数据中定义一些变量:
szHomePage db "http://bbs.pediy.com",0
szEmail    db "mailto:langxang@126.com",0
szErrMess  db "输入的序列号不正确!",0
szErrName  db "输入的必须为英文字母!",0
szFormat db "%d",0  ;将除数的注册码转为十进制字符格式
szBuff db 50 dup(0) ;定义50个字节的内存空间,用于保存注册码。

在代码窗口中写入:
    lea eax,hInput1
    XOR ESI,ESI
    MOV ESI,EAX         
    PUSH ESI   
    XOR EAX,EAX
  n2:
    MOV AL,BYTE PTR [ESI]
    TEST AL,AL
    JE n4
    CMP AL,41h
    JB n9
    CMP AL,5Ah
    JNB n1
    INC ESI
    JMP n2
  n1:
    SUB AL,20h               
    MOV BYTE PTR [ESI],AL
    INC ESI
    JMP n2
  n4:
    POP ESI
    XOR EDI,EDI              
    XOR ECX,ECX
  n8:
    MOV CL,BYTE PTR [ESI]
    TEST CL,CL
    JE n6
    ADD EDI,ECX
    INC ESI
    JMP n8
  n6:
    XOR EDI,5678h
    XOR EDI,1234h
    MOV EAX,EDI                           
    JMP n5     
  n9:                     
    lea eax,szErrName       ; 提示输入的必须为字母
  n5:
    invoke wsprintf,addr szBuff,addr szFormat,edi  ; 将注册码转10进制
    LEA EAX,szBuff          ; EAX指向注册码的框

编译后就是个算法注册机了.
上传的附件:
2006-8-31 13:44
0
雪    币: 209
活跃值: (47)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
学习一下!
2006-8-31 21:23
0
雪    币: 82
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
最初由 laomms 发布
如果利用KEYMAKE就更简单了.
在数据中定义一些变量:
szHomePage db "http://bbs.pediy.com",0
szEmail db "mailto:langxang@126.com",0
szErrMess db "输入的序列号不正确!",0
........

好方便的KeyMake。
2006-9-1 15:38
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
还是什么好用就用什么写把
高级语言里面嵌汇编觉得挺折腾的
不过原来见过有大牛写的C中嵌汇编
那叫一个牛啊
C方便的时候用C,汇编方便的时候用汇编
2006-9-1 17:01
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
支持,文章好!
2006-9-1 18:18
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
其实用c和c++语言写注册机还是蛮爽的。
如楼上所说,不但必要的时候可以嵌入汇编码;而且这2种语言可以很有效的模拟汇编算法:
汇编代码中的寄存器是32位的,那我们可以定义一个unsigned long类型的整型变量var,就可以代表该寄存器;另外很多运算符号也可以很方便的使用,例如:
AND eax, 5      就可以写成  (var | 5)  //unsigned long var = ax;
MOVSX eax,al    就可以写成   var = var1;  //unsigned long var = ax; int var1 = int(al);
2006-9-2 09:43
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
好文章  不顶对不起楼主
2006-9-2 14:21
0
雪    币: 338
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
强悍!!学习!
2006-9-2 15:33
0
雪    币: 1309
活跃值: (232)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
请教下楼主, 我也用Asm2Clipboard 复制了一下汇编代码, 但是复制出来的代码是这样的:

  jnb L004
  mov ecx, 2000
L004:
  SUB     ECX, 1
  cmp     ECX, 0

  就是复制出来的所有标号都是Lxxx 开头的, 和你例子中的@ 开头的不一样. Lxx 这样的用在delphi 里面有很大问题, 不象@ 一样不用声明, 所以对于大量的代码来说很是麻烦.

  请问你是如何复制出来是@ 开头标号的?
2006-9-22 21:25
0
雪    币: 716
活跃值: (162)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
18
看过lz的其他文章,LZ对原程序的代码的驾驭能力实在很强,学习了!!!
2006-9-22 23:03
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
19
最初由 deepwater 发布
请教下楼主, 我也用Asm2Clipboard 复制了一下汇编代码, 但是复制出来的代码是这样的:

jnb L004
mov ecx, 2000
L004:
........


DELPHI中内联汇编不支持L***,你可以用搜索替换的方法,将L0全部替换成@。
2006-10-16 06:14
0
雪    币: 312
活跃值: (27)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
DELPHI嵌入汇编有太多限制!不大方便!
我想还不如直接用RadAsm来的快!
2006-10-16 20:16
0
游客
登录 | 注册 方可回帖
返回
//