天上飞的鱼 发表于 2016-7-31 12:56:46

Pixel Editor 算法分析详解及易语言编写KeyGen

本帖最后由 天上飞的鱼 于 2016-7-31 12:58 编辑

这是一款像素图片制作软件,自己也挺喜欢用的,趁官网刚更新版本,所以赶紧来一发算法分析~
这次来款不是明码的算法分析,希望大家喜欢。{:soso__13496012817283154022_2:}

讲的不对的地方也欢迎指正,有什么问题也可以回帖留言,只要有时间都会来答复问题。

进入正题:

目标↓




通过PEID查壳 确定是 Borland Delphi 4.0 - 5.0,打开注册框随意输入用户名,EMAIL,注册码,点击出现,Wrong key..
简单粗暴的方法,直接搜索字符串,直接定位关键切入点。




通过双击来到了关键地方,然后从段首下段开始分析。

006AE334/$55            push ebp
006AE335|.8BEC          mov ebp,esp
006AE337|.B9 06000000   mov ecx,0x6
006AE33C|>6A 00         /push 0x0
006AE33E|.6A 00         |push 0x0
006AE340|.49            |dec ecx
006AE341|.^ 75 F9         \jnz short pixedit.006AE33C
006AE343|.53            push ebx
006AE344|.8BD8          mov ebx,eax
006AE346|.33C0          xor eax,eax
006AE348|.55            push ebp
006AE349|.68 BAE56A00   push pixedit.006AE5BA
006AE34E|.64:FF30       push dword ptr fs:
006AE351|.64:8920       mov dword ptr fs:,esp
006AE354|.8D55 E8       lea edx,
006AE357|.8B83 F8020000 mov eax,dword ptr ds:
006AE35D|.E8 3A8AD8FF   call pixedit.00436D9C
006AE362|.8B45 E8       mov eax,                        ;取注册码
006AE365|.8D55 F8       lea edx,
006AE368|.E8 23AFD5FF   call pixedit.00409290
006AE36D|.8D55 E4       lea edx,
006AE370|.8B83 00030000 mov eax,dword ptr ds:
006AE376|.E8 218AD8FF   call pixedit.00436D9C
006AE37B|.8B45 E4       mov eax,                        ;取邮箱
006AE37E|.8D55 F4       lea edx,
006AE381|.E8 0AAFD5FF   call pixedit.00409290
006AE386|.837D F8 00    cmp ,0x0                        ;注册码是否为空
006AE38A|.75 0C         jnz short pixedit.006AE398
006AE38C|.A1 B4397100   mov eax,dword ptr ds:
006AE391|.8B00          mov eax,dword ptr ds:
006AE393|.E8 20FFFFFF   call pixedit.006AE2B8
006AE398|>837D F4 00    cmp ,0x0                        ;邮箱是否为空
006AE39C|.75 16         jnz short pixedit.006AE3B4
006AE39E|.B9 D4E56A00   mov ecx,pixedit.006AE5D4               ;Please enter email used in your order
006AE3A3|.B2 01         mov dl,0x1
006AE3A5|.A1 04844000   mov eax,dword ptr ds:
006AE3AA|.E8 05E4D5FF   call pixedit.0040C7B4
006AE3AF|.E8 5C55D5FF   call pixedit.00403910
006AE3B4|>8B45 F8       mov eax,                        ;kernel32.7C816040
006AE3B7|.E8 885DD5FF   call pixedit.00404144
006AE3BC|.83F8 0A       cmp eax,0xA
006AE3BF|.7D 0C         jge short pixedit.006AE3CD               ;strlen>=10
006AE3C1|.A1 B4397100   mov eax,dword ptr ds:
006AE3C6|.8B00          mov eax,dword ptr ds:
006AE3C8|.E8 EBFEFFFF   call pixedit.006AE2B8
006AE3CD|>8D55 E0       lea edx,
006AE3D0|.8B83 F8020000 mov eax,dword ptr ds:
006AE3D6|.E8 C189D8FF   call pixedit.00436D9C                  ;strlen
006AE3DB|.8B45 E0       mov eax,
006AE3DE|.E8 C970EAFF   call pixedit.005554AC                  ;关键CALL
006AE3E3|.85C0          test eax,eax                           ;不等于0 则失败
006AE3E5|.74 0A         je short pixedit.006AE3F1
006AE3E7|.B8 04E66A00   mov eax,pixedit.006AE604               ;Wrong key.
006AE3EC|.E8 C7FEFFFF   call pixedit.006AE2B8
006AE3F1|>8B45 F8       mov eax,                        ;kernel32.7C816040
006AE3F4|.E8 1371EAFF   call pixedit.0055550C
006AE3F9|.8B93 08030000 mov edx,dword ptr ds:
006AE3FF|.8B45 F8       mov eax,                        ;kernel32.7C816040
006AE402|.E8 316FEAFF   call pixedit.00555338                  ;<-第二个关键CALLL
006AE407|.85C0          test eax,eax
006AE409|.74 0A         je short pixedit.006AE415
006AE40B|.B8 18E66A00   mov eax,pixedit.006AE618               ;Wrong key for this application.
006AE410|.E8 A3FEFFFF   call pixedit.006AE2B8
006AE415|>B2 01         mov dl,0x1
006AE417|.A1 34F64700   mov eax,dword ptr ds:
006AE41C|.E8 1313DDFF   call pixedit.0047F734
006AE421|.8945 F0       mov ,eax
006AE424|.33C0          xor eax,eax
006AE426|.55            push ebp
006AE427|.68 3BE56A00   push pixedit.006AE53B
006AE42C|.64:FF30       push dword ptr fs:
006AE42F|.64:8920       mov dword ptr fs:,esp
006AE432|.BA 01000080   mov edx,0x80000001
006AE437|.8B45 F0       mov eax,
006AE43A|.E8 D113DDFF   call pixedit.0047F810
006AE43F|.68 40E66A00   push pixedit.006AE640                  ;Software\
006AE444|.FFB3 0C030000 push dword ptr ds:
006AE44A|.68 54E66A00   push pixedit.006AE654                  ;\
006AE44F|.FFB3 10030000 push dword ptr ds:
006AE455|.68 54E66A00   push pixedit.006AE654                  ;\
006AE45A|.8D45 D8       lea eax,
006AE45D|.E8 E670EAFF   call pixedit.00555548
006AE462|.FF75 D8       push                         ;ntdll.7C930228
006AE465|.8D45 DC       lea eax,
006AE468|.BA 06000000   mov edx,0x6
006AE46D|.E8 925DD5FF   call pixedit.00404204
006AE472|.8B55 DC       mov edx,
006AE475|.B1 01         mov cl,0x1
006AE477|.8B45 F0       mov eax,
006AE47A|.E8 F913DDFF   call pixedit.0047F878
006AE47F|.8845 FF       mov byte ptr ss:,al
006AE482|.807D FF 00    cmp byte ptr ss:,0x0
006AE486|.0F84 99000000 je pixedit.006AE525
006AE48C|.8B4D F8       mov ecx,                        ;kernel32.7C816040
006AE48F|.BA 60E66A00   mov edx,pixedit.006AE660               ;Key
006AE494|.8B45 F0       mov eax,
006AE497|.E8 4018DDFF   call pixedit.0047FCDC
006AE49C|.BA 60E66A00   mov edx,pixedit.006AE660               ;Key
006AE4A1|.8D4D D4       lea ecx,
006AE4A4|.8B45 F0       mov eax,
006AE4A7|.E8 5C18DDFF   call pixedit.0047FD08
006AE4AC|.8B55 D4       mov edx,                     ;kernel32.7C816037
006AE4AF|.8B45 F8       mov eax,                        ;kernel32.7C816040
006AE4B2|.E8 9D5DD5FF   call pixedit.00404254
006AE4B7|.0F9445 FF   sete byte ptr ss:
006AE4BB|.E8 18C5D5FF   call pixedit.0040A9D8
006AE4C0|.83C4 F8       add esp,-0x8
006AE4C3|.DD1C24      fstp qword ptr ss:
006AE4C6|.9B            wait
006AE4C7|.BA 6CE66A00   mov edx,pixedit.006AE66C               ;Time
006AE4CC|.8B45 F0       mov eax,
006AE4CF|.E8 AC18DDFF   call pixedit.0047FD80
006AE4D4|.8B8B 14030000 mov ecx,dword ptr ds:
006AE4DA|.8B93 14030000 mov edx,dword ptr ds:
006AE4E0|.8B45 F0       mov eax,
006AE4E3|.E8 F417DDFF   call pixedit.0047FCDC
006AE4E8|.8D55 D0       lea edx,
006AE4EB|.8B83 EC020000 mov eax,dword ptr ds:
006AE4F1|.E8 A688D8FF   call pixedit.00436D9C
006AE4F6|.8B45 D0       mov eax,
006AE4F9|.8D55 EC       lea edx,
006AE4FC|.E8 8FADD5FF   call pixedit.00409290
006AE501|.837D EC 00    cmp ,0x0
006AE505|.8B4D EC       mov ecx,
006AE508|.BA 7CE66A00   mov edx,pixedit.006AE67C               ;UserName
006AE50D|.8B45 F0       mov eax,
006AE510|.E8 C717DDFF   call pixedit.0047FCDC
006AE515|.8B4D F4       mov ecx,                        ;kernel32.7C839B48
006AE518|.BA 90E66A00   mov edx,pixedit.006AE690               ;Email
006AE51D|.8B45 F0       mov eax,
006AE520|.E8 B717DDFF   call pixedit.0047FCDC
006AE525|>33C0          xor eax,eax
006AE527|.5A            pop edx                                  ;kernel32.7C816037
006AE528|.59            pop ecx                                  ;kernel32.7C816037
006AE529|.59            pop ecx                                  ;kernel32.7C816037
006AE52A|.64:8910       mov dword ptr fs:,edx               ;ntdll.KiFastSystemCallRet
006AE52D|.68 42E56A00   push pixedit.006AE542
006AE532|>8B45 F0       mov eax,
006AE535|.E8 1E4CD5FF   call pixedit.00403158
006AE53A\.C3            retn

首先是对注册码,邮箱,以及注册码进行判断,通过下图我们就可得知注册码,邮箱不能为空,注册码不能小于10位



再接下来看这里,明显Wrong key就在下面如果不跳则失败,那么就证明这个是关键跳,上面就是关键CALL了,我们要继续进CALL

006AE3CD|> \8D55 E0       lea edx,
006AE3D0|.8B83 F8020000 mov eax,dword ptr ds:
006AE3D6|.E8 C189D8FF   call pixedit.00436D9C                  ;strlen
006AE3DB|.8B45 E0       mov eax,
006AE3DE|.E8 C970EAFF   call pixedit.005554AC                  ;关键CALL
006AE3E3|.85C0          test eax,eax
006AE3E5|.74 0A         je short pixedit.006AE3F1
006AE3E7|.B8 04E66A00   mov eax,pixedit.006AE604               ;Wrong key.
006AE3EC|.E8 C7FEFFFF   call pixedit.006AE2B8
006AE3F1|>8B45 F8       mov eax,                        ;kernel32.7C816040

进CALL之后,发现这里代码非常简短,也没有任何计算过程,稍微分析一下,可以看到这里有个Sleep函数,难怪注册的时候会那么小卡一下,误导人以为网络验证,然后我们可以看到这个循环是一个ESI累加,段尾处我们依然可以看到mov eax,esi,那么明显我们可以很容易判断前面进CALL前要确保EAX为0才可注册成功,累加肯定就代表005554D5这个CALL里面又是一个关键CALL,结果必须依然EAX为0才可以。我们得继续跟进。


005554AC/$55            push ebp
005554AD|.8BEC          mov ebp,esp
005554AF|.51            push ecx
005554B0|.53            push ebx
005554B1|.56            push esi
005554B2|.8945 FC       mov ,eax
005554B5|.8B45 FC       mov eax,                        ;ASCII "abcdef0123456789"
005554B8|.E8 3BEEEAFF   call pixedit.004042F8
005554BD|.33C0          xor eax,eax
005554BF|.55            push ebp
005554C0|.68 FC545500   push pixedit.005554FC
005554C5|.64:FF30       push dword ptr fs:
005554C8|.64:8920       mov dword ptr fs:,esp
005554CB|.33F6          xor esi,esi
005554CD|.BB 0A000000   mov ebx,0xA
005554D2|>8B45 FC       /mov eax,                     ;ASCII "abcdef0123456789"
005554D5|.E8 6AFDFFFF   |call pixedit.00555244                   ;验证
005554DA|.03F0          |add esi,eax                           ;累加ESI
005554DC|.6A 64         |push 0x64                               ; /Timeout = 100. ms
005554DE|.E8 4D1FEBFF   |call <jmp.&kernel32.Sleep>            ; \Sleep
005554E3|.4B            |dec ebx
005554E4|.^ 75 EC         \jnz short pixedit.005554D2
005554E6|.33C0          xor eax,eax
005554E8|.5A            pop edx                                  ;kernel32.7C816037
005554E9|.59            pop ecx                                  ;kernel32.7C816037
005554EA|.59            pop ecx                                  ;kernel32.7C816037
005554EB|.64:8910       mov dword ptr fs:,edx               ;ntdll.KiFastSystemCallRet
005554EE|.68 03555500   push pixedit.00555503
005554F3|>8D45 FC       lea eax,
005554F6|.E8 C9E9EAFF   call pixedit.00403EC4
005554FB\.C3            retn
005554FC   .^ E9 D7E3EAFF   jmp pixedit.004038D8
00555501   .^ EB F0         jmp short pixedit.005554F3
00555503   .8BC6          mov eax,esi
00555505   .5E            pop esi                                  ;kernel32.7C816037
00555506   .5B            pop ebx                                  ;kernel32.7C816037
00555507   .59            pop ecx                                  ;kernel32.7C816037
00555508   .5D            pop ebp                                  ;kernel32.7C816037
00555509   .C3            retn

到了下面这段代码后,就可以看到应该是些算法了,然后继续分析..

00555244      55            push ebp
00555245      8BEC          mov ebp,esp
00555247      83C4 F4       add esp,-0xC
0055524A|.53            push ebx
0055524B|.56            push esi
0055524C|.33D2          xor edx,edx
0055524E|.8955 F4       mov ,edx
00555251|.8945 FC       mov ,eax
00555254|.8B45 FC       mov eax,                     
00555257|.E8 9CF0EAFF   call pixedit.004042F8
0055525C|.33C0          xor eax,eax
0055525E|.55            push ebp
0055525F|.68 FF525500   push pixedit.005552FF
00555264|.64:FF30       push dword ptr fs:
00555267|.64:8920       mov dword ptr fs:,esp
0055526A|.33C0          xor eax,eax
0055526C|.8945 F8       mov ,eax
0055526F|.8D55 F4       lea edx,
00555272|.8B45 FC       mov eax,                     ;ASCII "abcdef0123456789"
00555275|.E8 02FFFFFF   call pixedit.0055517C                   ;这里有个计算。回头再跟进
;*************************************上面字符做了次处理**********************************************************

0055527A|.8B55 F4       mov edx,                     
0055527D|.8D45 FC       lea eax,
00555280|.E8 D7ECEAFF   call pixedit.00403F5C
00555285|.8B45 FC       mov eax,                     ;ASCII "abcdef2345679"
00555288|.E8 B7EEEAFF   call pixedit.00404144
0055528D|.8BF0          mov esi,eax                           ;strlen>=7
0055528F|.83FE 07       cmp esi,0x7
00555292|.7D 09         jge short pixedit.0055529D
00555294|.C745 F8 0B000>mov ,0xB                     ;标志
0055529B|.EB 44         jmp short pixedit.005552E1
0055529D|>33DB          xor ebx,ebx
0055529F|.8B45 FC       mov eax,
005552A2|.E8 9DEEEAFF   call pixedit.00404144
005552A7|.48            dec eax
005552A8|.83E8 02       sub eax,0x2                           ;strlen-2
005552AB|.7C 14         jl short pixedit.005552C1
005552AD|.40            inc eax
005552AE|.BA 02000000   mov edx,0x2
005552B3|>8B4D FC       /mov ecx,                      ;ASCII "abcdef2345679"
005552B6|.0FB64C11 FF   |movzx ecx,byte ptr ds:    ;从第2位开始逐个取字
005552BB|.33D9          |xor ebx,ecx                            ;xor ebx
005552BD|.42            |inc edx
005552BE|.48            |dec eax
005552BF|.^ 75 F2         \jnz short pixedit.005552B3
005552C1|>8BC3          mov eax,ebx                           ;结果存给EAX
005552C3|.B9 1E000000   mov ecx,0x1E                            ;mod 1E == 30
005552C8|.99            cdq
005552C9|.F7F9          idiv ecx
005552CB|.42            inc edx                                 ;
005552CC|.B8 18535500   mov eax,pixedit.00555318                ;2345679qwertyupadfghjkzxcvbnms
005552D1|.8A4410 FF   mov al,byte ptr ds:      ;取第EDX值的字符
005552D5|.8B55 FC       mov edx,                     ;ASCII "abcdef2345679"
005552D8|.3A4432 FF   cmp al,byte ptr ds:      ;与最后一位比较
005552DC|.74 03         je short pixedit.005552E1
005552DE|.FF45 F8       inc                            ;pixedit.00452B0E
005552E1|>33C0          xor eax,eax
005552E3|.5A            pop edx
005552E4|.59            pop ecx
005552E5|.59            pop ecx
005552E6|.64:8910       mov dword ptr fs:,edx
005552E9|.68 06535500   push pixedit.00555306
005552EE|>8D45 F4       lea eax,
005552F1|.E8 CEEBEAFF   call pixedit.00403EC4
005552F6|.8D45 FC       lea eax,
005552F9|.E8 C6EBEAFF   call pixedit.00403EC4
005552FE\.C3            retn
005552FF   .^ E9 D4E5EAFF   jmp pixedit.004038D8
00555304   .^ EB E8         jmp short pixedit.005552EE
00555306   .8B45 F8       mov eax,dword ptr ss:          ;pixedit.00452B0E
00555309   .5E            pop esi
0055530A   .5B            pop ebx
0055530B   .8BE5          mov esp,ebp
0055530D   .5D            pop ebp
0055530E   .C3            retn

这里有一个CALL对我们得注册码进行了处理,所以这里暂时没看出明显规律,一会还得继续跟进..先做个标记,继续分析下面。



这里把计算出的结果位数比较是否小于7位,若小于标志位赋值为0xB,那肯定是失败,所以这里要注意下,上面CALL计算结果的是strlen>=7即可。



下面这段就是主要的算法,我们可以看到前面的mov edx,2,下面是常见的逐个取字,所以是从第2位开始取,取完与EBX进行异或,最后循环完与0x1E求余
然后最终的计算结果取余数为取表里的取值位置(说得有点绕,大家自己详细再看下),这里可以看到0x555318这个内存地址存放着一个表,就是取这个的那一位字符,与计算的结果
最后一位比较,如果相同则Local.2这时还会是0,不同则进行累加。


005552AE|.BA 02000000   mov edx,0x2
005552B3|>8B4D FC       /mov ecx,                     ;ASCII "abcdef2345679"
005552B6|.0FB64C11 FF   |movzx ecx,byte ptr ds:   ;从第2位开始逐个取字
005552BB|.33D9          |xor ebx,ecx                           ;xor ebx
005552BD|.42            |inc edx                                 ;ntdll.KiFastSystemCallRet
005552BE|.48            |dec eax
005552BF|.^ 75 F2         \jnz short pixedit.005552B3
005552C1|>8BC3          mov eax,ebx                              ;结果存给EAX
005552C3|.B9 1E000000   mov ecx,0x1E
005552C8|.99            cdq
005552C9|.F7F9          idiv ecx                                 ;mod 1E
005552CB|.42            inc edx                                  ;ntdll.KiFastSystemCallRet
005552CC|.B8 18535500   mov eax,pixedit.00555318               ;2345679qwertyupadfghjkzxcvbnms
005552D1|.8A4410 FF   mov al,byte ptr ds:         ;取计算结果的那一位字符
005552D5|.8B55 FC       mov edx,                        ;ASCII "abcdef2345679"
005552D8|.3A4432 FF   cmp al,byte ptr ds:         ;与最后一位比较
005552DC|.74 03         je short pixedit.005552E1
005552DE|.FF45 F8       inc                             ;累加

这个关键CALL就全部分析完毕了,然后我们再进之前对字符进行处理的CALL,进一步分析,看看它这个CALL到底是如何处理我们得注册码。

0055517C/$55            push ebp
0055517D|.8BEC          mov ebp,esp
0055517F|.83C4 F8       add esp,-0x8
00555182|.53            push ebx
00555183|.56            push esi
00555184|.33C9          xor ecx,ecx
00555186|.894D F8       mov ,ecx
00555189|.8BF2          mov esi,edx                           ;ntdll.KiFastSystemCallRet
0055518B|.8945 FC       mov ,eax
0055518E|.8B45 FC       mov eax,
00555191|.E8 62F1EAFF   call pixedit.004042F8
00555196|.33C0          xor eax,eax
00555198|.55            push ebp
00555199|.68 0C525500   push pixedit.0055520C
0055519E|.64:FF30       push dword ptr fs:
005551A1|.64:8920       mov dword ptr fs:,esp
005551A4|.8B45 FC       mov eax,                     ;ASCII "1234567890"
005551A7|.E8 98EFEAFF   call pixedit.00404144                   ;strlen
005551AC|.8BD8          mov ebx,eax
005551AE|.83FB 01       cmp ebx,0x1
005551B1|.7C 34         jl short pixedit.005551E7
005551B3|>8D45 F8       /lea eax,
005551B6|.8B55 FC       |mov edx,                      ;ASCII "1234567890"
005551B9|.8A541A FF   |mov dl,byte ptr ds:       ;倒取开始逐步取字
005551BD|.E8 AAEEEAFF   |call pixedit.0040406C                  ;<- unicode
005551C2|.8B45 F8       |mov eax,
005551C5|.BA 24525500   |mov edx,pixedit.00555224               ;2345679qwertyupadfghjkzxcvbnms
005551CA|.E8 61F2EAFF   |call pixedit.00404430                  ;是否存在
005551CF|.85C0          |test eax,eax                           ;存在,EAX == 表的第几位
005551D1|.75 0F         |jnz short pixedit.005551E2
005551D3|.8D45 FC       |lea eax,
005551D6|.B9 01000000   |mov ecx,0x1
005551DB|.8BD3          |mov edx,ebx
005551DD|.E8 AAF1EAFF   |call pixedit.0040438C                  ;去掉字符
005551E2|>4B            |dec ebx
005551E3|.85DB          |test ebx,ebx
005551E5|.^ 75 CC         \jnz short pixedit.005551B3             ;循环注册码长度
005551E7|>8BC6          mov eax,esi
005551E9|.8B55 FC       mov edx,
005551EC|.E8 27EDEAFF   call pixedit.00403F18
005551F1|.33C0          xor eax,eax
005551F3|.5A            pop edx                                 ;user32.77D29C7F
005551F4|.59            pop ecx                                 ;user32.77D29C7F
005551F5|.59            pop ecx                                 ;user32.77D29C7F
005551F6|.64:8910       mov dword ptr fs:,edx            ;ntdll.KiFastSystemCallRet
005551F9|.68 13525500   push pixedit.00555213
005551FE|>8D45 F8       lea eax,
00555201|.BA 02000000   mov edx,0x2
00555206|.E8 DDECEAFF   call pixedit.00403EE8
0055520B\.C3            retn
0055520C   .^ E9 C7E6EAFF   jmp pixedit.004038D8
00555211   .^ EB EB         jmp short pixedit.005551FE
00555213   .5E            pop esi                                 ;user32.77D29C7F
00555214   .5B            pop ebx                                 ;user32.77D29C7F
00555215   .59            pop ecx                                 ;user32.77D29C7F
00555216   .59            pop ecx                                 ;user32.77D29C7F
00555217   .5D            pop ebp                                 ;user32.77D29C7F
00555218   .C3            retn

从这里分析后,我们大体可以得到这个CALL就是把我们得注册码与表进行比对,把表里不存在的字符都去掉,组成新的字符串。



到这里,结合出CALL的前面分析,我们基本就可以把这个Wrong key给Pass了,然而如果以为这样就能注册成功那就错了-.-,因为我们回到最前面的wrong key再往下面看~




当我们看见wrong key 下面还有一句:Wrong key for this application,就知道....出现了第2个关键call,耐心把他再分析一下,因为我们已经成功了一半了,加油~undefined


00555338      55            push ebp
00555339      8BEC          mov ebp,esp
0055533B      33C9          xor ecx,ecx
0055533D      51            push ecx
0055533E|.51            push ecx
0055533F|.51            push ecx
00555340|.51            push ecx
00555341|.51            push ecx
00555342|.53            push ebx
00555343|.56            push esi
00555344|.8955 F8       mov ,edx
00555347|.8945 FC       mov ,eax
0055534A|.8B45 FC       mov eax,                     ;ASCII "feedexeopg"
0055534D|.E8 A6EFEAFF   call pixedit.004042F8
00555352|.8B45 F8       mov eax,                     ;ASCII "Pixel Editor"
00555355|.E8 9EEFEAFF   call pixedit.004042F8
0055535A|.33C0          xor eax,eax
0055535C|.55            push ebp
0055535D|.68 73545500   push pixedit.00555473
00555362|.64:FF30       push dword ptr fs:
00555365|.64:8920       mov dword ptr fs:,esp
00555368|.33F6          xor esi,esi
0055536A|.8D55 F0       lea edx,
0055536D|.8B45 FC       mov eax,                     ;ASCII "feedexeopg"
00555370|.E8 07FEFFFF   call pixedit.0055517C                   ;再次调用这个CALL
00555375|.8B55 F0       mov edx,                     ;ASCII "feedexepg"
00555378|.8D45 FC       lea eax,
0055537B|.E8 DCEBEAFF   call pixedit.00403F5C
00555380|.8B45 FC       mov eax,
00555383|.E8 BCEDEAFF   call pixedit.00404144
00555388|.83F8 07       cmp eax,0x7
0055538B|.7D 0A         jge short pixedit.00555397            ;strlen>=7
0055538D|.BE 0B000000   mov esi,0xB
00555392|.E9 C1000000   jmp pixedit.00555458
00555397|>837D F8 00    cmp ,0x0
0055539B|.0F84 B7000000 je pixedit.00555458
005553A1|.33DB          xor ebx,ebx
005553A3|.8B45 F8       mov eax,                     ;ASCII "Pixel Editor"
005553A6|.E8 99EDEAFF   call pixedit.00404144
005553AB|.48            dec eax                                 ;strlen
005553AC|.85C0          test eax,eax
005553AE|.7E 13         jle short pixedit.005553C3
005553B0|.BA 01000000   mov edx,0x1
005553B5|>8B4D F8       /mov ecx,                      ;循环"Pixel Editor"的长度-1
005553B8|.0FB64C11 FF   |movzx ecx,byte ptr ds:
005553BD|.03D9          |add ebx,ecx                            ;累加EBX
005553BF|.42            |inc edx
005553C0|.48            |dec eax
005553C1|.^ 75 F2         \jnz short pixedit.005553B5
005553C3|>8BC3          mov eax,ebx
005553C5|.B9 1E000000   mov ecx,0x1E                            ;EBX与1E MOD
005553CA|.99            cdq
005553CB|.F7F9          idiv ecx
005553CD|.42            inc edx
005553CE|.B8 8C545500   mov eax,pixedit.0055548C                ;2345679qwertyupadfghjkzxcvbnms
005553D3|.8A4410 FF   mov al,byte ptr ds:
005553D7|.8B55 FC       mov edx,
005553DA|.3A42 01       cmp al,byte ptr ds:            ;结果与newstr第2位 cmp
005553DD|.74 01         je short pixedit.005553E0
005553DF|.46            inc esi
005553E0|>8D55 F4       lea edx,
005553E3|.8B45 F8       mov eax,                     ;ASCII "Pixel Editor"
005553E6|.E8 6D3CEBFF   call pixedit.00409058                   ;<-转小写
005553EB|.8D45 EC       lea eax,
005553EE|.8B55 F4       mov edx,
005553F1|.8A12          mov dl,byte ptr ds:                ;取第一个小写字符p
005553F3|.E8 74ECEAFF   call pixedit.0040406C
005553F8|.8B45 EC       mov eax,                     ;comctl32.771BF26F
005553FB|.BA 8C545500   mov edx,pixedit.0055548C                ;2345679qwertyupadfghjkzxcvbnms
00555400|.E8 2BF0EAFF   call pixedit.00404430
00555405|.85C0          test eax,eax                            ;在表的第15位是p
00555407|.7E 11         jle short pixedit.0055541A
00555409|.8D45 FC       lea eax,
0055540C|.E8 03EFEAFF   call pixedit.00404314
00555411|.8B55 F4       mov edx,
00555414|.8A12          mov dl,byte ptr ds:
00555416|.8810          mov byte ptr ds:,dl                ;把p替换原始KEY的第一位
00555418|.EB 3E         jmp short pixedit.00555458
0055541A|>33DB          xor ebx,ebx
0055541C|.8B45 F8       mov eax,
0055541F|.E8 20EDEAFF   call pixedit.00404144
00555424|.48            dec eax
00555425|.85C0          test eax,eax
00555427|.7E 13         jle short pixedit.0055543C
00555429|.BA 01000000   mov edx,0x1
0055542E|>8B4D F8       /mov ecx,
00555431|.0FB64C11 FF   |movzx ecx,byte ptr ds:
00555436|.33D9          |xor ebx,ecx
00555438|.42            |inc edx
00555439|.48            |dec eax
0055543A|.^ 75 F2         \jnz short pixedit.0055542E
0055543C|>8BC3          mov eax,ebx
0055543E|.B9 1E000000   mov ecx,0x1E
00555443|.99            cdq
00555444|.F7F9          idiv ecx
00555446|.42            inc edx
00555447|.B8 8C545500   mov eax,pixedit.0055548C                ;2345679qwertyupadfghjkzxcvbnms
0055544C|.8A4410 FF   mov al,byte ptr ds:
00555450|.8B55 FC       mov edx,
00555453|.3A02          cmp al,byte ptr ds:
00555455|.74 01         je short pixedit.00555458
00555457|.46            inc esi
00555458|>33C0          xor eax,eax
0055545A|.5A            pop edx                                 ;0012F390
0055545B|.59            pop ecx                                 ;0012F390
0055545C|.59            pop ecx                                 ;0012F390
0055545D|.64:8910       mov dword ptr fs:,edx
00555460|.68 7A545500   push pixedit.0055547A
00555465|>8D45 EC       lea eax,
00555468|.BA 05000000   mov edx,0x5
0055546D|.E8 76EAEAFF   call pixedit.00403EE8
00555472\.C3            retn
00555473   .^ E9 60E4EAFF   jmp pixedit.004038D8
00555478   .^ EB EB         jmp short pixedit.00555465
0055547A   .8BC6          mov eax,esi
0055547C   .5E            pop esi                                 ;0012F390
0055547D   .5B            pop ebx                                 ;0012F390
0055547E   .8BE5          mov esp,ebp
00555480   .5D            pop ebp                                 ;0012F390
00555481   .C3            retn

这里依旧出现了之前我们刚分析过的对注册码处理的那个CALL。所以这里我们就没必要再分析了,知道这个套路了~



然后再下来这一段是不是很熟悉,跟前面的005554D5这个验证CALL基本一致,只是这次验证的不是注册码,是固定的ASCII "Pixel Editor"值进行计算,而且注意下图,EBX之前是xor,这次是进行累加




计算的结果依然是取固定的表值,而这里的字符串也是固定的,那么我们可以很简单得出,这里其实不需要去做太多分析,因为他始终得到的结果都是一样的。只需要注意的是他到底跟我们得注册码计算出来的那个字符串的第几位比较即可,下面图我们就可以看到,他取得的固定字符是"n",与计算注册码的字符串第2位比较。相同则跳过ESI累加。




接下来这里通过分析可以看到虽然这里对输入的注册码进行一系列的替换处理,但最终跳过了对ESI进行累加,flag是通过ESI赋值的,所以这个CALL只要保证处理注册码后的结果第2位是n字符即可满足条件,到此我们总算把所以的算法都分析完毕了。接下来我们来总结下编写KeyGen,怎么来具体构造Key。

1.注册码必须不小于10位。
2.通过分析我们取巧,只要第1位是表里存在的字符就不会被去除,那么注册码的第一位就应该是表里存在的任何一个字符,而第二位我们要满足第二个关键CALL,所以第二位为n字符。
3.通过第一个关键CALL的计算必须满足注册码处理后的字符串最后一位是关键CALL计算的结果。

写好后先算一下测试:
name: 飘云阁论坛
email:kkapskok@gmail.com
key:fnsbrqxspq





最后附上成品注册机与易语言注册机源码,写得比较搓,简单粗暴的写了一下,也没做简化,懒得再动脑了。
写这篇文章写了一个晚上,好累,谢谢大家耐心观看完,洗洗睡了~晚安 {:soso__8960193549861888490_2:}


wangwei1978 发表于 2016-7-31 20:35:26

厉害学习了

expasy 发表于 2016-7-31 22:41:29

2345679qwertyupadfghjkzxcvbnms 这个字符串好像见过

天上飞的鱼 发表于 2016-7-31 23:33:36

expasy 发表于 2016-7-31 22:41
2345679qwertyupadfghjkzxcvbnms 这个字符串好像见过

Perfect Icon 是不是这个软件见过? 反正这算法好像他的网站下的软件都大同小异的样子··

2016pygg 发表于 2016-8-1 08:41:15

大牛,写得很详细啊,辛苦了,多谢分享

chc591 发表于 2016-8-1 09:40:13

马克,学习分析算法

wzgangwzgang 发表于 2016-8-1 10:43:06

向楼主学习,!!!

expasy 发表于 2016-8-1 13:24:54

天上飞的鱼 发表于 2016-7-31 23:33
Perfect Icon 是不是这个软件见过? 反正这算法好像他的网站下的软件都大同小异的样子··

ahasoft 全系列
http://www.aha-soft.com/
好像都是这个
难道是同一个作者

天上飞的鱼 发表于 2016-8-1 15:50:22

expasy 发表于 2016-8-1 13:24
ahasoft 全系列
http://www.aha-soft.com/
好像都是这个


{:soso__13496012817283154022_2:}反正软柿子比较好虐点

gujin162 发表于 2016-8-1 21:03:43


膜拜神贴,后面的请保持队形~
页: [1] 2
查看完整版本: Pixel Editor 算法分析详解及易语言编写KeyGen