cxj98 发表于 2014-3-9 20:35:44

小菜对 SomkeFX 的 KeygenMe v1.0 的简单算法分析过程

本帖最后由 cxj98 于 2014-3-9 21:05 编辑

本小菜初学算法分析,所以到处网上搜索一些简单的 KeygenMe。功夫不负有心人,终于在某 CrackMe 网站找到一款比较适合初学者入门的算法分析软件。

下面本小菜就开始这个 KeygenMe 的分析计算过程。

主程序载入OD后,然后F9直接跑起来,习惯性地输入用户名:cxj98,假码:1234567890,点击 Unlock 按扭,弹出错误提示:


---------------------------
Invalid Serial
---------------------------
Insert Coin Try Again!
---------------------------
OK   
---------------------------


有错误提示框,好办,下 bp MessageboxA 断点,重新点击 Unlock 按扭。

程序果断中断下来,断在


76DFFD1E >8BFF            MOV   EDI, EDI                                 ; smokefx.004589F8
76DFFD20    55            PUSH    EBP
76DFFD21    8BEC            MOV   EBP, ESP
76DFFD23    6A 00         PUSH    0x0
76DFFD25    FF75 14         PUSH    DWORD PTR SS:
76DFFD28    FF75 10         PUSH    DWORD PTR SS:
76DFFD2B    FF75 0C         PUSH    DWORD PTR SS:
76DFFD2E    FF75 08         PUSH    DWORD PTR SS:
76DFFD31    E8 A0FFFFFF   CALL    user32.MessageBoxExA
76DFFD36    5D            POP   EBP


右下角堆栈中右键菜单里选择反汇编窗口中跟随,


0018FAF4   004545BF/CALL 到 MessageBoxA 来自 smokefx.004545BA
0018FAF8   000E1C24|hOwner = 000E1C24 ('SmokeFX',class='TApplication')
0018FAFC   01C89A7C|Text = "Insert Coin Try Again!"
0018FB00   004589F8|Title = "Invalid Serial"
0018FB04   00000030\Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
0018FB08   0018FB80指向下一个 SEH 记录的指针
0018FB0C   00454629SE处理程序
0018FB10   0018FB74


来到


004545B0|.53            PUSH    EBX                                    ; /Style
004545B1|.57            PUSH    EDI                                    ; |Title
004545B2|.56            PUSH    ESI                                    ; |Text
004545B3|.8B45 FC       MOV   EAX, DWORD PTR SS:            ; |
004545B6|.8B40 30       MOV   EAX, DWORD PTR DS:             ; |
004545B9|.50            PUSH    EAX                                    ; |hOwner
004545BA|.E8 C91FFBFF   CALL    <JMP.&user32.MessageBoxA>                ; \MessageBoxA


往上找段首:


004544D4/[      DISCUZ_CODE_88      ]nbsp; 55            PUSH    EBP                                    ;// 段首
004544D5|.8BEC          MOV   EBP, ESP
004544D7|.83C4 AC       ADD   ESP, -0x54
004544DA|.53            PUSH    EBX


发现多处调用:


本地调用来自 004546D1, 0045878D, 00458868, 004588EB, 00458938, 00458982


不管是正确提示,错误提示,注册码长度不对提示,都会调到到这里,习惯性地按下 Ctrl + K, 打开 查看调用树,如下:


Call tree
调用来自                        函数过程                        调用                              注释
smokefx.004546D1                  smokefx.004544D4                   > smokefx.00402278               ???
smokefx.0045878D                                                   > smokefx.004026DC
smokefx.00458868                                                   > smokefx.004027C0
smokefx.004588EB                                                   > smokefx.00402818
smokefx.00458938                                                   > smokefx.00403AC8               Leaf
smokefx.00458982                                                   > smokefx.00403AF0               ???
                                                                     > smokefx.00403C60               Leaf
                                                                     > smokefx.00403CBC               Leaf
                                                                     > smokefx.00403CEC
                                                                     > smokefx.00403D78
                                                                     > smokefx.00403E50
                                                                     > smokefx.00403E5C
                                                                     > smokefx.00405464               ???
                                                                     > smokefx.00405BAC
                                                                     > smokefx.00405BB8               Leaf
                                                                     > smokefx.00405BC0
                                                                     > smokefx.00405C04
                                                                  smokefx.0044B168                  Leaf
                                                                  smokefx.0044B170                  Leaf
                                                                  smokefx.0044B24C                  ???
                                                                  smokefx.0044B300
                                                                  smokefx.004533E8                  Leaf
                                                                     > kernel32.TlsGetValue         ???
                                                                     > kernel32.WriteFile             ???
                                                                     > kernel32.TlsSetValue         ???
                                                                     > kernel32.LocalAlloc            ???
                                                                     > kernel32.FreeLibrary         ???
                                                                     > kernel32.GetStdHandle          ???
                                                                     > user32.IsWindow                ???
                                                                  user32.GetWindowRect            ???
                                                                  user32.SetWindowPos               ???
                                                                     > user32.EnableWindow            ???
                                                                  user32.SetActiveWindow            ???
                                                                  user32.GetActiveWindow            ???
                                                                  user32.MessageBoxA                ???
                                                                  未知目标


右键菜单中,选择 在每个调用上设置断点,然后继续 F9 跑起来,再次点击 Unlock 按扭,看看到底先在哪个调用上断下来。

经过分析,发现果断断在了如下位置:


004588F5|> \6A 30         PUSH    0x30                                     ;// 注册失败提示处
004588F7|.8D4D D4       LEA   ECX, DWORD PTR SS:
004588FA|.A1 E0A14500   MOV   EAX, DWORD PTR DS:
004588FF|.8B00          MOV   EAX, DWORD PTR DS:
00458901|.8B80 FC020000 MOV   EAX, DWORD PTR DS:
00458907|.8B80 18020000 MOV   EAX, DWORD PTR DS:
0045890D|.BA 05000000   MOV   EDX, 0x5
00458912|.8B18          MOV   EBX, DWORD PTR DS:
00458914|.FF53 0C       CALL    NEAR DWORD PTR DS:
00458917|.8B45 D4       MOV   EAX, DWORD PTR SS:
0045891A|.8D55 D8       LEA   EDX, DWORD PTR SS:
0045891D|.E8 FEF9FFFF   CALL    smokefx.00458320
00458922|.8B45 D8       MOV   EAX, DWORD PTR SS:             ;// 注册码不正确,请重试!
00458925|.E8 FEB9FAFF   CALL    smokefx.00404328
0045892A|.8BD0          MOV   EDX, EAX
0045892C|.B9 F8894500   MOV   ECX, smokefx.004589F8
00458931|.A1 C4A04500   MOV   EAX, DWORD PTR DS:
00458936|.8B00          MOV   EAX, DWORD PTR DS:
00458938|.E8 97BBFFFF   CALL    smokefx.004544D4                         ;// 经过运行,发现果断在此处断了下来。


往上找段首,然后疯狂按 F8 一路分析下去:


004587CC/.55            PUSH    EBP                                    ;// 段首
004587CD|.8BEC          MOV   EBP, ESP
004587CF|.B9 06000000   MOV   ECX, 0x6
004587D4|>6A 00         /PUSH    0x0
004587D6|.6A 00         |PUSH    0x0
004587D8|.49            |DEC   ECX
004587D9|.^ 75 F9         \JNZ   SHORT smokefx.004587D4
004587DB|.51            PUSH    ECX
004587DC|.53            PUSH    EBX
004587DD|.8BD8          MOV   EBX, EAX
004587DF|.33C0          XOR   EAX, EAX
004587E1|.55            PUSH    EBP
004587E2|.68 D4894500   PUSH    smokefx.004589D4
004587E7|.64:FF30       PUSH    DWORD PTR FS:
004587EA|.64:8920       MOV   DWORD PTR FS:, ESP
004587ED|.8D55 FC       LEA   EDX, DWORD PTR SS:
004587F0|.8B83 14030000 MOV   EAX, DWORD PTR DS:
004587F6|.E8 CDBEFDFF   CALL    smokefx.004346C8
004587FB|.837D FC 00    CMP   DWORD PTR SS:, 0x0            ;// 用户名输入了木有?
004587FF|.0F84 3A010000 JE      smokefx.0045893F                         ;// 木有的话,跳到提示你要输入用户名处,否则工作继续。
00458805|.8D55 F8       LEA   EDX, DWORD PTR SS:
00458808|.8B83 14030000 MOV   EAX, DWORD PTR DS:
0045880E|.E8 B5BEFDFF   CALL    smokefx.004346C8
00458813|.8B45 F8       MOV   EAX, DWORD PTR SS:
00458816|.E8 0DBBFAFF   CALL    smokefx.00404328
0045881B|.E8 ECFBFAFF   CALL    smokefx.0040840C
00458820|.83F8 04       CMP   EAX, 0x4                                 ;// 用户名长度是否大于4位数?
00458823|.73 4D         JNB   SHORT smokefx.00458872                   ;// 如果大于4位就跳,否则执行下面的出错提示
00458825|.6A 10         PUSH    0x10
00458827|.8D4D F0       LEA   ECX, DWORD PTR SS:
0045882A|.A1 E0A14500   MOV   EAX, DWORD PTR DS:
0045882F|.8B00          MOV   EAX, DWORD PTR DS:
00458831|.8B80 FC020000 MOV   EAX, DWORD PTR DS:
00458837|.8B80 18020000 MOV   EAX, DWORD PTR DS:
0045883D|.BA 04000000   MOV   EDX, 0x4
00458842|.8B18          MOV   EBX, DWORD PTR DS:
00458844|.FF53 0C       CALL    NEAR DWORD PTR DS:
00458847|.8B45 F0       MOV   EAX, DWORD PTR SS:
0045884A|.8D55 F4       LEA   EDX, DWORD PTR SS:
0045884D|.E8 CEFAFFFF   CALL    smokefx.00458320
00458852|.8B45 F4       MOV   EAX, DWORD PTR SS:            ;// 出错:用户名字符数必须大于4位数
00458855|.E8 CEBAFAFF   CALL    smokefx.00404328
0045885A|.8BD0          MOV   EDX, EAX
0045885C|.B9 E0894500   MOV   ECX, smokefx.004589E0                  ;ASCII 53,"mokeFX ERROR"
00458861|.A1 C4A04500   MOV   EAX, DWORD PTR DS:
00458866|.8B00          MOV   EAX, DWORD PTR DS:
00458868|.E8 67BCFFFF   CALL    smokefx.004544D4                         ;// 调用 出错提示框
0045886D|.E9 15010000   JMP   smokefx.00458987
00458872|>8D55 EC       LEA   EDX, DWORD PTR SS:             ;// 用户名如果大于4位数,则从这里继续往下执行。
00458875|.8B83 18030000 MOV   EAX, DWORD PTR DS:
0045887B|.E8 48BEFDFF   CALL    smokefx.004346C8
00458880|.8B45 EC       MOV   EAX, DWORD PTR SS:             ;// 获取 假码给 EAX
00458883|.50            PUSH    EAX
00458884|.8D55 E4       LEA   EDX, DWORD PTR SS:
00458887|.8B83 14030000 MOV   EAX, DWORD PTR DS:
0045888D|.E8 36BEFDFF   CALL    smokefx.004346C8
00458892|.8B45 E4       MOV   EAX, DWORD PTR SS:             ;// 获取 用户名给 EAX
00458895|.8D55 E8       LEA   EDX, DWORD PTR SS:
00458898|.E8 4BFBFFFF   CALL    smokefx.004583E8                         ;// 核心算法,必须 F7 进入瞅瞅。


F8 走到核心算法,按 F7 进去瞅瞅吧!然后又是从算法的段首开始,一路疯狂地按 F8 继续分析下去:


004583E8/[      DISCUZ_CODE_93      ]nbsp; 55            PUSH    EBP                                    ;// F7 进入后,这里就是算法的段首
004583E9|.8BEC          MOV   EBP, ESP
004583EB|.33C9          XOR   ECX, ECX
004583ED|.51            PUSH    ECX
004583EE|.51            PUSH    ECX
004583EF|.51            PUSH    ECX
004583F0|.51            PUSH    ECX
004583F1|.51            PUSH    ECX
004583F2|.53            PUSH    EBX
004583F3|.56            PUSH    ESI
004583F4|.8BF2          MOV   ESI, EDX
004583F6|.8945 FC       MOV   DWORD PTR SS:, EAX
004583F9|.8B45 FC       MOV   EAX, DWORD PTR SS:
004583FC|.E8 17BFFAFF   CALL    smokefx.00404318
00458401|.33C0          XOR   EAX, EAX                                 ;// EAX 与 EAX 异或,相同值为 0
00458403|.55            PUSH    EBP
00458404|.68 85844500   PUSH    smokefx.00458485
00458409|.64:FF30       PUSH    DWORD PTR FS:
0045840C|.64:8920       MOV   DWORD PTR FS:, ESP
0045840F|.8B45 FC       MOV   EAX, DWORD PTR SS:            ;// 用户名给 EAX
00458412|.E8 11BFFAFF   CALL    smokefx.00404328
00458417|.E8 F0FFFAFF   CALL    smokefx.0040840C
0045841C|.8BD8          MOV   EBX, EAX                                 ;// 用户名长度给 EBX
0045841E|.8D55 F8       LEA   EDX, DWORD PTR SS:
00458421|.8BC3          MOV   EAX, EBX                                 ;// 用户名长度又给 EAX
00458423|.E8 B4F9FAFF   CALL    smokefx.00407DDC
00458428|.FF75 F8       PUSH    DWORD PTR SS:                   ;// 长度值 (即:cxj98 = 5)
0045842B|.8D55 F4       LEA   EDX, DWORD PTR SS:
0045842E|.69C3 9A020000 IMUL    EAX, EBX, 0x29A                        ;// EAX= EBX * 666 (EBX 为用户名长度)
00458434|.E8 A3F9FAFF   CALL    smokefx.00407DDC
00458439|.FF75 F4       PUSH    DWORD PTR SS:                   ;// 计算出值 (用户名 cxj98 为5位数, 5 * 666 = 3330)
0045843C|.8D55 F0       LEA   EDX, DWORD PTR SS:
0045843F|.69C3 FA000000 IMUL    EAX, EBX, 0xFA                           ;// EAX = EBX * 250 (EBX 为用户名长度)
00458445|.E8 92F9FAFF   CALL    smokefx.00407DDC
0045844A|.FF75 F0       PUSH    DWORD PTR SS:                  ;// 计算出值 (用户名 cxj98 为5位数, 5 * 250 = 1250)
0045844D|.8D55 EC       LEA   EDX, DWORD PTR SS:
00458450|.69C3 10270000 IMUL    EAX, EBX, 0x2710                         ;// EAX= EBX * 10000 (EBX 为用户名长度)
00458456|.E8 81F9FAFF   CALL    smokefx.00407DDC
0045845B|.FF75 EC       PUSH    DWORD PTR SS:                  ;// 计算出值 (用户名 cxj98 为5位数, 5 * 10000 = 50000)
0045845E|.8BC6          MOV   EAX, ESI
00458460|.BA 04000000   MOV   EDX, 0x4
00458465|.E8 7EBDFAFF   CALL    smokefx.004041E8
0045846A|.33C0          XOR   EAX, EAX
0045846C|.5A            POP   EDX
0045846D|.59            POP   ECX
0045846E|.59            POP   ECX
0045846F|.64:8910       MOV   DWORD PTR FS:, EDX
00458472|.68 8C844500   PUSH    smokefx.0045848C
00458477|>8D45 EC       LEA   EAX, DWORD PTR SS:
0045847A|.BA 05000000   MOV   EDX, 0x5
0045847F|.E8 08BAFAFF   CALL    smokefx.00403E8C                         ;// 注册码循环比较 call, 这里可以 F7 进入瞅瞅
00458484\.C3            RETN
00458485   .^ E9 E2B3FAFF   JMP   smokefx.0040386C
0045848A   .^ EB EB         JMP   SHORT smokefx.00458477
0045848C   .5E            POP   ESI
0045848D   .5B            POP   EBX
0045848E   .8BE5          MOV   ESP, EBP
00458490   .5D            POP   EBP
00458491   .C3            RETN


F8走到上面这里,也就走出了整个核心算法,来到下面的地址,还是继续疯狂按 F8 一路分析下去:


0045889D|.8B55 E8       MOV   EDX, DWORD PTR SS:             ;// 弹出真码,(即:53330125050000),此处可内存注册机
004588A0|.58            POP   EAX                                    ;// EAX 弹出假码 (即:1234567890)
004588A1|.E8 CEB9FAFF   CALL    smokefx.00404274                         ;// 真假码比较 call,此处无须 F7 进入瞅瞅,可以略过,当然有兴趣的也可以进去一观到底。
004588A6|.75 4D         JNZ   SHORT smokefx.004588F5                   ;// 如果真假码不匹配,则跳向 注册码错误 提示处!
004588A8|.6A 40         PUSH    0x40                                     ;// 注册成功提示处
004588AA|.8D4D DC       LEA   ECX, DWORD PTR SS:
004588AD|.A1 E0A14500   MOV   EAX, DWORD PTR DS:
004588B2|.8B00          MOV   EAX, DWORD PTR DS:
004588B4|.8B80 FC020000 MOV   EAX, DWORD PTR DS:
004588BA|.8B80 18020000 MOV   EAX, DWORD PTR DS:
004588C0|.BA 06000000   MOV   EDX, 0x6
004588C5|.8B18          MOV   EBX, DWORD PTR DS:
004588C7|.FF53 0C       CALL    NEAR DWORD PTR DS:
004588CA|.8B45 DC       MOV   EAX, DWORD PTR SS:
004588CD|.8D55 E0       LEA   EDX, DWORD PTR SS:
004588D0|.E8 4BFAFFFF   CALL    smokefx.00458320
004588D5|.8B45 E0       MOV   EAX, DWORD PTR SS:             ;// 恭喜你成功计算出注册码。
004588D8|.E8 4BBAFAFF   CALL    smokefx.00404328
004588DD|.8BD0          MOV   EDX, EAX
004588DF|.B9 F0894500   MOV   ECX, smokefx.004589F0
004588E4|.A1 C4A04500   MOV   EAX, DWORD PTR DS:
004588E9|.8B00          MOV   EAX, DWORD PTR DS:
004588EB|.E8 E4BBFFFF   CALL    smokefx.004544D4
004588F0|.E9 92000000   JMP   smokefx.00458987
004588F5|>6A 30         PUSH    0x30                                     ;// 注册失败提示处
004588F7|.8D4D D4       LEA   ECX, DWORD PTR SS:
004588FA|.A1 E0A14500   MOV   EAX, DWORD PTR DS:
004588FF|.8B00          MOV   EAX, DWORD PTR DS:
00458901|.8B80 FC020000 MOV   EAX, DWORD PTR DS:
00458907|.8B80 18020000 MOV   EAX, DWORD PTR DS:
0045890D|.BA 05000000   MOV   EDX, 0x5
00458912|.8B18          MOV   EBX, DWORD PTR DS:
00458914|.FF53 0C       CALL    NEAR DWORD PTR DS:
00458917|.8B45 D4       MOV   EAX, DWORD PTR SS:
0045891A|.8D55 D8       LEA   EDX, DWORD PTR SS:
0045891D|.E8 FEF9FFFF   CALL    smokefx.00458320
00458922|.8B45 D8       MOV   EAX, DWORD PTR SS:             ;// 注册码不正确,请重试!
00458925|.E8 FEB9FAFF   CALL    smokefx.00404328
0045892A|.8BD0          MOV   EDX, EAX
0045892C|.B9 F8894500   MOV   ECX, smokefx.004589F8
00458931|.A1 C4A04500   MOV   EAX, DWORD PTR DS:
00458936|.8B00          MOV   EAX, DWORD PTR DS:
00458938|.E8 97BBFFFF   CALL    smokefx.004544D4                         ;// 经过运行,发现果断在此处断了下来。
0045893D|.EB 48         JMP   SHORT smokefx.00458987
0045893F|>6A 20         PUSH    0x20
00458941|.8D4D CC       LEA   ECX, DWORD PTR SS:
00458944|.A1 E0A14500   MOV   EAX, DWORD PTR DS:
00458949|.8B00          MOV   EAX, DWORD PTR DS:
0045894B|.8B80 FC020000 MOV   EAX, DWORD PTR DS:
00458951|.8B80 18020000 MOV   EAX, DWORD PTR DS:
00458957|.BA 03000000   MOV   EDX, 0x3
0045895C|.8B18          MOV   EBX, DWORD PTR DS:
0045895E|.FF53 0C       CALL    NEAR DWORD PTR DS:
00458961|.8B45 CC       MOV   EAX, DWORD PTR SS:
00458964|.8D55 D0       LEA   EDX, DWORD PTR SS:
00458967|.E8 B4F9FFFF   CALL    smokefx.00458320
0045896C|.8B45 D0       MOV   EAX, DWORD PTR SS:
0045896F|.E8 B4B9FAFF   CALL    smokefx.00404328
00458974|.8BD0          MOV   EDX, EAX
00458976|.B9 F0894500   MOV   ECX, smokefx.004589F0
0045897B|.A1 C4A04500   MOV   EAX, DWORD PTR DS:
00458980|.8B00          MOV   EAX, DWORD PTR DS:
00458982|.E8 4DBBFFFF   CALL    smokefx.004544D4
00458987|>33C0          XOR   EAX, EAX
00458989|.5A            POP   EDX
0045898A|.59            POP   ECX
0045898B|.59            POP   ECX
0045898C|.64:8910       MOV   DWORD PTR FS:, EDX
0045898F|.68 DB894500   PUSH    smokefx.004589DB
00458994|>8D45 CC       LEA   EAX, DWORD PTR SS:
00458997|.BA 06000000   MOV   EDX, 0x6
0045899C|.E8 EBB4FAFF   CALL    smokefx.00403E8C
004589A1|.8D45 E4       LEA   EAX, DWORD PTR SS:
004589A4|.E8 BFB4FAFF   CALL    smokefx.00403E68
004589A9|.8D45 E8       LEA   EAX, DWORD PTR SS:
004589AC|.E8 B7B4FAFF   CALL    smokefx.00403E68
004589B1|.8D45 EC       LEA   EAX, DWORD PTR SS:
004589B4|.E8 AFB4FAFF   CALL    smokefx.00403E68
004589B9|.8D45 F0       LEA   EAX, DWORD PTR SS:
004589BC|.BA 02000000   MOV   EDX, 0x2
004589C1|.E8 C6B4FAFF   CALL    smokefx.00403E8C
004589C6|.8D45 F8       LEA   EAX, DWORD PTR SS:
004589C9|.BA 02000000   MOV   EDX, 0x2
004589CE|.E8 B9B4FAFF   CALL    smokefx.00403E8C
004589D3\.C3            RETN


至此,整个算法分析完成,所以对算法有了一个大概的了解。

下面我们就来总结一下这个 KeygenMe 的算法:

注册码 = 用户名长度 & 用户名长度 * 666 & 用户名长度 * 250 & 用户名长度 * 10000
即: sn = lenth(UserName) & Lenth(UserName) * 666 & Lenth(UserName) * 250 & Lenth(UserName) * 10000
因为 cxj98 = 5 位数,
所以 5 & 5 * 666 & 5 * 250 & 5 * 10000 = 5 3330 1250 50000

因此计算出来的注册码为:53330125050000

将计算出来的注册码输入进去,再次点击 Unlock 按扭,果断弹出:


---------------------------
SmokeFX
---------------------------
Congratulations you beat the code :) regards, Wayne Modz
---------------------------
OK   
---------------------------


完毕收工。

本文由 cxj98 原创发表,如果要转载,请保留完整的破文内容等信息,谢谢。

KeygenMe 本地下载:








  

GGLHY 发表于 2014-3-9 20:38:35

第一次离大牛这么近

wgz001 发表于 2014-3-9 20:38:58


都分析算法了

ochchina 发表于 2014-3-9 20:58:41

大牛啊,又看到你了。在那都能看到你犀利的身影啊。 膜拜的。收我为徒吧。。{:lol:}{:lol:}{:lol:}{:lol:}{:lol:}

飞天 发表于 2014-3-9 20:59:38

cxj98是个大牛呀,吾爱常见。

lpxx 发表于 2014-3-9 21:00:50

都往算法方向了,这个非常耗费时间的。

逍遥枷锁 发表于 2014-3-9 21:21:25

这样可以更好的学习下,谢谢老师。

montana 发表于 2014-3-9 21:36:02


第一次离大牛这么近

月之精灵 发表于 2014-3-10 18:09:42

不错,不错,支持下

开心啦 发表于 2014-3-28 14:03:23

来学习一下了,支持大牛
页: [1] 2
查看完整版本: 小菜对 SomkeFX 的 KeygenMe v1.0 的简单算法分析过程