首页
社区
课程
招聘
rFactor 1.250 破解过程详述
发表于: 2007-2-15 23:01 19477

rFactor 1.250 破解过程详述

2007-2-15 23:01
19477

【文章标题】: rFactor 1.250 破解过程详述
【文章作者】: noword
【作者主页】: bbs.srfc.com.cn
【软件名称】: rFactor
【下载地址】: http://www.rfactor.net/index.php?page=downloads
【加壳方式】: ActiveMark
【保护方式】: ActiveMark + 阴险的暗桩
【使用工具】: FileMon, OllyICE
【操作平台】: Win XP
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
  【简介】
  rFactor是ISI最新的一款模拟赛车游戏,售价34.99欧元。游戏原始引擎最初用于ISI公司99年出版的Sports Car GT (SCGT)模拟赛车游戏,在经过了近8年的不断发展,现在rF采用的是经过ISI全面改进和升级的被称为isiMotor 2.0的开发环境,这是ISI积累了多年赛车游戏经验的技术结晶。rF是这款游戏引擎的首部作品,随后FIA官方游戏GT Legends、 GTR 2也相继采用了这款游戏引擎。相比较ISI过去的游戏引擎,rF增加了真实的动力学,更加真实的操作感,更加逼真的图像,让玩家体验身临其境的感觉。
  
  以前,rFactor一直是一个来自波兰叫Passeli的组织或个人破解的,而在1.150出来之后却迟迟不见动静,倒是有两个假档出现在emule上,于是只好亲自出马,破而解之,造福于天下。
  
  07年1月25日,1.250的补丁出来了,拿到手后,粗看之下同1.150的加密方式没什么不同,但是事后证明这只是表相……
  
  
  【保护手法】
  该游戏使用了ActiveMark(http://www.trymedia.com)的保护方案,可执行文件被其加壳,启动后如果是未付费用户,则跳出付费窗口,且只能进入有一定时间限制的demo模式。
  用FileMonitor可发现,rFactor.exe会读写在C:\Documents and Settings\All Users\Application Data\Trymedia下的两个目录 data 和 licenses。
  data目录中有4个文件:
  {51AE6369-615F-A146-E860-D9D8FF2E73D5}
  {F5E9419B-BF55-B4A2-21B9-EA3C4E7E854E}
  {C405FC19-D234-E01E-D4FF-F24278204F43}
  {439B1256-E959-D772-E973-7835AE2AAE1C}
  每次运行后文件中的内容都会变化,应该是记录了游戏运行时间等信息,这样开发商就能限制用户的试玩时间了。
  而licensens目录中是空的,程序会试图打开一个名为d27248b8604abd930ed681c3033da219.lcn的文件,密匙应该就在其中。
  
  ps:关于ActiveMark,在http://tutorials.accessroot.com/有好几篇教程,图文并茂,非常详细。
  
  
  【初步破解】
  用OllyICE载入rFactor.exe,停在了入口00EA9003处,按Alt-M:

  00400000   00001000   rFactor              
  00401000   0023E000   rFactor    .data     
  0063F000   000B4000   rFactor    .bss      
  006F3000   003FA000   rFactor    .text     
  00AED000   00009000   rFactor    .rsrc     
  00AF6000   0016E000   rFactor    .rdata    第二层
  00C64000   00004000   rFactor    .idata    
  00C68000   0000A000   rFactor    .rsrc     
  00C72000   00231000   rFactor    .data     
  00EA3000   00001000   rFactor    .idata    
  00EA4000   00005000   rFactor    .rsrc     
  00EA9000   00018000   rFactor    .bss      第一层
  00EC1000   00001000   rFactor    .text     
  00EC2000   0000A000   rFactor    .rdata    
  00ECC000   00001000   rFactor    .idata
  00636B03  |> \68 04010000     push    104                              ; /BufSize = 104 (260.)
  00636B08  |.  BE 60B3AE00     mov     esi, 00AEB360                    ; |
  00636B0D  |.  56              push    esi                              ; |PathBuffer => rFactor.00AEB360
  00636B0E  |.  53              push    ebx                              ; |hModule
  00636B0F  |.  881D 64B4AE00   mov     byte ptr [AEB464], bl            ; |
  00636B15  |.  90              nop                                      ; \GetModuleFileNameA
  00636B16  |.  E8 E24E5400     call    00B7B9FD
  00636B1B  |.  A1 68C9AE00     mov     eax, dword ptr [AEC968]
  地址  线程   命令                                           ; 寄存器和注释
  00B7BA02 主       jmp     short 00B7BA07
  00B7BA07 主       call    00C40794                          ; ESP=0012FF0C
  00C40794 主       push    -1                                ; ESP=0012FF08
  00C40796 主       push    eax                               ; ESP=0012FF04
  00C40797 主       mov     eax, dword ptr fs:[0]             ; EAX=0012FFB0
  00C4079D 主       push    eax                               ; ESP=0012FF00
  00C4079E 主       mov     eax, dword ptr [esp+C]            ; EAX=00B7BA0C
  00C407A2 主       mov     dword ptr fs:[0], esp
  00C407A9 主       mov     dword ptr [esp+C], ebp
  00C407AD 主       lea     ebp, dword ptr [esp+C]            ; EBP=0012FF0C
  00C407B1 主       push    eax                               ; ESP=0012FEFC
  00C407B2 主       retn                                      ; ESP=0012FF00
  00B7BA0C 主       jmp     short 00B7BA10
  00B7BA10 主       sub     esp, 20                           ; FL=0, ESP=0012FEE0
  00B7BA13 主       jmp     short 00B7BA17
  00B7BA17 主       mov     al, byte ptr [ebp+13]             ; EAX=00B7BA00
  00B7BA1A 主       push    ebx                               ; ESP=0012FEDC
  00B7BA1B 主       push    esi                               ; ESP=0012FED8
  00B7BA1C 主       jmp     short 00B7BA20
  00B7BA20 主       jmp     00B7AD3E
  00B7AD3E 主       xor     esi, esi                          ; FL=PZ, ESI=00000000
  00B7AD40 主       jmp     short 00B7AD44
  00B7AD44 主       push    edi                               ; ESP=0012FED4
  00B7AD45 主       jmp     short 00B7AD49
  00B7AD49 主       push    esi                               ; ESP=0012FED0
  00B7AD4A 主       jmp     00B7B6B9
  00B7B6B9 主       lea     ecx, dword ptr [ebp-2C]           ; ECX=0012FEE0
  00B7B6BC 主       push    00B7A2E8                          ; ESP=0012FECC
  00B7B6C1 主       retn                                      ; ESP=0012FED0
  00B7A2E8 主       mov     byte ptr [ebp-2C], al
  00B7A2EB 主       push    00B7A8A4                          ; ESP=0012FECC
  00B7A2F0 主       retn                                      ; ESP=0012FED0
  00B7A8A4 主       jmp     short 00B7A8A8
  00B7A8A8 主       jmp     00B7BBDC
  00B7BBDC 主       call    00B66F53                          ; ESP=0012FECC
  00B66F53 主       cmp     byte ptr [esp+4], 0
  00B66F58 主       push    esi                               ; ESP=0012FEC8
  00B66F59 主       mov     esi, ecx                          ; ESI=0012FEE0
  00B66F5B 主       je      short 00B66F7F
  00B66F7F 主       and     dword ptr [esi+4], 0
  00B66F83 主       and     dword ptr [esi+8], 0
  00B66F87 主       and     dword ptr [esi+C], 0
  00B66F8B 主       pop     esi                               ; ESP=0012FECC, ESI=00000000
  00B66F8C 主       retn    4                                 ; ESP=0012FED4
  00B7BBE1 主       jmp     short 00B7BBE5
  00B7BBE5 主       push    00B7B05E                          ; ESP=0012FED0
  00B7BBEA 主       retn                                      ; ESP=0012FED4
  00B7B05E 主       push    dword ptr [ebp+10]                ; ESP=0012FED0
  00B7B061 主       jmp     short 00B7B065
  00B7B065 主       mov     ebx, dword ptr [ebp+C]            ; EBX=00AEB360
  00B7B068 主       jmp     00B7A3CB
  00B7A3CB 主       mov     dword ptr [ebp-4], esi
  00B7A3CE 主       push    ebx                               ; ESP=0012FECC
  00B7A3CF 主       jmp     short 00B7A3D3
  00B7A3D3 主       jmp     dword ptr [B7A3DB]
  00B7B804 主       push    dword ptr [ebp+8]                 ; ESP=0012FEC8
  00B7B807 主       call    dword ptr [kernel32.GetModuleFileNameA]   ; EAX=0000001B, ECX=7C93056D, EDX=098A0000, ESP=0012FED4
  ...
  00C423DE 主       call    dword ptr [ntdll.RtlAllocateHeap]         ; FL=PZ, EAX=01C44698, ECX=7C9306EB, EDX=01220006, ESP=0012FE34
  ...
  00C423DE 主       call    dword ptr [ntdll.RtlAllocateHeap]         ; FL=PZ, EAX=01C446D0, ECX=7C9306EB, EDX=01220005, ESP=0012FC6C
  ...
  00C423DE 主       call    dword ptr [ntdll.RtlAllocateHeap]         ; FL=PZ, EAX=01C4A598, ECX=7C9306EB, EDX=01220004, ESP=0012FCA4
  ...
  00C0D080 主       call    dword ptr [kernel32.FindFirstFileA]       ; FL=PZ, EAX=00152820, ECX=000000D9, EDX=0012FAC0, ESP=0012FD38
  ...
  00C0D0E5 主       call    dword ptr [kernel32.FindClose]            ; FL=PS, EAX=00000001, ECX=7C80EE67, EDX=003B0000, ESP=0012FD38
  ...
  00C0D080 主       call    dword ptr [kernel32.FindFirstFileA]]      ; FL=PZ, EAX=00152820, ECX=000000D9, EDX=0012FAC0, ESP=0012FD38
  ...
  00C0D0E5 主       call    dword ptr [kernel32.FindClose]            ; FL=PS, EAX=00000001, ECX=7C80EE67, EDX=003C0000, ESP=0012FD38
  ...
  00C0D080 主       call    dword ptr [kernel32.FindFirstFileA]]      ; FL=PZ, EAX=00152820, ECX=000000D9, EDX=0012FAC0, ESP=0012FD38
  ...
  00C0D0E5 主       call    dword ptr [kernel32.FindClose]            ; FL=PS, EAX=00000001, ECX=7C80EE67, EDX=003D0000, ESP=0012FD38
  ...
  00C422A4 主       call    dword ptr [ntdll.RtlFreeHeap]             ; FL=PZ, EAX=0278E201, ECX=7C93056D, EDX=01220003, ESP=0012FCE4
  ...
  00C422A4 主       call    dword ptr [ntdll.RtlFreeHeap]             ; FL=PZ, EAX=01C4A501, ECX=7C93056D, EDX=01230004, ESP=0012FE80
  ...
  00C422A4 主       call    dword ptr [ntdll.RtlFreeHeap]             ; FL=PZ, EAX=01C44601, ECX=7C93056D, EDX=01240005, ESP=0012FE80
  ...
  00B7AF89 主       jmp     00B7B0EB
  00B7B0EB 主       leave                                     ; ESP=0012FF10, EBP=0012FF38
  00B7B0EC 主       retn    0C                                ; ESP=0012FF20
      断点位于 rFactor.00636B1B
  00636B1B 主       mov     eax, dword ptr [AEC968]
      RUN 跟踪已关闭
  0053BAD0      56              push    esi
  0053BAD1      8BF1            mov     esi, ecx
  0053BAD3      807E 70 00      cmp     byte ptr [esi+70], 0
  0053BAD7   .  75 12           jnz     short 0053BAEB
  0053BAD9   .  6A 00           push    0
  0053BADB   .  90              nop
  0053BADC   .  E8 518F6300     call    00B74A32
  0053BAE1   .  24 01           and     al, 1
  0053BAE3   .  83C4 04         add     esp, 4
  0053BAE6   .  04 01           add     al, 1
  0053BAE8   .  8846 70         mov     byte ptr [esi+70], al
  0053BAEB   >  807E 70 02      cmp     byte ptr [esi+70], 2
  0053BAEF   .  5E              pop     esi
  0053BAF0   .  0F94C0          sete    al
  0053BAF3   .  C3              retn
  
  0053BAD0      33C0            xor     eax, eax
  0053BAD2      40              inc     eax
  0053BAD3      C3              retn
    do
      {
        WaitForDebugEvent (&DBEvent, INFINITE);
        GetThreadContext (pi.hThread, &Regs);
        ContinueStatus = DBG_CONTINUE;
        switch (DBEvent.dwDebugEventCode)
          {
          case EXCEPTION_DEBUG_EVENT:
            {
              switch (DBEvent.u.Exception.ExceptionRecord.ExceptionCode)
                {
                case EXCEPTION_ACCESS_VIOLATION:
                case EXCEPTION_FLT_DENORMAL_OPERAND:
                case EXCEPTION_FLT_DIVIDE_BY_ZERO:
                case EXCEPTION_FLT_INEXACT_RESULT:
                case EXCEPTION_FLT_INVALID_OPERATION:
                case EXCEPTION_FLT_OVERFLOW:
                case EXCEPTION_FLT_STACK_CHECK:
                case EXCEPTION_FLT_UNDERFLOW:
                  {
                    ContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
                    break;
                  }
                case EXCEPTION_SINGLE_STEP:
                  if (Regs.Eip == OEP1)					//到达第二层的OEP
                    {
                      OEPStatus++;
                      Regs.Dr0 = 0;
                      Regs.Dr7 = 0x404;
                      SetThreadContext (pi.hThread, &Regs);
                      SuspendOtherThread (pi);			//挂起除主线程之外的其他线程
  		    ApplyPatch (pi.hProcess, patch);	        //写入补丁数据
                    }
                  else if (Regs.Eip == OEP2)				//到达真正的OEP
                    {
                      OEPStatus++;
                      Regs.Dr1 = Regs.Dr7 = 0;
                      SetThreadContext (pi.hThread, &Regs);
                      SuspendOtherThread (pi);			//挂起除主线程之外的其他线程
                      ContinueDebugEvent (DBEvent.dwProcessId,
                                          DBEvent.dwThreadId, ContinueStatus);
                      STOP = TRUE;
                    }
                  else
                    ContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
                  break;
                case EXCEPTION_BREAKPOINT:
  			    //是否在第一层或第二层
                  if ((Regs.Eip >= 0xEA9000 && Regs.Eip <= 0xEC1000)
                      || (Regs.Eip >= 0xAED000 && Regs.Eip <= 0xC64000))
                    ContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
  				//两处int3陷阱,必须将EAX设置为-1
  		  if (Regs.Eip == 0xEAAD18 || Regs.Eip == 0xEB61CF)
  				{
  					Regs.Eax = -1;
  					SetThreadContext(pi.hThread, &Regs);
  				}
                  break;
                }
              break;
            }
          case LOAD_DLL_DEBUG_EVENT:
  	  //每次载入新的DLL时,都在OEP处下一次硬件断点
            if (OEPStatus == 0)
              {
                Regs.Dr0 = OEP1;
                Regs.Dr1 = OEP2;
                Regs.Dr7 = 0x505;
                SetThreadContext (pi.hThread, &Regs);
              }
            else if (OEPStatus == 1)
              {
                Regs.Dr1 = OEP2;
                Regs.Dr7 = 0x404;
                SetThreadContext (pi.hThread, &Regs);
              }
            break;
          case EXIT_PROCESS_DEBUG_EVENT:
            STOP = TRUE;
            ExitProcess (-1);
            break;
          }
        if (!STOP)
          {
            ContinueDebugEvent (DBEvent.dwProcessId, DBEvent.dwThreadId,
                                ContinueStatus);
          }
      }
    while (!STOP);
  
  void
  SuspendOtherThread (PROCESS_INFORMATION pi)
  {
    THREADENTRY32 te32 = { 0 };
    te32.dwSize = sizeof (THREADENTRY32);
    HANDLE hThreadSnap = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, 0);
    if (Thread32First (hThreadSnap, &te32))
      {
        do
          {
            if (te32.th32OwnerProcessID == pi.dwProcessId
                && te32.th32ThreadID != pi.dwThreadId)
              {
                HANDLE hThread = OpenThread (THREAD_SUSPEND_RESUME, FALSE,
                                             te32.th32ThreadID);
                SuspendThread (hThread);
              }
          }
        while (Thread32Next (hThreadSnap, &te32));
      }
    CloseHandle (hThreadSnap);
  }

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (17)
雪    币: 180
活跃值: (59)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
好文,膜拜一下
2007-2-15 23:30
0
雪    币: 158
活跃值: (43)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
这种方式见过,但搞不下,这下有参照了..
2007-2-15 23:51
0
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
4
深度佩服之中,不是一般的强
2007-2-16 11:11
0
雪    币: 214
活跃值: (70)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
好文``强!!
2007-2-16 16:07
0
雪    币: 0
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
6
真强...佩服啊 真有耐心
2007-2-16 16:29
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
7
专程来拜楼主
2007-2-16 18:10
0
雪    币: 277
活跃值: (312)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
8
在寻找暗桩的日子里。
2007-2-16 19:18
0
雪    币: 61
活跃值: (160)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
9
好文
2007-2-20 17:05
0
雪    币: 225
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ywb
10
转了几圈,还是来膜拜楼主一下!
2007-2-20 20:17
0
雪    币: 4441
活跃值: (805)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
楼主真是太强了,仰视中
2007-2-21 09:07
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
真的很强,难望楼主项背。
2007-2-21 11:25
0
雪    币: 277
活跃值: (312)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
13
建议你的loader加个猛壳,就不怕他分析了。
2007-2-23 09:27
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
强 好文,膜拜膜拜
2007-2-23 13:58
0
雪    币: 167
活跃值: (1574)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
15
暴强 已经看晕菜了
2007-2-24 21:07
0
雪    币: 340
活跃值: (922)
能力值: ( LV9,RANK:220 )
在线值:
发帖
回帖
粉丝
16
最初由 wangshq397 发布
建议你的loader加个猛壳,就不怕他分析了。

没用,只要在运行起来后再attach,就可以知道内存补丁改了些什么东西了。
2007-2-25 10:25
0
雪    币: 95
活跃值: (419)
能力值: ( LV9,RANK:310 )
在线值:
发帖
回帖
粉丝
17
太厉害了,学习中...
2007-3-26 00:50
0
雪    币: 225
活跃值: (218)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
顶你个肺啊
2007-3-26 08:54
0
游客
登录 | 注册 方可回帖
返回
//