首页
社区
课程
招聘
[原创]“以彼之道,还施彼身”——对付CrackMe之小蜜蜂v1[原创]
发表于: 2007-12-12 10:33 13976

[原创]“以彼之道,还施彼身”——对付CrackMe之小蜜蜂v1[原创]

petnt 活跃值
12
2007-12-12 10:33
13976

【文章标题】: “以彼之道,还施彼身”——对付CrackMe之小蜜蜂v1
【文章作者】: petnt
【作者邮箱】: petnt@sohu.com
【软件名称】: 小蜜蜂V1
【下载地址】: 见附件
【使用工具】: OllyDBG; Stud_PE; UltraEdit_32
【操作平台】: XP SP2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  为了便于总结和以后复习,下面将整个过程分为三部分:下断、分析 和编写注册机。

  第一部分 下断

  其实,如何下断一直是困扰小菜我的一个问题,可能很多新手也会被同样的问题困扰着。无奈好多大侠根本不屑提及此类问题,也只好抱块石头,慢慢品尝其中滋味。真心希望各位大侠在写破文的时候,能顺便提及一下如何下断,小菜在此将不胜感激。
  这个CrackMe的下断确实让我费了不少功夫,在我有限的知识水平内根本断不下来,字符串、API都无从参考。从头跟踪一下,发现小蜜蜂把所有重要的操作都放在了一个附属文件krnln.fnr中。这个文件像是Dll,在被释放后就被加载到进程中了。即使在这个文件中,容易被下断了函数好像也没有直接调用,相关功能小菜我也分析不出他是如何实现的。我虽然用下面的方法断下了程序,但整个过程显得过分的笨拙,希望路过的大侠能从中指点一二。
  OllyDBG载入,F9,Alt+W,我们会发现只有两个 EDIT是保持原貌,其他的控件都已经罩上了马甲。点出小蜜蜂,输入假的用户名和注册码,回到OllyDbg的 windows ,Afx类的行上右键,在ClassProc上切换断点。再次点击小蜜蜂,程序被断在系统领空。观察堆栈我们发现这是个默认的消息处理函数,当然我们关心的并不是这些默认的消息处理,这样做的目的只是为了让我们在点击注册按钮后程序被断下。按住F9,界面会被慢慢的刷出来。鼠标移动到注册按钮之上,按住F9到程序运行,按下左键。程序被断下,Alt+M,选择小蜜蜂的Tls段,右键,设置内存访问断点,双击取消系统领空的断点,F9,程序被断下。(上述过程中省略了数万字的无用过程)

  第二部分 分析

  由于下面过程中涉及到了我不熟悉的指令(好像是浮点操作,更大的原因是跟踪krnln.fnr里面函数的复杂性),下面的分析(特别是对Call的分析)包含了大量的个人猜测成分,仅供参考。

0041E89C    55              push    ebp                       ; 程序被我们断在了这里
0041E89D    8BEC            mov     ebp, esp
0041E89F    81EC 44000000   sub     esp, 44
0041E8A5    C745 FC 0000000>mov     dword ptr [ebp-4], 0
0041E8AC    C745 F8 0000000>mov     dword ptr [ebp-8], 0
0041E8B3    C745 F4 0000000>mov     dword ptr [ebp-C], 0
0041E8BA    6A FF           push    -1
0041E8BC    6A 08           push    8
0041E8BE    68 10000116     push    16010010
0041E8C3    68 01000152     push    52010001
0041E8C8    E8 FC0A0000     call    0041F3C9                  ; 读取用户名
0041E8CD    83C4 10         add     esp, 10
0041E8D0    8945 F0         mov     [ebp-10], eax
0041E8D3    68 04000080     push    80000004
0041E8D8    6A 00           push    0
0041E8DA    8B45 F0         mov     eax, [ebp-10]
0041E8DD    85C0            test    eax, eax
0041E8DF    75 05           jnz     short 0041E8E6            ; 用户名为空不跳
0041E8E1    B8 8A014100     mov     eax, 0041018A
0041E8E6    50              push    eax
0041E8E7    68 01000000     push    1
0041E8EC    BB 30010000     mov     ebx, 130
0041E8F1    E8 B50A0000     call    0041F3AB                  ; 获取用户名长度
0041E8F6    83C4 10         add     esp, 10
0041E8F9    8945 EC         mov     [ebp-14], eax
0041E8FC    8B5D F0         mov     ebx, [ebp-10]
0041E8FF    85DB            test    ebx, ebx                  ; 
0041E901    74 09           je      short 0041E90C
0041E903    53              push    ebx
0041E904    E8 AE0A0000     call    0041F3B7                  ; 好像是清理工作
0041E909    83C4 04         add     esp, 4
0041E90C    8B45 EC         mov     eax, [ebp-14]
0041E90F    33C9            xor     ecx, ecx
0041E911    50              push    eax
0041E912    8D45 FC         lea     eax, [ebp-4]
0041E915    8BD8            mov     ebx, eax
0041E917    58              pop     eax
0041E918    41              inc     ecx
0041E919    51              push    ecx
0041E91A    53              push    ebx
0041E91B    890B            mov     [ebx], ecx
0041E91D    50              push    eax
0041E91E    3BC8            cmp     ecx, eax                  ; 用用户名长度构造循环
0041E920    0F8F 17010000   jg      0041EA3D                  ; 不小于 转移
0041E926    6A FF           push    -1
0041E928    6A 08           push    8
0041E92A    68 10000116     push    16010010
0041E92F    68 01000152     push    52010001
0041E934    E8 900A0000     call    0041F3C9                  ; 获取用户名
0041E939    83C4 10         add     esp, 10
0041E93C    8945 F0         mov     [ebp-10], eax
0041E93F    68 01030080     push    80000301
0041E944    6A 00           push    0
0041E946    FF75 FC         push    dword ptr [ebp-4]         ; 循环数
0041E949    68 04000080     push    80000004
0041E94E    6A 00           push    0
0041E950    8B45 F0         mov     eax, [ebp-10]
0041E953    85C0            test    eax, eax                  ; 判断用户名是否为空
0041E955    75 05           jnz     short 0041E95C
0041E957    B8 8A014100     mov     eax, 0041018A
0041E95C    50              push    eax
0041E95D    68 02000000     push    2
0041E962    BB 44010000     mov     ebx, 144
0041E967    E8 3F0A0000     call    0041F3AB                  ; 取用户名第循环数位
0041E96C    83C4 1C         add     esp, 1C
0041E96F    8945 EC         mov     [ebp-14], eax
0041E972    8B5D F0         mov     ebx, [ebp-10]
0041E975    85DB            test    ebx, ebx                  ; 用户名是否为空
0041E977    74 09           je      short 0041E982
0041E979    53              push    ebx
0041E97A    E8 380A0000     call    0041F3B7
0041E97F    83C4 04         add     esp, 4
0041E982    DB45 EC         fild    dword ptr [ebp-14]
0041E985    DD5D E4         fstp    qword ptr [ebp-1C]
0041E988    DD45 E4         fld     qword ptr [ebp-1C]
0041E98B    DC05 8B014100   fadd    qword ptr [41018B]        ; 公用变量 27.000000000
0041E991    DD5D DC         fstp    qword ptr [ebp-24]
0041E994    DD45 DC         fld     qword ptr [ebp-24]
0041E997    DC0D 93014100   fmul    qword ptr [410193]        ; 公用变量 4.0000000000
0041E99D    DD5D D4         fstp    qword ptr [ebp-2C]
0041E9A0    68 01060080     push    80000601
0041E9A5    68 00003B40     push    403B0000
0041E9AA    68 00000000     push    0
0041E9AF    68 01060080     push    80000601
0041E9B4    FF75 D8         push    dword ptr [ebp-28]
0041E9B7    FF75 D4         push    dword ptr [ebp-2C]
0041E9BA    68 02000000     push    2
0041E9BF    BB 48000000     mov     ebx, 48
0041E9C4    E8 E2090000     call    0041F3AB                  ; 注意 Eax and Edx
0041E9C9    83C4 1C         add     esp, 1C
0041E9CC    8945 C4         mov     [ebp-3C], eax
0041E9CF    8955 C8         mov     [ebp-38], edx
0041E9D2    DD45 C4         fld     qword ptr [ebp-3C]
0041E9D5    E8 71FAFFFF     call    0041E44B                  ; 变换 Eax  正确注册码
0041E9DA    68 01030080     push    80000301
0041E9DF    6A 00           push    0
0041E9E1    50              push    eax
0041E9E2    68 01000000     push    1
0041E9E7    BB D4010000     mov     ebx, 1D4
0041E9EC    E8 BA090000     call    0041F3AB                  ; 是将Eax 转换成 ASCII
0041E9F1    83C4 10         add     esp, 10
0041E9F4    8945 C0         mov     [ebp-40], eax
0041E9F7    FF75 C0         push    dword ptr [ebp-40]
0041E9FA    FF75 F8         push    dword ptr [ebp-8]
0041E9FD    B9 02000000     mov     ecx, 2
0041EA02    E8 9CFDFFFF     call    0041E7A3                  ; 合并 字符串
0041EA07    83C4 08         add     esp, 8
0041EA0A    8945 BC         mov     [ebp-44], eax
0041EA0D    8B5D C0         mov     ebx, [ebp-40]
0041EA10    85DB            test    ebx, ebx
0041EA12    74 09           je      short 0041EA1D
0041EA14    53              push    ebx
0041EA15    E8 9D090000     call    0041F3B7
0041EA1A    83C4 04         add     esp, 4
0041EA1D    8B45 BC         mov     eax, [ebp-44]
0041EA20    50              push    eax
0041EA21    8B5D F8         mov     ebx, [ebp-8]
0041EA24    85DB            test    ebx, ebx
0041EA26    74 09           je      short 0041EA31
0041EA28    53              push    ebx
0041EA29    E8 89090000     call    0041F3B7
0041EA2E    83C4 04         add     esp, 4
0041EA31    58              pop     eax
0041EA32    8945 F8         mov     [ebp-8], eax
0041EA35    58              pop     eax
0041EA36    5B              pop     ebx
0041EA37    59              pop     ecx
0041EA38  ^ E9 DBFEFFFF     jmp     0041E918                  ; 循环完毕将产生注册码中间部分
0041EA3D    83C4 0C         add     esp, 0C
0041EA40    837D FC 02      cmp     dword ptr [ebp-4], 2      ; cmp 用户名长度+1,2
0041EA44    0F8E D5000000   jle     0041EB1F
0041EA4A    6A FF           push    -1
0041EA4C    6A 08           push    8
0041EA4E    68 11000116     push    16010011
0041EA53    68 01000152     push    52010001
0041EA58    E8 6C090000     call    0041F3C9                  ; 读取注册码
0041EA5D    83C4 10         add     esp, 10
0041EA60    8945 EC         mov     [ebp-14], eax
0041EA63    68 01030080     push    80000301
0041EA68    6A 00           push    0
0041EA6A    68 04000000     push    4
0041EA6F    68 04000080     push    80000004
0041EA74    6A 00           push    0
0041EA76    8B45 EC         mov     eax, [ebp-14]
0041EA79    85C0            test    eax, eax
0041EA7B    75 05           jnz     short 0041EA82            ; 注册码是否为空
0041EA7D    B8 8A014100     mov     eax, 0041018A
0041EA82    50              push    eax
0041EA83    68 02000000     push    2
0041EA88    BB 38010000     mov     ebx, 138
0041EA8D    E8 19090000     call    0041F3AB                  ; 取 注册码 后四位
0041EA92    83C4 1C         add     esp, 1C
0041EA95    8945 E8         mov     [ebp-18], eax
0041EA98    8B5D EC         mov     ebx, [ebp-14]
0041EA9B    85DB            test    ebx, ebx
0041EA9D    74 09           je      short 0041EAA8            ; 注册码是否为空
0041EA9F    53              push    ebx
0041EAA0    E8 12090000     call    0041F3B7
0041EAA5    83C4 04         add     esp, 4
0041EAA8    68 6A000000     push    6A                        ; 
0041EAAD    B8 9B014100     mov     eax, 0041019B             ; 
0041EAB2    8945 E4         mov     [ebp-1C], eax
0041EAB5    8D45 E4         lea     eax, [ebp-1C]
0041EAB8    50              push    eax
0041EAB9    E8 98060000     call    0041F156                  ; 产生注册码 后四位
0041EABE    8945 E0         mov     [ebp-20], eax
0041EAC1    8B5D E4         mov     ebx, [ebp-1C]
0041EAC4    85DB            test    ebx, ebx
0041EAC6    74 09           je      short 0041EAD1
0041EAC8    53              push    ebx
0041EAC9    E8 E9080000     call    0041F3B7
0041EACE    83C4 04         add     esp, 4
0041EAD1    8B45 E0         mov     eax, [ebp-20]
0041EAD4    50              push    eax
0041EAD5    FF75 E8         push    dword ptr [ebp-18]
0041EAD8    E8 22FDFFFF     call    0041E7FF                  ;比较 注册码后四位
0041EADD    83C4 08         add     esp, 8
0041EAE0    83F8 00         cmp     eax, 0
0041EAE3    B8 00000000     mov     eax, 0
0041EAE8    0F94C0          sete    al
0041EAEB    8945 DC         mov     [ebp-24], eax
0041EAEE    8B5D E8         mov     ebx, [ebp-18]
0041EAF1    85DB            test    ebx, ebx
0041EAF3    74 09           je      short 0041EAFE
0041EAF5    53              push    ebx
0041EAF6    E8 BC080000     call    0041F3B7
0041EAFB    83C4 04         add     esp, 4
0041EAFE    8B5D E0         mov     ebx, [ebp-20]
0041EB01    85DB            test    ebx, ebx
0041EB03    74 09           je      short 0041EB0E
0041EB05    53              push    ebx
0041EB06    E8 AC080000     call    0041F3B7
0041EB0B    83C4 04         add     esp, 4
0041EB0E    837D DC 00      cmp     dword ptr [ebp-24], 0     ; 判断比较结果
0041EB12    0F84 07000000   je      0041EB1F                  ; 关键跳转
0041EB18    B8 01000000     mov     eax, 1
0041EB1D    EB 02           jmp     short 0041EB21
0041EB1F    33C0            xor     eax, eax                  ; 用户名<2跳入点
0041EB21    85C0            test    eax, eax
0041EB23    0F84 CD050000   je      0041F0F6
0041EB29    68 01030080     push    80000301
0041EB2E    6A 00           push    0
0041EB30    68 04000000     push    4
0041EB35    68 01030080     push    80000301
0041EB3A    6A 00           push    0
0041EB3C    68 01000000     push    1
0041EB41    68 02000000     push    2
0041EB46    BB 94000000     mov     ebx, 94
0041EB4B    E8 5B080000     call    0041F3AB                  ; 
0041EB50    83C4 1C         add     esp, 1C
0041EB53    8945 F0         mov     [ebp-10], eax
0041EB56    68 01030080     push    80000301
0041EB5B    6A 00           push    0
0041EB5D    68 F2000000     push    0F2
0041EB62    68 01030080     push    80000301
0041EB67    6A 00           push    0
0041EB69    FF75 F0         push    dword ptr [ebp-10]
0041EB6C    68 01030080     push    80000301
0041EB71    6A 00           push    0
0041EB73    68 0A000000     push    0A
0041EB78    68 03000000     push    3
0041EB7D    BB 10000000     mov     ebx, 10
0041EB82    B8 01000000     mov     eax, 1
0041EB87    E8 25080000     call    0041F3B1
0041EB8C    83C4 28         add     esp, 28
0041EB8F    6A FF           push    -1
0041EB91    6A 08           push    8
0041EB93    68 11000116     push    16010011
0041EB98    68 01000152     push    52010001
0041EB9D    E8 27080000     call    0041F3C9                  ; 取注册码
0041EBA2    83C4 10         add     esp, 10
0041EBA5    8945 F0         mov     [ebp-10], eax
0041EBA8    68 01030080     push    80000301
0041EBAD    6A 00           push    0
0041EBAF    68 13000000     push    13
0041EBB4    68 04000080     push    80000004
0041EBB9    6A 00           push    0
0041EBBB    8B45 F0         mov     eax, [ebp-10]
0041EBBE    85C0            test    eax, eax
0041EBC0    75 05           jnz     short 0041EBC7            ; 是否为空
0041EBC2    B8 8A014100     mov     eax, 0041018A
0041EBC7    50              push    eax
0041EBC8    68 02000000     push    2
0041EBCD    BB 34010000     mov     ebx, 134
0041EBD2    E8 D4070000     call    0041F3AB                  ; 取注册码前19位
0041EBD7    83C4 1C         add     esp, 1C
0041EBDA    8945 EC         mov     [ebp-14], eax
0041EBDD    8B5D F0         mov     ebx, [ebp-10]
0041EBE0    85DB            test    ebx, ebx
0041EBE2    74 09           je      short 0041EBED
0041EBE4    53              push    ebx
0041EBE5    E8 CD070000     call    0041F3B7
0041EBEA    83C4 04         add     esp, 4
0041EBED    68 4F000000     push    4F
0041EBF2    B8 A0014100     mov     eax, 004101A0
0041EBF7    8945 E8         mov     [ebp-18], eax
0041EBFA    8D45 E8         lea     eax, [ebp-18]
0041EBFD    50              push    eax
0041EBFE    E8 53050000     call    0041F156                  ; 产生注册码前19位
0041EC03    8945 E4         mov     [ebp-1C], eax
0041EC06    8B5D E8         mov     ebx, [ebp-18]
0041EC09    85DB            test    ebx, ebx
0041EC0B    74 09           je      short 0041EC16
0041EC0D    53              push    ebx
0041EC0E    E8 A4070000     call    0041F3B7
0041EC13    83C4 04         add     esp, 4
0041EC16    8B45 E4         mov     eax, [ebp-1C]
0041EC19    50              push    eax
0041EC1A    FF75 EC         push    dword ptr [ebp-14]
0041EC1D    E8 DDFBFFFF     call    0041E7FF                  ; 比较前19位
0041EC22    83C4 08         add     esp, 8
0041EC25    83F8 00         cmp     eax, 0
0041EC28    B8 00000000     mov     eax, 0
0041EC2D    0F94C0          sete    al
0041EC30    8945 E0         mov     [ebp-20], eax
0041EC33    8B5D EC         mov     ebx, [ebp-14]
0041EC36    85DB            test    ebx, ebx
0041EC38    74 09           je      short 0041EC43
0041EC3A    53              push    ebx
0041EC3B    E8 77070000     call    0041F3B7
0041EC40    83C4 04         add     esp, 4
0041EC43    8B5D E4         mov     ebx, [ebp-1C]
0041EC46    85DB            test    ebx, ebx
0041EC48    74 09           je      short 0041EC53
0041EC4A    53              push    ebx
0041EC4B    E8 67070000     call    0041F3B7
0041EC50    83C4 04         add     esp, 4
0041EC53    837D E0 00      cmp     dword ptr [ebp-20], 0     ; 测试比较结果
0041EC57    0F84 58040000   je      0041F0B5                  ; 第二处关键跳转
0041EC5D    6A FF           push    -1
0041EC5F    6A 08           push    8
0041EC61    68 11000116     push    16010011
0041EC66    68 01000152     push    52010001
0041EC6B    E8 59070000     call    0041F3C9                 ; 读入注册码

;...;中间省略代码用读入的注册码通过变换得到另一组
;...;中加码,由于此段代码过长且与我们的分析关系
;...;不大,故省略。

0041EF1E    E8 DCF8FFFF     call    0041E7FF                  ; 比较 用户名 和 中间码
0041EF23    83C4 08         add     esp, 8
0041EF26    83F8 00         cmp     eax, 0
0041EF29    B8 00000000     mov     eax, 0
0041EF2E    0F95C0          setne   al
0041EF31    8945 E4         mov     [ebp-1C], eax
0041EF34    8B5D E8         mov     ebx, [ebp-18]
0041EF37    85DB            test    ebx, ebx
0041EF39    74 09           je      short 0041EF44
0041EF3B    53              push    ebx
0041EF3C    E8 76040000     call    0041F3B7
0041EF41    83C4 04         add     esp, 4
0041EF44    837D E4 00      cmp     dword ptr [ebp-1C], 0     ; 测试上面比较结果
0041EF48    0F84 62010000   je      0041F0B0                  ; 跳转的话 将没有任何提示信息返回
0041EF4E    68 04000080     push    80000004
0041EF53    6A 00           push    0
0041EF55    8B45 F8         mov     eax, [ebp-8]
0041EF58    85C0            test    eax, eax
0041EF5A    75 05           jnz     short 0041EF61
0041EF5C    B8 8A014100     mov     eax, 0041018A
0041EF61    50              push    eax
0041EF62    68 01000000     push    1
0041EF67    BB 30010000     mov     ebx, 130
0041EF6C    E8 3A040000     call    0041F3AB                  ; 取得注册码中间部分长度
0041EF71    83C4 10         add     esp, 10
0041EF74    8945 F0         mov     [ebp-10], eax
0041EF77    6A FF           push    -1
0041EF79    6A 08           push    8
0041EF7B    68 11000116     push    16010011
0041EF80    68 01000152     push    52010001
0041EF85    E8 3F040000     call    0041F3C9                  ; 读入注册码
0041EF8A    83C4 10         add     esp, 10
0041EF8D    8945 EC         mov     [ebp-14], eax
0041EF90    68 01030080     push    80000301
0041EF95    6A 00           push    0
0041EF97    FF75 F0         push    dword ptr [ebp-10]
0041EF9A    68 01030080     push    80000301
0041EF9F    6A 00           push    0
0041EFA1    68 14000000     push    14
0041EFA6    68 04000080     push    80000004
0041EFAB    6A 00           push    0
0041EFAD    8B45 EC         mov     eax, [ebp-14]
0041EFB0    85C0            test    eax, eax
0041EFB2    75 05           jnz     short 0041EFB9
0041EFB4    B8 8A014100     mov     eax, 0041018A
0041EFB9    50              push    eax
0041EFBA    68 03000000     push    3
0041EFBF    BB 3C010000     mov     ebx, 13C
0041EFC4    E8 E2030000     call    0041F3AB                  ; 取输入注册码的中间部分
0041EFC9    83C4 28         add     esp, 28
0041EFCC    8945 E8         mov     [ebp-18], eax
0041EFCF    8B5D EC         mov     ebx, [ebp-14]
0041EFD2    85DB            test    ebx, ebx
0041EFD4    74 09           je      short 0041EFDF
0041EFD6    53              push    ebx
0041EFD7    E8 DB030000     call    0041F3B7
0041EFDC    83C4 04         add     esp, 4
0041EFDF    8B45 F8         mov     eax, [ebp-8]
0041EFE2    50              push    eax
0041EFE3    FF75 E8         push    dword ptr [ebp-18]
0041EFE6    E8 14F8FFFF     call    0041E7FF                  ; 比较注册码 中间部分
0041EFEB    83C4 08         add     esp, 8
0041EFEE    83F8 00         cmp     eax, 0
0041EFF1    B8 00000000     mov     eax, 0
0041EFF6    0F95C0          setne   al
0041EFF9    8945 E4         mov     [ebp-1C], eax
0041EFFC    8B5D E8         mov     ebx, [ebp-18]
0041EFFF    85DB            test    ebx, ebx
0041F001    74 09           je      short 0041F00C
0041F003    53              push    ebx
0041F004    E8 AE030000     call    0041F3B7
0041F009    83C4 04         add     esp, 4
0041F00C    837D E4 00      cmp     dword ptr [ebp-1C], 0     ; 测试比较结果
0041F010    0F84 41000000   je      0041F057                  ; 第三处关键点 跳向成功
0041F016    68 02000080     push    80000002                  ; 注册码中间部分 比较失败跳入点
0041F01B    6A 00           push    0
0041F01D    68 01000000     push    1
0041F022    68 01000100     push    10001
0041F027    68 00000106     push    6010000
0041F02C    68 01000152     push    52010001
0041F031    68 01000100     push    10001
0041F036    68 23000106     push    6010023
0041F03B    68 24000152     push    52010024
0041F040    68 03000000     push    3
0041F045    BB 20030000     mov     ebx, 320
0041F04A    E8 5C030000     call    0041F3AB                  ; 提示失败
0041F04F    83C4 28         add     esp, 28
0041F052    E9 59000000     jmp     0041F0B0
0041F057    6A 00           push    0                         ; 成功跳入点
0041F059    68 01000000     push    1
0041F05E    6A FF           push    -1
0041F060    6A 0E           push    0E
0041F062    68 00000106     push    6010000
0041F067    68 01000152     push    52010001
0041F06C    E8 52030000     call    0041F3C3
0041F071    83C4 18         add     esp, 18
0041F074    68 02000080     push    80000002
0041F079    6A 00           push    0
0041F07B    68 01000000     push    1
0041F080    68 01000100     push    10001
0041F085    68 00000106     push    6010000
0041F08A    68 01000152     push    52010001
0041F08F    68 01000100     push    10001
0041F094    68 21000106     push    6010021
0041F099    68 22000152     push    52010022
0041F09E    68 03000000     push    3
0041F0A3    BB 20030000     mov     ebx, 320
0041F0A8    E8 FE020000     call    0041F3AB                  ; 提示成功
0041F0AD    83C4 28         add     esp, 28
0041F0B0    E9 3C000000     jmp     0041F0F1                  ; 成功返回路径
0041F0B5    68 02000080     push    80000002                  ; 前19为比较失败 跳入点
0041F0BA    6A 00           push    0
0041F0BC    68 01000000     push    1
0041F0C1    68 01000100     push    10001
0041F0C6    68 00000106     push    6010000
0041F0CB    68 01000152     push    52010001
0041F0D0    68 01000100     push    10001
0041F0D5    68 23000106     push    6010023
0041F0DA    68 24000152     push    52010024
0041F0DF    68 03000000     push    3
0041F0E4    BB 20030000     mov     ebx, 320
0041F0E9    E8 BD020000     call    0041F3AB                  ; 提示 失败
0041F0EE    83C4 28         add     esp, 28
0041F0F1    E9 3C000000     jmp     0041F132                  ; 成功返回路径
0041F0F6    68 02000080     push    80000002                  ; 后四 比较失败跳入点 用户名<2跳入点
0041F0FB    6A 00           push    0
0041F0FD    68 01000000     push    1
0041F102    68 01000100     push    10001
0041F107    68 00000106     push    6010000
0041F10C    68 01000152     push    52010001
0041F111    68 01000100     push    10001
0041F116    68 23000106     push    6010023
0041F11B    68 24000152     push    52010024
0041F120    68 03000000     push    3
0041F125    BB 20030000     mov     ebx, 320
0041F12A    E8 7C020000     call    0041F3AB                  ; 提示 失败
0041F12F    83C4 28         add     esp, 28
0041F132    8B5D F8         mov     ebx, [ebp-8]              ; 成功返回路径
0041F135    85DB            test    ebx, ebx
0041F137    74 09           je      short 0041F142
0041F139    53              push    ebx
0041F13A    E8 78020000     call    0041F3B7                  ; 清理工作
0041F13F    83C4 04         add     esp, 4
0041F142    8B5D F4         mov     ebx, [ebp-C]
0041F145    85DB            test    ebx, ebx
0041F147    74 09           je      short 0041F152
0041F149    53              push    ebx
0041F14A    E8 68020000     call    0041F3B7                  ; 清理工作
0041F14F    83C4 04         add     esp, 4
0041F152    8BE5            mov     esp, ebp
0041F154    5D              pop     ebp
0041F155    C3              retn                              ; 返回

  整理分析思路:(顺序即程序流程)

  1. 利用用户名经过算法变换,得到注册码中间部分。
  2. 比较用户名是否<2,是则跳向失败。
  3. 计算出注册码后4位,并与输入的注册码后4位进行比较,不符则跳向失败。
  4. 计算出注册码前19位,并与输入的注册码前19位进行比较,不符则跳向失败。
  5. 利用输入的假注册码,变换得到一中间码,与输入的用户名比较,相符则无提示返回。(省略部分)
  6. 取输入的假注册码的中间部分,与计算所得的注册码中间部分相比,不符则跳向失败。
  7. 前面的2,3,4,6部分均走向成功的话,表明注册成功。

  注: 前面3,4中提到注册码及注册码位数与输入的用户名无关,是否与个人机器码相关我没有分析。前面6中的取假注册码中间部分的取法是从前面取,意即是越过4中的位数取的。
  我们先不谈算法,先来看看我们发现的有趣的事情,即小蜜蜂只关心注册码的后4位,前19位,以及紧跟在前19后面的n位,并没有审核注册码的总长度。也就是说我们可以在得到注册码后,在注册码的第19+n位后,后4位前加入任何字符,都同样可以注册成功。哪怕你加入的是斗大的汉字:小蜜蜂,嗡嗡翁!
  同样的道理,我们会发现注册码的中间部分是根据用户名按位计算取得的,意即同样的字符产生同样的注册码。结合上面的分析很容易知道:如果name1仅仅是比name2短几位(其余对应位字符相同)的话,name1用name2的注册码同样会注册成功。例如: 我用petnt得到的注册码,同样适用于 pe、 pet、 petn。
  一句话概括我们的发现:用户名和注册码并不一一对应。

  第三部分 编写注册机

  其实,破文之所以取上面的名字,就源于这一部分。经过上面的分析,我本想再跟踪一下算法写出注册机。但是我不得不把责任再一次推向那个可恶的krnln.fnr,那里面的函数一层层call的我头晕脑涨,而且它的参数是大都是一些莫名其妙的数字,并且不断的使用公用变量。这些使我不得不放弃了跟踪算法的想法。难道就这样眼睁睁的放走他?

  “授权任意人士可随时随地的随意对本软件进行反汇编,反编译,修改或分解等另类操作。”(引自小蜜蜂《免责声明》中程序授权第5条)

  哈哈,看来我们的权利还真不小。经过算法分析我们看出,虽然注册码比较分了三部分,但每一部分都用的明码比较,也就是说在程序中存在着我们想要的东西,只是我们看不到他。呵呵,可能你我已经想到了一起:把程序搬上手术台,取出我们想得到的东西,并且把它挂在脸上。(好象有些不人道,总感觉对不起小蜜蜂。) 

  请出Stud_PE,对我们的想法进行一下可行性分析:

No  | Name      | VSize      | VOffset    | RSize      | ROffset    | Charact.   | 
01  | .text     | 00005A77   | 00001000   | 00006000   | 00001000   | 60000020   | 
02  | .rdata    | 00000AB4   | 00007000   | 00001000   | 00007000   | 40000040   | 
03  | .data     | 00003FA0   | 00008000   | 00004000   | 00008000   | C0000040   | 
04  | .tls      | 00014000   | 0000C000   | 00014000   | 0000C000   | E0000040   | 
05  | .rsrc     | 00000D60   | 00020000   | 00001000   | 00020000   | 40000040   | 
*   | ExtraDat  |            |            | 0005BAC1   | 00021000   |            |

  代码段、数据段都有足够的空间给我们用,可以实施手术。就连各段的VOffset和ROffset都相等,真是天公作美啊。准备动手!

  别急,还是理一下思路吧。

  1. 改变程序流程,让我们想看到的都出现。
  2. 寻找合适的地方,引走程序,完成任务后再引回来。
  3. 清理现场,美化程序。

  第一步应该比较简单,只要把关键跳转部分改动以下,程序就会乖乖的给我们计算注册码。改动如下:

  第一处 0041eb12  0f 84 07 00 00 00   -> 90 90 90 90 90 90
  第二处 0041ec57  0f 84 58 04 00 00   -> 90 90 90 90 90 90
  第三处 0041f010  0f 84 41 00 00 00   -> eb 45 90 90 90 90
  
  其实上面的工作相当于一次爆破。经过上面改动后,除注册名长度<2回注册失败外,其余各种情况均会注册成功。
  
  第二步要复杂一些,我们同样要选择合适的改动地方。我选的两处是:0041ead8、0041ec1d。

  之所以选这两处,最重要的原因当然是程序运行到这里的时候,正确的注册码刚好在堆栈或寄存器中。其二jmp 和 call 同样是条5字节指令,而且在这个例子中,这两条指令的最后一个字节都是FF,所以,我们只相当于修改了4字节,这样我们就可以很方便的进行恢复了。在代码段的空白处选两个合适的位置,准备放我们的处理指令。具体修改如下:

  第一处  0041ead8   e8 22 fd ff -> e9 9a 7f fe
    
  补丁程序内存中地址 00406a77 (此段程序我们将获得注册码后4位),具体代码如下:

00406A77      60            pushad                                             ;保存现场
00406A78      8BF0          mov     esi, eax                                   ;Eax中即注册码后四位的地址
00406A7A      BF 00984000   mov     edi, 00409800                              ;注册码后4位存放地址
00406A7F      33C9          xor     ecx, ecx
00406A81      33DB          xor     ebx, ebx
00406A83      0FB61418      movzx   edx, byte ptr [eax+ebx]
00406A87      41            inc     ecx
00406A88      43            inc     ebx
00406A89      83FA 00       cmp     edx, 0
00406A8C    ^ 75 F5         jnz     short 00406A83
00406A8E      F3:A4         rep     movs byte ptr es:[edi], byte ptr [esi]
00406A90      B8 E822FDFF   mov     eax, FFFD22E8                              ;恢复原指令
00406A95      A3 D8EA4100   mov     [41EAD8], eax
00406A9A      61            popad                                              ;恢复现场
00406A9B    - E9 38800100   jmp     0041EAD8

  第二处  0041ec1d   e8 dd fb ff -> e9 8b 7e fe

  补丁程序地址 00406aad (此段程序我们将获得注册码的前19位 和 中间n位),具体代码如下:

00406AAD      60            pushad
00406AAE      8BF0          mov     esi, eax                              ;Eax 为注册码前19位
00406AB0      BF 80984000   mov     edi, 00409880                         ;存放地址
00406AB5      33C9          xor     ecx, ecx
00406AB7      33DB          xor     ebx, ebx
00406AB9      0FB61418      movzx   edx, byte ptr [eax+ebx]
00406ABD      41            inc     ecx
00406ABE      43            inc     ebx
00406ABF      83FA 00       cmp     edx, 0
00406AC2    ^ 75 F5         jnz     short 00406AB9
00406AC4      F3:A4         rep     movs byte ptr es:[edi], byte ptr [esi]
00406AC6      8BEC          mov     ebp, esp
00406AC8      8B45 28       mov     eax, [ebp+28]                         ;这个栈址中放着注册码中间部分
00406ACB      8BF0          mov     esi, eax
00406ACD      BF 40984000   mov     edi, 00409840                         ;存放地址
00406AD2      33C9          xor     ecx, ecx
00406AD4      33DB          xor     ebx, ebx
00406AD6      0FB61418      movzx   edx, byte ptr [eax+ebx]
00406ADA      41            inc     ecx
00406ADB      43            inc     ebx
00406ADC      83FA 00       cmp     edx, 0
00406ADF    ^ 75 F5         jnz     short 00406AD6
00406AE1      F3:A4         rep     movs byte ptr es:[edi], byte ptr [esi]
00406AE3      B8 E8DDFBFF   mov     eax, FFFBDDE8
00406AE8      A3 1DEC4100   mov     [41EC1D], eax
00406AED      61            popad
00406AEE    - E9 2A810100   jmp     0041EC1D
  
  好了,经过以上修改,我们程序会在每次的注册码验证过程中,将正确的注册码存放在固定的3个位置上。下面的任务上如何想办法将正确的注册码合并并显示在编辑框中。

  在这之前,我们先来美化下程序吧。我们总不能让注册码显示在编辑框的同时还弹出正确或者错误的提示框吧,我们先把这些没用的指令nop掉。根据分析我们应该nop的两处如下:

  0001f057---------0001f0af  nop(提示注册成功的地方)
  0001f0f6---------0001f131  nop(由于用户名太短而提示失败的地方)
  
  我们nop出了好多空间,这里可以很方便的加入我们的代码了,不用到处找了。好了,该是我们考虑如何实现想法的时候了。幸运的是程序导入表中有两个重要的函数,LoadLibrary 和 GetProcAddress。有了他们两个我们还有什么事不能做呢?为了方便灵活的写我们的代码,同样只是在空空的nop处用jmp指令跳出。

  注册成功的地方,应该放我们合并并显示注册码的代码。具体修改及代码如下:

  0041f060 处   90 90 90 90 90 -> e9 9b 7a fe ff
  
  00406b00 处 存放处理程序 :
 
00406B00      60            pushad
00406B01      B8 E99A7FFE   mov     eax, FE7F9AE9
00406B06      A3 D8EA4100   mov     [41EAD8], eax
00406B0B      B8 E98B7EFE   mov     eax, FE7E8BE9
00406B10      A3 1DEC4100   mov     [41EC1D], eax
00406B15      68 3C964000   push    0040963C                        ;  ASCII "User32.dll"
00406B1A      FF15 04704000 call    [407004]                        ;  LoadLibray
00406B20      50            push    eax
00406B21      68 30964000   push    00409630                        ;  ASCII "FindWindowA"
00406B26      50            push    eax
00406B27      FF15 00704000 call    [407000]                        ;  GetProcAddress
00406B2D      A3 20974000   mov     [409720], eax
00406B32      58            pop     eax
00406B33      68 53964000   push    00409653                        ;  ASCII "SetDlgItemTextA"
00406B38      50            push    eax
00406B39      FF15 00704000 call    [407000]                      
00406B3F      A3 28974000   mov     [409728], eax
00406B44      68 40984000   push    00409840                       
00406B49      68 80984000   push    00409880                   
00406B4E      E8 CD000000   call    00406C20                        ; 自定义字符串合并程序
00406B53      68 00984000   push    00409800                     
00406B58      68 80984000   push    00409880                  
00406B5D      E8 BE000000   call    00406C20
00406B62      68 29964000   push    00409629                        ;  存放窗口名
00406B67      68 6B964000   push    0040966B                        ;  ASCII "Afx:10000000:b:10011:1900015:0"
00406B6C      FF15 20974000 call    [409720]                        ;  USER32.FindWindowA
00406B72      68 80984000   push    00409880                        ;  
00406B77      68 AA000000   push    0AA
00406B7C      50            push    eax                             ;  窗口句柄
00406B7D      FF15 28974000 call    [409728]                        ;  USER32.SetDlgItemTextA
00406B83      61            popad
00406B84    - E9 DC840100   jmp     0041F065

  值得注意的是,上面的处理过程中,我们用到了很多预定义的字符串,请事先加入到数据段的固定位置。另外不得不说两句的是我居然没有找到ASCII字符串合并函数,不知是MS根本没写还是我没找到(有StrCatW,却没有A的),郁闷的我只能自己写一个来实现了。代码如下:

00406C20      55            push    ebp
00406C21      8BEC          mov     ebp, esp
00406C23      60            pushad
00406C24      FC            cld
00406C25      8B75 0C       mov     esi, [ebp+C]
00406C28      8B7D 08       mov     edi, [ebp+8]
00406C2B      33C9          xor     ecx, ecx
00406C2D      33DB          xor     ebx, ebx
00406C2F      0FB6143B      movzx   edx, byte ptr [ebx+edi]
00406C33      41            inc     ecx
00406C34      43            inc     ebx
00406C35      83FA 00       cmp     edx, 0
00406C38    ^ 75 F5         jnz     short 00406C2F
00406C3A      49            dec     ecx
00406C3B      03F9          add     edi, ecx
00406C3D      33C9          xor     ecx, ecx
00406C3F      33DB          xor     ebx, ebx
00406C41      0FB61433      movzx   edx, byte ptr [ebx+esi]
00406C45      41            inc     ecx
00406C46      43            inc     ebx
00406C47      83FA 00       cmp     edx, 0
00406C4A    ^ 75 F5         jnz     short 00406C41
00406C4C      F3:A4         rep     movs byte ptr es:[edi], byte ptr>
00406C4E      61            popad
00406C4F      5D            pop     ebp
00406C50      C2 0800       retn    8

  还有一种情况要考虑一下,用户名不符合条件我们总得给个提示吧。

  0041F0FE  90 90 90 90 90 -> E9 8D 7A FE FF     jmp     00406B90

  00406b90 处存放处理程序如下:

00406B90      60            pushad
00406B91      68 3C964000   push    0040963C                         ;  ASCII "User32.dll"
00406B96      FF15 04704000 call    [<&KERNEL32.LoadLibraryA>]       ;  kernel32.LoadLibraryA
00406B9C      50            push    eax
00406B9D      68 30964000   push    00409630                         ;  ASCII "FindWindowA"
00406BA2      50            push    eax
00406BA3      FF15 00704000 call    [<&KERNEL32.GetProcAddress>]     ;  kernel32.GetProcAddress
00406BA9      A3 20974000   mov     [409720], eax
00406BAE      58            pop     eax
00406BAF      68 53964000   push    00409653                         ;  ASCII "SetDlgItemTextA"
00406BB4      50            push    eax
00406BB5      FF15 00704000 call    [<&KERNEL32.GetProcAddress>]     ;  kernel32.GetProcAddress
00406BBB      A3 28974000   mov     [409728], eax
00406BC0      68 29964000   push    00409629
00406BC5      68 6B964000   push    0040966B                         ;  
00406BCA      FF15 20974000 call    [409720]
00406BD0      68 10964000   push    00409610                         ;  预定义的错误提示字符串
00406BD5      68 AA000000   push    0AA
00406BDA      50            push    eax
00406BDB      FF15 28974000 call    [409728]
00406BE1      61            popad
00406BE2    - E9 1F850100   jmp     0041F106

  好了,把所有改动应用于文件,一个CrackMe就这样被打造成了注册机。“以彼之道,还施彼身”的形容算不算恰当呢?反正用了小蜜蜂的算法,作了小蜜蜂的注册机。一切皆怪小蜜蜂让我分析不出算法,:-),希望小蜜蜂看了被小菜我改得乱七八糟的CrackMe不要生气。如有分析有误之处,敬请批评指正,收工!
  
  另附一个点了没有反应的用户名和注册码:(真想知道小蜜蜂这葫芦里装得什么药)
  注册名:NAK-19EA1A6194A06198111A63018713F13281483F20.oN-GCD
  注册码:[DCG][OCN][PYG]-No.101A585-KAN
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年12月11日 01:09:10


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (29)
雪    币: 2319
活跃值: (565)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
2
随便问一下,楼主是不是用繁体字转换简体的 ?
2007-12-12 11:01
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
3
没有啊,有什么问题吗?
2007-12-12 11:06
0
雪    币: 2319
活跃值: (565)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
4
没问题,只是感觉有点像广东话,有点像我说的语言

写得不错
2007-12-12 11:23
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
太厉害了,很崇拜你啊!
2007-12-12 17:07
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
强大啊 强大
崇拜啊 崇拜
偶像啊 偶像
不懂啊 不懂
收藏啊 收藏
2007-12-16 19:09
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
7
分析得不错~~~
2007-12-17 12:21
0
雪    币: 452
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
8
相当的厉害呀!
2007-12-26 14:48
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
不知道有什么好的方法下段不??
这个太难断了   
2007-12-29 16:01
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
不是很懂,飘过~```
2008-1-7 20:17
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
CALL真的很多呀~~不过我没看明白你是怎么下的断呀`~~能不能指教一下哈~~~
2008-1-16 19:55
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
12
我下断的方法很笨,还是请高手们出手指点吧,我一同学习
2008-1-17 07:59
0
雪    币: 97697
活跃值: (200829)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
13
Thanks again for sharing your efforts petnt!
2008-1-22 23:42
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
14
斑竹怎么都这么客气。。
2008-1-22 23:46
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
15
回过头来看看算法,好像并不是很复杂。
中间部分算法为:
(用户名每一位+27)*4 再除以 27 后取余
把取得余数变16进制 后变字符
循环之后拚得字串即为 中间部分注册码
2008-1-23 00:14
0
雪    币: 242
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
budong,路过
2008-1-23 20:23
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
17
monkeycz斑竹的ECE看来是浪费了
2008-1-25 23:10
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
18
haha,刚开始还不知道有这么好的东西。
现在有了。
2008-1-25 23:46
0
雪    币: 452
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
19
ECE对这个CM不起作用吧?
这个CM是按照4.06版本改写的!

顺便发个变形工具吧:
上传的附件:
2008-1-28 14:07
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
20
谢谢,研究一下
2008-1-28 14:12
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
能问一下,ECE到底是什么东西呀```刚学,本人菜鸟.请高手指教!!!
2008-2-14 19:41
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
22
是E语言的反编译工具。
可google "E-Code Explorer"
2008-2-14 19:56
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
历害..还说是小菜...谦虚了
2008-2-15 12:43
0
雪    币: 108
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
24
好像易语言都会有krnln.fnr,试一下断GetProcAddres,可能会找到点有用的。
2008-2-15 16:24
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
谢22楼回复```有空一定常来转``
2008-2-17 21:46
0
游客
登录 | 注册 方可回帖
返回
//