吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6581|回复: 5
上一主题 下一主题
收起左侧

[CrackMe] 【吾爱2013CM大赛解答】 -- Crack Me--RedAgl 保护技巧+算法逆向分析

[复制链接]
跳转到指定楼层
楼主
playboysen 发表于 2013-12-15 18:42 回帖奖励
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。

本帖最后由 playboysen 于 2013-12-16 13:19 编辑

本文是针对下面这个CM的解答:
http://www.52pojie.cn/thread-228420-1-1.html

本着“授人以渔”的思路,本文写的比较详细,高手觉得啰嗦拉到最下面即可{:1_912:}

主程序名“2013CM.exe”,本机Win7 x64用OD无法加载运行,被迫转移到虚拟机XP,OD加载F9运行直接退出,换个OD后使用ODbyDYK加载成功跑起

踩踩点,OD查找字符串嘛玩意儿木有,猜测应该是将敏感字符放在了资源文件或者加密待程序运行时动态解密显示,eXeScope加载主程序依次看到“资源——字符串——518”中有“8280,注册成功!”字样,十进制8280转换为十六进制是0x2058,有门儿!

大概看看程序入口觉得像C或C++代码(可以用PEid确认),F9运行程序填写用户名“playboysen”注册码随便,然后下断点GetWindowTextA(C代码最常用的取文本API),点击Register断在了User32.dll中,不急,F8慢慢走回主程序代码处
[AppleScript] 纯文本查看 复制代码
00401B83  |.  68 04010000   push 104                                       ; /Count = 104 (260.)
00401B88  |.  8D85 F0FEFFFF lea eax,dword ptr ss:[ebp-110]                 ; |
00401B8E  |.  50            push eax                                       ; |Buffer
00401B8F  |.  FF35 78534000 push dword ptr ds:[405378]                     ; |hWnd = NULL
00401B95  |.  FF15 60414000 call dword ptr ds:[<&USER32.GetWindowTextA>]   ; \GetWindowTextA
00401B9B  |.  68 04010000   push 104                                       ; /n = 104 (260.)
00401BA0  |.  6A 00         push 0                                         ; |c = 00
00401BA2  |.  83F8 04       cmp eax,4                                      ; |用户名必须大于等于4位
00401BA5  |.  7D 1C         jge short 2013CM.00401BC3                      ; |
00401BA7  |.  FF35 D0534000 push dword ptr ds:[4053D0]                     ; |s = NULL
00401BAD  |.  E8 D6150000   call <jmp.&MSVCR110.memset>                    ; \memset
00401BB2  |.  83C4 0C       add esp,0C
......
00401BD8  |.  68 04010000   push 104                                       ; /Count = 104 (260.)
00401BDD  |.  50            push eax                                       ; |Buffer
00401BDE  |.  FF35 74534000 push dword ptr ds:[405374]                     ; |hWnd = NULL
00401BE4  |.  FF15 60414000 call dword ptr ds:[<&USER32.GetWindowTextA>]   ; \GetWindowTextA
00401BEA  |.  68 04010000   push 104                                       ; /n = 104 (260.)
00401BEF  |.  6A 00         push 0                                         ; |c = 00
00401BF1  |.  FF35 D4534000 push dword ptr ds:[4053D4]                     ; |s = NULL
00401BF7  |.  E8 8C150000   call <jmp.&MSVCR110.memset>                    ; \memset
00401BFC  |.  8D8D F0FEFFFF lea ecx,dword ptr ss:[ebp-110]                 ;  注册码放入ecx
00401C02  |.  83C4 0C       add esp,0C
00401C05  |.  8D51 01       lea edx,dword ptr ds:[ecx+1]                   ;  *****begin*****
00401C08  |>  8A01          /mov al,byte ptr ds:[ecx]
00401C0A  |.  41            |inc ecx
00401C0B  |.  84C0          |test al,al                                    ;  求出并判断注册码长度
00401C0D  |.^ 75 F9         \jnz short 2013CM.00401C08
00401C0F  |.  2BCA          sub ecx,edx
00401C11  |.  83F9 04       cmp ecx,4                                      ;  注册码必须大于4位
00401C14  |.  7C 29         jl short 2013CM.00401C3F                       ;  *****end*****
00401C16  |.  8D85 F0FEFFFF lea eax,dword ptr ss:[ebp-110]
00401C1C  |.  50            push eax
00401C1D  |.  68 04010000   push 104
00401C22  |.  FF35 D4534000 push dword ptr ds:[4053D4]
00401C28  |.  FF15 FC404000 call dword ptr ds:[<&MSVCR110.strcpy_s>]       ;  MSVCR110.strcpy_s
00401C2E  |.  83C4 0C       add esp,0C                                     ;  ESP指向注册码
00401C31  |.  E8 FA0A0000   call 2013CM.00402730                           ;  注册码验证关键算法

一路走到00401C31,进入主算法依个人习惯Ctrl+A分析完代码后,一路滚轮下去先看看关键API,猜猜作者在玩什么游戏——GetVolumeInformationW、_itoa_s、CharUpperBuffW嗯好像在获取分区信息然后做了什么计算后将计算值转为文本后大写,关键代码如下:
[AppleScript] 纯文本查看 复制代码
00402787  |.  68 04010000   push 104                              ; /pFileSystemNameSize = 00000104
0040278C  |.  8D85 D8F6FFFF lea eax,dword ptr ss:[ebp-928]        ; |
00402792  |.  50            push eax                              ; |pFileSystemNameBuffer
00402793  |.  8D85 CCF6FFFF lea eax,dword ptr ss:[ebp-934]        ; |
00402799  |.  50            push eax                              ; |pFileSystemFlags
0040279A  |.  8D85 D0F6FFFF lea eax,dword ptr ss:[ebp-930]        ; |
004027A0  |.  50            push eax                              ; |pMaxFilenameLength
004027A1  |.  8D85 D4F6FFFF lea eax,dword ptr ss:[ebp-92C]        ; |
004027A7  |.  50            push eax                              ; |pVolumeSerialNumber
004027A8  |.  68 04010000   push 104                              ; |MaxVolumeNameSize = 104 (260.)
004027AD  |.  8D85 E0F8FFFF lea eax,dword ptr ss:[ebp-720]        ; |
004027B3  |.  50            push eax                              ; |VolumeNameBuffer
004027B4  |.  6A 00         push 0                                ; |RootPathName = NULL
004027B6  |.  C785 D0F6FFFF>mov dword ptr ss:[ebp-930],0FF        ; |
004027C0  |.  FF15 58404000 call dword ptr ds:[<&KERNEL32.GetVolu>; \GetVolumeInformationW
004027C6  |.  33C9          xor ecx,ecx
004027C8  |.  85F6          test esi,esi
004027CA  |.  7E 11         jle short 2013CM.004027DD
004027CC  |.  8B15 D0534000 mov edx,dword ptr ds:[4053D0]         ;  "playboysen161564"
004027D2  |>  0FBE040A      /movsx eax,byte ptr ds:[edx+ecx]
004027D6  |.  41            |inc ecx
004027D7  |.  03F8          |add edi,eax
004027D9  |.  3BCE          |cmp ecx,esi
004027DB  |.^ 7C F5         \jl short 2013CM.004027D2             ;  "playboysen161564"十六进制之和转化成大写文本“57D”
004027DD  |>  8B35 04414000 mov esi,dword ptr ds:[<&MSVCR110._ito>;  MSVCR110._itoa_s
......
0040287A  |.  FFD6          call esi                              ;  <&MSVCR110.strcpy_s>
0040287C  |.  8D85 F0FCFFFF lea eax,dword ptr ss:[ebp-310]        ;  GetVolumeInformationW得到C盘十进制ID值“886854821”
00402882  |.  50            push eax
00402883  |.  8D85 F4FDFFFF lea eax,dword ptr ss:[ebp-20C]        ;  “57D”
00402889  |.  68 04010000   push 104
0040288E  |.  50            push eax
0040288F  |.  FF15 08414000 call dword ptr ds:[<&MSVCR110.strcat_>;  MSVCR110.strcat_s
00402895  |.  68 04010000   push 104                              ; /n = 104 (260.)
0040289A  |.  6A 00         push 0                                ; |c = 00
0040289C  |.  FF35 CC534000 push dword ptr ds:[4053CC]            ; |s = 00168998
004028A2  |.  E8 E1080000   call <jmp.&MSVCR110.memset>           ; \memset
004028A7  |.  8D85 F4FDFFFF lea eax,dword ptr ss:[ebp-20C]
004028AD  |.  50            push eax
004028AE  |.  68 04010000   push 104
004028B3  |.  FF35 CC534000 push dword ptr ds:[4053CC]
004028B9  |.  FFD6          call esi                              ;  <&MSVCR110.strcpy_s>

一路F8过去知道这段代码功能大概就是将"playboysen161564"十六进制之和转化成大写文本“57D”,GetVolumeInformationW得到C盘十进制ID值“886854821”,二者相连接组成一个新字符串“57D886854821”我们设为tempCode,然后呢?这个函数结束了……

F8走出当前函数,到了这里
[AppleScript] 纯文本查看 复制代码
00401C2E  |.  83C4 0C       add esp,0C                            ;  ESP指向注册码
00401C31  |.  E8 FA0A0000   call 2013CM.00402730                  ;  注册码验证关键算法
00401C36  |.  85C0          test eax,eax
00401C38  |.  74 05         je short 2013CM.00401C3F
00401C3A  |.  E8 11000000   call 2013CM.00401C50                  ;  第二个关键点
00401C3F  |>  8B4D FC       mov ecx,dword ptr ss:[ebp-4]
00401C42  |.  33CD          xor ecx,ebp

嗯,F7进入00401C3A看看,依次发现了VirtualAllocEx、memset、OpenProcess、strcpy、LoadStringA、GetModuleHandleA、GetProcAddress、WriteProcessMemory、CreateRemoteThread等API,程序在干什么??你猜猜……
(还记得开头我们看资源中“8280,注册成功!”字符串的ID值吗?十进制8280转换为十六进制是0x2058,你也可以将OD代码窗口滚动到首行,右键查找——常量——2058,也可以找到这个关键验证函数)
[AppleScript] 纯文本查看 复制代码
00401D2C  |. /0F84 F6020000 je 2013CM.00402028
00401D32  |> |8B35 7C404000 mov esi,dword ptr ds:[<&KERNEL32.Open>;  kernel32.OpenProcess
00401D38  |. |50            push eax                              ; /ProcessId
00401D39  |. |6A 00         push 0                                ; |Inheritable = FALSE
00401D3B  |. |68 FFFF1F00   push 1FFFFF                           ; |Access = TERMINATE|CREATE_THREAD|VM_OPERATION|VM_READ|VM_WRITE|DUP_HANDLE|CREATE_PROCESS|SET_QUOTA|SET_INFORMATION|QUERY_INFORMATION|SYNCHRONIZE|STANDARD_RIGHTS_REQUIRED|F804
00401D40  |. |FFD6          call esi                              ; \OpenProcess
......
00401DD7  |. |8B35 58414000 mov esi,dword ptr ds:[<&USER32.LoadSt>;  USER32.LoadStringA
00401DDD  |. |6A 0D         push 0D                               ; /Count = D (13.)
00401DDF  |. |FFB5 B0FDFFFF push dword ptr ss:[ebp-250]           ; |Buffer
00401DE5  |. |2BCA          sub ecx,edx                           ; |
00401DE7  |. |68 52200000   push 2052                             ; |RsrcID = STRING "Kernel32.dll"
00401DEC  |. |FF35 B0534000 push dword ptr ds:[4053B0]            ; |hInst = 00400000
00401DF2  |. |898D C4FDFFFF mov dword ptr ss:[ebp-23C],ecx        ; |
00401DF8  |. |FFD6          call esi                              ; \LoadStringA
00401DFA  |. |FFB5 B0FDFFFF push dword ptr ss:[ebp-250]           ; /pModule
00401E00  |. |FF15 78404000 call dword ptr ds:[<&KERNEL32.GetModu>; \GetModuleHandleA
......
00401E24  |. |57            push edi                              ; /ProcNameOrOrdinal
00401E25  |. |FFB5 C8FDFFFF push dword ptr ss:[ebp-238]           ; |hModule
00401E2B  |. |FF15 74404000 call dword ptr ds:[<&KERNEL32.GetProc>; \GetProcAddress
00401E31  |. |8BBD A8FDFFFF mov edi,dword ptr ss:[ebp-258]
00401E37  |. |6A 0C         push 0C
00401E39  |. |57            push edi
00401E3A  |. |68 56200000   push 2056                             ;  “MessageBoxA”
00401E3F  |. |FF35 B0534000 push dword ptr ds:[4053B0]            ;  2013CM.00400000
00401E45  |. |8945 F4       mov dword ptr ss:[ebp-C],eax
00401E48  |. |FFD6          call esi                              ;  USER32.LoadStringA
......
00401E9A  |. |FFB5 ACFDFFFF push dword ptr ss:[ebp-254]
00401EA0  |. |8D45 EA       lea eax,dword ptr ss:[ebp-16]
00401EA3  |. |6A 0C         push 0C
00401EA5  |. |50            push eax                              ;  “注册成功!”
00401EA6  |. |FFD7          call edi                              ;  <&MSVCR110.strcpy_s>
00401EA8  |. |8B35 44404000 mov esi,dword ptr ds:[<&KERNEL32.Virt>;  kernel32.VirtualAllocEx
00401EAE  |. |83C4 0C       add esp,0C
00401EB1  |. |6A 04         push 4
00401EB3  |. |68 00300000   push 3000
00401EB8  |. |68 00100000   push 1000
00401EBD  |. |6A 00         push 0
00401EBF  |. |53            push ebx
00401EC0  |. |FFD6          call esi                              ;  <&KERNEL32.VirtualAllocEx>
00401EC2  |. |8BF8          mov edi,eax
00401EC4  |. |89BD BCFDFFFF mov dword ptr ss:[ebp-244],edi
00401ECA  |. |85FF          test edi,edi
00401ECC  |. |0F84 F5000000 je 2013CM.00401FC7
00401ED2  |. |6A 00         push 0                                ; /pBytesWritten = NULL
00401ED4  |. |68 38020000   push 238                              ; |BytesToWrite = 238 (568.)
00401ED9  |. |8D85 C0FDFFFF lea eax,dword ptr ss:[ebp-240]        ; |
00401EDF  |. |50            push eax                              ; |Buffer
00401EE0  |. |57            push edi                              ; |Address
00401EE1  |. |53            push ebx                              ; |hProcess
00401EE2  |. |FF15 18404000 call dword ptr ds:[<&KERNEL32.WritePr>; \WriteProcessMemory
00401EE8  |. |85C0          test eax,eax                          ;  将注册成功字符串、假注册码、用户名计算生成的字符串等等信息写入新申请的内存
......
00401F44  |.  6A 00         push 0                                ; /pBytesWritten = NULL
00401F46  |.  68 00080000   push 800                              ; |BytesToWrite = 800 (2048.)
00401F4B  |.  68 50234000   push 2013CM.00402350                  ; |Buffer = 2013CM.00402350
00401F50  |.  56            push esi                              ; |Address
00401F51  |.  53            push ebx                              ; |hProcess
00401F52  |.  FF15 18404000 call dword ptr ds:[<&KERNEL32.WritePr>; \WriteProcessMemory
00401F58  |.  85C0          test eax,eax                          ;  将00402350处的2048字节数据写入新申请的内存
......
00401FB2  |> |6A 00         push 0
00401FB4  |. |6A 00         push 0
00401FB6  |. |57            push edi                              ;  数据区块地址
00401FB7  |. |56            push esi                              ;  代码区段地址
00401FB8  |. |6A 00         push 0
00401FBA  |. |6A 00         push 0
00401FBC  |. |53            push ebx                              ;  OpenProcess ID
00401FBD  |. |FF15 24404000 call dword ptr ds:[<&KERNEL32.CreateR>;  kernel32.CreateRemoteThread

整段代码上百行,上面是关键部分
好像程序随机打开某个进程,然后申请两个内存将注册成功字符串、假注册码、用户名计算生成的字符串等等信息和00402350处的2048字节数据写入新申请的内存中,最后创建了远程线程,主程序的主验证函数结束了

嗯,关键的地方来了,我们怎么用OD去调试新线程呢???
大概思路是新开一个OD去附加目标进程,然后在新线程入口处下断点即可
通过OpenProcess参数ProcessId可知目标进程的PID、CreateRemoteThread参数可知新线程执行的代码入口(具体见上段代码注释)

好滴,先在CreateRemoteThread即00401FBD处下断点(这个API一过,新线程已经运行,我们就不能附加调试了)再打开一个ODbyDYK附加目标进程,然后F9也让目标进程正常运行,在新开的OD代码窗口Ctrl+G跳转到新线程入口(比如00C40000),代码如下:
[AppleScript] 纯文本查看 复制代码
00C40000    60            pushad
00C40001    8B0B          mov ecx,dword ptr ds:[ebx]
00C40003    8B53 04       mov edx,dword ptr ds:[ebx+4]
00C40006    3BCA          cmp ecx,edx
00C40008    74 02         je short 00C4000C                              ; 这里直接跳过去,否则线程会检测退出
00C4000A    61            popad
00C4000B    C3            retn
00C4000C    8BC3          mov eax,ebx                                    ; ebx指向主程序写入该进程的数据区
00C4000E    51            push ecx                                       ; len(tempCode)
00C4000F    BF 1C000000   mov edi,1C
00C40014    BE 20010000   mov esi,120
00C40019    03F8          add edi,eax                                    ; edi = 假注册码
00C4001B    03F0          add esi,eax                                    ; esi = tempCode
00C4001D    57            push edi
00C4001E    56            push esi
00C4001F    83F9 0F       cmp ecx,0F                                     ; len(tempCode) < 16
00C40022    72 05         jb short 00C40029
00C40024    83E9 0F       sub ecx,0F
00C40027  ^ EB F6         jmp short 00C4001F
00C40029    33C0          xor eax,eax
00C4002B    8BF7          mov esi,edi                                    ; esi = edi = tempCode
00C4002D    FC            cld
00C4002E    AC            lods byte ptr ds:[esi]                         ; 将tempCode从前往后逐位参与计算
00C4002F    3C 2D         cmp al,2D                                      ; 若当前字符为“-”则跳过
00C40031    74 02         je short 00C40035                              ; 即“-”符号原封不动保留
00C40033    33C1          xor eax,ecx
00C40035    AA            stos byte ptr es:[edi]                         ; 将计算后的eax逐字节存入[edi]地址,同时ecx-1
00C40036  ^ E2 F6         loopd short 00C4002E
00C40038    5E            pop esi
00C40039    5F            pop edi
00C4003A    59            pop ecx
00C4003B    FC            cld
00C4003C    F3:A6         repe cmps byte ptr es:[edi],byte ptr ds:[esi]  ;比较edi和esi
00C4003E    74 02         je short 00C40042
00C40040    61            popad
00C40041    C3            retn

上面代码量不大,主要功能就两个:一个是简单检测是否被调试修改,第二就是再次验证注册码,细节见注释
其实在00C40038这里已经可以看到明码了(见图右下角),而且如果直接修改00C40008和00C4003E两处的je为jmp即可爆破(有人说这个是临时线程你修改了也没用啊,其实换种思路即可,临时线程的代码全部都是主程序中复制过来的,可以直接在主程序中搜索到相同代码,修改主程序即可)


到这里,理论上所有算法已经分析完毕了,不过在逆向注册机时又发现个问题
上面说到生成tempCode时用到了"playboysen161564"(设为tempUserName)??这个是什么玩意儿??开头测试输入的用户名不是“playboysen”吗?嗯,用户名后多出一串数字,根据前面的分析觉得以作者的编程习惯,这里应该是用户名和什么一起做了运算得出的数字,既然这样数字总要转成文本,输入用户名时下断_itoa_s函数,轻松找到关键点:
[AppleScript] 纯文本查看 复制代码
00402655  |.  E8 2E0B0000   call <jmp.&MSVCR110.memset>           ; \memset
0040265A  |.  8BF3          mov esi,ebx                           ;  实时监测用户名输入,输入完自动计算
0040265C  |.  83C4 0C       add esp,0C
0040265F  |.  8D4E 01       lea ecx,dword ptr ds:[esi+1]
00402662  |>  8A06          /mov al,byte ptr ds:[esi]
00402664  |.  46            |inc esi
00402665  |.  84C0          |test al,al
00402667  |.^ 75 F9         \jnz short 2013CM.00402662
00402669  |.  2BF1          sub esi,ecx                           ;  用户名位数ESI
0040266B  |.  89B5 E8FEFFFF mov dword ptr ss:[ebp-118],esi
00402671  |.  83FE 04       cmp esi,4                             ;  用户名应不小于4位
00402674  |.  0F8C A3000000 jl 2013CM.0040271D
0040267A  |.  57            push edi
0040267B  |.  FFB5 F4FEFFFF push dword ptr ss:[ebp-10C]
00402681  |.  8D46 01       lea eax,dword ptr ds:[esi+1]
00402684  |.  50            push eax
00402685  |.  FF35 D0534000 push dword ptr ds:[4053D0]
0040268B  |.  33FF          xor edi,edi
0040268D  |.  33DB          xor ebx,ebx
0040268F  |.  FF15 FC404000 call dword ptr ds:[<&MSVCR110.strcpy_>;  MSVCR110.strcpy_s
00402695  |.  8B95 F4FEFFFF mov edx,dword ptr ss:[ebp-10C]
0040269B  |.  83C4 0C       add esp,0C
0040269E  |.  33C9          xor ecx,ecx
004026A0  |.  83FE 02       cmp esi,2
004026A3  |.  7C 25         jl short 2013CM.004026CA
004026A5  |.  8D46 FF       lea eax,dword ptr ds:[esi-1]
004026A8  |.  8985 ECFEFFFF mov dword ptr ss:[ebp-114],eax
004026AE  |.  8BF0          mov esi,eax
004026B0  |>  0FBE040A      /movsx eax,byte ptr ds:[edx+ecx]      ;  用户名逐位参与运算
004026B4  |.  03F8          |add edi,eax
004026B6  |.  0FBE440A 01   |movsx eax,byte ptr ds:[edx+ecx+1]
004026BB  |.  83C1 02       |add ecx,2
004026BE  |.  03D8          |add ebx,eax
004026C0  |.  3BCE          |cmp ecx,esi
004026C2  |.^ 7C EC         \jl short 2013CM.004026B0
004026C4  |.  8BB5 E8FEFFFF mov esi,dword ptr ss:[ebp-118]
004026CA  |>  3BCE          cmp ecx,esi
004026CC  |.  7D 0A         jge short 2013CM.004026D8
004026CE  |.  0FBE040A      movsx eax,byte ptr ds:[edx+ecx]
004026D2  |.  8985 F0FEFFFF mov dword ptr ss:[ebp-110],eax
004026D8  |>  8B8D F0FEFFFF mov ecx,dword ptr ss:[ebp-110]
004026DE  |.  6A 0A         push 0A
004026E0  |.  68 04010000   push 104
004026E5  |.  8D85 F8FEFFFF lea eax,dword ptr ss:[ebp-108]
004026EB  |.  50            push eax
004026EC  |.  81C1 DD070000 add ecx,7DD                           ;  +0x7DD
004026F2  |.  8D043B        lea eax,dword ptr ds:[ebx+edi]
004026F5  |.  03C1          add eax,ecx
004026F7  |.  6BC0 34       imul eax,eax,34                       ;  结果 * 0x34
004026FA  |.  50            push eax
004026FB  |.  FF15 04414000 call dword ptr ds:[<&MSVCR110._itoa_s>;  MSVCR110._itoa_s
00402701  |.  8D85 F8FEFFFF lea eax,dword ptr ss:[ebp-108]

哈哈,至此全部分析完成,我们来总结一下算法概要,程序的验证逻辑分两段:
一、主算法(主程序中):
1.(用户名十六进制总和+0x7DD) * 0x34形成一个十进制常数,然后再与用户名相连接组成tempUserName
2.tempUserName逐位相加得出十六进制总和,直接将求出的十六进制数转为大写字符串
3.GetVolumeInformation得出C盘序列号(十进制),然后与第2步的字符串相连接组成tempCode

到这里主程序中存在的所有算法结束,不过此时的tempCode只能说是半个注册码,因为程序随机附加了某个进程并创建了个远程线程

二、辅算法(新线程中):
将tempCode从前往后逐字节与len(tempCode)-1异或计算,不过“-”符号不参与异或直接保留,最终形成RegCode!!!

用Python写了段注册机生成代码(本想用论坛注册机生成器,但其1.01版本无法运行,1.0版也无法获取分区ID,被迫放弃):
Python注册机算法表示(调试XP X86/Python 2.7/pywin32):
[Python] 纯文本查看 复制代码
from win32api import GetVolumeInformation

"""求给定字符串各字符十六进制总和,返回十进制数"""
def addBytes(Str):
        i = 0
        for b in Str:
                i = i + ord(b)
        return i

"""
主算法(主程序中):
1.(用户名十六进制总和+0x7DD) * 0x34形成一个十进制常数,然后再与用户名相连接组成tempUserName
2.tempUserName十六进制总和(十六进制),直接将求出的十六进制数转为大写字符串
3.GetVolumeInformation得出C盘序列号(十进制),然后与第2步的字符串相连接组成tempCode
  到这里主程序中存在的所有算法都结束了,不过此时的tempCode只能说是半个注册码
  因为程序随机附加了某个进程并创建了个远程线程,还有一些算法在新线程中验证,所以主程序中是木有明码滴~~
"""
def geneTempCode(UserName):
        tempUserName = UserName + str((addBytes(UserName) + 0x7DD)*0x34)
        tempCode = hex(addBytes(tempUserName)).upper()[2:] + str(GetVolumeInformation("C:\\")[1])
        return tempCode

"""
辅算法(新线程中):
将tempCode从前往后逐字节与len(tempCode)-1异或计算,不过“-”符号不参与异或直接保留,最终形成RegCode!!!
"""
def geneCode(tempCode):
        i = 0
        Code = ""
        if len(tempCode)<0x0F:
                tempLen = len(tempCode) + 1
        else:
                tempLen = len(tempCode) + 1 - 0x0F

        for b in tempCode:
                tempLen = tempLen-1
                if b == "-":
                        Code = Code + b
                else:
                        Code = Code + chr(ord(b) ^ tempLen)        
        return Code

"""使用playboysen作为用户名计算注册码"""
print geneCode(geneTempCode("playboysen"))


最后说一下个人感受:
研究分析还原算法用时2个多小时,但编写测试注册机写文章也用了近3个小时,汗

整体来说这个CM也蛮别出心裁,自带调试器基本防护,注册码绑定磁盘,没有错误提示,注册码正确与否都一视同仁ShowWindow一下(防止Cracker以此作区别下断点),部分验证算法在另外一个进程的新线程中进行(有效浪费分析者蛮多时间)

但还是有些地方考虑不尽周全,建议加密字串(防止别人在资源列表中查看突破)用的时候新线程动态解密,关键函数尽量少用系统API或者添加混淆(防止一目了然,也防止了在IDA中F5),注册码部分不要只是简单加减可以考虑来点大数运算什么的,需要写入新进程的代码应该加密存储于主程序中,使用时先动态解密还原(防止在主程序爆破)

附件“吾爱破解2013CM Loader”是使用吾爱破解内存补丁生成器做的Loader(注意用户名和密码都要不小于4位

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 2热心值 +2 收起 理由
sunflover + 1 楼主功夫好深
Chief + 1 吾爱破解2013CM大赛,有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
qfhy123 发表于 2013-12-15 18:50
膜拜懂算法的大牛
3#
brack 发表于 2013-12-15 19:02
4#
RedAngel丶 发表于 2013-12-15 19:30
5#
 楼主| playboysen 发表于 2013-12-15 19:47 |楼主
RedAngel丶 发表于 2013-12-15 19:30
真心膜拜认真玩cm的大牛
下次会注意的

作为CM做的已经相当不错了,认真分析是对作者的基本尊重 呼呼

6#
 楼主| playboysen 发表于 2013-12-18 21:22 |楼主
这个CM我在虚拟机XP中还原算法编写注册机 经测试在两台虚拟XP上均可以注册成功
但是在我的本机Win7上无论怎么点注册都没有反应 就算使用爆破Loader都不行

不知道是不是系统适用问题

点评

32的win7肯定可以,64位不能用32位注入  发表于 2013-12-18 22:29
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 15:07

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表