Mysoft 发表于 2006-8-4 15:25:51

TNT也是一种不错的方法。

888999 发表于 2006-9-28 17:17:51

呵呵~~~~~~~~~~~~~~

spc_cll 发表于 2006-9-29 10:59:18

注册信息就保存在那同名的lic文件里了,只是被加密了。
可以自己造一个这样的大小相等的文件,看程序什么时候读写这个lic文件,然后分析他的判断是否注册的程序就行了。

62261280 发表于 2006-10-2 19:30:11

虽然提示注册成功.但还是没有注册成功!!

char1204 发表于 2006-10-9 17:17:36

几乎看不懂哦……

hch686 发表于 2006-10-10 01:07:42

这个好象是个没爆破完全的

yunfeng 发表于 2006-10-10 06:43:37

标 题: 【原创】魔术手数码相片处理软件:nEO iMAGING 注册算法分析和注册机(C#)
作 者: qiweixue
时 间: 2006-10-02,20:04
链 接: http://bbs.pediy.com/showthread.php?threadid=32775

魔术手数码相片处理软件:neo imaging”是一个对数码照片画质进行改善及效果处理的软件。简单、易用,不需要任何专业的图象技术,就可以制作出专业胶片摄影的色彩效果~ “neo imaging”
官方网站:http://www.neoimaging.cn/
版本0.20,
由于没有上网,分析该软件纯熟巧合(从一个同学那里拷贝的),最新版本的0.22版本的没有时间再看了,应该都查不多的.
软件加壳,弱壳.脱壳.
Broland Delphi 6.0-7.0编译
开始分析:
第一步骤:获取机器码函数:

说明:根据关键 call <sub_5028BC>函数获取唯一本地码,如果它小于10个字符,就把机器码用另个全局字符常量代替.
string 005DC3D0是保存注册码地址
string 005A5424 ="nEO iMAGING"

005A526D|.8D45 E4       lea   eax,
005A5270|.E8 47D6F5FF   call    <sub_5028BC>--------->关键获取本地机器码的函数,看下边分析.
005A5275|.8B55 E4       mov   edx, --->返回字符串:76481-640-1153263-23182.
005A5278|.B8 D0C35D00   mov   eax, 005DC3D0--------->保存机器码地址的全局变量
005A527D|.E8 4EFAE5FF   call    <@System@@LStrAsg$qqrpvpxv>
005A5282|.A1 D0C35D00   mov   eax,
005A5287|.E8 B0FCE5FF   call    <@@LStrLen_Or_DynArrayLength$qqr>
005A528C|.83F8 0A       cmp   eax, 0A------------>大于10个字符就跳
005A528F|.7D 0F         jge   short <loc_5A52A0>
005A5291|.B8 D0C35D00   mov   eax, 005DC3D0
005A5296|.BA 24545A00   mov   edx, <dword_5A5424> ---->全局字符常量:nEO iMAGING            
005A529B|.E8 30FAE5FF   call    <@System@@LStrAsg$qqrpvpxv>------>给机器码赋予新串

call    <sub_5028BC>--------->关键获取本地机器码的函数
说明:这个函数是获取注册表项HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\ProductID的数据,
这个数据是Window OS 注册产品ID号的数据,它具有本地唯一性
吾XP OS注册ID号: 76481-640-1153263-23182.
005028BC >/$55            push    ebp
005028BD|.8BEC          mov   ebp, esp
005028BF|.51            push    ecx
005028C0|.53            push    ebx
005028C1|.8BD8          mov   ebx, eax
005028C3|.8BC3          mov   eax, ebx
005028C5|.E8 B223F0FF   call    <@System@@LStrClr$qqrpv>
005028CA|.B2 01         mov   dl, 1
005028CC|.A1 0C354400   mov   eax, [<off_44350C>]
005028D1|.E8 360DF4FF   call    <@Registry@TRegistry@$bctr$qqrv>----->构造TRegistry对象
005028D6|.8945 FC       mov   , eax
005028D9|.33C0          xor   eax, eax
005028DB|.55            push    ebp
005028DC|.68 28295000   push    <sub_502928>
005028E1|.64:FF30       push    dword ptr fs:
005028E4|.64:8920       mov   fs:, esp
005028E7|.BA 02000080   mov   edx, 80000002
005028EC|.8B45 FC       mov   eax,
005028EF|.E8 B80DF4FF   call    <@Registry@TRegistry@SetRootKey$qqr>---->获取根注册表项:HKEY_LOCAL_MACHINE的句柄
005028F4|.33C9          xor   ecx, ecx
005028F6|.BA 3C295000   mov   edx, <aSoftwareMicros> ----->全局字符常量: "Software\Microsoft\Windows\CurrentVersion"
005028FB|.8B45 FC       mov   eax,
005028FE|.E8 110EF4FF   call    <@Registry@TRegistry@OpenKey$qqrx17>
00502903|.8BCB          mov   ecx, ebx
00502905|.BA 70295000   mov   edx, <aProductid>   --------->全局字符常量: ASCII "ProductID"
0050290A|.8B45 FC       mov   eax,
0050290D|.E8 AA11F4FF   call    <@Registry@TRegistry@ReadString$qqr>--->根据以上参数读取出注册项字符串数据
00502912|.33C0          xor   eax, eax
00502914|.5A            pop   edx
00502915|.59            pop   ecx
00502916|.59            pop   ecx
00502917|.64:8910       mov   fs:, edx
0050291A|.68 2F295000   push    <loc_50292F>
0050291F >|>8B45 FC       mov   eax,
00502922|.E8 2115F0FF   call    <@System@TObject@Free$qqrv>------>析构注册对象
00502927\.C3            retn------------------>函数返回

-------------------------------------------------------------------------------------------------------------------------------
76481-640-1153263-23182
第二步骤:校验注册信息

说明:程序每一次启动都要从本地目录下的注册文件中:nEOiMAGING.lic读取注册信息.它的内部结构与*.ini结构相同,结构如下:

SN=vosmhusa---------->注册用户名
SC=647<4;1<9=03677045500:------>注册码
注意:nEOiMAGING.lic信息被加密处理了,这并不是真正用户输入的注册信息.这里要先解码注册信,再校验其正确.
解码的时候要与本机器码相互运算.
解码关键函数是:void call <sub_502310>(string eax,string ecx,string edx);ecx是返回值,
当用户名和注册码解码完毕(用户名:qiweixue,注册码:1234567890123456787312),再经过关键注册算法函数call    <sub_5B1150>.请看下边分析:
--------------------------------------------------------
用户名局部变量:string ="vosmhusa"
注册码局部变量:string ="647<4;1<9=03677045500:"
解码用户名变量:string ="qiweixue"
解码注册码变量:string ="1234567890123456789012"
全局机器码指针:PCHAR *="76481-640-1153263-23182"
005A8BE8   .55            push    ebp
005A8BE9   .68 288D5A00   push    <loc_5A8D28>
005A8BEE   .64:FF30       push    dword ptr fs:
005A8BF1   .64:8920       mov   fs:, esp
005A8BF4   .6A 00         push    0
005A8BF6   .8D45 E4       lea   eax,
005A8BF9   .50            push    eax--->返回值地址
005A8BFA   .B9 E08E5A00   mov   ecx, <dword_5A8EE0> ----->字符串:ASCII "SC"
005A8BFF   .BA EC8E5A00   mov   edx, <off_5A8EEC>   ------->字符串:ASCII "LIC"
005A8C04   .8B45 E8       mov   eax,
005A8C07   .8B18          mov   ebx,
005A8C09   .FF13          call    -------->内部调用API:GetPrivateProfileStringA获取注册码节字符串
005A8C0B   .8B45 E4       mov   eax, ---->SC=647<4;1<9=03677045500:
005A8C0E   .8D4D F0       lea   ecx, ------>返回值地址
005A8C11   .8B15 C0395C00 mov   edx, ----->机器码指针地址         
005A8C17   .8B12          mov   edx,
005A8C19   .E8 F296F5FF   call    <sub_502310>------------>关键解码函数,解码注册码字符串,下边有解释.
005A8C1E   .8B45 F0       mov   eax,
005A8C21 > .E8 16C3E5FF   call    <@@LStrLen_Or_DynArrayLength$qqrv>--->获取注册码长度
005A8C26   .83F8 16       cmp   eax, 16------>不大于16个字符串就over
005A8C29   .0F8C E3000000 jl      <loc_5A8D12>--->跳就game over
005A8C2F   .6A 00         push    0
005A8C31   .8D45 D8       lea   eax,
005A8C34   .50            push    eax--->x--->返回值地址
005A8C35   .B9 F88E5A00   mov   ecx, <dword_5A8EF8>   ----->字符串: ASCII "SN"
005A8C3A   .BA EC8E5A00   mov   edx, <off_5A8EEC>   ----->字符串: ASCII "LIC"
005A8C3F   .8B45 E8       mov   eax,
005A8C42   .8B18          mov   ebx,
005A8C44   .FF13          call    ---->-------->内部调用API:GetPrivateProfileStringA获取注册用户节字符串
005A8C46   .8B45 D8       mov   eax, ----->SN=vosmhusa
005A8C49   .8D4D DC       lea   ecx, --->返回值地址
005A8C4C   .8B15 C0395C00 mov   edx, ----->机器码指针地址   
005A8C52   .8B12          mov   edx,
005A8C54   .E8 B796F5FF   call    <sub_502310>------------>关键解码函数,解码用户名字符串,下边有解释.
005A8C59   .8B55 DC       mov   edx, --->解码的用户注册名:qiweixue
005A8C5C   .8D4D E0       lea   ecx, --->返回值地址
005A8C5F   .8B45 FC       mov   eax, --->主窗体对象指针.
005A8C62   .E8 E9840000   call    <sub_5B1150>----->关键注册算法函数
005A8C67   .8B45 E0       mov   eax, --->正确注册码返回结果
005A8C6A   .50            push    eax--------------------->正确注册码关键之处压栈
005A8C6B   .8D45 D4       lea   eax,
005A8C6E   .50            push    eax---->返回结果
005A8C6F   .B9 04000000   mov   ecx, 4
005A8C74   .BA 13000000   mov   edx, 13
005A8C79   .8B45 F0       mov   eax, ----------->解码注册码变量:string ="1234567890123456787312"
005A8C7C > .E8 1BC5E5FF   call    <@System@@LStrCopy$qqrv>--->提取注册码的最后4个字符
005A8C81   .8B55 D4       mov   edx, ---->注册码的最后4个字符:7312
005A8C84   .58            pop   eax---->弹出正确的注册码:7312
005A8C85 > .E8 FEC3E5FF   call    <@System@@LStrCmp$qqrv>--->相互比较
005A8C8A   .0F85 82000000 jnz   <loc_5A8D12>--->注意:这里是关键跳.跳了说明注册码不对,没有跳要再提取注册码第12个字符开始的
8个字符,例如:string ="1234567890123456787312",提取的8位字符是:12345678.与机器编进行三次乱码处理,好象以下是程序功能的相关
释放.因为已经通过注册关键跳,和具体注册算法关联不是很大.下边程序表示的意思很模糊,愿意分析自己分析.简单说明1下:


005A8C90   .8D45 F0       lea   eax, --->注册码string ="1234567890123456787312"
005A8C93   .50            push    eax--->返回地址
005A8C94   .B9 08000000   mov   ecx, 8--->提取8个
005A8C99   .BA 0B000000   mov   edx, 0B---->从第12个字符开始
005A8C9E   .8B45 F0       mov   eax,
005A8CA1 > .E8 F6C4E5FF   call    <@System@@LStrCopy$qqrv> --->拷贝提取的字符串:12345678
005A8CA6   .33DB          xor   ebx, ebx--->清零
005A8CA8 > >8D85 CCFEFFFF lea   eax,
005A8CAE   .50            push    eax
005A8CAF   .8BD3          mov   edx, ebx
005A8CB1   .03D2          add   edx, edx--->注意ebx是地址指针记数,与下边地址005A8D0C呼应.要进行三次地址累加
005A8CB3   .A1 C0395C00   mov   eax, --->机器码指针
005A8CB8   .8B00          mov   eax, --->机器码变量:76481-640-1153263-23182.
005A8CBA   .B9 04000000   mov   ecx, 4--->提取4个字符
005A8CBF > .E8 D8C4E5FF   call    <@System@@LStrCopy$qqrv>--->第一次拷贝提取的字符串:7648,
005A8CC4   .8B95 CCFEFFFF mov   edx,
005A8CCA   .8D8D D0FEFFFF lea   ecx,
005A8CD0   .8B45 F0       mov   eax,
005A8CD3   .E8 3896F5FF   call    <sub_502310>--->
005A8CD8   .8B95 D0FEFFFF mov   edx,
005A8CDE   .8D85 D4FEFFFF lea   eax,
005A8CE4   .B9 FF000000   mov   ecx, 0FF
005A8CE9 > .E8 2AC2E5FF   call    <@System@@LStrToString$qqrv> -->字符串特殊处理.
005A8CEE   .8D95 D4FEFFFF lea   edx,
005A8CF4   .8BC3          mov   eax, ebx
005A8CF6   .C1E0 05       shl   eax, 5
005A8CF9   .2BC3          sub   eax, ebx
005A8CFB   .8B4D FC       mov   ecx, ----->主窗体对象地址
005A8CFE   .8D8401 A90900>lea   eax, ------>关键对象字段
005A8D05   .B1 1E         mov   cl, 1E
005A8D07 > .E8 ACA5E5FF   call    <@System@@PStrNCpy$qqrp28System@_Sm>--->function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar;
005A8D0C   .43            inc   ebx--->
005A8D0D   .83FB 03       cmp   ebx, 3------->三次变换才退出,看下边内存,出现三组诡异的数字.
005A8D10   .^ 75 96         jnz   short <loc_5A8CA8>
005A8D12 > >33C0          xor   eax, eax
005A8D14   .5A            pop   edx
005A8D15   .59            pop   ecx
005A8D16   .59            pop   ecx
005A8D17   .64:8910       mov   fs:, edx
005A8D1A   .68 2F8D5A00   push    <loc_5A8D2F>
005A8D1F > >8B45 E8       mov   eax,
005A8D22 > .E8 21B1E5FF   call    <@System@TObject@Free$qqrv>   ---->析构对象
005A8D27   .C3            retn
00FC64E908 36 34 37 3C 32 30 33 30 00 00 00 00 00 00 00647<2030.......
00FC64F900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08...............
00FC650937 36 3B 34 33 32 3F 38 00 00 00 00 00 00 00 0076;432?8........
00FC651900 00 00 00 00 00 00 00 00 00 00 00 00 00 08 39..............9
00FC652932 3E 32 3D 36 3A 3E 00 00 00 00 00 00 00 00 002>2=6:>.........


解码关键函数是:void call <sub_502310>(string eax,string ecx,string edx);ecx是返回值,
这个函数很有意思,负责把用户输入的名:qiweixue和机器码,乱码成:vosmiusa和注册码:1234567890123456789012和机器码,乱码成:647<4;1<9=03677045500:
当程序启动的时候,它又负责把nEOiMAGING.lic文件中乱码vosmiusa和机器码解析为:qiweixue和把乱码647<4;1<9=03677045500和机器码:解析成:1234567890123456789012
从而达到注册信息迷惑,不散播,从而确定软件注册唯一化.
分析如下:
00502310 >/$55            push    ebp
00502311|.8BEC          mov   ebp, esp
00502313|.83C4 F0       add   esp, -10
00502316|.53            push    ebx
00502317|.56            push    esi
00502318|.57            push    edi
00502319|.894D F4       mov   , ecx         
0050231C|.8955 F8       mov   , edx----->机器码:76481-640-1153263-23182
0050231F|.8945 FC       mov   , eax-----> 用户名或者是密码
00502322|.8B45 FC       mov   eax,
00502325|.E8 022EF0FF   call    <@System@@LStrAddRef$qqrpv> -->字符串引用
0050232A|.8B45 F8       mov   eax,
0050232D|.E8 FA2DF0FF   call    <@System@@LStrAddRef$qqrpv> --->字符串引用
00502332|.33C0          xor   eax, eax
00502334|.55            push    ebp
00502335|.68 DA235000   push    <sub_5023DA>
0050233A|.64:FF30       push    dword ptr fs:
0050233D|.64:8920       mov   fs:, esp
00502340|.837D F8 00    cmp   dword ptr , 0 ---> 是机器编码
00502344|.75 0D         jnz   short <loc_502353>
00502346|.8D45 F8       lea   eax,       ---> eax 返回参数
00502349|.BA F0235000   mov   edx, <dword_5023F0>   -->ASCII "nEO iMAGING"
0050234E|.E8 C129F0FF   call    <@System@@LStrLAsg$qqrpvpxv>    -->ystem.@LStrLAsg(void;void;void;void);
00502353 >|>BE 01000000   mov   esi, 1--->初始化计数器esi=1
00502358|.8B45 FC       mov   eax,       --> 用户名或者是密码
0050235B|.E8 DC2BF0FF   call    <@@LStrLen_Or_DynArrayLength$qqr>--->System.@LStrLen(String):Integer;
00502360|.8BF8          mov   edi, eax   --->用户名或者是密码的长度
00502362|.85FF          test    edi, edi
00502364|.7E 4E         jle   short <loc_5023B4>
00502366|.BB 01000000   mov   ebx, 1--->初始化计数器ebx=1
0050236B >|>8B45 FC       /mov   eax,    ---> 用户名和密码或者是带加工的字符串
0050236E|.8A4418 FF   |mov   al, --->逐次把字节给al
00502372|.24 0F         |and   al, 0F---->与0F与运算      
00502374|.8B55 F8       |mov   edx,
00502377|.8A5432 FF   |mov   dl, --->逐次把机器码给dl
0050237B|.80E2 0F       |and   dl, 0F-->与0F与运算
0050237E|.32C2          |xor   al, dl--->相互异或
00502380|.8845 F3       |mov   , al    ---> 放到
00502383|.8D45 FC       |lea   eax,           --->用户名和密码
00502386|.E8 092EF0FF   |call    <j_@InternalUniqueString$qqrrv_>
0050238B|.8B55 FC       |mov   edx, ---> 用户名和密码或者是带加工的字符串
0050238E|.8A541A FF   |mov   dl, --->--->逐次把字节给dl
00502392|.80E2 F0       |and   dl, 0F0--->---->与0F0与运算   
00502395|.8A4D F3       |mov   cl,
00502398|.02D1          |add   dl, cl--->互加
0050239A|.885418 FF   |mov   , dl
0050239E|.46            |inc   esi
0050239F|.8B45 F8       |mov   eax,
005023A2|.E8 952BF0FF   |call    <@@LStrLen_Or_DynArrayLength$qq>;System.@LStrLen(String):Integer;
005023A7|.3BF0          |cmp   esi, eax
005023A9|.7E 05         |jle   short <loc_5023B0>
005023AB|.BE 01000000   |mov   esi, 1
005023B0 >|>43            |inc   ebx
005023B1|.4F            |dec   edi
005023B2|.^ 75 B7         \jnz   short <loc_50236B>
005023B4 >|>8B45 F4       mov   eax,       ---> eax 存放函数返回数值参数地址
005023B7|.8B55 FC       mov   edx,
005023BA|.E8 1129F0FF   call    <@System@@LStrAsg$qqrpvpxv>
005023BF|.33C0          xor   eax, eax
005023C1|.5A            pop   edx
005023C2|.59            pop   ecx
005023C3|.59            pop   ecx
005023C4|.64:8910       mov   fs:, edx
005023C7|.68 E1235000   push    <loc_5023E1>
005023CC >|>8D45 F8       lea   eax,
005023CF|.BA 02000000   mov   edx, 2
005023D4|.E8 C728F0FF   call    <@System@@LStrArrayClr$qqrpvi>---->析构机器码清理字符串
005023D9\.C3            retn




关键注册算法函数
call    <sub_5B1150>.(in string ,out string ),
这才是关键重重之处,前边都是为这里做铺垫的.功能是:把用户名qiweixue和机器码,经过乱码成vosmiusa,在根据vosmiusa计算出
一个整数,再把整数格式花成字符串,再再提取出注册码:1234567890123456789012的后四位,也就是从13位开始提取,最后相互比较,
如果相等就注册成功,否则就over.至于注册码前13位有可能作者在程序限制功能中使用(纯熟猜测).分析如下:

005B1150 >/$55            push    ebp
005B1151|.8BEC          mov   ebp, esp
005B1153|.83C4 E8       add   esp, -18
005B1156|.53            push    ebx
005B1157|.56            push    esi
005B1158|.33DB          xor   ebx, ebx
005B115A|.895D F4       mov   , ebx
005B115D|.895D F0       mov   , ebx
005B1160|.894D F8       mov   , ecx---->返回值地址
005B1163|.8955 FC       mov   , edx--->用户名:qiweixue
005B1166|.8B45 FC       mov   eax, --->主窗体对象
005B1169|.E8 BE3FE5FF   call    <@System@@LStrAddRef$qqrpv>--->引用用户名字符串
005B116E|.33C0          xor   eax, eax
005B1170|.55            push    ebp
005B1171|.68 47125B00   push    <sub_5B1247>
005B1176|.64:FF30       push    dword ptr fs:
005B1179|.64:8920       mov   fs:, esp
005B117C|.8B45 FC       mov   eax, --->--->用户名:qiweixue
005B117F|.E8 B83DE5FF   call    <@@LStrLen_Or_DynArrayLength$qqrv>-->求长度函数
005B1184|.83F8 04       cmp   eax, 4
005B1187|.7D 0D         jge   short <loc_5B1196>->大于4就跳,否则Over
005B1189|.8D45 F4       lea   eax,
005B118C|.E8 EB3AE5FF   call    <@System@@LStrClr$qqrpv>-->清返回地址为0
005B1191|.E9 83000000   jmp   <loc_5B1219>
005B1196 >|>8D4D F0       lea   ecx,
005B1199|.8B15 C0395C00 mov   edx, ---->机器码:76481-640-1153263-23182                     
005B119F|.8B12          mov   edx,
005B11A1|.8B45 FC       mov   eax, --->用户名
005B11A4|.E8 6711F5FF   call    <sub_502310>--->用户名和机器码相互处理
005B11A9|.8B45 F0       mov   eax, -->得到结果:"vosmiusa"
005B11AC|.E8 8B3DE5FF   call    <@@LStrLen_Or_DynArrayLength$qqrv>
005B11B1|.8BC8          mov   ecx, eax
005B11B3|.33DB          xor   ebx, ebx
005B11B5|.8BC1          mov   eax, ecx
005B11B7|.48            dec   eax
005B11B8|.85C0          test    eax, eax
005B11BA|.7C 14         jl      short <loc_5B11D0>--->如果小于0就跳
005B11BC|.40            inc   eax
005B11BD|.33D2          xor   edx, edx
005B11BF >|>8B75 F0       /mov   esi,
005B11C2|.0FB67416 FF   |movzx   esi, byte ptr --->逐次提取:vosmiusa
005B11C7|.0FAFF1      |imul    esi, ecx-->相互乘于其长度
005B11CA|.03DE          |add   ebx, esi--->相加
005B11CC|.42            |inc   edx
005B11CD|.48            |dec   eax
005B11CE|.^ 75 EF         \jnz   short <loc_5B11BF>
005B11D0 >|>81FB 0F270000 cmp   ebx, 270F---------->计算结果与270F比较
005B11D6|.7E 0E         jle   short <loc_5B11E6>
005B11D8|.8BC3          mov   eax, ebx
005B11DA|.B9 10270000   mov   ecx, 2710---->加2710
005B11DF|.99            cdq
005B11E0|.F7F9          idiv    ecx--->除以长度
005B11E2|.8BDA          mov   ebx, edx
005B11E4|.EB 0E         jmp   short <loc_5B11F4>
005B11E6 >|>81FB 28230000 cmp   ebx, 2328----------->结算结果与2328比较
005B11EC|.7D 06         jge   short <loc_5B11F4>
005B11EE|.81C3 E8030000 add   ebx, 3E8--->加3E8
005B11F4 >|>8D45 F0       lea   eax,
005B11F7|.50            push    eax    ---->返回值地址                           
005B11F8|.895D E8       mov   , ebx------->计算结果给                     
005B11FB|.C645 EC 00    mov   byte ptr , 0               
005B11FF|.8D55 E8       lea   edx,                      
005B1202|.33C9          xor   ecx, ecx                           
005B1204|.B8 5C125B00   mov   eax, <off_5B125C> --->参数"%4d"                  
005B1209|.E8 AE9AE5FF   call    <@Sysutils@Format$qqrx17System@Ansi>-->把整数格式为字符串
005B120E|.8D45 F4       lea   eax, ---->结果地址给eax
005B1211|.8B55 F0       mov   edx,
005B1214|.E8 FB3AE5FF   call    <@System@@LStrLAsg$qqrpvpxv>-->字符串相互赋值
005B1219 >|>8B45 F8       mov   eax, --->最终结果地址给eax
005B121C|.8B55 F4       mov   edx,
005B121F|.E8 AC3AE5FF   call    <@System@@LStrAsg$qqrpvpxv>-->字符串相互赋值
005B1224|.33C0          xor   eax, eax
005B1226|.5A            pop   edx
005B1227|.59            pop   ecx
005B1228|.59            pop   ecx
005B1229|.64:8910       mov   fs:, edx
005B122C|.68 4E125B00   push    <loc_5B124E>
005B1231 >|>8D45 F0       lea   eax,
005B1234|.BA 02000000   mov   edx, 2
005B1239|.E8 623AE5FF   call    <@System@@LStrArrayClr$qqrpvi>
005B123E|.8D45 FC       lea   eax,
005B1241|.E8 363AE5FF   call    <@System@@LStrClr$qqrpv>
005B1246\.C3            retn

到这里基本流程分析完毕,根据以上分析就可以写出一个注册机.这个程序的分析的方法不外乎两种顺序分析:根据程序启动的时候跟踪算法流程
.其次是逆向分析:根据注册窗口的事件,和交互信息找出算法分析.这里都可以的.我是采用顺序分析,因为这样写文章,个人爱好吧!
还有一点必须说明:就是输入注册窗体Edit控件中的机器码显示的是:#93;89 739#6?0<2?>,5:??<#,而我这里说的是内存中的机器码76481-640-1153263-23182,
Edit控件显示的是乱码是迷惑我们,当然可以解码就是用上边说的那个解码函数,真正用的是内存中那个格式清晰的机器码.


计算本地机器码源代码(C# .Net SDK 2.0编译)
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;
using System.Diagnostics;


namespace MachinePediy
{
    class Pediy
    {

      static void Main(string[] args)
      {
            string userStr = "nEO iMAGING";
            string machineStr;
            char[] userCode;
            char[] machineCode;
            byte code1 = 15;
            byte code2 = 240;
            RegistryKey RegKey = Registry.LocalMachine;
            RegKey = RegKey.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion");
            Object val = RegKey.GetValue("ProductId");
          // System.Console.WriteLine("Window OS ProductID:" + val);
            machineStr = ((String)val);
         
            userCode = userStr.ToCharArray();
            machineCode =machineStr.ToCharArray();

            for (int i = 0,j=0; i < machineStr.Length;i++,j++ )
            {
                byte a,b,c;
                if (j>=userStr.Length )
                {
                  j = 0;
                }
                a = (byte)machineCode;
                a=(byte)(a & code1);

                b = (byte)userCode;
                b = (byte)(b & code1);

                c = (byte)(a ^ b);

                a = (byte)machineCode;
                a = (byte)(a & code2);

                a = (byte)(a + c);
                machineCode =(char) a;
               
            
            }

            System.Console.Write("机器码:" + "#");
            for (int i = 0; i < machineStr.Length; i++)
            {
                System.Console.Write(machineCode);
            }
            System.Console.Write("#");
            System.Console.ReadLine();
         
      }
    }
}

计算注册码源代码:(C# .Net SDK 2.0编译)
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32;
using System.Diagnostics;


namespace Pediy
{
    class Pediy
    {

      static void Main(string[] args)
      {
            string machineStr;
            char[] machineCode;
            char[] userCode;
            byte code1 = 15;
            byte code2 = 240;
            Int32 key = 0;
            string keyStr = "76481-640-1153263-";

            RegistryKey RegKey = Registry.LocalMachine;
            RegKey = RegKey.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion");
            Object val = RegKey.GetValue("ProductId");
            // System.Console.WriteLine("Window OS ProductID:" + val);
            machineStr = ((String)val);

            if (machineStr.Length < 10)
            {
                machineStr = "nEO iMAGING";
            }
            machineCode = machineStr.ToCharArray();
      label: System.Console.WriteLine("请输入5-10个用户名字符");
            string userStr = System.Console.ReadLine();
            if (userStr.Length < 4)
            {
                System.Console.WriteLine("请输入5-10个用户名字符");
                goto label;
            }
            System.Console.WriteLine("用户名:" + userStr);
            userCode = userStr.ToCharArray();

            for (int i = 0, j = 0; i < userStr.Length; i++, j++)
            {
                byte a, b, c;
                if (j >= machineStr.Length)
                {
                  j = 0;
                }
                a = (byte)userCode;
                a = (byte)(a & code1);

                b = (byte)machineCode;
                b = (byte)(b & code1);

                c = (byte)(a ^ b);

                a = (byte)userCode;
                a = (byte)(a & code2);

                a = (byte)(a + c);
                userCode = (char)a;


            }

            // for(int i=0;i<userStr.Length;i++)
            //{
            //   System.Console.Write(userCode);
            //   }
            //   System.Console.WriteLine();

            for (int i = 0; i < userStr.Length - 1; i++)
            {
                int len = userStr.Length;
                Int32 a = 0;
                a = (byte)userCode;
                a = (Int32)(a * len);
                key = (a + key);

            }


            if (!(key <= 9999/*0x270F8*/))
            {
                key = key % 10000;
               
            }
            else if (!(key >= 9000/*0x2328*/))
            {
                key = key + 0x3E8;

            }

            string str = string.Format("{0:d4}", (UInt32)key);
            //    System.Console.WriteLine(str);
            if (((str.ToCharArray()).GetValue(0)).Equals('0'))
            {
                (str.ToCharArray()).SetValue(' ', 0);
            //str.Insert(0, " ");
            }
            System.Console.WriteLine("注册码:" + keyStr + str);
            System.Console.ReadLine();


      }
    }
}


注册机算法和机器码算法在自己机器上通过验证,没有时间在其他机器测试了,应该存在bug,大家多指点.源文件不用上传了,直接拷贝成.cs文件就可以编译,平台.Net 2.0
页: 1 [2]
查看完整版本: 一种比较麻烦的注册方式