欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

我的破解心得(4) (13千字)

我的破解心得(4) (13千字)

版权说明:本文作者为Chcw, 未经作者同意,不得转载此文。
破解程序:
    IrfanView32
破解工具:
    Extract 1.0
    Sourcer 7.0        
    Visual C++ 5.0
    在我的破解心得(3)中,我们采用手工调试的方法获得了Name="chcw"时对应的注册码
Code="283226906"。更进一步,我们希望能够编写一个注册码生成器,使得对应于不同的
用户姓名,可以生成相应的正确注册码。我们知道,不少程序的注册检验函数都可以表示
为以下的流程:    
    user_name = get_username()        /* 获取用户输入的姓名 */
    user_regcode = get_userregcode()    /* 获取用户输入的注册码 */
    regcode = compute_regcode(user_name)    /* 对用户姓名做复杂的计算,得到一个合法的
                        注册码 */
    if (!isequal(usr_regcode, regcode))    /* 将上述合法的注册码与用户输入的注册码比较,
        register_error()           若不相同则认为注册非法 */
    通常,如果我们要实现一个注册码生成器,必须了解整个注册检验过程中compute_regcode()
部分的工作机制,然后用编码实现与之相类似的效果。显然,这种方法费时费力,而且只对
当前所破解的软件有效,意义不大。
    其实,我们完全可以不必了解compute_regcode()的内部机制,只需要直接将应用程序中
compute_regcode部分反汇编拷贝到注册码生成器中,然后重新编译即可。这种方法不仅减少
了编写注册机的工作量,而且由于这部分代码是源于应用程序的,因此一般不会出错。                        
    仍以IrfanView32为例,在破解心得(3)中,我们已经知道函数00401000子程序是注册检验
函数,该函数在00401275处的ds:edx是指向合法注册码的一个指针。显然在从程序入口到
00401275处是生成注册码的部分。下面我们将把它反编译并加入到我们的注册机中:
1.IrfanView32的程序文件I_View32.exe很大,无法直接用Sourcer进行反汇编,因此需要先用
  一个叫Extract的工具对它进行处理。Extract是"Undocumented Windows"一书所附带的一个
  程序,其功能是将二进制程序的一部分截取出来。
      由于我们所要返汇编的函数为00401000,用W32Dasm可以得到它在执行程序I_view32.exe
  中的偏移地址为0x400,函数00401000同时还调用了0046C700等子函数,我们就大致取截取
  长度为0x70000,使之能将函数00401000和0046C700同时包含进来。
      输入命令 Extract I_view32.exe 0x400 0x70000 Tmp.bin 将生成一个二进制文件Tmp.bin。
2.用Sourcer打开Tmp.bin, 将反汇编的File Format设置为.asm文件,将编译的平台设置为
  386 Protected,并在Analysis Option中打开Default to USE32选项。设置完所有参数后,
  按'G',反汇编Tmp.bin,生成Tmp.asm文件。
3.在Visual C++中建立一个工程,类型为Win32 Console Application,并在工程中添加一个KeyMaker.C
  的源程序文件。
4.在KeyMaker.C文件中构造一个新函数makekey(),打开文件Tmp.asm,将函数00401000(以
  start::为启始标志)中的语句复制到makekey()函数中,并加上__asm外套,如下所示:
    __declspec(naked) void makekey()
    {
        __asm  {
        mov    eax,dword ptr [esp+8]        ;    函数00401000的第一条语句
                ...
        retn                    ;    函数00401000的返回语句
        }
    }    
  其中__declspec(naked)是用来去除MakeKey()函数的标准堆栈框的。
5.在函数00401000中还调用了其他几个函数, 其中call sub_763就是对函数0045F770的调用,在破解心
  得(3)中我们已经知道,在00401000函数中对0045F770函数的两处调用并没有什么意义。因此可以直接
  将其该改为nop语句(这里必须保证堆栈的正确性), 如下所示:
    call sub_763        改为->        nop
        ...                ...
    call sub_999                call sub_999
        ...                ...
    call sub_763        改为->        nop
6.接下来,我们需要处理sub_999函数,在KeyMaker.C文件中构造一个新函数func1(),将函数sub_999的语
  句复制到func1()内,并将makekey()中对sub_999的调用作相应的改动:
    __declspec(naked) void func1()
    {
        __asm  {
            mov    ecx,dword ptr [esp+0Ch]        ;    函数sub_999的第一条语句
                ...
        retn                    ;    函数sub_999的返回语句
        }
    }    
    __declspec(naked) void makekey()
    {
        __asm  {
        ...
        call func1()    ;    函数MakeKey()中对函数sub_999的调用语句
        ...            
        }
    }
7.同理也可以对func1()函数中进一步调用的其他函数作相应的处理。
8.到现在为止,我们已经将IrfanView32中的注册码生成部分复制到makekey()函数中了,接下来我们
  需要考虑makekey()函数的环境处理,即正确的输入和输出。从上一节我们知道,makekey()函数的
  输入参数是用户输入的注册码和注册名,因此在调用该函数之前,应该在栈中压入正确的参数:
    char usrcode[32]="9530109";
    char name[32]="chcw"; 
    __asm  {
        lea eax,dword ptr usrcode
        push eax            ;    将用户输入的注册码字符串地址压栈
        lea eax,dword ptr name
        push eax            ;    将用户输入的姓名字符串的地址压栈
        call makekey()            ;    调用函数makekey()
        add  esp, 8h            
    }
  当然,在调用完makekey()之后,应当调整堆栈指针。    
9.makekey()函数的输出应该是正确的注册码,在上文中,我们已经说过,在:00401275处执行push edx
  语句时的ds:edx指向正确注册码的地址。由于这个注册码是在堆栈中生成的,在调用完函数makekey()
  并退栈之后将不复存在, 因此为了使主程序能够得到完整的注册码,必须将其保存下来:
      我们首先声明一个全局变量regcode, 用它来保存注册码的值:
        char regcode[256];
      然后,在00401275处的语句之后加上一端代码,将ds:edx所指的注册码复制到regcode中:
            push    edx                ; 原字符串地址压栈    
            lea    eax, dword ptr regcode
            push    eax                ; 目标字符串regcode地址压栈
            call    strcpy                ; 调用strcpy函数进行复制
            add    esp,8                ; 调整栈指针
      通过这种方法,我们就成功的将00401000函数(makekey()函数)生成的临时注册码保存在regcode
  中了。
9.最后,我们可以在调用00401000函数(makekey()函数)的主程序main()中加上一些输入输出语句,使程
  序更为完善。                
附:IrfanView32的注册码生成器KeyMaker.C
--------------------------  KeyMaker.C  ----------------------------------
#include <string.h>
#include <stdio.h>
char regcode[256]="";
__declspec(naked) void func2()
{
    __asm  {
        mov    eax,dword ptr [esp+10h]
        push    ebx
        push    ebp
        push    esi
        mov    esi,dword ptr [esp+14h]
        push    edi
        test    eax,eax
        jz    short loc_9308        ; Jump if zero
        mov    edi,dword ptr [esp+14h]
        mov    byte ptr [esi],2Dh    ; '-'
        inc    esi
        neg    edi
        jmp    short loc_9309
loc_9308:
        mov    edi,dword ptr [esp+14h]
loc_9309:
        mov    ebp,dword ptr [esp+1Ch]
        mov    ebx,esi
loc_9310:
        mov    eax,edi
        xor    edx,edx            ; Zero register
        div    ebp            ; ax,dx rem=dx:ax/reg
        mov    eax,edi
        mov    ecx,edx
        xor    edx,edx            ; Zero register
        div    ebp            ; ax,dx rem=dx:ax/reg
        cmp    ecx,9
        mov    edi,eax
        jbe    short loc_9311        ; Jump if below or =
        add    cl,57h            ; 'W'
        jmp    short loc_9312
loc_9311:
        add    cl,30h            ; '0'
loc_9312:
        mov    [esi],cl
        inc    esi
        test    edi,edi
        ja    loc_9310        ; Jump if above
        mov    byte ptr [esi],0
        dec    esi
loc_9313:
        mov    cl,[ebx]
        mov    al,[esi]
        mov    [esi],cl
        mov    [ebx],al
        dec    esi
        inc    ebx
        cmp    ebx,esi
        jb    loc_9313        ; Jump if below
        pop    edi
        pop    esi
        pop    ebp
        pop    ebx
        retn
    }
}
__declspec(naked) void func1()
{
    __asm  {
        mov    ecx,dword ptr [esp+0Ch]
        mov    edx,dword ptr [esp+4]
        cmp    ecx,0Ah
        push    esi
        jnz    short loc_9314        ; Jump if not zero
        test    edx,edx
        jge    short loc_9314        ; Jump if > or =
        mov    esi,dword ptr [esp+0Ch]
        mov    eax,1
        push    eax
        push    ecx
        push    esi
        push    edx
        call    func2
        add    esp,10h
        mov    eax,esi
        pop    esi
        retn
loc_9314:
        mov    esi,dword ptr [esp+0Ch]
        xor    eax,eax            ; Zero register
        push    eax
        push    ecx
        push    esi
        push    edx
        call    func2
        add    esp,10h
        mov    eax,esi
        pop    esi
        retn
    }
}
__declspec(naked) void makekey()
{
    __asm  {
        mov    eax,dword ptr [esp+8]
        sub    esp,14h
        push    ebx
        push    ebp
        push    esi
        push    edi
        push    eax
        xor    ebx,ebx            ; Zero register
        nop
        mov    esi,dword ptr [esp+2Ch]
        mov    ebp,eax
        mov    edi,esi
        or    ecx,0FFFFFFFFh
        xor    eax,eax            ; Zero register
        add    esp,4
        xor    edx,edx            ; Zero register
        repne    scasb            ; Rep zf=0+cx >0 Scan es:[di] for al
        not    ecx
        dec    ecx
        test    ecx,ecx
        jle    short loc_4        ; Jump if < or =
loc_3:
        movsx    ecx,byte ptr [edx][esi]    ; Mov w/sign extend
        add    ebx,ecx
        mov    edi,esi
        or    ecx,0FFFFFFFFh
        xor    eax,eax            ; Zero register
        inc    edx
        repne    scasb            ; Rep zf=0+cx >0 Scan es:[di] for al
        not    ecx
        dec    ecx
        cmp    edx,ecx
        jl    loc_3            ; Jump if <
loc_4:
        mov    eax,104h
        push    dword ptr 0Ah
        sub    eax,ebx
        cdq                ; dword to quad word
        xor    eax,edx
        sub    eax,edx
        add    eax,14Ch
        mov    edx,eax
        shl    edx,3            ; Shift w/zeros fill
        sub    edx,eax
        lea    ecx,[eax][edx*4]    ; Load effective addr
        lea    edx,dword ptr [esp+14h]    ; Load effective addr
        push    edx
        lea    esi,[eax][ecx*2]    ; Load effective addr
        shl    esi,3            ; Shift w/zeros fill
        push    esi
        call    func1
        add    esp,0Ch
        cmp    esi,0F423Fh
        ja    loc_5            ; Jump if above
        mov    cl,byte ptr [esp+14h]
        mov    al,byte ptr [esp+15h]
        mov    dl,byte ptr [esp+13h]
        mov    byte ptr [esp+16h],cl
        mov    cl,byte ptr [esp+11h]
        mov    byte ptr [esp+18h],al
        mov    al,byte ptr [esp+12h]
        mov    byte ptr [esp+12h],cl
        mov    ecx,dword ptr [esp+18h]
        mov    byte ptr [esp+13h],al
        and    ecx,0FFh
        mov    byte ptr [esp+15h],dl
        mov    edx,dword ptr [esp+14h]
        lea    eax,[ecx][ecx*4]    ; Load effective addr
        and    edx,0FFh
        shl    eax,3            ; Shift w/zeros fill
        sub    eax,ecx
        mov    ecx,edx
        shl    ecx,5            ; Shift w/zeros fill
        sub    ecx,edx
        lea    edx,[ecx][ecx*2]    ; Load effective addr
        sub    eax,edx
        cdq                ; dword to quad word
        mov    ecx,eax
        xor    ecx,edx
        sub    ecx,edx
        lea    eax,[ecx][ecx*4]    ; Load effective addr
        shl    eax,3            ; Shift w/zeros fill
        sub    eax,ecx
        mov    ecx,9
        cdq                ; dword to quad word
        idiv    ecx            ; ax,dx rem=dx:ax/reg
        mov    eax,dword ptr [esp+13h]
        and    eax,0FFh
        add    edx,30h
        mov    byte ptr [esp+17h],dl
        lea    edx,[eax][eax*2]    ; Load effective addr
        shl    edx,4            ; Shift w/zeros fill
        sub    edx,eax
        mov    eax,dword ptr [esp+15h]
        and    eax,0FFh
        lea    ecx,[eax][eax*8]    ; Load effective addr
        lea    eax,[eax][ecx*4]    ; Load effective addr
        lea    eax,[edx][eax*2]    ; Load effective addr
        cdq                ; dword to quad word
        xor    eax,edx
        sub    eax,edx
        lea    ecx,[eax][eax*8]    ; Load effective addr
        lea    eax,[eax][ecx*4]    ; Load effective addr
        mov    ecx,9
        shl    eax,1            ; Shift w/zeros fill
        cdq                ; dword to quad word
        idiv    ecx            ; ax,dx rem=dx:ax/reg
        mov    ecx,dword ptr [esp+10h]
        and    ecx,0FFh
        lea    eax,[ecx][ecx*2]    ; Load effective addr
        lea    eax,[eax][eax*8]    ; Load effective addr
        shl    eax,1            ; Shift w/zeros fill
        sub    eax,ecx
        add    edx,30h
        mov    byte ptr [esp+14h],dl
        mov    edx,dword ptr [esp+11h]
        and    edx,0FFh
        mov    ecx,edx
        shl    ecx,3            ; Shift w/zeros fill
        sub    ecx,edx
        lea    edx,[ecx][ecx*4]    ; Load effective addr
        sub    eax,edx
        cdq                ; dword to quad word
        mov    ecx,eax
        xor    ecx,edx
        sub    ecx,edx
        lea    eax,[ecx][ecx*2]    ; Load effective addr
        lea    eax,[eax][eax*8]    ; Load effective addr
        shl    eax,1            ; Shift w/zeros fill
        sub    eax,ecx
        jmp    loc_6
loc_5:
        mov    al,byte ptr [esp+15h]
        mov    dl,byte ptr [esp+16h]
        mov    cl,byte ptr [esp+14h]
        mov    byte ptr [esp+16h],al
        mov    al,byte ptr [esp+11h]
        mov    byte ptr [esp+18h],dl
        mov    dl,byte ptr [esp+12h]
        mov    byte ptr [esp+15h],cl
        mov    ecx,dword ptr [esp+16h]
        mov    byte ptr [esp+12h],al
        mov    eax,dword ptr [esp+18h]
        and    ecx,0FFh
        and    eax,0FFh
        mov    byte ptr [esp+13h],dl
        mov    edx,ecx
        lea    eax,[eax][eax*8]    ; Load effective addr
        shl    edx,6            ; Shift w/zeros fill
        shl    eax,2            ; Shift w/zeros fill
        sub    edx,ecx
        mov    ecx,9
        sub    eax,edx
        cdq                ; dword to quad word
        xor    eax,edx
        sub    eax,edx
        lea    eax,[eax][eax*8]    ; Load effective addr
        shl    eax,2            ; Shift w/zeros fill
        cdq                ; dword to quad word
        idiv    ecx            ; ax,dx rem=dx:ax/reg
        mov    eax,dword ptr [esp+13h]
        and    eax,0FFh
        add    edx,30h
        mov    byte ptr [esp+17h],dl
        lea    edx,[eax][eax*4]    ; Load effective addr
        shl    edx,3            ; Shift w/zeros fill
        sub    edx,eax
        mov    eax,dword ptr [esp+14h]
        and    eax,0FFh
        add    eax,20h
        mov    ecx,eax
        shl    ecx,3            ; Shift w/zeros fill
        sub    ecx,eax
        lea    eax,[eax][ecx*4]    ; Load effective addr
        lea    eax,[eax][eax*2]    ; Load effective addr
        lea    eax,[eax][edx*2]    ; Load effective addr
        cdq                ; dword to quad word
        xor    eax,edx
        sub    eax,edx
        mov    ecx,eax
        shl    ecx,3            ; Shift w/zeros fill
        sub    ecx,eax
        lea    eax,[eax][ecx*4]    ; Load effective addr
        mov    ecx,9
        lea    eax,[eax][eax*2]    ; Load effective addr
        cdq                ; dword to quad word
        idiv    ecx            ; ax,dx rem=dx:ax/reg
        mov    eax,dword ptr [esp+10h]
        and    eax,0FFh
        add    dl,30h            ; '0'
        mov    byte ptr [esp+14h],dl
        mov    edx,eax
        shl    edx,3            ; Shift w/zeros fill
        sub    edx,eax
        lea    eax,[eax][edx*4]    ; Load effective addr
        mov    edx,dword ptr [esp+11h]
        and    edx,0FFh
        mov    ecx,edx
        shl    ecx,4            ; Shift w/zeros fill
        add    ecx,edx
        shl    eax,1            ; Shift w/zeros fill
        lea    ecx,[ecx][ecx*4]    ; Load effective addr
        sub    eax,ecx
        cdq                ; dword to quad word
        xor    eax,edx
        sub    eax,edx
        mov    edx,eax
        shl    edx,3            ; Shift w/zeros fill
        sub    edx,eax
        lea    eax,[eax][edx*4]    ; Load effective addr
        shl    eax,1            ; Shift w/zeros fill
loc_6:
        cdq                ; dword to quad word
        mov    ecx,9
        mov    byte ptr [esp+19h],0
        idiv    ecx            ; ax,dx rem=dx:ax/reg
        add    edx,30h
        mov    byte ptr [esp+11h],dl
        lea    edx,dword ptr [esp+10h]    ; Load effective addr
        push    edx
        push    edx
        lea    eax, dword ptr regcode
        push    eax
        call    strcpy
        add    esp,8
        add    esp,4
        xor    ecx,ecx            ; Zero register
        cmp    ebp,eax
        pop    edi
        pop    esi
        sete    cl            ; Set byte if equal
        pop    ebp
        mov    eax,edx
        pop    ebx
        add    esp,14h
        retn
    }
}
void main()
{
    char usrcode[32]="9530109";
    char name[32]="chcw"; 
    
    printf("KeyMaker for IrfanView32\n");
    printf("Written By Mr. Chcw\n");
    printf("Please enter your name:");
    gets(name);
    __asm  {
        lea eax,dword ptr usrcode
        push eax
        lea eax,dword ptr name
        push eax
        call makekey
        add  esp, 8h
    }
    printf("The register code is: %s\n", regcode);
}
----------------------- End of File  KeyMaker.C  -------------------------

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功