本帖最后由 hflywolf 于 2009-3-4 19:18 编辑
zapline转载CM(第十一天)分析
【文章标题】: zapline转载CM(第十一天)分析
【文章作者】: hflywolf
【作者邮箱】: 95192939@qq.com
【下载地址】: http://www.52pojie.cn/thread-18703-1-1.html
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
-----------------------------------------------------------------
【详细过程】
嘿嘿,到这会见没大牛分析,小菜就现丑一下好了。
CM无壳,汇编写的.
OD载入CM
获取程序的句柄00401000 > $ 6A 00 push 0 ; /pModule = NULL
00401002 . E8 87020000 call <jmp.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA
00401007 . A3 AB214000 mov dword ptr [4021AB], eax ; 将获取的程序句柄保存到4021AB地址空间
载入图标0040100C . C705 34214000>mov dword ptr [402134], 4003
00401016 . C705 38214000>mov dword ptr [402138], 004010AB
00401020 . C705 3C214000>mov dword ptr [40213C], 0
0040102A . C705 40214000>mov dword ptr [402140], 0
00401034 . A1 AB214000 mov eax, dword ptr [4021AB] ; 从4021AB地址空间取出程序句柄保存到eax
00401039 . A3 44214000 mov dword ptr [402144], eax
0040103E . 6A 01 push 1 ; /RsrcName = 1.
00401040 . 50 push eax ; 程序句柄(hInstance)
00401041 . E8 38030000 call <jmp.&USER32.LoadIconA> ; \LoadIconA
00401046 . A3 48214000 mov dword ptr [402148], eax ; 将图标句柄保存到402148地址空间
载入光标0040104B . 68 007F0000 push 7F00 ; /RsrcName = IDC_ARROW
00401050 . 6A 00 push 0 ; |hInst = NULL
00401052 . E8 33030000 call <jmp.&USER32.LoadCursorA> ; \LoadCursorA
00401057 . A3 4C214000 mov dword ptr [40214C], eax ; 将光标句柄保存到40214C地址空间
创建模态对话框0040105C . 6A 00 push 0 ; /lParam = NULL
0040105E . 68 CE104000 push 004010CE ; |DlgProc = due-cm4.004010CE
00401063 . 6A 00 push 0 ; |hOwner = NULL
00401065 . 6A 01 push 1 ; |pTemplate = 1
00401067 . FF35 AB214000 push dword ptr [4021AB] ; |hInst = NULL
0040106D . E8 88020000 call <jmp.&USER32.DialogBoxParamA> ; \DialogBoxParamA
00401072 . EB 53 jmp short 004010C7 ; 跳到4010C7
消息循环00401074 > 6A 00 push 0 ; /MsgFilterMax = 0
00401076 . 6A 00 push 0 ; |MsgFilterMin = 0
00401078 . 6A 00 push 0 ; |hWnd = NULL
0040107A . 68 18214000 push 00402118 ; |pMsg = due-cm4.00402118
0040107F . E8 3C030000 call <jmp.&USER32.GetMessageA> ; \GetMessageA
00401084 . 66:3D 0000 cmp ax, 0 ; 如果GetMessageA函数接受到WM_QUIT消息后,退出消息循环。
00401088 . 74 16 je short 004010A0 ; 跳向退出代码
0040108A . 68 18214000 push 00402118 ; /pMsg = WM_NULL
0040108F . E8 80030000 call <jmp.&USER32.TranslateMessage> ; \TranslateMessage
00401094 . 68 18214000 push 00402118 ; /pMsg = WM_NULL
00401099 . E8 6E020000 call <jmp.&USER32.DispatchMessageA> ; \DispatchMessageA
0040109E .^ EB D4 jmp short 00401074 ; 消息循环
退出004010A0 > FF35 20214000 push dword ptr [402120] ; /ExitCode = 0
004010A6 . E8 19020000 call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
消息处理函数004010B4 |> FF75 14 push dword ptr [ebp+14] ; /lParam
004010B7 |. FF75 10 push dword ptr [ebp+10] ; |wParam
004010BA |. FF75 0C push dword ptr [ebp+C] ; |Message
004010BD |. FF75 08 push dword ptr [ebp+8] ; |hWnd
004010C0 |. E8 F5020000 call <jmp.&USER32.DefWindowProcA> ; \DefWindowProcA
提示注册成功004010D7 > /68 00200000 push 2000 ; /Style = MB_OK|MB_TASKMODAL
004010DC . |68 01204000 push 00402001 ; |Title = "Duelist's Crackme #4"
004010E1 . |68 61204000 push 00402061 ; |Text = "Congratulations! Please send your keygen (working one) to duelist@beer.com!"
004010E6 . |6A 00 push 0 ; |hOwner = NULL
004010E8 . |E8 79020000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
取name长度,如果name为空或大于8位跳到40121A提示错误00401127 > 6A 00 push 0 ; /lParam = 0
00401129 . 6A 00 push 0 ; |wParam = 0
0040112B . 6A 0E push 0E ; |Message = WM_GETTEXTLENGTH
0040112D . 6A 03 push 3 ; |ControlID = 3
0040112F . FF75 08 push dword ptr [ebp+8] ; |hWnd
00401132 . E8 41020000 call <jmp.&USER32.SendDlgItemMessageA>; \SendDlgItemMessageA
00401137 . A3 AF214000 mov dword ptr [4021AF], eax
0040113C . 83F8 00 cmp eax, 0
0040113F . 0F84 D5000000 je 0040121A
00401145 . 83F8 08 cmp eax, 8
00401148 . 0F8F CC000000 jg 0040121A
取code长度,如果code为空或不等于name长度则跳向40121A提示错误0040114E . 8BF0 mov esi, eax
00401150 . 6A 00 push 0 ; /lParam = 0
00401152 . 6A 00 push 0 ; |wParam = 0
00401154 . 6A 0E push 0E ; |Message = WM_GETTEXTLENGTH
00401156 . 6A 04 push 4 ; |ControlID = 4
00401158 . FF75 08 push dword ptr [ebp+8] ; |hWnd
0040115B . E8 18020000 call <jmp.&USER32.SendDlgItemMessageA>; \SendDlgItemMessageA
00401160 . 83F8 00 cmp eax, 0
00401163 . 0F84 B1000000 je 0040121A
00401169 . 3BF0 cmp esi, eax
0040116B . 0F85 A9000000 jnz 0040121A
取name的值,放到402160地址空间中00401171 . 68 60214000 push 00402160 ; /lParam = 402160
00401176 . 6A 08 push 8 ; |wParam = 8
00401178 . 6A 0D push 0D ; |Message = WM_GETTEXT
0040117A . 6A 03 push 3 ; |ControlID = 3
0040117C . FF75 08 push dword ptr [ebp+8] ; |hWnd
0040117F . E8 F4010000 call <jmp.&USER32.SendDlgItemMessageA>; \SendDlgItemMessageA
取code的值,放到402179地址空间中00401184 . 68 79214000 push 00402179 ; /lParam = 402179
00401189 . 6A 10 push 10 ; |wParam = 10
0040118B . 6A 0D push 0D ; |Message = WM_GETTEXT
0040118D . 6A 04 push 4 ; |ControlID = 4
0040118F . FF75 08 push dword ptr [ebp+8] ; |hWnd
00401192 . E8 E1010000 call <jmp.&USER32.SendDlgItemMessageA>; \SendDlgItemMessageA
先判断name的值的合法性。
1、name只能是字母,不能为其它字符。如果不合法就跳到40121A提示错误
2、如果name中含小写字母就转大写.
再依次取name的值,如果取完就跳到4011DB判断注册码00401197 . B9 FFFFFFFF mov ecx, -1
0040119C > 41 inc ecx
0040119D . 0FBE81 602140>movsx eax, byte ptr [ecx+402160]
004011A4 . 83F8 00 cmp eax, 0 ; Switch (cases 0..7A)
004011A7 . 74 32 je short 004011DB
004011A9 . BE FFFFFFFF mov esi, -1
004011AE . 83F8 41 cmp eax, 41
004011B1 . 7C 67 jl short 0040121A
004011B3 . 83F8 7A cmp eax, 7A
004011B6 . 77 62 ja short 0040121A
004011B8 . 83F8 5A cmp eax, 5A
004011BB . 7C 03 jl short 004011C0
004011BD . 83E8 20 sub eax, 20 ; Cases 5A ('Z'),5B ('['),5C ('\'),5D (']'),5E ('^'),5F ('_'),60 ('`'),61 ('a'),62 ('b'),63 ('c'),64 ('d'),65 ('e'),66 ('f'),67 ('g'),68 ('h'),69 ('i'),6A ('j'),6B ('k'),6C ('l'),6D ('m')... of switch 004011A4
402017-402039地址的值是对应name的表:A1LSK2DJF4HGP3QWO5EIR6UTYZ8MXN7CBV9。记为表a
40203C-40205E地址的值是对应code的表:SU7CSJKF09NCSDO9SDF09SDRLVK7809S4NF。记为表b
首先将name各位的值与表a中的值对照,记下表a中值所在位置的序号
然后根据所得的序号在表b对应的位置查找,将得到的字符依次连接就是真code.
最后将真code保存到402194地址空间,用于与输入的code比较.004011C0 > 46 inc esi ; Cases 41 ('A'),42 ('B'),43 ('C'),44 ('D'),45 ('E'),46 ('F'),47 ('G'),48 ('H'),49 ('I'),4A ('J'),4B ('K'),4C ('L'),4D ('M'),4E ('N'),4F ('O'),50 ('P'),51 ('Q'),52 ('R'),53 ('S'),54 ('T')... of switch 004011A4
004011C1 . 0FBE96 172040>movsx edx, byte ptr [esi+402017]
004011C8 . 3BC2 cmp eax, edx
004011CA .^ 75 F4 jnz short 004011C0
004011CC . 0FBE86 3C2040>movsx eax, byte ptr [esi+40203C]
004011D3 . 8981 94214000 mov dword ptr [ecx+402194], eax
004011D9 .^ EB C1 jmp short 0040119C
比较code,如果输入的code为真则跳向4010D7提示注册成功,否则跳向40121A提示错误.004011DB > FF35 AF214000 push dword ptr [4021AF] ; Case 0 of switch 004011A4
004011E1 . 68 94214000 push 00402194
004011E6 . 68 79214000 push 00402179
004011EB . E8 54000000 call 00401244
004011F0 . 83F8 01 cmp eax, 1
004011F3 .^\0F84 DEFEFFFF je 004010D7
004011F9 . EB 1F jmp short 0040121A
提示错误0040121A > 68 00200000 push 2000 ; /Style = MB_OK|MB_TASKMODAL; Default case of switch 004011A4
0040121F . 68 01204000 push 00402001 ; |Title = "Duelist's Crackme #4"
00401224 . 68 AE204000 push 004020AE ; |Text = "Your registration info is invalid... Note that most of the special chars may raise registration problems!"
00401229 . 6A 00 push 0 ; |hOwner = NULL
0040122B . E8 36010000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
注册码比较0040124D |. 8B7D 08 mov edi, dword ptr [ebp+8]
00401250 |. 8B75 0C mov esi, dword ptr [ebp+C]
00401253 |. 8B4D 10 mov ecx, dword ptr [ebp+10]
00401256 |. F3:A6 repe cmps byte ptr es:[edi], byte ptr>
00401258 |. 67:E3 05 jcxz short 00401260
0040125B |. B8 00000000 mov eax, 0
总结:
1、用户名位数在1-8位之间
2、用户名不能为数字或其他字符,只能为26个英语字母
3、用户名如果为小写要转换成大写
4、作者在CM程序中初始化了两张数据表.
a)、对应用户名的表为表a,表a="A1LSK2DJF4HGP3QWO5EIR6UTYZ8MXN7CBV9"
b)、对应注册码的表为表b.表b="SU7CSJKF09NCSDO9SDF09SDRLVK7809S4NF"
根据name各位的值在表a中的位置,在表b中相应位置查找字符,依次将字符连接就是注册码.
附上E语言写的注册机代码:.版本 2
.子程序 _按钮1_被单击
.参数 功能键状态, 整数型
.局部变量 name, 文本型
.局部变量 lenN, 整数型
.局部变量 code, 文本型
.局部变量 I, 整数型
.局部变量 临时变量, 整数型
.局部变量 代码变量, 文本型
name = 到大写 (编辑框1.内容)
lenN = 取文本长度 (name)
.变量循环首 (1, lenN, 1, I)
临时变量 = 取代码 (name, I)
.如果真 (临时变量 ≥ 48 且 临时变量 ≤ 57) 'name不能为数字
编辑框2.内容 = “用户名非法,只能是字母”
返回 ()
.如果真结束
.如果真 (临时变量 < 65 或 临时变量 > 90) 'name不能为除了英文字母以外的字符
编辑框2.内容 = “用户名非法,只能是字母”
返回 ()
.如果真结束
代码变量 = 取文本中间 (name, I, 1)
.判断开始 (代码变量 = “A” 或 代码变量 = “C” 或 代码变量 = “K” 或 代码变量 = “O” 或 代码变量 = “P”)
code = code + “S”
.判断 (代码变量 = “B”)
code = code + “4”
.判断 (代码变量 = “D”)
code = code + “K”
.判断 (代码变量 = “E” 或 代码变量 = “J”)
code = code + “F”
.判断 (代码变量 = “F” 或 代码变量 = “I” 或 代码变量 = “N”)
code = code + “0”
.判断 (代码变量 = “G” 或 代码变量 = “S”)
code = code + “C”
.判断 (代码变量 = “H” 或 代码变量 = “V”)
code = code + “N”
.判断 (代码变量 = “L” 或 代码变量 = “M”)
code = code + “7”
.判断 (代码变量 = “Q”)
code = code + “O”
.判断 (代码变量 = “R” 或 代码变量 = “W”)
code = code + “9”
.判断 (代码变量 = “T”)
code = code + “R”
.判断 (代码变量 = “U”)
code = code + “D”
.判断 (代码变量 = “X”)
code = code + “8”
.判断 (代码变量 = “Y”)
code = code + “L”
.判断 (代码变量 = “Z”)
code = code + “V”
.默认
code = “无法生成注册码”
.判断结束
.变量循环尾 ()
编辑框2.内容 = code
忘记把注册机传上来的: (补上下载地址)
[ 本帖最后由 hflywolf 于 2009-2-7 14:07 编辑 ] |