吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4340|回复: 7
收起左侧

[CrackMe] 【吾爱2013CM大赛解答】 -- 驱动crackme -- 网际座山雕 KeyGen分析

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

本帖最后由 JoyChou 于 2013-12-19 14:20 编辑

程序拿到手后是MFC程序,还是用MFC按钮入口查看器查看,在上一篇破文中,我已经发了附件了。
找到按钮入口地址为00401A50,下断,F9,输入序列号LoveKido,断下来,先看看程序整理流程。

豁然的看到DeviceIoControl这个API,由此可以看出,此程序是通过DeviceIoControl产生IRP_MJ_DEVICE_CONTROL例程来和sys通信的。
不过这个函数,可以看到发送到sys的数据已经返回到exe的数据,通过DeviceIoControl函数的参数
发送到sys的InBuffer:
  
即机器码+自己输入的序列号

返回到exe的OutBuffer:
  
可以看出只有9位,中间被00截断了,由此推断序列号只有9位,刚好和机器码相同

继续往下看就可以看到程序中唯一的一个关键跳
[AppleScript] 纯文本查看 复制代码
00401BC3   .  803D 22684400>cmp byte ptr ds:[0x446822],0x21          ;  关键判断 446822-446780 = A2 
00401BCA   .  75 21         jnz Xmycrack.00401BED
00401BCC   .  B8 80674400   mov eax,mycrack.00446780
00401BD1   .  C605 D8674400>mov byte ptr ds:[0x4467D8],0xDB
00401BD8   .  FFD0          call eax                                 ;  正确提示
00401BDA   .  8B4C24 14     mov ecx,dword ptr ss:[esp+0x14]
00401BDE   .  64:890D 00000>mov dword ptr fs:[0],ecx
00401BE5   .  59            pop ecx
00401BE6   .  5F            pop edi
00401BE7   .  5E            pop esi
00401BE8   .  5B            pop ebx
00401BE9   .  83C4 10       add esp,0x10
00401BEC   .  C3            retn
00401BED   >  6A 00         push 0x0
00401BEF   .  6A 00         push 0x0
00401BF1   .  68 30984300   push mycrack.00439830                    ;  胜败乃兵家常事,大侠请重新来过。
00401BF6   .  8BCF          mov ecx,edi
00401BF8   .  E8 47690000   call mycrack.00408544                    ;  错误提示


分析到这,可能有的Cracker都想这么简单?直接就爆破就完事了?
不过发现00401BD8 这个call里面的内容是加密后的,必须靠正确的序列号才能解码。
现在就可以开始算法分析了……

先看驱动层
IDA载入,在DriverEntry中找到IRP_MJ_DEVICE_CONTROL例程函数,它的宏是十进制的14,对应sub_10748这个函数,F5一目了然


最后的算法:buffer = buffer[i+9] - buffer + 1  

至于为什么Irp堆栈指针偏移0x3就是控制码,用Windbg dt下IO_STACK_LOCATION结构,就可以很清楚的看到。
[AppleScript] 纯文本查看 复制代码
0:000> dt _IO_STACK_LOCATION 
ntdll!_IO_STACK_LOCATION
   +0x000 MajorFunction    : UChar
   +0x001 MinorFunction    : UChar
   +0x002 Flags            : UChar
   +0x003 Control          : UChar


接着就可以继续分析exe的算法
先从00401BCA关键跳入手,[0x446822]的值必须为0x21,很明显可以发现[446822]的值是由0x446780地址引起的。
446822 - 446780 = 0xA2,当ecx为0xA2的时候,edx = ecx % 9(取9的余) = 0,
[AppleScript] 纯文本查看 复制代码
00401B70   > /8A99 F8384400 mov bl,byte ptr ds:[ecx+0x4438F8]        ;  d 004438f8+0a2 = 0x22
00401B76   . |80FB E0       cmp bl,0xE0
00401B79   . |73 16         jnb Xmycrack.00401B91
00401B7B   . |B8 398EE338   mov eax,0x38E38E39                       ;  edx = ecx mod 9
00401B80   . |F7E1          mul ecx
00401B82   . |D1EA          shr edx,1
00401B84   . |8D04D2        lea eax,dword ptr ds:[edx+edx*8]
00401B87   . |8BD1          mov edx,ecx
00401B89   . |2BD0          sub edx,eax                              ;  edx = 0,1,2,3,4到8
00401B8B   . |2A9A 70654400 sub bl,byte ptr ds:[edx+0x446570]        ;  446570 驱动返回出来的buffer
00401B91   > |8899 80674400 mov byte ptr ds:[ecx+0x446780],bl        ;  ecx=A2时,bl必须=0x21


先要这段的作用是edx = ecx % 9,
原理可以看看《C++反汇编与逆向分析技术揭密》,里面有相关的证明 或 百度398EE338这个Magic Number
[AppleScript] 纯文本查看 复制代码
00401B7B   .  B8 398EE338   mov eax,0x38E38E39                       ;  edx = ecx mod 9
00401B80   .  F7E1          mul ecx
00401B82   .  D1EA          shr edx,1
00401B84   .  8D04D2        lea eax,dword ptr ds:[edx+edx*8]
00401B87   .  8BD1          mov edx,ecx
00401B89   .  2BD0          sub edx,eax                              ;  edx = 0,1,2,3,4到8


现在看00401B8B这句,当ecx = 0xA2,此时的edx=0,bl = 0x22,
因为执行完00401B8B这句后,bl必须=0x21,所以[0x446570]等于1(数字的1,而不是ASCII的'1')
也就是说,驱动返回的OutBuffer第一个必须是数字1,那其它的呢?可耻的猜驱动返回的OutBuffer为{1,2,3,4,5,6,7,8,9}
那么根据buffer = buffer[i+9] - buffer + 1  即等价于{1,2,3,4,5,6,7,8,9} = buffer[i+9] - buffer + 1
buffer[i+9]是输入的,buffer即机器码
做一个等号两边移位的等价操作,可以推算出: buffer[i+9] = buffer + {0,1,2,3,4,5,6,7,8}

简单的写了个C语言的注册机,测试下,成功。
像类似这样的代码,推荐直接在OD里面汇编操作,或者python


[AppleScript] 纯文本查看 复制代码
#include "stdafx.h"
#include <string.h>
#include <windows.h>

int main(int argc, char *argv[])
{
        char szMachineCode[MAX_PATH] = {0};

        char szResult[9] = {0};
        printf("输入机器码:");
        scanf("%s", szMachineCode);

        for (int i = 0; i < 9; i++)
        {
                szResult = szMachineCode + i;
        }
        szResult = '\0';

        puts(szResult);
        return 0;
}


最后分析下为什么这个shellcode在win7上不能运行
[AppleScript] 纯文本查看 复制代码
004467C6    33C0            xor eax,eax                              ; mycrack.00446780
004467C8    64:3340 30      xor eax,dword ptr fs:[eax+0x30]          ; ppeb
004467CC    8B40 0C         mov eax,dword ptr ds:[eax+0xC]           ; pldr
004467CF    8B70 1C         mov esi,dword ptr ds:[eax+0x1C]          ; InInitializationOrderModuleList->Flink(即ntdll.dll)
004467D2    AD              lods dword ptr ds:[esi]                  ; kernel32.dll
004467D3    8B48 08         mov ecx,dword ptr ds:[eax+0x8]           ; ldr_data_talbe_entry结果中距离InInitializationOrderModuleList偏移0x8,即dllbase


在win7上,InInitializationOrderModuleList模块的顺序是ntdll.dll->kernelBase.dll->Kernel32.dll

最后给一个win7和xp可以用的shellcode
[AppleScript] 纯文本查看 复制代码
int main()
{
    _asm{
            nop
            nop         
            nop
            nop
            nop
            CLD                 ; clear flag DF
            ;store hash
            push 0x1e380a6a     ;hash of MessageBoxA
            push 0x4fd18963     ;hash of ExitProcess
            push 0x0c917432     ;hash of LoadLibraryA
            mov esi,esp         ; esi = addr of first function hash 
            lea edi,[esi-0xc]   ; edi = addr to start writing function 
            ; make some stack space
            xor ebx,ebx
            mov bh, 0x04             
            sub esp, ebx 
            ; push a pointer to "user32" onto stack 
            mov bx, 0x3233      ; rest of ebx is null 
            push ebx 
            push 0x72657375 
            push esp 
            xor edx,edx
        ; find base addr of kernel32.dll 
            mov ebx,fs:[0x30]   //得到peb结构体的地址
            mov ebx,[ebx + 0xc] //得到Ldr结构体的地址
            mov ebx,[ebx + 0xc] //得到ldr.InLoadOrderModuleList.Flink 第一个模块,当前进程
            mov ebx,[ebx]   //得到第二个模块地址 ntdll.dll
            mov ebx,[ebx]   //得到第三个模块地址 kernel32.dll
            mov ebx,[ebx+0x18]  //得到第三个模块地址(kernel32模块的dllbase)
            mov ebp,ebx
        find_lib_functions: 
            lodsd                   ; load next hash into al and increment esi 
            cmp eax, 0x1e380a6a     ; hash of MessageBoxA - trigger 
                                    ; LoadLibrary("user32") 
            jne find_functions 
            xchg eax, ebp           ; save current hash 
            call [edi - 0x8]        ; LoadLibraryA 
            xchg eax, ebp           ; restore current hash, and update ebp 
                                    ; with base address of user32.dll 
        find_functions: 
            pushad                      ; preserve registers 
            mov eax, [ebp + 0x3c]       ; eax = start of PE header 
            mov ecx, [ebp + eax + 0x78] ; ecx = relative offset of export table 
            add ecx, ebp                ; ecx = absolute addr of export table 
            mov ebx, [ecx + 0x20]       ; ebx = relative offset of names table 
            add ebx, ebp                ; ebx = absolute addr of names table 
            xor edi, edi                ; edi will count through the functions 
        next_function_loop: 
            inc edi                     ; increment function counter 
            mov esi, [ebx + edi * 4]    ; esi = relative offset of current function name 
            add esi, ebp                ; esi = absolute addr of current function name 
            cdq                         ; dl will hold hash (we know eax is small) 
        hash_loop: 
            movsx eax, byte ptr[esi]
            cmp al,ah
            jz compare_hash
            ror edx,7
            add edx,eax
            inc esi
            jmp hash_loop
        compare_hash:   
            cmp edx, [esp + 0x1c]       ; compare to the requested hash (saved on stack from pushad) 
            jnz next_function_loop 
            mov ebx, [ecx + 0x24]       ; ebx = relative offset of ordinals table 
            add ebx, ebp                ; ebx = absolute addr of ordinals table 
            mov di, [ebx + 2 * edi]     ; di = ordinal number of matched function 
            mov ebx, [ecx + 0x1c]       ; ebx = relative offset of address table 
            add ebx, ebp                ; ebx = absolute addr of address table 
            add ebp, [ebx + 4 * edi]    ; add to ebp (base addr of module) the 
                                        ; relative offset of matched function 
            xchg eax, ebp               ; move func addr into eax 
            pop edi                     ; edi is last onto stack in pushad 
            stosd                       ; write function addr to [edi] and increment edi 
            push edi 
            popad                   ; restore registers 
                                    ; loop until we reach end of last hash 
            cmp eax,0x1e380a6a
            jne find_lib_functions 
        function_call:
            xor ebx,ebx
            push ebx            // cut string
            push 0x20756F68     //push  " uoh" 
            push 0x43796F4A     //push  "CyoJ"
            mov eax,esp         //load address of JoyChou
            push ebx    
            push eax
            push eax
            push ebx
            call [edi - 0x04] ; //call MessageboxA
            push ebx
            call [edi - 0x08] ; // call ExitProcess
            nop
            nop
            nop
            nop
    }
    return 0;
}

本帖子中包含更多资源

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

x

免费评分

参与人数 1热心值 +1 收起 理由
Chief + 1 吾爱破解2013CM大赛,有你更精彩!

查看全部评分

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

 楼主| JoyChou 发表于 2013-12-15 18:04
沙发还是自己坐。
wanghongmin1 发表于 2013-12-15 18:25
xjun 发表于 2013-12-15 18:25
头像被屏蔽
bambooqj 发表于 2013-12-15 19:02
提示: 作者被禁止或删除 内容自动屏蔽
a070458 发表于 2013-12-15 19:39
{:1_931:}学习了 感谢大大
Sandman 发表于 2013-12-15 21:22
为毛那个最终的KeyBuffer = {0,1,2,3,4,5,6,7,8}都是猜出来的

点评

没有更多的Tips  发表于 2013-12-15 21:52
网际座山雕 发表于 2013-12-17 09:38

楼主做的好,非常详细的分析。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止回复与主题无关非技术内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2024-4-29 11:16

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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