破解 crackme(浅析去除警告窗口)

系统 : Windows xp

程序 : crackme

程序下载地址 :http://pan.baidu.com/s/1kUrbcAr

要求 : 注册机编写 & 去除Nag窗口

使用工具 : IDA Pro & OD

可在“PEDIY CrackMe 2007”中查找关于此程序的讨论,标题为“Pj一个超简单的Crackme,适合像我一样的新手~_~”。

运行该程序,发现一开始就给了我们一个大大的警告窗口:

  这不找抽吗?载入IDA查看字串表,发现字串“Patch Me if you can”,双击定位到定义位置,再双击交叉引用来到调用处。发现程序调用MessageBox来显示窗口,OD载入程序,将call MessageBox函数这一行改为add esp 10:

运行程序:

咦?我保存了的啊,什么还是显示了Nag窗口?而且我的断点也失效了?

初步判断,该程序开始运行时,进行清除断点的工作。并且,对载入内存的MessageBox部分代码进行了还原。

想要去除Nag窗口,可能就需要书后面的反跟踪以及打补丁的技巧。这里,我们暂时忍一下,先放过它。

重新返回字串表,发现该程序没有错误提示。。。找到成功注册的提示,向上翻找定位关键代码:

00401219   .  C705 643C4000>mov     dword ptr [403C64], <jmp.&user32.GetWindowTextA>   ;  将函数地址存入 403C64
00401223   .  832D 643C4000>sub     dword ptr [403C64], 9
0040122A   >  68 FF010000   push    1FF                                                ;  循环两次读入用户名和密码。
0040122F   .  83FB 01       cmp     ebx, 1                                             ;  用户名存入403054,序列号403654
00401232   .  75 0D         jnz     short 00401241
00401234   .  68 54304000   push    00403054                                           ;  ASCII "pediy"
00401239   .  FF35 4C304000 push    dword ptr [40304C]
0040123F   .  EB 0B         jmp     short 0040124C
00401241   >  68 54364000   push    00403654                                           ;  ASCII "1111111111"
00401246   .  FF35 50304000 push    dword ptr [403050]
0040124C   >  83FB 01       cmp     ebx, 1
0040124F   .  74 07         je      short 00401258
00401251   .  8305 643C4000>add     dword ptr [403C64], 9
00401258   >  FF15 643C4000 call    dword ptr [403C64]                                 ;  <jmp.&user32.GetWindowTextA>
0040125E   .  43            inc     ebx
0040125F   .  83FB 02       cmp     ebx, 2
00401262   .^ 7C C6         jl      short 0040122A
00401264   .  C705 703C4000>mov     dword ptr [403C70], <jmp.&kernel32.lstrlenA>
0040126E   .  FF0D 703C4000 dec     dword ptr [403C70]                                 ;  crackme.004016DC
00401274   .  C705 683C4000>mov     dword ptr [403C68], <jmp.&user32.GetWindowTextLeng>
0040127E   .  FF05 683C4000 inc     dword ptr [403C68]                                 ;  crackme.00401670
00401284   .  FF35 4C304000 push    dword ptr [40304C]
0040128A   .  FF0D 683C4000 dec     dword ptr [403C68]                                 ;  crackme.00401670
00401290   .  FF15 683C4000 call    dword ptr [403C68]                                 ;  <jmp.&user32.GetWindowTextLengthA>
00401296   .  83F8 05       cmp     eax, 5                                             ;  用户名是否小于5?
00401299   .  0F8C 43010000 jl      004013E2                                           ;  是则跳转至出错代码
0040129F   .  83F8 08       cmp     eax, 8                                             ;  用户名是否大于等于8?
004012A2   .  0F8D 3A010000 jge     004013E2                                           ;  是则跳转至出错代码
004012A8   .  8BC8          mov     ecx, eax
004012AA   .  890D 543C4000 mov     dword ptr [403C54], ecx                            ;  长度存入内存
004012B0   .  33DB          xor     ebx, ebx
004012B2   .  8D35 54304000 lea     esi, dword ptr [403054]                            ;  取用户名
004012B8   .  8D3D 54324000 lea     edi, dword ptr [403254]                            ;  开辟内存储存密钥
004012BE   >  8A4431 FF     mov     al, byte ptr [ecx+esi-1]                           ;  倒序迭代字串
004012C2   .  80F9 04       cmp     cl, 4                                              ;  长度为4?
004012C5   .  74 13         je      short 004012DA                                     ;  是则存储‘-’字符并结束本次循环
004012C7   .  3C 4D         cmp     al, 4D                                             ;  是否小于0x4D?
004012C9   .  7C 04         jl      short 004012CF
004012CB   .  2C 11         sub     al, 11                                             ;  大于0x4D则减去0x11
004012CD   .  EB 02         jmp     short 004012D1
004012CF   >  04 15         add     al, 15
004012D1   >  32C1          xor     al, cl                                             ;  处理过的字符值 ^ 长度
004012D3   .  34 02         xor     al, 2                                              ;  处理过的字符值^2
004012D5   .  88043B        mov     byte ptr [ebx+edi], al                             ;  保存密钥
004012D8   .  EB 04         jmp     short 004012DE
004012DA   >  C6043B 2D     mov     byte ptr [ebx+edi], 2D
004012DE   >  43            inc     ebx                                                ;  指向下一个存储单元
004012DF   .^ E0 DD         loopdne short 004012BE                                     ;  类似loop,另外测试ZF标志位是否为1则退出循环
004012E1   .  8D35 54324000 lea     esi, dword ptr [403254]                            ;  取序列号
004012E7   .  8D3D 54344000 lea     edi, dword ptr [403454]                            ;  开辟内存储存新密钥
004012ED   .  8B0D 543C4000 mov     ecx, dword ptr [403C54]                            ;  长度存入ecx
004012F3   .  33DB          xor     ebx, ebx
004012F5   .  C705 5C3C4000>mov     dword ptr [403C5C], <jmp.&kernel32.lstrcatA>
004012FF   .  832D 5C3C4000>sub     dword ptr [403C5C], 2
00401306   .  C705 783C4000>mov     dword ptr [403C78], 0040207F                       ;  ASCII ":-)"
00401310   .  C705 7C3C4000>mov     dword ptr [403C7C], 00402070                       ;  ASCII "Correct Serial"
0040131A   .  832D 783C4000>sub     dword ptr [403C78], 5
00401321   .  832D 7C3C4000>sub     dword ptr [403C7C], 5
00401328   >  80F9 04       cmp     cl, 4                                              ;  长度为4?
0040132B   .  74 17         je      short 00401344                                     ;  是则存储‘-’字符并结束本次循环
0040132D   .  8A4431 FF     mov     al, byte ptr [ecx+esi-1]                           ;  倒序迭代密钥
00401331   .  3C 4D         cmp     al, 4D                                             ;  是否小于0x4D?
00401333   .  7C 04         jl      short 00401339                                     ;  小于0x4D则加上0x15
00401335   .  2C 11         sub     al, 11                                             ;  大于0x4D则减去0x11
00401337   .  EB 02         jmp     short 0040133B
00401339   >  04 15         add     al, 15
0040133B   >  32C1          xor     al, cl                                             ;  处理过的字符值 ^ 长度
0040133D   .  34 02         xor     al, 2                                              ;  处理过的字符值^2
0040133F   .  88043B        mov     byte ptr [ebx+edi], al                             ;  保存密钥
00401342   .  EB 04         jmp     short 00401348
00401344   >  C6043B 2D     mov     byte ptr [ebx+edi], 2D
00401348   >  43            inc     ebx                                                ;  指向下一个存储单元
00401349   .^ E0 DD         loopdne short 00401328                                     ;  类似loop,另外测试ZF标志位是否为1则退出循环
0040134B   .  C705 603C4000>mov     dword ptr [403C60], <jmp.&user32.MessageBoxA>      ;  Entry address
00401355   .  832D 603C4000>sub     dword ptr [403C60], 7
0040135C   .  68 54324000   push    00403254                                           ;  ASCII "o-RT\"
00401361   .  68 54344000   push    00403454                                           ;  ASCII "[email protected]]o-RT\"
00401366   .  8305 5C3C4000>add     dword ptr [403C5C], 2                              ;  ↓将旧密钥连接到新密钥后面
0040136D   .  FF15 5C3C4000 call    dword ptr [403C5C]                                 ;  <jmp.&kernel32.lstrcatA>
00401373   .  68 54344000   push    00403454                                           ;  ASCII "[email protected]]o-RT\"
00401378   .  FF05 703C4000 inc     dword ptr [403C70]                                 ;  crackme.004016DC
0040137E   .  FF15 703C4000 call    dword ptr [403C70]                                 ;  <jmp.&kernel32.lstrlenA>
00401384   .  A3 743C4000   mov     dword ptr [403C74], eax                            ;  ↑算出密钥长度↓算出输入的序列号长度
00401389   .  68 54364000   push    00403654                                           ;  ASCII "1111111111"
0040138E   .  FF15 703C4000 call    dword ptr [403C70]                                 ;  <jmp.&kernel32.lstrlenA>
00401394   .  3B05 743C4000 cmp     eax, dword ptr [403C74]                            ;  长度一样?
0040139A   .  75 46         jnz     short 004013E2
0040139C   .  FF35 543C4000 push    dword ptr [403C54]                                 ;  长度入栈
004013A2   .  68 54344000   push    00403454                                           ;  ASCII "[email protected]]o-RT\"
004013A7   .  68 54364000   push    00403654                                           ;  ASCII "1111111111"
004013AC   .  E8 9F000000   call    00401450                                           ;  字串是否相等?
004013B1   .  83F8 01       cmp     eax, 1                                             ;  不相等则跳转出错
004013B4   .  74 2C         je      short 004013E2                                     ;  相等则提示成功

这是一个F(用户名)=序列号的例子,我们将F(用户名)用高级语言写出来即可完成注册机。

打开打开http://www.cnblogs.com/ZRBYYXDM/p/5115596.html中搭建的框架,为CKengen_TemplateDlg添加成员函数CreateSerial:

CString CKengen_TemplateDlg::CreateSerial(CString str)
{
    CString res = "";
    int len = str.GetLength();

    int i = len - 1,count = len;
    for ( ; i != -1 ; i--,count-- ){
        if ( count == 4 ){
            res += ‘-‘;
            continue;
        }

        if ( str[i] < 0x4D )                                    //小于0x4D
            str.SetAt( i,str[i] + 0x15 );
        else
            str.SetAt( i,str[i] - 0x11 );

        str.SetAt( i,str[i] ^ ( i+1 ) ^ 2 );
        res += str[i];
    }

    return res;
}

并修改OnBtnDecrypt如下:

void CKengen_TemplateDlg::OnBtnDecrypt()
{
    // TODO: Add your control notification handler code here
    CString str;
    GetDlgItemText( IDC_EDIT_NAME,str );                    //获取用户名字串基本信息。
    int len = str.GetLength();

    if ( len >= 5 && len < 8 ){                                        //格式控制。
        CString Temp = CreateSerial( str );                            //第一个密钥
        CString Serial = CreateSerial( Temp );                        //第二个密钥

        Serial += Temp;

        SetDlgItemText( IDC_EDIT_PASSWORD,Serial );
    }
    else
        MessageBox( "用户名格式错误!" );
}

再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("CRACKME_Keygen"));

运行效果:

-------------------------------------------------------------------------------------------------------------------

后记:看了pediy crackme 2007中的原破文受了启发,既然反跟踪和恢复MessageBox函数都是作者之前实现的,那找到它nop掉不就行了?这里,一步步跟踪开头的代码:发现调用401477子程序之后,MessageBox被恢复了:

00401000 >/$  6A 00         push    0                                ; /pModule = NULL
00401002  |.  E8 B7060000   call    <jmp.&kernel32.GetModuleHandleA> ; \GetModuleHandleA
00401007  |.  A3 40304000   mov     dword ptr [403040], eax
0040100C  |.  E8 A1060000   call    <jmp.&kernel32.GetCommandLineA>  ; [GetCommandLineA
00401011  |.  A3 44304000   mov     dword ptr [403044], eax
00401016  |.  6A 0A         push    0A
00401018  |.  FF35 44304000 push    dword ptr [403044]
0040101E  |.  6A 00         push    0
00401020  |.  FF35 40304000 push    dword ptr [403040]               ;  crackme.00400000
00401026  |.  E8 06000000   call    00401031
0040102B  |.  50            push    eax                              ; /ExitCode
0040102C  \.  E8 7B060000   call    <jmp.&kernel32.ExitProcess>      ; \ExitProcess
00401031  /$  55            push    ebp
00401032  |.  8BEC          mov     ebp, esp
00401034  |.  83C4 B0       add     esp, -50
00401037      E8 3B040000   call    00401477

我们nop掉它就OK了^▼^

但运行保存后的程序,单击check之后会出错,这又是为什么?帖子评论里就有牛人来讲解了:

程序一开始调用4次WriteProcessMemory恢复40103C处的机器码
并在按下check后调用ReadProcessMemory检查自身一大段机器码

动态SMC 值得学习  

  原来的确运用了补丁技术,而且断点失效并非我一开始推测的断点全部清除。我们都知道断点其实就是int 3指令,WriteProcessMemory恢复了MessageBox的机器码,自然就覆盖了断点的int 3指令,所以MessageBox处的断点失效而注册算法的断点没有失效。

时间: 2024-11-03 22:36:06

破解 crackme(浅析去除警告窗口)的相关文章

第五章——演示版保护技术-去除警告窗口实例

去除警告窗口意为将广告弹窗去除,去除的思路归根结底是:在不影响主程序的条件下,查找到警告窗口创建的位置将其跳过或者nop掉,显示窗口的函数主要有Messagebox.DialogBoxPara.ShowWindow.CreateWindowEx.还有一种去除的方式是通过消息断点的方式准根溯源到窗口创建的代码. 这里的实例是加密解密书上的实例程序,演示为了熟悉整个操作的思路和流程 源程序: 演示程序是一个调用了DialogBoxParamA函数来显示资源中的对话框 我们可以用eXeScope打开它

去除警告,打电话,发信息,应用程序之间跳转,打印沙盒路径,字符串名字转换方法,包装导航控制器等的代码

从偏好设置中读取值: 打电话代码: 发信息代码: 打印沙盒路径代码: 应用程序之间跳转代码: 跳转到苹果商店代码: 去除警告代码: 根据字符串名称转换成相对应方法的代码: #import "SZMSettingsCell.h" @implementation SZMSettingsCell //选择不同的cell类型 + (UITableViewCellStyle)cellStyleWithDict:(NSDictionary *)dict{ UITableViewCellStyle

iOS 学习笔记 九 (2015.04.02)IOS8中使用UIAlertController创建警告窗口

1.IOS8中使用UIAlertController创建警告窗口 #pragma mark - 只能在IOS8中使用的,警告窗口- (void)showOkayCancelAlert{    NSString *title = NSLocalizedString(@"修改组名", nil);    NSString *message = NSLocalizedString(@"请输入新的组名", nil);    NSString *cancelButtonTitl

exchange服务器证书过期,导致outlook客户端不停的弹出证书过期的警告窗口

具体症状:exchange服务器证书过期,导致outlook客户端不停的弹出证书过期的警告窗口(但点击警告窗口确定之后,outlook客户端仍旧可以使用.且OWA一切正常). 于是决定在过期的证书上续订证书.续订证书的方法为: 1,右键单击过期证书----续订证书.导出一个命名为test.req的文件.此时生成了一个挂起的续订证书. 2:打开IE浏览器,进入CA审批页面---申请证书----高级证书申请---使用base64位编码---将111.req文件里的内容复制粘贴(证书模版:web服务器

[Xcode10 实际操作]四、常用控件-(9)普通警告窗口的使用

本文将演示警告窗口的使用方法. 警告窗口不仅可以给用户展现提示信息,还可以提供若干选项供用户选择. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] 1 import UIKit 2 3 class ViewController: UIViewController { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 // Do any additional setup after loading

[Xcode10 实际操作]四、常用控件-(10)动作表样式警告窗口的使用

本文将演示动作表单窗口的使用. 动作表单可以给用户展现一系列的选项, 和警告窗口不同的是,动作表单的展示形式和设备的尺寸有关. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] 1 import UIKit 2 3 class ViewController: UIViewController { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 // Do any additional setup

去除警告: FutureWarning: In future, it will be treated as `np.float64 == np.dtype(float).type`.

文章目录: 一.警告原因分析 二.解决方法 最近在使用tensorflow-gpu的时候总是报警告,就我这强迫症能够忍他吗,no!绝对不能忍!!! 我的环境: cudnn=7.0 cuda=9.0 tensorflow-gpu=1.8 或 1.9 或 1.10.0 或 1.11.0 在上面的这个环境配置下都会报这个警告,解决方式都是一样的 一.警告原因分析 从下面包的警告可以看出,是和h5py这个库包有关的 import tensorflow as tf /home/mosheng/minico

软件破解入门(暴力破解CrackMe)

所谓暴力破解,就是通过修改汇编代码进而控制程序的运行流程,达到不需注册码也能正常使用软件的目的.相对于解出算法进而编写注册机,暴破的技术含量是比较低的.但也正是因为一本05年的杂志上介绍“暴力破解”的文章,让我入了这个大坑.近来想重拾调试器,就先从最简单的CrackMe入手,熟练一下各工具方法. 下载CrackMe3文件(我用的是看雪<加密与解密>中的CFF CrackMe #3 程序  http://pan.baidu.com/s/1dD9v9x3 ). 1.查看此程序是否加壳.加壳的话还得

破解 CrackMe#1 [UBC] by bRaINbuSY

系统 : Windows xp 程序 : CrackMe#1 程序下载地址 :http://pan.baidu.com/s/1nuagj6h 要求 : 编写注册机 使用工具 :IDA & OD 可在看雪论坛中查找关于此程序的破文:http://bbs.pediy.com/showthread.php?t=29063 IDA载入程序,找出提示破解成功的字串“You cracked the UBC CrackMe#1 ! Please send your solution to [email pro