魔术手数码相片处理软件: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 菩提本无树,明镜易非苔,本来无一物,何处惹尘埃
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课