一个屏幕抓取工具的破解思路与分析

好久没有写这方面的文章了,常常都是随手破了后丢到论坛里。
由于博客新开,内容实在是太少了,只好努力一点,多写写东西了,希望大家从中能有所得,呵呵……

具体的软件介绍或者下载,大家可以到这里查阅:http://www.newhua.com/soft/12371.htm
如果需要下载破解版,则请到论坛下载:http://bbs.7softs.com/read.php?tid=30682&page=1&toread=1

好了,不多说了,开始我们的分析,按照流程来吧:
1、查壳,显示为:Microsoft Visual C++ 7.0 [调试]
2、载入后,看了看文件头,肯定了无壳:


00507F7E S>  6A 60               push 60
00507F80     68 E04F7300         push ScreenHu.00734FE0
00507F85     E8 22480000         call ScreenHu.0050C7AC
00507F8A     BF 94000000         mov edi,94
00507F8F     8BC7                mov eax,edi
00507F91     E8 BACDFFFF         call ScreenHu.00504D50
00507F96     8965 E8             mov dword ptr ss:[ebp-18],esp
00507F99     8BF4                mov esi,esp
00507F9B     893E                mov dword ptr ds:[esi],edi
00507F9D     56                  push esi
00507F9E     FF15 08B97B00       call dword ptr ds:[<&KERNEL32.GetVersi>; kernel32.GetVersionExA

3、F9运行起来,然后输入假码:11111-22222-33333-44444-55555
有错误提示,不过不是通过弹出对话框,而是通过文本控件来显示的:“Invalid License……”
用插件和OD自带的字符查找工具查找了一下,都没有找到,不过却找到了一些相关的看似有用的信息,如图:

4、试着在上面下了断点,然后再次注册,不过没有断下来:


005B09C0     68 A8C46F00    push ScreenHu.006FC4A8         ; licensekey1
                                         //在上面一行下了断点!
005B09C5     B9 C8F17800    mov ecx,ScreenHu.0078F1C8
005B09CA     E8 3D36E5FF    call ScreenHu.0040400C
005B09CF     68 705C6700    push ScreenHu.00675C70
005B09D4     E8 3D3BF5FF    call ScreenHu.00504516
005B09D9     59             pop ecx
005B09DA     C3             retn

5、对一些常用的API函数下断点:
万能断点————————–无效
bp GetDlgItemTextA———-无效
bp SetDlgitemTextA———–无效
于是我又现次下了一个:SetWindowTextA的断点,呵呵终于断了下来


77D2F56B U>  8BFF           mov edi,edi
         //此时提示窗口提示为
      //edi=0109BF78, (ASCII "Invalid License Key. Please try again or contact Wisdom Software.")

77D2F56D     55             push ebp
77D2F56E     8BEC           mov ebp,esp
77D2F570     8B4D 08        mov ecx,dword ptr ss:[ebp+8]
77D2F573     56             push esi
77D2F574     E8 678FFEFF    call USER32.77D184E0

留意此时的堆栈窗口:


0012F5A0   0054D397  /CALL 到 SetWindowTextA 来自 ScreenHu.0054D391
0012F5A4   0007060C  |hWnd = 0007060C ('Invalid License Key. Please t...',class='Static',parent=000E05C4)
0012F5A8   0109C038  \Text = "Invalid License Key. Please try again or contact Wisdom Software."
0012F5AC   0044032D  返回到 ScreenHu.0044032D 来自 ScreenHu.0054D383
     //在这一行,我们右键跟随到反汇编窗口,就找到了关键断,不过我没有细跟
     //这里,我又试着另一种方法去分析!
0012F5B0   0109C038  ASCII "Invalid License Key. Please try again or contact Wisdom Software."
0012F5B4   00000001
0012F5B8   0070129C  ScreenHu.0070129C
0012F5BC   0109C038  ASCII "Invalid License Key. Please try again or contact Wisdom Software."
0012F5C0   0012F700  指针到下一个 SEH 记录
0012F5C4   005A4218  SE 句柄

6、让我们想一想,程序是如何确定要显示程序前的这个注册窗口的呢??
所以在这个注册窗口运行起来之前必然有一个是否注册的判断,而我们只要找到这个判断的位置,我们也就可以十分容易的破解掉这个注册机制了!!!如何找到这个位置呢???呵,我常用的F12堆栈暂停法,又有了用武之地了……

7、在程序运行来那个注册窗口之后,稍等一下(等待其完全运行好),按F12暂停:


7C92E4F4 n>  C3             retn
7C92E4F5     8DA424 0000000>lea esp,dword ptr ss:[esp]
7C92E4FC     8D6424 00      lea esp,dword ptr ss:[esp]

再然后打开堆栈调用窗口,如图:

在这一行上,点击右键->显示调用,来到反汇编窗口:
调用堆栈 ,项目 6
地址=0012FE34
堆栈=00467A7F
函数例程=ScreenHu.004034D6
调用来自=ScreenHu.00467A7A


00467A5C     50             push eax
00467A5D     E8 95ADF9FF    call ScreenHu.004027F7
00467A62     8B86 1C010000  mov eax,dword ptr ds:[esi+11C]
00467A68     83C4 04        add esp,4
00467A6B     3BC5           cmp eax,ebp
00467A6D     74 09          je short ScreenHu.00467A78
00467A6F     E8 789FF9FF    call ScreenHu.004019EC
00467A74     85C0           test eax,eax
00467A76     7F 07          jg short ScreenHu.00467A7F
00467A78     8BCE           mov ecx,esi
00467A7A     E8 57BAF9FF    call ScreenHu.004034D6
             //返回到这里:
             //由此可知,此处调用是用来显示注册窗口的!(可以测试一下)    

我们往上面找,在00467A5C处下断,然后重新载入程序,中断后单步运行,通过分析上面的代码,我们可以得出:
  A、00467A6D处跳转不能实现,否则就直接跳向了注册对话框了,我们单步时,通过修改寄存器的ZF标志位,让其没有跳转
  B、00467A76处的跳转必须跳,否则不能跳过注册对话框,同样的,通过修改寄存器的ZF标志位,让其实现

然后我们F9运行起程序来,果然没有了注册对话框,不过依然显示为未注册版(UNREGISTED!)
这说明直接改上面的跳转是不是行的了

8、重新载入程序,跟进上面一段代码里的两个CALL
A、call ScreenHu.004027F7,直接来到段尾:


0041C673     84DB           test bl,bl
0041C675     74 12          je short ScreenHu.0041C689
0041C677     5E             pop esi
0041C678     C705 743B7A00 >mov dword ptr ds:[7A3B74],0
0041C682     33C0           xor eax,eax
0041C684     5B             pop ebx
0041C685     83C4 10        add esp,10
0041C688     C3             retn
0041C689     5E             pop esi      //如果能够跳到这里,必须是正确注册的了
0041C68A     B8 01000000    mov eax,1
0041C68F     5B             pop ebx
0041C690     83C4 10        add esp,10

我们单步时,会发现我们跳到了这里:0041C678
好了,开始我们的第1 个修改:


0041C678     C705 743B7A00 >mov dword ptr ds:[7A3B74],1
0041C682     B0 01          mov al,1
0041C684     5B             pop ebx
0041C685     83C4 10        add esp,10
0041C688     C3             retn

B、call ScreenHu.004019EC


0041ADA0     A1 CC407A00    mov eax,dword ptr ds:[7A40CC]
0041ADA5     8B0D 24287900  mov ecx,dword ptr ds:[792824]
0041ADAB     56             push esi
0041ADAC     50             push eax
0041ADAD     51             push ecx
0041ADAE     33F6           xor esi,esi
0041ADB0     E8 21990E00    call ScreenHu.005046D6
0041ADB5     83C4 08        add esp,8
0041ADB8     85C0           test eax,eax
0041ADBA     75 07          jnz short ScreenHu.0041ADC3
0041ADBC     B8 01000000    mov eax,1
0041ADC1     5E             pop esi
0041ADC2     C3             retn

这个CALL里的修改更为直接,直接将0041ADBA 处的跳转NOP掉,然后运行起来,OK了!
然后把修改后的程序保存一份!

这样,一个破解过程就完成了,呵呵!!

发表评论