魔术手数码相片处理软件: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, [ebp-1C]
005A5270  |.  E8 47D6F5FF   call    <sub_5028BC>--------->关键获取本地机器码的函数,看下边分析.
005A5275  |.  8B55 E4       mov     edx, [ebp-1C]--->返回字符串:76481-640-1153263-23182.
005A5278  |.  B8 D0C35D00   mov     eax, 005DC3D0--------->保存机器码地址的全局变量
005A527D  |.  E8 4EFAE5FF   call    <@System@@LStrAsg$qqrpvpxv>
005A5282  |.  A1 D0C35D00   mov     eax, [5DC3D0]
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     [ebp-4], eax
005028D9  |.  33C0          xor     eax, eax
005028DB  |.  55            push    ebp
005028DC  |.  68 28295000   push    <sub_502928>
005028E1  |.  64:FF30       push    dword ptr fs:[eax]
005028E4  |.  64:8920       mov     fs:[eax], esp
005028E7  |.  BA 02000080   mov     edx, 80000002
005028EC  |.  8B45 FC       mov     eax, [ebp-4]
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, [ebp-4]
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, [ebp-4]
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:[eax], edx
0050291A  |.  68 2F295000   push    <loc_50292F>
0050291F >|>  8B45 FC       mov     eax, [ebp-4]
00502922  |.  E8 2115F0FF   call    <@System@TObject@Free$qqrv>------>析构注册对象
00502927  \.  C3            retn------------------>函数返回

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

说明:程序每一次启动都要从本地目录下的注册文件中:nEOiMAGING.lic读取注册信息.它的内部结构与*.ini结构相同,结构如下:
[LIC]
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 [ebp-28]="vosmhusa"
注册码局部变量:string [ebp-1C]="647<4;1<9=03677045500:"
解码用户名变量:string [ebp-10]="qiweixue"
解码注册码变量:string [ebp-24]="1234567890123456789012"
全局机器码指针:PCHAR *[5C39C0]="76481-640-1153263-23182"
005A8BE8   .  55            push    ebp
005A8BE9   .  68 288D5A00   push    <loc_5A8D28>
005A8BEE   .  64:FF30       push    dword ptr fs:[eax]
005A8BF1   .  64:8920       mov     fs:[eax], esp
005A8BF4   .  6A 00         push    0
005A8BF6   .  8D45 E4       lea     eax, [ebp-1C]
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, [ebp-18]
005A8C07   .  8B18          mov     ebx, [eax]
005A8C09   .  FF13          call    [ebx]-------->内部调用API:GetPrivateProfileStringA获取注册码节字符串
005A8C0B   .  8B45 E4       mov     eax, [ebp-1C]---->SC=647<4;1<9=03677045500:
005A8C0E   .  8D4D F0       lea     ecx, [ebp-10]------>返回值地址
005A8C11   .  8B15 C0395C00 mov     edx, [5C39C0] ----->机器码指针地址           
005A8C17   .  8B12          mov     edx, [edx]
005A8C19   .  E8 F296F5FF   call    <sub_502310>------------>关键解码函数,解码注册码字符串,下边有解释.
005A8C1E   .  8B45 F0       mov     eax, [ebp-10]
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, [ebp-28]
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, [ebp-18]
005A8C42   .  8B18          mov     ebx, [eax]
005A8C44   .  FF13          call    [ebx]---->-------->内部调用API:GetPrivateProfileStringA获取注册用户节字符串
005A8C46   .  8B45 D8       mov     eax, [ebp-28]----->SN=vosmhusa
005A8C49   .  8D4D DC       lea     ecx, [ebp-24]--->返回值地址
005A8C4C   .  8B15 C0395C00 mov     edx, [5C39C0]----->机器码指针地址   
005A8C52   .  8B12          mov     edx, [edx]
005A8C54   .  E8 B796F5FF   call    <sub_502310>------------>关键解码函数,解码用户名字符串,下边有解释.
005A8C59   .  8B55 DC       mov     edx, [ebp-24]--->解码的用户注册名:qiweixue
005A8C5C   .  8D4D E0       lea     ecx, [ebp-20]--->返回值地址
005A8C5F   .  8B45 FC       mov     eax, [ebp-4]--->主窗体对象指针.
005A8C62   .  E8 E9840000   call    <sub_5B1150>----->关键注册算法函数
005A8C67   .  8B45 E0       mov     eax, [ebp-20]--->正确注册码返回结果
005A8C6A   .  50            push    eax--------------------->正确注册码关键之处压栈
005A8C6B   .  8D45 D4       lea     eax, [ebp-2C]
005A8C6E   .  50            push    eax---->返回结果
005A8C6F   .  B9 04000000   mov     ecx, 4
005A8C74   .  BA 13000000   mov     edx, 13
005A8C79   .  8B45 F0       mov     eax, [ebp-10]----------->解码注册码变量:string [ebp-24]="1234567890123456787312"
005A8C7C > .  E8 1BC5E5FF   call    <@System@@LStrCopy$qqrv>--->提取注册码的最后4个字符
005A8C81   .  8B55 D4       mov     edx, [ebp-2C]---->注册码的最后4个字符:7312
005A8C84   .  58            pop     eax---->弹出正确的注册码:7312
005A8C85 > .  E8 FEC3E5FF   call    <@System@@LStrCmp$qqrv>--->相互比较
005A8C8A   .  0F85 82000000 jnz     <loc_5A8D12>--->注意:这里是关键跳.跳了说明注册码不对,没有跳要再提取注册码第12个字符开始的
8个字符,例如:string [ebp-10]="1234567890123456787312",提取的8位字符是:12345678.与机器编进行三次乱码处理,好象以下是程序功能的相关
释放.因为已经通过注册关键跳,和具体注册算法关联不是很大.下边程序表示的意思很模糊,愿意分析自己分析.简单说明1下:


005A8C90   .  8D45 F0       lea     eax, [ebp-10]--->注册码string [ebp-10]="1234567890123456787312"
005A8C93   .  50            push    eax--->返回地址
005A8C94   .  B9 08000000   mov     ecx, 8--->提取8个
005A8C99   .  BA 0B000000   mov     edx, 0B---->从第12个字符开始
005A8C9E   .  8B45 F0       mov     eax, [ebp-10]
005A8CA1 > .  E8 F6C4E5FF   call    <@System@@LStrCopy$qqrv> --->拷贝提取的字符串:12345678
005A8CA6   .  33DB          xor     ebx, ebx--->清零
005A8CA8 > >  8D85 CCFEFFFF lea     eax, [ebp-134]
005A8CAE   .  50            push    eax
005A8CAF   .  8BD3          mov     edx, ebx
005A8CB1   .  03D2          add     edx, edx--->注意ebx是地址指针记数,与下边地址005A8D0C呼应.要进行三次地址累加
005A8CB3   .  A1 C0395C00   mov     eax, [5C39C0]--->机器码指针
005A8CB8   .  8B00          mov     eax, [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, [ebp-134]
005A8CCA   .  8D8D D0FEFFFF lea     ecx, [ebp-130]
005A8CD0   .  8B45 F0       mov     eax, [ebp-10]
005A8CD3   .  E8 3896F5FF   call    <sub_502310>--->
005A8CD8   .  8B95 D0FEFFFF mov     edx, [ebp-130]
005A8CDE   .  8D85 D4FEFFFF lea     eax, [ebp-12C]
005A8CE4   .  B9 FF000000   mov     ecx, 0FF
005A8CE9 > .  E8 2AC2E5FF   call    <@System@@LStrToString$qqrv> -->字符串特殊处理.
005A8CEE   .  8D95 D4FEFFFF lea     edx, [ebp-12C]
005A8CF4   .  8BC3          mov     eax, ebx
005A8CF6   .  C1E0 05       shl     eax, 5
005A8CF9   .  2BC3          sub     eax, ebx
005A8CFB   .  8B4D FC       mov     ecx, [ebp-4]----->主窗体对象地址
005A8CFE   .  8D8401 A90900>lea     eax, [ecx+eax+9A9]------>[ecx+eax+9A9]关键对象字段
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:[eax], edx
005A8D1A   .  68 2F8D5A00   push    <loc_5A8D2F>
005A8D1F > >  8B45 E8       mov     eax, [ebp-18]
005A8D22 > .  E8 21B1E5FF   call    <@System@TObject@Free$qqrv>   ---->析构对象
005A8D27   .  C3            retn
00FC64E9  08 36 34 37 3C 32 30 33 30 00 00 00 00 00 00 00  647<2030.......
00FC64F9  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08  ...............
00FC6509  37 36 3B 34 33 32 3F 38 00 00 00 00 00 00 00 00  76;432?8........
00FC6519  00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 39  ..............9
00FC6529  32 3E 32 3D 36 3A 3E 00 00 00 00 00 00 00 00 00  2>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     [ebp-C], ecx           
0050231C  |.  8955 F8       mov     [ebp-8], edx----->机器码:76481-640-1153263-23182
0050231F  |.  8945 FC       mov     [ebp-4], eax  -----> [ebp-4]用户名或者是密码
00502322  |.  8B45 FC       mov     eax, [ebp-4]
00502325  |.  E8 022EF0FF   call    <@System@@LStrAddRef$qqrpv> -->字符串引用[ebp-4]
0050232A  |.  8B45 F8       mov     eax, [ebp-8]
0050232D  |.  E8 FA2DF0FF   call    <@System@@LStrAddRef$qqrpv> --->字符串引用 [ebp-8] 
00502332  |.  33C0          xor     eax, eax
00502334  |.  55            push    ebp
00502335  |.  68 DA235000   push    <sub_5023DA>
0050233A  |.  64:FF30       push    dword ptr fs:[eax]
0050233D  |.  64:8920       mov     fs:[eax], esp
00502340  |.  837D F8 00    cmp     dword ptr [ebp-8], 0 ---> [ebp-8]是机器编码
00502344  |.  75 0D         jnz     short <loc_502353>
00502346  |.  8D45 F8       lea     eax, [ebp-8]      ---> 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, [ebp-4]      --> [ebp-4]用户名或者是密码
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, [ebp-4]   ---> [ebp-4] 用户名和密码或者是带加工的字符串
0050236E  |.  8A4418 FF     |mov     al, [eax+ebx-1]--->逐次把字节给al
00502372  |.  24 0F         |and     al, 0F  ---->与0F与运算        
00502374  |.  8B55 F8       |mov     edx, [ebp-8]
00502377  |.  8A5432 FF     |mov     dl, [edx+esi-1]--->逐次把机器码给dl
0050237B  |.  80E2 0F       |and     dl, 0F-->与0F与运算
0050237E  |.  32C2          |xor     al, dl--->相互异或
00502380  |.  8845 F3       |mov     [ebp-D], al    ---> 放到[ebp-D]
00502383  |.  8D45 FC       |lea     eax, [ebp-4]          --->  [ebp-4]用户名和密码
00502386  |.  E8 092EF0FF   |call    <j_@InternalUniqueString$qqrrv_>
0050238B  |.  8B55 FC       |mov     edx, [ebp-4]---> [ebp-4] 用户名和密码或者是带加工的字符串
0050238E  |.  8A541A FF     |mov     dl, [edx+ebx-1]--->--->逐次把字节给dl
00502392  |.  80E2 F0       |and     dl, 0F0--->---->与0F0与运算    
00502395  |.  8A4D F3       |mov     cl, [ebp-D]
00502398  |.  02D1          |add     dl, cl--->互加
0050239A  |.  885418 FF     |mov     [eax+ebx-1], dl
0050239E  |.  46            |inc     esi
0050239F  |.  8B45 F8       |mov     eax, [ebp-8]
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, [ebp-C]      ---> eax 存放函数返回数值参数地址
005023B7  |.  8B55 FC       mov     edx, [ebp-4]
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:[eax], edx
005023C7  |.  68 E1235000   push    <loc_5023E1>
005023CC >|>  8D45 F8       lea     eax, [ebp-8]
005023CF  |.  BA 02000000   mov     edx, 2
005023D4  |.  E8 C728F0FF   call    <@System@@LStrArrayClr$qqrpvi>---->析构机器码清理字符串
005023D9  \.  C3            retn




关键注册算法函数
call    <sub_5B1150>.(in string [ebp-4],out string [ebp-8]),
这才是关键重重之处,前边都是为这里做铺垫的.功能是:把用户名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     [ebp-C], ebx
005B115D  |.  895D F0       mov     [ebp-10], ebx
005B1160  |.  894D F8       mov     [ebp-8], ecx---->返回值地址
005B1163  |.  8955 FC       mov     [ebp-4], edx--->用户名:qiweixue
005B1166  |.  8B45 FC       mov     eax, [ebp-4]--->主窗体对象
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:[eax]
005B1179  |.  64:8920       mov     fs:[eax], esp
005B117C  |.  8B45 FC       mov     eax, [ebp-4]--->--->用户名: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, [ebp-C]
005B118C  |.  E8 EB3AE5FF   call    <@System@@LStrClr$qqrpv>-->清返回地址为0
005B1191  |.  E9 83000000   jmp     <loc_5B1219>
005B1196 >|>  8D4D F0       lea     ecx, [ebp-10]
005B1199  |.  8B15 C0395C00 mov     edx, [5C39C0] ---->机器码:76481-640-1153263-23182                     
005B119F  |.  8B12          mov     edx, [edx]
005B11A1  |.  8B45 FC       mov     eax, [ebp-4]--->用户名
005B11A4  |.  E8 6711F5FF   call    <sub_502310>--->用户名和机器码相互处理
005B11A9  |.  8B45 F0       mov     eax, [ebp-10]-->得到结果:"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, [ebp-10]
005B11C2  |.  0FB67416 FF   |movzx   esi, byte ptr [esi+edx-1]--->逐次提取: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, [ebp-10]
005B11F7  |.  50            push    eax    ---->返回值地址                            
005B11F8  |.  895D E8       mov     [ebp-18], ebx  ------->计算结果给[ebp-14]                     
005B11FB  |.  C645 EC 00    mov     byte ptr [ebp-14], 0                
005B11FF  |.  8D55 E8       lea     edx, [ebp-18]                       
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, [ebp-C]---->结果地址给eax
005B1211  |.  8B55 F0       mov     edx, [ebp-10]
005B1214  |.  E8 FB3AE5FF   call    <@System@@LStrLAsg$qqrpvpxv>-->字符串相互赋值
005B1219 >|>  8B45 F8       mov     eax, [ebp-8]--->最终结果地址给eax
005B121C  |.  8B55 F4       mov     edx, [ebp-C]
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:[eax], edx
005B122C  |.  68 4E125B00   push    <loc_5B124E>
005B1231 >|>  8D45 F0       lea     eax, [ebp-10]
005B1234  |.  BA 02000000   mov     edx, 2
005B1239  |.  E8 623AE5FF   call    <@System@@LStrArrayClr$qqrpvi>
005B123E  |.  8D45 FC       lea     eax, [ebp-4]
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[i];
                a=(byte)(a & code1);

                b = (byte)userCode[j];
                b = (byte)(b & code1);

                c = (byte)(a ^ b);

                a = (byte)machineCode[i];
                a = (byte)(a & code2);

                a = (byte)(a + c);
                machineCode[i] =(char) a;
               
            
            }

            System.Console.Write("机器码:" + "#");
            for (int i = 0; i < machineStr.Length; i++)
            {
                System.Console.Write(machineCode[i]);
            }
            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[i];
                a = (byte)(a & code1);

                b = (byte)machineCode[j];
                b = (byte)(b & code1);

                c = (byte)(a ^ b);

                a = (byte)userCode[i];
                a = (byte)(a & code2);

                a = (byte)(a + c);
                userCode[i] = (char)a;


            }

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

            for (int i = 0; i < userStr.Length - 1; i++)
            {
                int len = userStr.Length;
                Int32 a = 0;
                a = (byte)userCode[i];
                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


菩提本无树,明镜易非苔,本来无一物,何处惹尘埃