首页 > 逆向调试 > 初探逆向之URLegal破解

初探逆向之URLegal破解

【文章标题】: 初探逆向之URLegal破解
【文章作者】: 代码疯子
【作者邮箱】: stackexploit@gmail.com
【操作系统】: Windows XP
【软件名称】: URLegal 3.3.0.0
【软件介绍】: 可以自动找出HTML文件中的断链接并自动对其进行修复
【加壳方式】: 无
【保护方式】: 注册码
【编写语言】: Microsoft Visual C++ 6.0
【使用工具】: OD + PEID + IDA
【作者声明】: 纯属技术交流,没有其他目的。仅以本文献给跟我一样刚接触逆向的朋友,文章写得比较啰嗦,大牛们请飘过!

本人小菜,刚接触逆向,前几天看了传说中的天草破解教程,看到里面有一个拿一个国外软件URLegal来做例子,很是感兴趣,于是视频还没看完就自己动起手来进行分析,试图去分析注册码计算算法,奈何功底不足,最终只做了个内存注册机,但仍然倍感兴奋,故发帖于看雪。失误之处请指正。附件为内存注册机汇编源码。

这个URLegal 3.3.0.0网上很多大型软件下载站有下载,请朋友们自己下载和安装。
首先,用PEID对目标程序进行查壳,发现没有加壳,显示“Microsoft Visual C++ 6.0”,很好,省的像我这样的初学者去脱壳了。

接下来,试着去注册一下,在“File->Register”菜单下可以进行注册,试着输入假码进行一下测试:Name填ForEduOnly,Code填112233445566778899。点击“Validate My Codes”,提示“Name / Code mis-match. Try again.”的消息框。以前看别人的分析帖子时,往往提到去搜索消息框中的字符串,那我们也来试试。

打开OD,将Urlegal.exe载入,然后在反汇编窗口中单击右键,选择“超级字串参考->ASCII”,接着在弹出的字符串窗口中Ctrl+F查找“Name / Code mis-match. Try again.”这个字符串。在找到字符串之后双击改行,来到程序中对应的位置,对应的子程序反汇编代码如下:

004025C6  /.  55            PUSH EBP
004025C7  |.  8BEC          MOV EBP,ESP
004025C9  |.  6A FF         PUSH -1
004025CB  |.  68 AA754100   PUSH Urlegal.004175AA                    ;  SE 处理程序安装
004025D0  |.  64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
004025D6  |.  50            PUSH EAX
004025D7  |.  64:8925 00000>MOV DWORD PTR FS:[0],ESP
004025DE  |.  81EC 80000000 SUB ESP,80
004025E4  |.  898D 7CFFFFFF MOV DWORD PTR SS:[EBP-84],ECX
004025EA  |.  6A 00         PUSH 0                                   ; /Arg1 = 00000000
004025EC  |.  8D4D 8C       LEA ECX,DWORD PTR SS:[EBP-74]            ; |
004025EF  |.  E8 8C120000   CALL Urlegal.00403880                    ; \Urlegal.00403880
004025F4  |.  C745 FC 00000>MOV DWORD PTR SS:[EBP-4],0
004025FB  |.  8D4D 8C       LEA ECX,DWORD PTR SS:[EBP-74]
004025FE  |.  E8 09430100   CALL <JMP.&MFC42.#2514_?DoModal@CDialog@>
00402603  |.  83F8 01       CMP EAX,1
00402606  |.  0F85 D5000000 JNZ Urlegal.004026E1
0040260C  |.  E8 7FEEFFFF   CALL Urlegal.00401490
00402611  |.  8945 84       MOV DWORD PTR SS:[EBP-7C],EAX
00402614  |.  51            PUSH ECX
00402615  |.  8BCC          MOV ECX,ESP
00402617  |.  8965 80       MOV DWORD PTR SS:[EBP-80],ESP
0040261A  |.  8D45 F0       LEA EAX,DWORD PTR SS:[EBP-10]
0040261D  |.  50            PUSH EAX
0040261E  |.  E8 71450100   CALL <JMP.&MFC42.#535_??0CString@@QAE@AB>
00402623  |.  8985 78FFFFFF MOV DWORD PTR SS:[EBP-88],EAX            ; |
00402629  |.  8D4D 88       LEA ECX,DWORD PTR SS:[EBP-78]            ; |
0040262C  |.  51            PUSH ECX                                 ; |Arg1
0040262D  |.  8B4D 84       MOV ECX,DWORD PTR SS:[EBP-7C]            ; |
00402630  |.  81C1 D0000000 ADD ECX,0D0                              ; |
00402636  |.  E8 AE310000   CALL Urlegal.004057E9                    ; \Urlegal.004057E9
0040263B  |.  8985 74FFFFFF MOV DWORD PTR SS:[EBP-8C],EAX
00402641  |.  C645 FC 01    MOV BYTE PTR SS:[EBP-4],1
00402645  |.  8D4D 88       LEA ECX,DWORD PTR SS:[EBP-78]
00402648  |.  E8 C3050000   CALL Urlegal.00402C10
0040264D  |.  85C0          TEST EAX,EAX
0040264F  |.  75 76         JNZ SHORT Urlegal.004026C7
00402651  |.  8D55 EC       LEA EDX,DWORD PTR SS:[EBP-14]
00402654  |.  52            PUSH EDX                                 ; /Arg2
00402655  |.  8D45 88       LEA EAX,DWORD PTR SS:[EBP-78]            ; |
00402658  |.  50            PUSH EAX                                 ; |Arg1
00402659  |.  E8 02060000   CALL Urlegal.00402C60                    ; \Urlegal.00402C60
0040265E  |.  25 FF000000   AND EAX,0FF
00402663  |.  85C0          TEST EAX,EAX
00402665  |.  74 60         JE SHORT Urlegal.004026C7
00402667  |.  8D4D F0       LEA ECX,DWORD PTR SS:[EBP-10]
0040266A  |.  E8 E1050000   CALL Urlegal.00402C50
0040266F  |.  50            PUSH EAX                                 ; /Arg3
00402670  |.  68 04E24100   PUSH Urlegal.0041E204                    ; |name
00402675  |.  68 0CE24100   PUSH Urlegal.0041E20C                    ; |user
0040267A  |.  8B4D 84       MOV ECX,DWORD PTR SS:[EBP-7C]            ; |
0040267D  |.  81C1 C4000000 ADD ECX,0C4                              ; |
00402683  |.  E8 AD450000   CALL Urlegal.00406C35                    ; \Urlegal.00406C35
00402688  |.  8D4D EC       LEA ECX,DWORD PTR SS:[EBP-14]
0040268B  |.  E8 C0050000   CALL Urlegal.00402C50
00402690  |.  50            PUSH EAX                                 ; /Arg3
00402691  |.  68 14E24100   PUSH Urlegal.0041E214                    ; |code
00402696  |.  68 1CE24100   PUSH Urlegal.0041E21C                    ; |user
0040269B  |.  8B4D 84       MOV ECX,DWORD PTR SS:[EBP-7C]            ; |
0040269E  |.  81C1 C4000000 ADD ECX,0C4                              ; |
004026A4  |.  E8 8C450000   CALL Urlegal.00406C35                    ; \Urlegal.00406C35
004026A9  |.  8B4D 84       MOV ECX,DWORD PTR SS:[EBP-7C]
004026AC  |.  81C1 D0000000 ADD ECX,0D0
004026B2  |.  E8 72170000   CALL Urlegal.00403E29
004026B7  |.  6A 00         PUSH 0
004026B9  |.  6A 00         PUSH 0
004026BB  |.  68 24E24100   PUSH Urlegal.0041E224                    ;  thank you for registering!
004026C0  |.  E8 B1440100   CALL <JMP.&MFC42.#1200_?AfxMessageBox@@Y>
004026C5  |.  EB 0E         JMP SHORT Urlegal.004026D5
 
004026C7  |>  6A 00         PUSH 0
004026C9  |.  6A 00         PUSH 0
004026CB  |.  68 40E24100   PUSH Urlegal.0041E240                    ;  name / code mis-match. try again.
004026D0  |.  E8 A1440100   CALL <JMP.&MFC42.#1200_?AfxMessageBox@@Y>
 
004026D5  |>  C645 FC 00    MOV BYTE PTR SS:[EBP-4],0
004026D9  |.  8D4D 88       LEA ECX,DWORD PTR SS:[EBP-78]
004026DC  |.  E8 DF420100   CALL <JMP.&MFC42.#800_??1CString@@QAE@XZ>
004026E1  |>  C745 FC FFFFF>MOV DWORD PTR SS:[EBP-4],-1
004026E8  |.  8D4D 8C       LEA ECX,DWORD PTR SS:[EBP-74]
004026EB  |.  E8 C0040000   CALL Urlegal.00402BB0
004026F0  |.  8B4D F4       MOV ECX,DWORD PTR SS:[EBP-C]
004026F3  |.  64:890D 00000>MOV DWORD PTR FS:[0],ECX
004026FA  |.  8BE5          MOV ESP,EBP
004026FC  |.  5D            POP EBP
004026FD  \.  C3            RETN

004026C7至004026D0处的代码为错误提示的消息框,我们选中004026C7这一行,可以看到可以从两个地方跳转过来,分别是:

0040264F  |.  75 76         JNZ SHORT Urlegal.004026C7        ;一个关键跳转
0040264F  |.  75 76         JNZ SHORT Urlegal.004026C7        ;一个关键跳转

不管怎么样,先在这个过程的头部下个断点吧。接下来F9运行,并填入刚才的Name和Code进行注册……,还没有输入就断下了,那就F8单步吧。单步到这样一条的时候就可以输入Name和Code了:

004025FE  |.  E8 09430100   CALL <JMP.&MFC42.#2514_?DoModal@CDialog@> ;显示一个模态对话框供用户进行注册

继续小心的按F8进行单步跟踪。来到0040260C处的CALL,用F7单步跟进去一看,没什么,就是调用了AfxGetModuleState这个函数(这个什么函数具体我也不清楚,我以前MFC编程没有看到过,网上查了下,说跟数据库相关的,这里就忽略了)。

0040260C  |.  E8 7FEEFFFF   CALL Urlegal.00401490

接下来继续跟踪,发现经过00402636和00402648以及00402659处的三个CALL之后,程序跳转到了错误提示消息框,说明算法就在者三个CALL里面了。细心的朋友相信早就发现了OD堆栈窗口早就出现了明文了,但是我们是来分析加密算法的,不能就此满足,所以,还是继续分析吧。

细心的朋友应该已经发现,在00402659处的CALL里面看到了密钥的对比。现在我们仔细看看00402659处的这个call到底传了什么参数进去。

00402651  |.  8D55 EC       LEA EDX,DWORD PTR SS:[EBP-14]
00402654  |.  52            PUSH EDX                                                 ; /Arg2
00402655  |.  8D45 88       LEA EAX,DWORD PTR SS:[EBP-78]                            ; |
00402658  |.  50            PUSH EAX                                                 ; |Arg1
00402659  |.  E8 02060000   CALL Urlegal.00402C60                                    ; \Urlegal.00402C60

发现传入了两个堆栈偏移值,观察堆栈窗口:

0012FB1C   0012FB38  |Arg1 = 0012FB38
0012FB20   0012FB9C  \Arg2 = 0012FB9C

再看看这两个堆栈偏移值(即0012FB38和0012FB9C)在堆栈中到底有什么:

……
0012FB38   003AE688  ASCII "9FF9FB892C7ED5CA1DB021CE61B34C76"
……
0012FB9C   003AE598  ASCII "112233445566778899"
……

果然,是对密钥的一个比较,可以肯定9FF9FB892C7ED5CA1DB021CE61B34C76就是ForEduOnly所对应的真实的注册码了。也说明了生成注册码的算法在前面,而前面没有跟踪的只有两个CALL。

00402623  |.  8985 78FFFFFF MOV DWORD PTR SS:[EBP-88],EAX                            ; |
00402629  |.  8D4D 88       LEA ECX,DWORD PTR SS:[EBP-78]                            ; |
0040262C  |.  51            PUSH ECX                                                 ; |Arg1
0040262D  |.  8B4D 84       MOV ECX,DWORD PTR SS:[EBP-7C]                            ; |
00402630  |.  81C1 D0000000 ADD ECX,0D0                                              ; |
00402636  |.  E8 AE310000   CALL Urlegal.004057E9                                    ; \Urlegal.004057E9
0040263B  |.  8985 74FFFFFF MOV DWORD PTR SS:[EBP-8C],EAX
00402641  |.  C645 FC 01    MOV BYTE PTR SS:[EBP-4],1
00402645  |.  8D4D 88       LEA ECX,DWORD PTR SS:[EBP-78]
00402648  |.  E8 C3050000   CALL Urlegal.00402C10

现在重新加载程序,输入注册码,断下,F8单步来到第一个CALL,这时候观察一下堆栈窗口,没有看到真正的注册码。为了弄明白是哪个CALL进行了算法分析工作,这里继续F8,当这个CALL执行完之后,我们发现堆栈里面有注册码了,可以肯定这个CALL就是生成注册码的CALL,现在范围已经缩小到这个CALL了。

那好,继续重新加载分析。接下来,要跟进00402636处的这个CALL,看看里面做了什么事情(通过堆栈窗口可以发现,我们的用户名ForEduOnly被当做参数传进去了)。我们发现执行完这一句:

00405833  |.  E8 5C130100   CALL <JMP.&MFC42.#535_??0CString@@QAE@ABV0@@Z>

之后堆栈窗口中多了一个字符串:”YKC0YX9XTHTLAA7V”(比较敏感,先记下来),接下来又是一个CALL:

00405833  |.  E8 5C130100   CALL <JMP.&MFC42.#535_??0CString@@QAE@ABV0@@Z>   ;YKC0YX9XTHTLAA7V
00405838  |.  8945 C0       MOV DWORD PTR SS:[EBP-40],EAX                            ; |
0040583B  |.  8B4D C4       MOV ECX,DWORD PTR SS:[EBP-3C]                            ; |
0040583E  |.  E8 CD010000   CALL Urlegal.00405A10                                    ; \Urlegal.00405A10
00405843  |.  8945 BC       MOV DWORD PTR SS:[EBP-44],EAX
00405846  |.  8B4D BC       MOV ECX,DWORD PTR SS:[EBP-44]
00405849  |.  894D E8       MOV DWORD PTR SS:[EBP-18],ECX
0040584C  |.  837D E8 00    CMP DWORD PTR SS:[EBP-18],0
00405850  |.  75 34         JNZ SHORT Urlegal.00405886

即0040583E(对于这些暂时不分析的CALL,先记下来)处的CALL,进去看了一下,感觉有点复杂,执行完之后也没看到什么,先不管。继续向下跟踪。下面又有连个CALL,代码很简单,应该不是注册码算法,忽略。

00405897  |> /8D4D 0C       /LEA ECX,DWORD PTR SS:[EBP+C]
0040589A  |. |E8 A1D8FFFF   |CALL Urlegal.00403140                           ;一个CALL
0040589F  |. |8945 E4       |MOV DWORD PTR SS:[EBP-1C],EAX
004058A2  |. |8D4D 0C       |LEA ECX,DWORD PTR SS:[EBP+C]
004058A5  |. |E8 96D8FFFF   |CALL Urlegal.00403140                           ;一个CALL
004058AA  |. |83F8 10       |CMP EAX,10
004058AD  |. |7E 6D         |JLE SHORT Urlegal.0040591C                       ;跳转实现,中间一段代码忽略

对于下面00405944(对于这些暂时不分析的CALL,先记下来)处这一个CALL,算法比较复杂,先记下,继续跟踪:

0040593E  |.  8945 A8       |MOV DWORD PTR SS:[EBP-58],EAX                           ; |
00405941  |.  8B4D C4       |MOV ECX,DWORD PTR SS:[EBP-3C]                           ; |
00405944  |.  E8 2A020000   |CALL Urlegal.00405B73                                   ; 这个CALL我们先忽略
00405949  |.  8D4D D0       |LEA ECX,DWORD PTR SS:[EBP-30]
0040594C  |.  51            |PUSH ECX                                                ; /Arg1
0040594D  |.  8B4D C4       |MOV ECX,DWORD PTR SS:[EBP-3C]                           ; |
00405950  |.  E8 6C030000   |CALL Urlegal.00405CC1                                   ; 这个CALL我们跟进去看看

上面提到00405950这个CALL跟进去看看,我发现里面有一段代码重复执行了很多次,而且,观察到堆栈中生成了注册码。

00405D03  |> /8B45 EC       /MOV EAX,DWORD PTR SS:[EBP-14]
00405D06  |. |83C0 01       |ADD EAX,1
00405D09  |. |8945 EC       |MOV DWORD PTR SS:[EBP-14],EAX
00405D0C  |> |837D EC 10     CMP DWORD PTR SS:[EBP-14],10
00405D10  |. |0F8D AF000000 |JGE Urlegal.00405DC5
00405D16  |. |8B4D DC       |MOV ECX,DWORD PTR SS:[EBP-24]
00405D19  |. |034D EC       |ADD ECX,DWORD PTR SS:[EBP-14]
00405D1C  |. |8A51 75       |MOV DL,BYTE PTR DS:[ECX+75]         ;注意这里在从内存中取值,可疑!!!
00405D1F  |. |8855 E8       |MOV BYTE PTR SS:[EBP-18],DL
00405D22  |. |8A45 E8       |MOV AL,BYTE PTR SS:[EBP-18]
00405D25  |. |24 F0         |AND AL,0F0
00405D27  |. |8845 E8       |MOV BYTE PTR SS:[EBP-18],AL
00405D2A  |. |8B4D E8       |MOV ECX,DWORD PTR SS:[EBP-18]
00405D2D  |. |81E1 FF000000 |AND ECX,0FF
00405D33  |. |C1F9 04       |SAR ECX,4
00405D36  |. |884D E8       |MOV BYTE PTR SS:[EBP-18],CL
00405D39  |. |8B55 E8       |MOV EDX,DWORD PTR SS:[EBP-18]
00405D3C  |. |81E2 FF000000 |AND EDX,0FF
00405D42  |. |83FA 0A       |CMP EDX,0A
00405D45  |. |7D 10         |JGE SHORT Urlegal.00405D57
00405D47  |. |8B45 E8       |MOV EAX,DWORD PTR SS:[EBP-18]
00405D4A  |. |25 FF000000   |AND EAX,0FF
00405D4F  |. |83C0 30       |ADD EAX,30
00405D52  |. |8845 E4       |MOV BYTE PTR SS:[EBP-1C],AL
00405D55  |. |EB 0F         |JMP SHORT Urlegal.00405D66
00405D57  |> |8B4D E8       |MOV ECX,DWORD PTR SS:[EBP-18]
00405D5A  |. |81E1 FF000000 |AND ECX,0FF
00405D60  |. |83C1 37       |ADD ECX,37
00405D63  |. |884D E4       |MOV BYTE PTR SS:[EBP-1C],CL
00405D66  |> |8A55 E4       |MOV DL,BYTE PTR SS:[EBP-1C]
00405D69  |. |52            |PUSH EDX
00405D6A  |. |8D4D F0       |LEA ECX,DWORD PTR SS:[EBP-10]
00405D6D  |. |E8 120F0100   |CALL <JMP.&MFC42.#940_??YCString@@QAEABV0@D@Z>
00405D72  |. |8B45 DC       |MOV EAX,DWORD PTR SS:[EBP-24]
00405D75  |. |0345 EC       |ADD EAX,DWORD PTR SS:[EBP-14]
00405D78  |. |8A48 75       |MOV CL,BYTE PTR DS:[EAX+75]
00405D7B  |. |884D E8       |MOV BYTE PTR SS:[EBP-18],CL
00405D7E  |. |8A55 E8       |MOV DL,BYTE PTR SS:[EBP-18]
00405D81  |. |80E2 0F       |AND DL,0F
00405D84  |. |8855 E8       |MOV BYTE PTR SS:[EBP-18],DL
00405D87  |. |8B45 E8       |MOV EAX,DWORD PTR SS:[EBP-18]
00405D8A  |. |25 FF000000   |AND EAX,0FF
00405D8F  |. |83F8 0A       |CMP EAX,0A
00405D92  |. |7D 11         |JGE SHORT Urlegal.00405DA5
00405D94  |. |8B4D E8       |MOV ECX,DWORD PTR SS:[EBP-18]
00405D97  |. |81E1 FF000000 |AND ECX,0FF
00405D9D  |. |83C1 30       |ADD ECX,30
00405DA0  |. |884D E4       |MOV BYTE PTR SS:[EBP-1C],CL
00405DA3  |. |EB 0F         |JMP SHORT Urlegal.00405DB4
00405DA5  |> |8B55 E8       |MOV EDX,DWORD PTR SS:[EBP-18]
00405DA8  |. |81E2 FF000000 |AND EDX,0FF
00405DAE  |. |83C2 37       |ADD EDX,37
00405DB1  |. |8855 E4       |MOV BYTE PTR SS:[EBP-1C],DL
00405DB4  |> |8A45 E4       |MOV AL,BYTE PTR SS:[EBP-1C]
00405DB7  |. |50            |PUSH EAX
00405DB8  |. |8D4D F0       |LEA ECX,DWORD PTR SS:[EBP-10]
00405DBB  |. |E8 C40E0100   |CALL <JMP.&MFC42.#940_??YCString@@QAEABV0@D@Z>
00405DC0  |.^\E9 3EFFFFFF   \JMP Urlegal.00405D03

从上面的代码分析中看到00405D1C处从内存中取值,内存的位置大概在0042249F附近,到OD左下角的内存窗口中跟踪一下,发现这里已经生成好了注册码,对比堆栈窗口中还没有完全生成好的注册码,可以知道注册码开始于内存中的0042249D,如下图:
OD内存对比

继续分析待整个子程序结束,可以知道注册码为9FF9FB892C7ED5CA1DB021CE61B34C76,共16个字节;即注册码存在于内存中0042249D开始的16个字节。既然这个过程只是简单的将内存中的注册码复制过来,可知,注册码肯定在前面的CALL中生成。所以要分析前面忽略过的CALL。

现在我们可以再0042249D处下一个内存写入断点,这样在产生注册码时会自动断下。我比较懒,就直接分别F8跟过0040583E和00405944处的CALL,发现只有在经过00405944处的CALL之后,内存中才有了注册码,所以,接下来的重点就是分析00405944处的CALL了。下面是这个CALL的代码:

00405B73  /$  55            PUSH EBP
00405B74  |.  8BEC          MOV EBP,ESP
00405B76  |.  6A FF         PUSH -1
00405B78  |.  68 A97B4100   PUSH Urlegal.00417BA9                                    ;  SE 处理程序安装
00405B7D  |.  64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
00405B83  |.  50            PUSH EAX
00405B84  |.  64:8925 00000>MOV DWORD PTR FS:[0],ESP
00405B8B  |.  83EC 24       SUB ESP,24
00405B8E  |.  894D D0       MOV DWORD PTR SS:[EBP-30],ECX
00405B91  |.  C745 FC 00000>MOV DWORD PTR SS:[EBP-4],0
00405B98  |.  6A 11         PUSH 11                                                  ; /n = 11 (17.)
00405B9A  |.  6A 00         PUSH 0                                                   ; |c = 00
00405B9C  |.  8B45 D0       MOV EAX,DWORD PTR SS:[EBP-30]                            ; |
00405B9F  |.  83C0 64       ADD EAX,64                                               ; |
00405BA2  |.  50            PUSH EAX                                                 ; |s
00405BA3  |.  E8 1E140100   CALL <JMP.&MSVCRT.memset>                                ; \memset
00405BA8  |.  83C4 0C       ADD ESP,0C
00405BAB  |.  6A 10         PUSH 10                                                  ; /n = 10 (16.)
00405BAD  |.  6A 00         PUSH 0                                                   ; |c = 00
00405BAF  |.  8B4D D0       MOV ECX,DWORD PTR SS:[EBP-30]                            ; |
00405BB2  |.  83C1 75       ADD ECX,75                                               ; |
00405BB5  |.  51            PUSH ECX                                                 ; |s
00405BB6  |.  E8 0B140100   CALL <JMP.&MSVCRT.memset>                                ; \memset
00405BBB  |.  83C4 0C       ADD ESP,0C
00405BBE  |.  6A 11         PUSH 11                                                  ; /n = 11 (17.)
00405BC0  |.  6A 00         PUSH 0                                                   ; |c = 00
00405BC2  |.  8B55 D0       MOV EDX,DWORD PTR SS:[EBP-30]                            ; |
00405BC5  |.  81C2 85000000 ADD EDX,85                                               ; |
00405BCB  |.  52            PUSH EDX                                                 ; |s
00405BCC  |.  E8 F5130100   CALL <JMP.&MSVCRT.memset>                                ; \memset
00405BD1  |.  83C4 0C       ADD ESP,0C
00405BD4  |.  8D4D 08       LEA ECX,DWORD PTR SS:[EBP+8]
00405BD7  |.  E8 64D5FFFF   CALL Urlegal.00403140    
00405BDC  |.  83F8 10       CMP EAX,10
00405BDF  |.  7E 1E         JLE SHORT Urlegal.00405BFF
00405BE1  |.  C745 DC 00000>MOV DWORD PTR SS:[EBP-24],0
00405BE8  |.  C745 FC FFFFF>MOV DWORD PTR SS:[EBP-4],-1
00405BEF  |.  8D4D 08       LEA ECX,DWORD PTR SS:[EBP+8]
00405BF2  |.  E8 C90D0100   CALL <JMP.&MFC42.#800_??1CString@@QAE@XZ>
00405BF7  |.  8B45 DC       MOV EAX,DWORD PTR SS:[EBP-24]
00405BFA  |.  E9 B2000000   JMP Urlegal.00405CB1
00405BFF  |>  8D4D 08       LEA ECX,DWORD PTR SS:[EBP+8]
00405C02  |.  E8 39D5FFFF   CALL Urlegal.00403140
00405C07  |.  8945 E0       MOV DWORD PTR SS:[EBP-20],EAX
00405C0A  |.  C745 E4 00000>MOV DWORD PTR SS:[EBP-1C],0
00405C11  |.  EB 09         JMP SHORT Urlegal.00405C1C
00405C13  |>  8B45 E4       /MOV EAX,DWORD PTR SS:[EBP-1C]
00405C16  |.  83C0 01       |ADD EAX,1
00405C19  |.  8945 E4       |MOV DWORD PTR SS:[EBP-1C],EAX
00405C1C  |>  8B4D E4        MOV ECX,DWORD PTR SS:[EBP-1C]
00405C1F  |.  3B4D E0       |CMP ECX,DWORD PTR SS:[EBP-20]
00405C22  |.  7D 17         |JGE SHORT Urlegal.00405C3B
00405C24  |.  8B55 E4       |MOV EDX,DWORD PTR SS:[EBP-1C]
00405C27  |.  52            |PUSH EDX                                                ; /Arg1
00405C28  |.  8D4D 08       |LEA ECX,DWORD PTR SS:[EBP+8]                            ; |
00405C2B  |.  E8 60040000   |CALL Urlegal.00406090                                   ; \Urlegal.00406090
00405C30  |.  8B4D D0       |MOV ECX,DWORD PTR SS:[EBP-30]
00405C33  |.  034D E4       |ADD ECX,DWORD PTR SS:[EBP-1C]
00405C36  |.  8841 64       |MOV BYTE PTR DS:[ECX+64],AL
00405C39  |.^ EB D8         \JMP SHORT Urlegal.00405C13
00405C3B  |>  C745 E8 10000>MOV DWORD PTR SS:[EBP-18],10
00405C42  |.  8B55 E8       MOV EDX,DWORD PTR SS:[EBP-18]
00405C45  |.  C1E2 03       SHL EDX,3
00405C48  |.  8955 EC       MOV DWORD PTR SS:[EBP-14],EDX
00405C4B  |.  8B45 D0       MOV EAX,DWORD PTR SS:[EBP-30]
00405C4E  |.  83C0 75       ADD EAX,75
00405C51  |.  50            PUSH EAX                                                 ; /Arg5
00405C52  |.  8B4D E8       MOV ECX,DWORD PTR SS:[EBP-18]                            ; |
00405C55  |.  C1E1 03       SHL ECX,3                                                ; |
00405C58  |.  51            PUSH ECX                                                 ; |Arg4
00405C59  |.  8B55 D0       MOV EDX,DWORD PTR SS:[EBP-30]                            ; |
00405C5C  |.  83C2 64       ADD EDX,64                                               ; |
00405C5F  |.  52            PUSH EDX                                                 ; |Arg3
00405C60  |.  68 B8014200   PUSH Urlegal.004201B8                                    ; |Arg2 = 004201B8
00405C65  |.  68 90014200   PUSH Urlegal.00420190                                    ; |Arg1 = 00420190
00405C6A  |.  E8 AD460000   CALL Urlegal.0040A31C                                    ; \Urlegal.0040A31C
00405C6F  |.  83C4 14       ADD ESP,14
00405C72  |.  8945 F0       MOV DWORD PTR SS:[EBP-10],EAX
00405C75  |.  8B45 F0       MOV EAX,DWORD PTR SS:[EBP-10]
00405C78  |.  3B45 EC       CMP EAX,DWORD PTR SS:[EBP-14]
00405C7B  |.  74 1B         JE SHORT Urlegal.00405C98
00405C7D  |.  C745 D8 00000>MOV DWORD PTR SS:[EBP-28],0
00405C84  |.  C745 FC FFFFF>MOV DWORD PTR SS:[EBP-4],-1
00405C8B  |.  8D4D 08       LEA ECX,DWORD PTR SS:[EBP+8]
00405C8E  |.  E8 2D0D0100   CALL <JMP.&MFC42.#800_??1CString@@QAE@XZ>
00405C93  |.  8B45 D8       MOV EAX,DWORD PTR SS:[EBP-28]
00405C96  |.  EB 19         JMP SHORT Urlegal.00405CB1
00405C98  |>  C745 D4 01000>MOV DWORD PTR SS:[EBP-2C],1
00405C9F  |.  C745 FC FFFFF>MOV DWORD PTR SS:[EBP-4],-1
00405CA6  |.  8D4D 08       LEA ECX,DWORD PTR SS:[EBP+8]
00405CA9  |.  E8 120D0100   CALL <JMP.&MFC42.#800_??1CString@@QAE@XZ>
00405CAE  |.  8B45 D4       MOV EAX,DWORD PTR SS:[EBP-2C]
00405CB1  |>  8B4D F4       MOV ECX,DWORD PTR SS:[EBP-C]
00405CB4  |.  64:890D 00000>MOV DWORD PTR FS:[0],ECX
00405CBB  |.  8BE5          MOV ESP,EBP
00405CBD  |.  5D            POP EBP
00405CBE  \.  C2 0400       RETN 4

经过跟踪,确定了上面红色代码即为注册码生成算法。整个算法很长,也很复杂,用到了大量的抑或和移位操作,大大的打击了我继续分析下去的信心和勇气。听说IDA可以将反汇编代码生成C语言,于是我把程序拿到IDA下面分析,来到这个CALL之后,F5生成C代码,好长好长啊,可读性和可理解性极差。

最后,我想到了视频中说用PEID的插件来检测算法的,于是我看了下PEID的Krypto ANALyzer插件对程序的分析结果,是”TWOFISH“算法。马上去Google了一下,果然是很复杂,想到自己是初学者,为了能够有兴趣继续学习逆向,这个算法暂时放下。

就如本文开头所说,没能成功分析这个注册算法。但是还是可以处理一下:
一、爆破(也太没技术含量了 弃之)
二、内存注册机(可以尝试一下)

前面提到注册码存在于内存中0042249D开始的16个字节,所以可以去读取这个KEY。
大概思路:
运行URLegal——>输入假码注册——>获取URLegal的PID——>通过PID打开URLegal得到进程句柄——>读取进程内存——>将数据转换成字符串反馈给界面。
(获取URLegal的PID可以通过CreateToolhelp32Snapshot来查找进程实现)

注册机截图发一个效果图:
总结:虽然算法分析失败,但毕竟这是第一次逆向分析。整个软件采用明文对比,这个是非常危险的。
P.S. 注册信息保存在注册表的HKEY_LOCAL_MACHINE\SOFTWARE\Paul Gerhart Software\URLegal\User分支下面。
最后,感谢各位朋友的观赏,不正之处敬请指正。
我把注册机程序删除了,留下源码(MASM)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; URLegal Keygen
; Author:	代码疯子
; Blog:		http://www.programlife.net/
; Date:		2011-03-16
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
				.386
				.model flat, stdcall
				option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include			windows.inc
include			user32.inc
includelib		user32.lib
include			kernel32.inc
includelib		kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IDD_DLG			equ		1000
IDC_EDT_KEY		equ		1004
IDC_BTN_GEN		equ		1005
ICO_MAIN		equ		1006
 
PATCH_POSITION	equ		0042249Dh
KEY_LEN			equ		16
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
				.data?
hInstance		dd		?
dbKeyBytes		db		64 dup (?)
szKey			db		64 dup (?)
hWinMain		dd		?
hDstProcess		dd		?
dwPID			dd		?
szDstName		db		128 dup (?)
				.data
 
				.const
szErrMsg		db		'无法创建进程快照,请尝试以管理员身份运行本程序!', 0
szErrOpen		db		'无法打开目标进程,请尝试以管理员身份运行本程序!', 0
szErrTitle		db		'错误提示', 0
szRealName		db		'urlegal.exe', 0
szFormat		db		'%02X'
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
				.code
_MemToStr		proc	uses esi edi
				local	@dwCnt
 
				mov		esi, offset dbKeyBytes
				mov		edi, offset szKey
				mov		@dwCnt, 0
				.while	@dwCnt < KEY_LEN
						mov		al, byte ptr [esi]
						invoke	wsprintf, edi, addr szFormat, al
						add		edi, 2
						inc		esi
						mov		ecx, @dwCnt
						inc		ecx
						mov		@dwCnt, ecx
				.endw
				xor		al, al
				mov		byte ptr [edi], al
 
				ret
_MemToStr		endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_CmpName		proc	_dwSrc, _dwDst
				pushad
				mov		esi, _dwSrc
				mov		edi, _dwDst
				mov		al, 1
				mov		ah, 1
				.while	al != 0 && ah != 0
						mov		al, byte ptr [edi]
						mov		ah, byte ptr [esi]
						.if		al >= 'A' && al <= 'Z'
								sub		al, 'A'
								add		al, 'a'
						.endif
						cmp		al, ah
						jnz		_ret0
						inc		edi
						inc		esi
				.endw
				.if		al == 0 && ah == 0
						popad
						mov		eax, 1
						ret
				.endif
_ret0:
				popad
				mov		eax, 0
				ret
_CmpName		endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_GetPid			proc
				local	@stProcess:PROCESSENTRY32
				local	@hSnapShot
 
				invoke	RtlZeroMemory, addr @stProcess, sizeof @stProcess
				mov		@stProcess.dwSize, sizeof @stProcess
				invoke	CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS, 0
				.if		eax ==	INVALID_HANDLE_VALUE
						invoke	MessageBox, hWinMain, addr szErrMsg, \
								addr szErrTitle, MB_ICONWARNING
						ret
				.endif
				mov		@hSnapShot, eax
				invoke	Process32First, @hSnapShot, addr @stProcess
				.while	eax
						invoke	lstrcpy, addr szDstName, addr @stProcess.szExeFile
						invoke	_CmpName, addr szRealName, addr szDstName
						.if		eax
								push	@stProcess.th32ProcessID
								pop		dwPID
								ret
						.endif
						invoke	Process32Next, @hSnapShot, addr @stProcess
				.endw
				ret
_GetPid			endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_GenKey			proc
				invoke	_GetPid
				invoke	OpenProcess, PROCESS_VM_READ, FALSE, dwPID
				.if		eax ==	NULL
						invoke	MessageBox, hWinMain, addr szErrOpen, \
								addr szErrTitle, MB_ICONWARNING
						ret
				.endif
				mov		hDstProcess, eax
				invoke	ReadProcessMemory, hDstProcess, PATCH_POSITION, \
						addr dbKeyBytes, KEY_LEN, NULL
				invoke	CloseHandle, hDstProcess
				invoke	_MemToStr
				invoke	SendDlgItemMessage, hWinMain, IDC_EDT_KEY, \
						WM_SETTEXT, 0, addr szKey
				ret
 
_GenKey			endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain	proc	uses ebx esi edi hWnd, uMsg, wParam, lParam
				mov		eax, uMsg
				.if		eax ==	WM_CLOSE
						invoke	EndDialog, hWnd, NULL
				.elseif	eax ==	WM_INITDIALOG
						invoke	LoadIcon, hInstance, ICO_MAIN
						invoke	SendMessage, hWnd, WM_SETICON, \
								ICON_BIG, eax
						push	hWnd
						pop		hWinMain
				.elseif	eax ==	WM_COMMAND
						mov		eax, wParam
						.if		ax ==	IDC_BTN_GEN
								invoke	_GenKey
						.endif
				.else
						mov		eax, FALSE
						ret
				.endif
				mov		eax, TRUE
				ret
 
_ProcDlgMain	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
				invoke	GetModuleHandle, NULL
				mov		hInstance, eax
				invoke	DialogBoxParam, hInstance, IDD_DLG, NULL, \
						_ProcDlgMain, NULL
				invoke	ExitProcess, NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
				end		start

资源文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <resource.h>
 
#define ICO_MAIN 1006
#define IDD_DLG 1000
#define IDC_GRP1 1002
#define IDC_STC_ABOUT 1003
#define IDC_EDT_KEY 1004
#define IDC_BTN_GEN 1005
#define IDC_STC1 1001
ICO_MAIN ICON DISCARDABLE "Keygen.ico"
IDD_DLG DIALOGEX 6,5,208,72
CAPTION "URLegal Keygen"
FONT 8,"MS Sans Serif"
STYLE 0x10CA0800
EXSTYLE 0x00000000
BEGIN
  CONTROL "运行URLegal,并输入您的用户名和随意的假注册码注册。之后URLegal会提示注册失败,这时点击本程序的获取注册码按钮就可以得到真实的注册码了。",IDC_STC1,"Static",0x50000000,14,9,180,26,0x00000000
  CONTROL "使用说明",IDC_GRP1,"Button",0x50000007,4,0,200,39,0x00000000
  CONTROL "Enjoy it!  Author: 代码疯子 http://www.programlife.net/",IDC_STC_ABOUT,"Static",0x50000001,4,59,198,9,0x00000000
  CONTROL "",IDC_EDT_KEY,"Edit",0x50010000,4,42,146,13,0x00000200
  CONTROL "获取注册码",IDC_BTN_GEN,"Button",0x50010000,154,42,50,13,0x00000000
END

觉得文章还不错?点击此处对作者进行打赏!


本文地址: 程序人生 >> 初探逆向之URLegal破解
作者:代码疯子(Wins0n) 本站内容如无声明均属原创,转载请保留作者信息与原文链接,谢谢!


更多



  1. 2011年3月23日16:10 | #1

    学习了,破解这个对我来说很难的

    [回复]

  2. 2011年3月23日16:14 | #2

    对了哥们,咱们把链接做上吧。你的我已经添加了。

    [回复]

  3. 2011年3月23日19:15 | #3

    @西风
    不好意思,贵站内容跟本站内容不是很接近,暂时不做链接

    [回复]

  4. 2011年3月24日01:14 | #4

    Complicated

    [回复]

  5. 2011年3月24日16:59 | #5

    同道中人呀,多多交流呀。

    [回复]

  6. 2011年3月24日17:24 | #6

    @the5fire
    呵呵,多多交流,我是刚刚接触的新手

    [回复]

  7. 2011年3月24日17:25 | #7

    @C瓜哥
    是有点复杂了

    [回复]