zjid520 发表于 2007-12-18 19:52:17

菜鸟学算法<三>算法分析篇

作者:鹭影依凌
转贴自:一蓑烟雨
声明:
1.以下内容都是个人在学习中的一些心得体会,写给新手的,高手飘过
2.文章难免有疏漏之处,欢迎各位兄弟批评指正
3.本文原创于UnPaKcN,如转载,请保持文章完整性


经过的前面两篇知识积累和过程分析,下面我们开始进行第三篇---算法分析

程序实例仍旧是Media-WorkShop

前文回顾
先来看看我们在第二篇的部分代码分析
;---------------------------<载入注册计算方案(一)>-------------------|
0046021C|.57            push    edi                              ;压栈(序列号)
0046021D|.55            push    ebp                              ;压栈(用户名)
0046021E|.E8 6DF9FFFF   call    0045FB90                         ;|*|注册算法<一>
00460223|.83C4 08       add   esp, 8
00460226|.85C0          test    eax, eax                         ;标志位测试
00460228|.75 0E         jnz   short 00460238                   ;//不跳则进入算法二
;---------------------------<载入注册计算方案(二)>-------------------|
0046022A|.57            push    edi                              ;压栈(序列号)
0046022B|.55            push    ebp                              ;压栈(用户名)
0046022C|.E8 8FFBFFFF   call    0045FDC0                         ;|*|注册算法<二>
00460231|.83C4 08       add   esp, 8
00460234|.85C0          test    eax, eax                         ;标志位测试
00460236|.74 0A         je      short 00460242                   ;//跳则挂
;---------------------------<标志位赋值(注册成功EAX=1)>--------------|
00460238|>5F            pop   edi
00460239|.5E            pop   esi
0046023A|.5D            pop   ebp
0046023B|.B8 01000000   mov   eax, 1                           ;标志位赋值:EAX = 1
00460240|.5B            pop   ebx
00460241|.C3            retn                                     ;//返回
;---------------------------<标志位赋值(注册失败EAX=0)>--------------|
00460242|>5F            pop   edi                              ;跳转来自 004601DE, 0046021A, 00460236
00460243|.5E            pop   esi
00460244|.5D            pop   ebp
00460245|.33C0          xor   eax, eax                         ;EAX置零
00460247|.5B            pop   ebx
00460248\.C3            retn                                     ;//返回
;--------------------------------------------------------------------|




下面开始进行注册算法一的分析

;====================================================================|
;在地址0046021E处F7跟进注册算法CALL->0045FB90
;--------------------------------------------------------------------|
0045FB90/$6A FF         push    -1                               ;//本地调用来自 0046021E
0045FB92|.68 70414700   push    00474170                         ;SE 处理程序安装
0045FB97|.64:A1 0000000>mov   eax, dword ptr fs:
0045FB9D|.50            push    eax
0045FB9E|.64:8925 00000>mov   dword ptr fs:, esp
0045FBA5|.83EC 14       sub   esp, 14
0045FBA8|.8B4424 24   mov   eax, dword ptr           ;EAX = 用户名
0045FBAC|.53            push    ebx
0045FBAD|.55            push    ebp                              ;用户名压栈
0045FBAE|.56            push    esi
0045FBAF|.57            push    edi                              ;序列号压栈
0045FBB0|.50            push    eax                              ;用户名压栈
0045FBB1|.8D4C24 18   lea   ecx, dword ptr
0045FBB5|.E8 B8800000   call    <jmp.&MFC42.#537>
0045FBBA|.8D4C24 14   lea   ecx, dword ptr           ;ECX = 用户名的地址
0045FBBE|.C74424 2C 000>mov   dword ptr , 0
0045FBC6|.E8 E5840000   call    <jmp.&MFC42.#6282>
0045FBCB|.8D4C24 14   lea   ecx, dword ptr
0045FBCF|.E8 D6840000   call    <jmp.&MFC42.#6283>
0045FBD4|.6A 20         push    20
0045FBD6|.8D4C24 18   lea   ecx, dword ptr
0045FBDA|.E8 71870000   call    <jmp.&MFC42.#2915>
0045FBDF|.8B4C24 38   mov   ecx, dword ptr           ;ECX = 序列号
0045FBE3|.8BD8          mov   ebx, eax                         ;EBX = 用户名
0045FBE5|.51            push    ecx                              ;序列号压栈
0045FBE6|.8D4C24 14   lea   ecx, dword ptr
0045FBEA|.E8 83900000   call    <jmp.&MFC42.#537>
0045FBEF|.8D4C24 10   lea   ecx, dword ptr
0045FBF3|.C64424 2C 01mov   byte ptr , 1
0045FBF8|.E8 B3840000   call    <jmp.&MFC42.#6282>
0045FBFD|.8D4C24 10   lea   ecx, dword ptr
0045FC01|.E8 A4840000   call    <jmp.&MFC42.#6283>
0045FC06|.6A 20         push    20
0045FC08|.8D4C24 14   lea   ecx, dword ptr
0045FC0C|.E8 3F870000   call    <jmp.&MFC42.#2915>
0045FC11|.8BD0          mov   edx, eax                         ;EDX = 序列号
0045FC13|.83CE FF       or      esi, FFFFFFFF
0045FC16|.8BFA          mov   edi, edx                         ;EDI = 序列号
0045FC18|.8BCE          mov   ecx, esi
0045FC1A|.33C0          xor   eax, eax                         ;EAX置零
;---------------------------<用户名长度不能大于序列号长度>---------------|
0045FC1C|.895424 20   mov   dword ptr , edx          ; = 序列号
0045FC20|.F2:AE         repne   scas byte ptr es:
0045FC22|.F7D1          not   ecx
0045FC24|.49            dec   ecx                              ;ECX = 序列号长度
0045FC25|.8BFB          mov   edi, ebx                         ;EDI = 用户名
0045FC27|.8BE9          mov   ebp, ecx                         ;EBP = 用户名长度
0045FC29|.8BCE          mov   ecx, esi
0045FC2B|.F2:AE         repne   scas byte ptr es:
0045FC2D|.F7D1          not   ecx
0045FC2F|.49            dec   ecx                              ;ECX = 用户名长度
0045FC30|.3BCD          cmp   ecx, ebp
0045FC32|.0F87 54010000 ja      0045FD8C                         ;//跳则挂(未实现)
;---------------------------<用户名不能为空>---------------------------|
0045FC38|.8BFB          mov   edi, ebx                         ;EDI = 用户名
0045FC3A|.8BCE          mov   ecx, esi
0045FC3C|.F2:AE         repne   scas byte ptr es:
0045FC3E|.F7D1          not   ecx
0045FC40|.49            dec   ecx                              ;ECX = 用户名长度
0045FC41|.0F84 45010000 je      0045FD8C                         ;//跳则挂(未实现)
;---------------------------<序列号不能为空>---------------------------|
0045FC47|.8BFA          mov   edi, edx                         ;EDI = 序列号
0045FC49|.8BCE          mov   ecx, esi
0045FC4B|.F2:AE         repne   scas byte ptr es:
0045FC4D|.F7D1          not   ecx
0045FC4F|.49            dec   ecx                              ;ECX = 序列号长度
0045FC50|.0F84 36010000 je      0045FD8C                         ;//跳则挂(未实现)
;---------------------------<注册运算验证>-----------------------------|
0045FC56|.894424 38   mov   dword ptr , eax          ;初始化为0
;------------------------------------[第一层开始]
0045FC5A|>8B5424 38   /mov   edx, dword ptr          ;EDX =
0045FC5E|.8D4C24 34   |lea   ecx, dword ptr          ;加载序列号地址
0045FC62|.8A82 887E4900 |mov   al, byte ptr        ;三次依次出现'P'/'W'/'M'
0045FC68|.884424 18   |mov   byte ptr , al         ; = al
0045FC6C|.E8 37800000   |call    <jmp.&MFC42.#540>
0045FC71|.8BFB          |mov   edi, ebx                        ;EDI = 用户名
0045FC73|.83C9 FF       |or      ecx, FFFFFFFF
0045FC76|.33C0          |xor   eax, eax                        ;EAX置零
0045FC78|.33ED          |xor   ebp, ebp                        ;EBP置零
0045FC7A|.F2:AE         |repne   scas byte ptr es:
0045FC7C|.F7D1          |not   ecx
0045FC7E|.49            |dec   ecx                           ;ECX = 用户名长度
0045FC7F|.C64424 2C 02|mov   byte ptr , 2            ; = 2
0045FC84|.74 4B         |je      short 0045FCD1                  ;//作用:跳过下面循环体
;---------------------------[第二层开始]                              [对用户名字符进行查表替换]
0045FC86|>8A042B      |/mov   al, byte ptr          ;用户名的第i个字符
0045FC89|.33F6          ||xor   esi, esi                     ;ESI置零
;---------[第三层开始]                                                [对第i个字符进行查表替换]                                 
0045FC8B|>3A0475 207E49>||/cmp   al, byte ptr    ;查表比较
0045FC92|.74 08         |||je      short 0045FC9C                ;//找到后,跳出本循环体
0045FC94|.46            |||inc   esi                           ;ESI++
0045FC95|.83FE 34       |||cmp   esi, 34
0045FC98|.^ 7C F1         ||\jl      short 0045FC8B                ;//继续查找密码表中下一个字符
;---------[第三层结束]
0045FC9A|.EB 11         ||jmp   short 0045FCAD               ;//没找到,跳走
;---------<(I)找到了则跳到这>
0045FC9C|>8A0C75 217E49>||mov   cl, byte ptr     ;找到密码表中对应的字母
0045FCA3|.51            ||push    ecx
0045FCA4|.8D4C24 38   ||lea   ecx, dword ptr
0045FCA8|.E8 83820000   ||call    <jmp.&MFC42.#940>
;---------<(II)没找到则跳到这>
0045FCAD|>83FE 34       ||cmp   esi, 34                        ;和34比较
0045FCB0|.75 0E         ||jnz   short 0045FCC0               ;若上面没找到,则在此处不跳
;---------<没有找到时进行的操作>
0045FCB2|.8B5424 18   ||mov   edx, dword ptr       ;
0045FCB6|.8D4C24 34   ||lea   ecx, dword ptr       ;加载序列号地址
0045FCBA|.52            ||push    edx
0045FCBB|.E8 70820000   ||call    <jmp.&MFC42.#940>            ;将替换字符和前面所得字符串链接
;---------|
0045FCC0|>8BFB          ||mov   edi, ebx                     ;EDI = 用户名
0045FCC2|.83C9 FF       ||or      ecx, FFFFFFFF
0045FCC5|.33C0          ||xor   eax, eax                     ;EAX置零
0045FCC7|.45            ||inc   ebp
0045FCC8|.F2:AE         ||repne   scas byte ptr es:
0045FCCA|.F7D1          ||not   ecx
0045FCCC|.49            ||dec   ecx                            ;用户名长度
0045FCCD|.3BE9          ||cmp   ebp, ecx
0045FCCF|.^ 72 B5         |\jb      short 0045FC86               ;//循环length(name)次
;---------------------------[第二层]
;---------<当运算所得字符串长度>=10H时,直接作为序列号>
0045FCD1|>8B4424 34   |mov   eax, dword ptr          ;(ASCII "eWHEyMPP"
0045FCD5|.8B48 F8       |mov   ecx, dword ptr           ;字符串的长度
0045FCD8|.83F9 10       |cmp   ecx, 10
0045FCDB|.7D 3A         |jge   short 0045FD17                  ;//大于等于10跳走
;---------<当运算所得字符串长度<10H时,进行尾部补充>
0045FCDD|.8BC1          |mov   eax, ecx                        ;EAX = 长度
0045FCDF|.B9 10000000   |mov   ecx, 10                         ;ECX = 10H
0045FCE4|.2BC8          |sub   ecx, eax                        ;ECX = ECX - EAX
0045FCE6|.8D5424 1C   |lea   edx, dword ptr          ;加载补充字符串地址
0045FCEA|.51            |push    ecx                           ;补充字符串长度压栈
0045FCEB|.52            |push    edx
0045FCEC|.B9 C02B4E00   |mov   ecx, 004E2BC0
0045FCF1|.E8 42800000   |call    <jmp.&MFC42.#4129>            ;确定补充字符串
0045FCF6|.50            |push    eax
0045FCF7|.8D4C24 38   |lea   ecx, dword ptr          ;加载上面运算所得字符串地址
0045FCFB|.C64424 30 03|mov   byte ptr , 3
0045FD00|.E8 25820000   |call    <jmp.&MFC42.#939>               ;将两字符川进行链接
0045FD05|.8D4C24 1C   |lea   ecx, dword ptr
0045FD09|.C64424 2C 02|mov   byte ptr , 2
0045FD0E|.E8 4D7F0000   |call    <jmp.&MFC42.#800>
0045FD13|.8B4424 34   |mov   eax, dword ptr          ;(ASCII "eWHEyMPPLdQsBcmp"
0045FD17|>8B4C24 20   |mov   ecx, dword ptr          ;假码
0045FD1B|.51            |push    ecx                           ; /s2 = 真码
0045FD1C|.50            |push    eax                           ; |s1 = 假码
0045FD1D|.FF15 A45A4700 |call    dword ptr [<&MSVCRT._mbscmp>]   ; \(msvcrt._mbscmp)字符串比较
0045FD23|.83C4 08       |add   esp, 8
0045FD26|.8D4C24 34   |lea   ecx, dword ptr
0045FD2A|.85C0          |test    eax, eax                        ;测试标志位
0045FD2C|.C64424 2C 01|mov   byte ptr , 1            ; = 1
0045FD31|.74 1B         |je      short 0045FD4E                  ;//跳出循环体
0045FD33|.33F6          |xor   esi, esi                        ;ESI置零
0045FD35|.E8 267F0000   |call    <jmp.&MFC42.#800>
0045FD3A|.8B4424 38   |mov   eax, dword ptr
0045FD3E|.40            |inc   eax                           ;EAX++
0045FD3F|.83F8 03       |cmp   eax, 3
0045FD42|.894424 38   |mov   dword ptr , eax         ; = eax
0045FD46|.^ 0F8C 0EFFFFFF \jl      0045FC5A                        ;//循环(三次)
;------------------------------------[第一层结束]
;---------<若从这跳则越过ESI=1,进而EAX=ESI=0,注册失败>
0045FD4C|.EB 0A         jmp   short 0045FD58
0045FD4E|>BE 01000000   mov   esi, 1                           ;ESI = 1
0045FD53|.E8 087F0000   call    <jmp.&MFC42.#800>
0045FD58|>8D4C24 10   lea   ecx, dword ptr           ;加载假码地址
0045FD5C|.C64424 2C 00mov   byte ptr , 0
0045FD61|.E8 FA7E0000   call    <jmp.&MFC42.#800>
0045FD66|.8D4C24 14   lea   ecx, dword ptr           ;加载用户名地址
0045FD6A|.C74424 2C FFF>mov   dword ptr , -1
0045FD72|.E8 E97E0000   call    <jmp.&MFC42.#800>
0045FD77|.8BC6          mov   eax, esi                         ;EAX = ESI
0045FD79|.5F            pop   edi
0045FD7A|.5E            pop   esi
0045FD7B|.5D            pop   ebp
0045FD7C|.5B            pop   ebx
0045FD7D|.8B4C24 14   mov   ecx, dword ptr
0045FD81|.64:890D 00000>mov   dword ptr fs:, ecx
0045FD88|.83C4 20       add   esp, 20
0045FD8B|.C3            retn                                     ;//返回(EAX=ESI)
;-------------<跳到下面就算玩完~~~>
0045FD8C|>8D4C24 10   lea   ecx, dword ptr           ;跳转来自 0045FC32, 0045FC41, 0045FC50
0045FD90|.C64424 2C 00mov   byte ptr , 0
0045FD95|.E8 C67E0000   call    <jmp.&MFC42.#800>
0045FD9A|.8D4C24 14   lea   ecx, dword ptr
0045FD9E|.897424 2C   mov   dword ptr , esi
0045FDA2|.E8 B97E0000   call    <jmp.&MFC42.#800>
0045FDA7|.8B4C24 24   mov   ecx, dword ptr
0045FDAB|.5F            pop   edi
0045FDAC|.5E            pop   esi
0045FDAD|.5D            pop   ebp
0045FDAE|.33C0          xor   eax, eax                         ;EAX置零
0045FDB0|.5B            pop   ebx
0045FDB1|.64:890D 00000>mov   dword ptr fs:, ecx
0045FDB8|.83C4 20       add   esp, 20
0045FDBB\.C3            retn                                     ;//返回(EAX=0)
;====================================================================|

在运行到0045FC8B时候,
0045FC62|.8A82 887E4900 |mov       al, byte ptr
0045FC8B|>3A0475 207E49>||/cmp   al, byte ptr
跟随数据窗口,可以得到一张密码表换算表:

00497E2061 43 62 78 63 69 64 49 65 41 66 58 67 4D 68 6BaCbxcidIeAfXgMhk
00497E3069 45 6A 56 6B 5A 6C 65 6D 52 6E 79 6F 42 70 4BiEjVkZlemRnyoBpK
00497E4071 64 72 54 73 53 74 50 75 57 76 6C 77 6A 78 44qdrTsStPuWvlwjxD
00497E5079 48 7A 46 41 7A 42 71 43 70 44 4F 45 6B 46 67yHzFAzBqCpDOEkFg
00497E6047 59 48 6D 49 74 4A 61 4B 72 4C 51 4D 6E 4E 73GYHmItJaKrLQMnNs
00497E704F 75 50 55 51 47 52 4A 53 4C 54 4E 55 62 56 63OuPUQGRJSLTNUbVc
00497E8057 66 58 68 59 6F 5A 77 50 57 4D 00 25 30 32 64WfXhYoZwPWM.%02d
00497E903A 25 30 32 64 3A 25 30 32 64 00 00 25 73 25 73:%02d:%02d..%s%s
00497EA000 00 00 00 4C 64 51 73 42 63 6D 70 4A 70 61 45....LdQsBcmpJpaE
00497EB073 58 74 6F 00 00 00 00 25 30 38 6C 58 2D 25 30sXto....%08lX-%0

换算关系如下:
a -> C   b -> q   c -> i   d -> H   e -> S   f -> X   g -> M
h -> k   i -> E   j -> V   k -> Z   l -> e   m -> R   n -> y
o -> B   p -> K   q -> d   r -> T   s -> A   t -> F
u -> W   v -> l   w -> j   x -> D   y -> I   z -> P

A -> z   B -> x   C -> p   D -> O   E -> k   F -> g   G -> Y
H -> m   I -> t   J -> a   K -> r   L -> Q   M -> n   N -> s
O -> u   P -> U   Q -> G   R -> J   S -> L   T -> N
U -> b   V -> c   W -> f   X -> h   Y -> o   Z -> w

非大小写类字母统一替换成P或W或M
注意,只能替换成同一个字母,不允许P、W、M交杂

用于补充作用的链接字符串为dQsBcmpJpaEsXto

算法总结:
1.先将用户名的各个字符进行替换
替换规则如下
(1).大小写字母进行查表
(2).非字母则统一替换为P或W或M
2.进行序列号长度校验
若长度小于10H,则用LdQsBcmpJpaEsXto进行补充,直至长度等于10H
若长度>=10H,则直接作为序列号


运算示例:
ID:luying10
SN:eWHEyMPPLdQsBcmpeWHEyMWWLdQsBcmpeWHEyMMMLdQsBcmp

一个有趣的小问题
如果ID是中文的,因为不是英文字符,所以只能用P或W或M统一替换
所以,所有中文用户名对应的序列号只有三个
PPPPPPPPLdQsBcmp   WWWWWWWWLdQsBcmp    MMMMMMMMLdQsBcmp





好了,分析完注册算法一,借着兴致,一举拿下注册算法二

试练码:
ID:luying10
SN:10000000-02000000-00300000-00040000-00005000-00000600-00000070-00000008
BTW:在地址0045FF2B 处%08lx...提示了我们序列号的格式
sn = s1-s2-s3-s4-s5-s6-s7-s8

;====================================================================|
;在地址0046022C处跟进注册算法(二)CALL->0045FDC0
;====================================================================|
0045FDC0/$6A FF         push    -1                               ;//本地调用来自 0046022C
0045FDC2|.68 D9414700   push    004741D9                         ;SE 处理程序安装
0045FDC7|.64:A1 0000000>mov   eax, dword ptr fs:
0045FDCD|.50            push    eax
0045FDCE|.64:8925 00000>mov   dword ptr fs:, esp
0045FDD5|.81EC 94000000 sub   esp, 94
0045FDDB|.8B8424 A40000>mov   eax, dword ptr           ;EAX = = 用户名
0045FDE2|.53            push    ebx
0045FDE3|.56            push    esi
0045FDE4|.50            push    eax                              ;用户名压栈
0045FDE5|.8D4C24 10   lea   ecx, dword ptr
0045FDE9|.C74424 60 DF4>mov   dword ptr , C95841DF
0045FDF1|.C74424 64 12E>mov   dword ptr , 717AE412
0045FDF9|.C74424 68 ACE>mov   dword ptr , F015E3AC
0045FE01|.C74424 6C B17>mov   dword ptr , 1127EB1
0045FE09|.C74424 70 895>mov   dword ptr , 1D455E89
0045FE11|.C74424 74 51F>mov   dword ptr , 5375F151
0045FE19|.C74424 78 6E4>mov   dword ptr , D34D4B6E
0045FE21|.C74424 7C 81F>mov   dword ptr , 88C5F181

n = 0x88C5F181D34D4B6E5375F1511D455E8901127EB1F015E3AC717AE412C95841DF

0045FE29|.E8 447E0000   call    <jmp.&MFC42.#537>
0045FE2E|.8B8C24 B00000>mov   ecx, dword ptr           ;ECX = = 序列号
0045FE35|.C78424 A40000>mov   dword ptr , 0
0045FE40|.51            push    ecx                              ;序列号压栈
0045FE41|.8D4C24 0C   lea   ecx, dword ptr
0045FE45|.E8 287E0000   call    <jmp.&MFC42.#537>
0045FE4A|.8B5424 0C   mov   edx, dword ptr          ;EDX = = 用户名
0045FE4E|.8B35 A45A4700 mov   esi, dword ptr [<&MSVCRT._mbscmp>;msvcrt._mbscmp
;---------------------------<检测用户名是否为空>---------------------|
0045FE54|.68 84014A00   push    004A0184                         ; /s2 = ""
0045FE59|.52            push    edx                              ; |s1 = "用户名"
0045FE5A|.C68424 AC0000>mov   byte ptr , 1             ; | = 1
0045FE62|.FFD6          call    esi                              ; \_mbscmp
0045FE64|.83C4 08       add   esp, 8
0045FE67|.85C0          test    eax, eax
0045FE69|.0F84 0F020000 je      0046007E                         ;//跳则挂(未实现)
;---------------------------<检测序列号是否为空>---------------------|
0045FE6F|.8B4424 08   mov   eax, dword ptr          ;EAX = = 序列号
0045FE73|.68 84014A00   push    004A0184
0045FE78|.50            push    eax                              ;序列号压栈
0045FE79|.FFD6          call    esi
0045FE7B|.83C4 08       add   esp, 8
0045FE7E|.85C0          test    eax, eax
0045FE80|.0F84 F8010000 je      0046007E                         ;//跳则挂(未实现)
;--------------------------------------------------------------------|
0045FE86|.57            push    edi                              ;序列号压栈
0045FE87|.6A 00         push    0                              ;
0045FE89|.8D4C24 44   lea   ecx, dword ptr
0045FE8D|.E8 EE3D0000   call    00463C80                         ;
0045FE92|.6A 00         push    0
0045FE94|.8D4C24 4C   lea   ecx, dword ptr
0045FE98|.C68424 AC0000>mov   byte ptr , 2
0045FEA0|.E8 DB3D0000   call    00463C80                         ;
0045FEA5|.B3 03         mov   bl, 3
0045FEA7|.68 01000100   push    10001                            ;e = 10001H = 65537D
0045FEAC|.8D4C24 5C   lea   ecx, dword ptr
0045FEB0|.889C24 AC0000>mov   byte ptr , bl
0045FEB7|.E8 C43D0000   call    00463C80                         ;
0045FEBC|.8D4C24 58   lea   ecx, dword ptr
0045FEC0|.C68424 A80000>mov   byte ptr , 4
0045FEC8|.51            push    ecx
0045FEC9|.8D4C24 4C   lea   ecx, dword ptr
0045FECD|.E8 0E3E0000   call    00463CE0
0045FED2|.8D4C24 58   lea   ecx, dword ptr
0045FED6|.889C24 A80000>mov   byte ptr , bl
0045FEDD|.E8 4E3E0000   call    00463D30
0045FEE2|.8D5424 60   lea   edx, dword ptr
0045FEE6|.6A 08         push    8
0045FEE8|.52            push    edx
0045FEE9|.8D4C24 48   lea   ecx, dword ptr
0045FEED|.E8 5E3C0000   call    00463B50
0045FEF2|.B9 08000000   mov   ecx, 8
0045FEF7|.33C0          xor   eax, eax                         ;EAX置零
0045FEF9|.8D7C24 18   lea   edi, dword ptr
0045FEFD|.8D5424 2C   lea   edx, dword ptr
0045FF01|.F3:AB         rep   stos dword ptr es:
0045FF03|.8D4424 34   lea   eax, dword ptr
0045FF07|.8D4C24 30   lea   ecx, dword ptr
0045FF0B|.50            push    eax
0045FF0C|.51            push    ecx
0045FF0D|.8D4424 30   lea   eax, dword ptr
0045FF11|.52            push    edx
0045FF12|.8D4C24 30   lea   ecx, dword ptr
0045FF16|.50            push    eax
0045FF17|.8D5424 30   lea   edx, dword ptr
0045FF1B|.51            push    ecx
0045FF1C|.8D4424 30   lea   eax, dword ptr
0045FF20|.52            push    edx
0045FF21|.8B5424 24   mov   edx, dword ptr           ;EDX = = 序列号
0045FF25|.8D4C24 30   lea   ecx, dword ptr
;---------------------------<对假序列号进行变形运算>-----------------|
0045FF29|.50            push    eax
0045FF2A|.51            push    ecx
0045FF2B|.68 B87E4900   push    00497EB8                         ; |%08lx-%08lx-%08lx-%08lx-%08lx-%08lx-%08lx-%08lx\n
0045FF30|.52            push    edx                              ; |s
0045FF31|.FF15 405A4700 call    dword ptr [<&MSVCRT.sscanf>]   ; \sscanf
0045FF37|.8B4424 50   mov   eax, dword ptr           ;s5 = 00005000
0045FF3B|.8B4C24 4C   mov   ecx, dword ptr           ;s4 = 00040000
0045FF3F|.8B7C24 48   mov   edi, dword ptr           ;s3 = 00300000
0045FF43|.8B5424 44   mov   edx, dword ptr           ;s2 = 02000000
0045FF47|.03C1          add   eax, ecx                         ;s5 = s5 + s4 = 00045000
0045FF49|.8B4C24 5C   mov   ecx, dword ptr           ;s8 = 00000008
0045FF4D|.03C7          add   eax, edi                         ;s5 = s5 + s3 = 00345000
0045FF4F|.8B7C24 58   mov   edi, dword ptr           ;s7 = 00000070
0045FF53|.03C2          add   eax, edx                         ;s5 = s5 + s2 = 02345000
0045FF55|.8B5424 40   mov   edx, dword ptr           ;s1 = 10000000 (CDRIP.#299)
0045FF59|.33C8          xor   ecx, eax                         ;s8 = s8 | s5 = 02345008
0045FF5B|.8B4424 54   mov   eax, dword ptr           ;s6 = 00000600
0045FF5F|.83C4 28       add   esp, 28
0045FF62|.03C2          add   eax, edx                         ;s6 = s6 + s1 = 10000600
0045FF64|.894C24 34   mov   dword ptr , ecx          ;ecx=02345008
0045FF68|.33F8          xor   edi, eax                         ;s7 = s7 | s6 = 10000670
;--------------------------------------------------------------------|
0045FF6A|.6A 00         push    0
0045FF6C|.8D4C24 3C   lea   ecx, dword ptr
0045FF70|.897C24 34   mov   dword ptr , edi          ; = edi = 10000670 (CDRIP.10000670)
0045FF74|.E8 073D0000   call    00463C80
0045FF79|.8D4C24 18   lea   ecx, dword ptr
0045FF7D|.6A 08         push    8
0045FF7F|.51            push    ecx                              ;sn变形后的SerNum
0045FF80|.8D4C24 40   lea   ecx, dword ptr
0045FF84|.C68424 B00000>mov   byte ptr , 5
0045FF8C|.E8 BF3B0000   call    00463B50                         ;rsa_de(),计算 c = SerNum^e mod n
0045FF91|.8D5424 38   lea   edx, dword ptr
0045FF95|.8D4424 50   lea   eax, dword ptr
0045FF99|.52            push    edx
0045FF9A|.50            push    eax
0045FF9B|.8D4C24 48   lea   ecx, dword ptr
0045FF9F|.E8 0CC5FFFF   call    0045C4B0                         ;   结果以大数输出 c
0045FFA4|.B9 08000000   mov   ecx, 8
0045FFA9|.33C0          xor   eax, eax
0045FFAB|.8D7C24 18   lea   edi, dword ptr
0045FFAF|.6A 08         push    8
0045FFB1|.F3:AB         rep   stos dword ptr es:
0045FFB3|.8D4C24 1C   lea   ecx, dword ptr
0045FFB7|.C68424 AC0000>mov   byte ptr , 6
0045FFBF|.51            push    ecx
0045FFC0|.8D4C24 58   lea   ecx, dword ptr
0045FFC4|.E8 C73B0000   call    00463B90                         ;大数结果转为十六进制字节串
0045FFC9|.B9 08000000   mov   ecx, 8
0045FFCE|.33C0          xor   eax, eax                         ;EAX置零
0045FFD0|.8DBC24 800000>lea   edi, dword ptr
0045FFD7|.F3:AB         rep   stos dword ptr es:          ;   
0045FFD9|.5F            pop   edi                              ;   序列号
;-------------<交换每一个dword的高位,低位>
0045FFDA|>8A5404 17   /mov   dl, byte ptr
0045FFDE|.8A4C04 16   |mov   cl, byte ptr
0045FFE2|.885404 7C   |mov   byte ptr , dl
0045FFE6|.8B5404 14   |mov   edx, dword ptr
0045FFEA|.884C04 7D   |mov   byte ptr , cl
0045FFEE|.8A4C04 14   |mov   cl, byte ptr
0045FFF2|.C1EA 08       |shr   edx, 8
0045FFF5|.885404 7E   |mov   byte ptr , dl
0045FFF9|.884C04 7F   |mov   byte ptr , cl
0045FFFD|.83C0 04       |add   eax, 4                        ;EAX = EAX + 4
00460000|.83F8 20       |cmp   eax, 20
00460003|.^ 7C D5         \jl      short 0045FFDA                  ;//循环(8次)

循环前:
0012EEF4C4 3A 70 C1 5B DE 26 77 90 A1 42 3B E5 D8 0E 8A?p羀?w悺B;遑
0012EF0440 B3 B2 FE 55 96 4A 1B EC B3 E0 78 D2 AE 42 6A@巢?朖斐鄕耶Bj

循环后:
0012EF5CC1 70 3A C4 77 26 DE 5B 3B 42 A1 90 8A 0E D8 E5羛:膚&轠;B??劐
0012EF6CFE B2 B3 40 1B 4A 96 55 78 E0 B3 EC 6A 42 AE D2?矦J朥x喑靔B?

;--------------------------------------------------------------------|
00460005|.8D5424 7C   lea   edx, dword ptr           ;加载转换后的地址
00460009|.8D4C24 10   lea   ecx, dword ptr           ;//固定字符串地址
0046000D|.52            push    edx
0046000E|.E8 5F7C0000   call    <jmp.&MFC42.#537>
00460013|.8B4424 10   mov   eax, dword ptr           ;堆栈 ss:=02449248
00460017|.8B4C24 0C   mov   ecx, dword ptr          ;堆栈 ss:=003FB228, (ASCII "luying10")
0046001B|.50            push    eax                              ;转化后数值的地址
0046001C|.51            push    ecx                              ;用户名
0046001D|.FFD6          call    esi                              ;比较
0046001F|.83C4 08       add   esp, 8
00460022|.8D4C24 10   lea   ecx, dword ptr
00460026|.85C0          test    eax, eax
00460028|.C68424 A40000>mov   byte ptr , 6
00460030|.0F84 86000000 je      004600BC                         ;//关键跳
;--------------------------------------------------------------------|
00460036|.E8 257C0000   call    <jmp.&MFC42.#800>
0046003B|.8D4C24 4C   lea   ecx, dword ptr
0046003F|.C68424 A40000>mov   byte ptr , 5
00460047|.E8 E43C0000   call    00463D30
0046004C|.8D4C24 34   lea   ecx, dword ptr
00460050|.889C24 A40000>mov   byte ptr , bl
00460057|.E8 D43C0000   call    00463D30
0046005C|.8D4C24 44   lea   ecx, dword ptr
00460060|.C68424 A40000>mov   byte ptr , 8
00460068|.E8 C33C0000   call    00463D30
0046006D|.8D4C24 3C   lea   ecx, dword ptr
00460071|.C68424 A40000>mov   byte ptr , 1
00460079|.E8 B23C0000   call    00463D30
0046007E|>8D4C24 08   lea   ecx, dword ptr
00460082|.C68424 A40000>mov   byte ptr , 0
0046008A|.E8 D17B0000   call    <jmp.&MFC42.#800>
0046008F|.8D4C24 0C   lea   ecx, dword ptr
00460093|.C78424 A40000>mov   dword ptr , -1
0046009E|.E8 BD7B0000   call    <jmp.&MFC42.#800>
004600A3|.5E            pop   esi
004600A4|.33C0          xor   eax, eax                         ;EAX置零
004600A6|.5B            pop   ebx
004600A7|.8B8C24 940000>mov   ecx, dword ptr
004600AE|.64:890D 00000>mov   dword ptr fs:, ecx
004600B5|.81C4 A0000000 add   esp, 0A0
004600BB|.C3            retn                                     ;//返回(EAX=0)
;--------------------------------------------------------------------|
004600BC|>E8 9F7B0000   call    <jmp.&MFC42.#800>
004600C1|.8D4C24 4C   lea   ecx, dword ptr
004600C5|.C68424 A40000>mov   byte ptr , 5
004600CD|.E8 5E3C0000   call    00463D30
004600D2|.8D4C24 34   lea   ecx, dword ptr
004600D6|.889C24 A40000>mov   byte ptr , bl
004600DD|.E8 4E3C0000   call    00463D30
004600E2|.8D4C24 44   lea   ecx, dword ptr
004600E6|.C68424 A40000>mov   byte ptr , 9
004600EE|.E8 3D3C0000   call    00463D30
004600F3|.8D4C24 3C   lea   ecx, dword ptr
004600F7|.C68424 A40000>mov   byte ptr , 1
004600FF|.E8 2C3C0000   call    00463D30
00460104|.8D4C24 08   lea   ecx, dword ptr
00460108|.C68424 A40000>mov   byte ptr , 0
00460110|.E8 4B7B0000   call    <jmp.&MFC42.#800>
00460115|.8D4C24 0C   lea   ecx, dword ptr
00460119|.C78424 A40000>mov   dword ptr , -1
00460124|.E8 377B0000   call    <jmp.&MFC42.#800>
00460129|.8B8C24 9C0000>mov   ecx, dword ptr
00460130|.5E            pop   esi
00460131|.B8 01000000   mov   eax, 1                           ;EAX = 1
00460136|.5B            pop   ebx
00460137|.64:890D 00000>mov   dword ptr fs:, ecx
0046013E|.81C4 A0000000 add   esp, 0A0
00460144\.C3            retn                                     ;//返回(EAX=1)
;====================================================================|


算法总结:
1.对输入的假序列号进行变换
sn = s1-s2-s3-s4-s5-s6-s7-s8

s6' = s6 + s1
s7' = s7 | (s6 + s1)
s8' = s8 | (s2 + s3 + s4 + s5)

SerNum = s1-s2-s3-s4-s5-s6'-s7'-s8'

2.运算
c = SerNum ^ e mod n;

3.比较c和name


利用RSATool搞定RSA参数:

n = 88C5F181D34D4B6E5375F1511D455E8901127EB1F015E3AC717AE412C95841DF
e = 10001

n = p * q

p:92D9586271DFD8D47C9AE783DED37E9F
q:EE6F5C9077D0A54887558B9CA262B4C1

d:7AAB6636F5681EDE3D96CBAFDF9BE6F38A66563EB122E21AE8B94121DC164781

逆推:
1.将用户名每四个字符倒序排列,并且转成十六进制
2.进行ESA运算
3.计算SerNum
4.进行XOR运算,求得最终的serial number

ID:luying10
SN:8F2D4BBE-A742BFC7-0BBDF498-9E74023E-8AFCE799-AA97BDD7-1B8A741B-8980044D


通过文本,希望读者能够掌握两类比较典型的算法
1.查表类算法(密码表字符替换)
2.密码学算法(RSA)


关于算法分析推荐一篇文章:

《Ultra-$hare系列算法分析》
http://www.unpack.cn/viewthread.php?tid=19935

该实例特点:
1.非明码比较
2.运用密码学加密算法
3.有对字符和字符串的操作
4.一些隐含的东西(连字符,序列号头部特定字符等)

本篇是菜鸟学算法系列最后一篇,有些地方写的潦草,兄弟们多多担待~
希望各位兄弟早日步入算法分析的大门```.o(n_n)o.

hcx_20031211 发表于 2007-12-24 22:54:30

实现者 发表于 2007-12-25 15:51:49

谢谢提供,辛苦了/:L

anson2416 发表于 2008-2-16 23:53:20

谢谢提供,辛苦了/:L /:L

110120 发表于 2008-6-23 20:25:33

好东西~~~~~~~~~~学习了呵呵~~

hwmzly 发表于 2009-11-26 10:01:27

谢谢提供

tianfire 发表于 2009-11-29 07:52:13

通俗易懂,谢谢

qycong 发表于 2009-12-25 22:12:13

谢谢提供,辛苦了/:001 /:001

whdl 发表于 2010-5-24 18:04:05

标志位测试
是什么,

看来还要慢慢的学习才行。

12320374 发表于 2010-5-25 22:04:06

/:011 这个。。。这个 。。。很好 很强大
页: [1] 2
查看完整版本: 菜鸟学算法<三>算法分析篇