Sendige 发表于 2016-7-17 19:33

一个简单的keygen me算法分析

潜水吾爱很久了,第一次发帖,有什么错误的欢迎指正!!!

这个文章是自己原创的,如有雷同纯属巧合!!



上面的check hardecoded 这个就不跟了,非常的简单我们要跟的是下面那个 name/serial check

这个程序应该是用汇编写的,因为入口是push 0

BP GetWindowTextA下这个断点可以跟踪到关键算法

004015E5|.8BEC          mov ebp,esp
004015E7|.6A 20         push 0x20                              ; /Count = 20 (32.)
004015E9|.68 42324000   push Splish.00403242                     ; |Buffer = Splish.00403242
004015EE|.FF75 0C       push                            ; |hWnd = 000102F0 (class='Edit',parent=000202E4)
004015F1|.E8 34010000   call <jmp.&USER32.GetWindowTextA>      ; \GetWindowTextA
004015F6|.85C0          test eax,eax                           ;获取注册码长度
004015F8|.0F84 95000000 je Splish.00401693                     ;如果注册码码等于空则跳
004015FE|.A3 67344000   mov dword ptr ds:,eax          ;注册码长度
00401603|.6A 0B         push 0xB                                 ; /Count = B (11.)
00401605|.68 36324000   push Splish.00403236                     ; |name
0040160A|.FF75 08       push                            ; |hWnd = 000202E8 (class='Edit',parent=000202E4)
0040160D|.E8 18010000   call <jmp.&USER32.GetWindowTextA>      ; \GetWindowTextA
00401612|.85C0          test eax,eax                           ;获取name长度
00401614|.74 68         je short Splish.0040167E
00401616|.A3 63344000   mov dword ptr ds:,eax          ;name长度
0040161B|.33C9          xor ecx,ecx
0040161D|.33DB          xor ebx,ebx
0040161F|.33D2          xor edx,edx
00401621|.8D35 36324000 lea esi,dword ptr ds:          ;name
00401627|.8D3D 58324000 lea edi,dword ptr ds:

我们先看程序最后的比较, 它循环判断的次数是name的长度

004016A8|> \8D35 4D324000 lea esi,dword ptr ds:         指向name得出的结果Y
004016AE|.8D3D 58324000 lea edi,dword ptr ds:         指向serial得出的结果T
004016B4|.33DB          xor ebx,ebx
004016B6|>3B1D 63344000 /cmp ebx,dword ptr ds:         ;对比name长度
004016BC|.74 0F         |je short Splish.004016CD
004016BE|.0FBE041F      |movsx eax,byte ptr ds:
004016C2|.0FBE0C1E      |movsx ecx,byte ptr ds:
004016C6|.3BC1          |cmp eax,ecx                              Y和T对比
004016C8|.75 18         |jnz short Splish.004016E2                  不相等就挂
004016CA|.43            |inc ebx                                       ebx+1
004016CB|.^ EB E9         \jmp short Splish.004016B6

00401632|> /0FBE041E      /movsx eax,byte ptr ds:         ;逐个指向name
00401636|. |99            |cdq
00401637|. |F7F9          |idiv ecx                              ;name的16进制除以ecxecx=10 49/10=4....9
00401639|. |33D3          |xor edx,ebx                              edx和ebx异或
0040163B|. |83C2 02       |add edx,0x2                           ;余数+2
0040163E|. |80FA 0A       |cmp dl,0xA                                 
00401641|. |7C 03         |jl short Splish.00401646                ;少于A
00401643|. |80EA 0A       |sub dl,0xA                              ;dl-A
00401646|> |88141F      |mov byte ptr ds:,dl            ;余数1
00401649|. |43            |inc ebx
0040164A|. |3B1D 63344000 |cmp ebx,dword ptr ds:         ;循环name的长度次数
00401650|.^\75 E0         \jnz short Splish.00401632

小结:

name指向每个字符串记为namestr

namestr÷10   余数记为X

xor edx,ebx这里的ebx 每次自增1 ebx设为S

X和 S+1 异或

X+2 =Y

如果Y少于10

则直接跳向

mov byte ptr ds:,Y

否则

Y-10

mov byte ptr ds:,Y

例子:

name第一个为ASCII “1”hex数据是3110进制就是49

49/10=4......9

9和0异或 还是等于9

9+2=11

11》10

∴ 11-10=1

S=S+1

最后1 给

00401669|> /0FBE041E      /movsx eax,byte ptr ds:         ;逐个指向假码
0040166D|. |99            |cdq
0040166E|. |F7F9          |idiv ecx                              ;假码的16进制除以ecxecx=10 49/10=4....9
00401670|. |88141F      |mov byte ptr ds:,dl            ;余数2
00401673|. |43            |inc ebx
00401674|. |3B1D 67344000 |cmp ebx,dword ptr ds:         ;循环假码的长度
0040167A|.^\75 ED         \jnz short Splish.00401669

假码指向每个字符串记为 Serialstr

Serialstr÷10余数记为 T

movsx byte ptr ds:,T

所以要符合 Y=T    》》》注册成功

例子:

因为现在我们要计算得出Y=T

上面得出Y=1所以T也是等于1

然后就有以下算式

10T+T=11
11/10=1....1

刚好符合,这个条件有很多

例如: 51/10=5....1
         
是吧,这个公式成立的条件有很多,自己发挥想象。。。

所以 51/10=5...1这个得出51记住51是 10进制转换成16进制是3333是字符串 “3”

所以得出 namne 的1对应 serial 的3

name :12345678

1 3 5 3 9 3 5 3   Y
3 + 7 ! c ! 7 !   T

所以

name:12345678
注册码为:3+7!c!7!



附上易语言源码,代码写的很挫,将就看着吧{:1_936:}



最后附上 keygenme和算法的易语言源码

苏紫方璇 发表于 2016-7-19 21:45

楼主分析得不错   附件下来学习下。。

Sound 发表于 2016-7-20 11:45

Hmily 发表于 2016-7-19 17:42
@Sendige 文章我给你编辑了下,多用代码框方便阅读,第一篇技术文章给予精华鼓励,期待更多分析。

下次记得精华帖回复下。

yvhkchao 发表于 2016-7-17 20:17

这个.......没看懂!!!支持一下!!!

朱朱你堕落了 发表于 2016-7-17 22:35

本帖最后由 hahacker 于 2016-7-17 22:42 编辑

膜拜师傅。学习了。楼主可否用C写个注册机? E不会。

Hmily 发表于 2016-7-19 17:42

@Sendige 文章我给你编辑了下,多用代码框方便阅读,第一篇技术文章给予精华鼓励,期待更多分析。

wnagzihxain 发表于 2016-7-19 17:47

打注释是个好习惯,分析的很详细

Sendige 发表于 2016-7-19 19:23

Hmily 发表于 2016-7-19 17:42
@Sendige 文章我给你编辑了下,多用代码框方便阅读,第一篇技术文章给予精华鼓励,期待更多分析。

谢谢老大

Hmily 发表于 2016-7-20 17:00

Sound 发表于 2016-7-20 11:45
下次记得精华帖回复下。

{:1_937:}我又忘了。。。

jjjackup 发表于 2016-7-20 17:04

分析的很详细。
页: [1] 2 3 4 5 6 7 8 9
查看完整版本: 一个简单的keygen me算法分析