首页
社区
课程
招聘
[分享]终于脱掉了SecuROM 4.X-5.X
发表于: 2005-11-18 08:37 8652

[分享]终于脱掉了SecuROM 4.X-5.X

2005-11-18 08:37
8652
标题:Unpack SecuROM 4.x-5.x with FlyODBG v1.10
目标:秋之回忆:想君简体中文版
调试环境:WinXP、flyODBG、PEiD、LordPE、ImportREC
声明:纯粹为了速度和节省光驱的人。
作者:无聊的菜鸟
时间:2005年11月18日

前天花了30个小时才把秋之回忆:想君的简体中文版下下来(希望各位高人不要鄙视我这种喜欢GALGAME的菜鸟),装完一看SecuROM 4.X-5.X -> Sony DADC。无语了。
开启FlyODBG载入,先F9一下看看能运行不,结果可以,不过那个异常叫多啊。(大家记得要选上忽略0000 0000-FFFF FFFF段的所有异常,还有要把调试器的进程优先级设为低。。。)
下面就来找我们的OEP吧:
运行之后有个健康游戏提示,有拿它下手吧F2停下,然后下text段下个内存访问断点,找了半天没发现调用GetVersion的地方,API全是Call [18X XXXX]之类的东西,还有不少Call 18X XXXX之类的或前或后有个inc eax,nop,daa,cmc之类的指令(5+1字节的东西不用猜就知道是Call []的变形了)。
重来之后,He GetVersion,注意堆栈提示返回有text段的时候就可以停下了。返回后向上找一点,会发现传说中的OEP。然后我们再次重来,直接g OEP。漫长的等待之后,OD停在了OEP处。堆栈的顶部也是OEP,这就对了。
到这里之后就是没有技术含量的事情了,一个个Patch Call变形了返回,一个个的手动修改。数了一下大概有300个的样子,稍微熟练一下大概能10s一个,一两个小时也就能作完了。(其实我很想写PatchCode,不过Sony个贱人,你API调用得太快它就会丢个错误的结果给你,直接让你异常。)如果修复中出现错误的返回值的话,就在那里重新新建EIP,F8在取一次结果,一般就对了,不过不要重复太多次,Sony是很贱的。。。
其实真正返回API的地方不多,我这里就4处。
第一处:2XX XXXX的调用最后都会死到SFX段中的17X XXXX那里去(如果你小跟下前面的代码,你会发现它们就是从17X XXXX那里复制过去的),所以我们直接Patch尾部的JMP EAX为add esp,4;retn,Patch上面一点的Mov eax,[esi]为NOP,目的就是为了任他不去执行API直接返回,而且EAX里就是API的存储位置。然后还有三个是在SFX下面的那个段中的。大家就按着上面那个目标Patch吧,我记不得了,也没心情在去重装3CD的游戏。
最后我们用LordPE来个Dump Full,IAT在修复中你就会知道在哪里了,用ImportREC获取,添加新段修复(你爱写到其他地方也行,只要不影响运行。记得不选创建新的IAT。)
现在让DAEMON Tool(PS:终于出4.0了,等的好辛苦)弹出CD3,运行成功地出现了健康游戏提示。不容易啊~~~~~~~~~
之后又出现一个“请插入资料碟”的提示,这个东西的去除我就不想说了,改一个jnz就DONE了。
脱下来的文件居然是21.7MB,懒得优化了,直接UPX一下,1.08MB,启动速度没区别(C-M1.5G)。

PS:Fly版主,上次那片精华先帮我去掉把,毕竟还没完成的说。。。。

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (12)
雪    币: 898
活跃值: (4039)
能力值: ( LV9,RANK:3410 )
在线值:
发帖
回帖
粉丝
2
先保留吧,你可以继续研究,然后完成教程
2005-11-18 09:28
0
雪    币: 622
活跃值: (294)
能力值: ( LV13,RANK:410 )
在线值:
发帖
回帖
粉丝
3
再过一点时间在我把这个的相关代码也贴上来吧,做成一个教程类似物的东西。
2005-11-18 12:02
0
雪    币: 288
活跃值: (415)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
4
建议写个教程
前几个月我也搞过它
OEP很简单
但是那些变型的IAT就....太BT了
结果放弃了

也想写个IR的DLL来取IAT,不过没有SDK就一直没写成

游戏运行中的那个MessageBox是在一个CALL里面的
它是建立在一个循环里面的
也就是说游戏运行的话就一直会读光驱..
SONY想我们的光驱快点完蛋

BTW:用LORDPE重建一下DUMP后的PE文件就会小很多的了
建议把那个CALL也NOP掉
想君不太好玩的,それから还不错,不过还比不上MO1

BTW2:最好把这里改了
01820185    2B05 20739401   sub eax,dword ptr ds:[1947320]
0182018B    3D 60EA0000     cmp eax,0EA60
01820190    0F86 08010000   jbe OMOKIMI.0182029E
01820196    833D B0BE8A01 0>cmp dword ptr ds:[18ABEB0],0
0182019D    74 0F           je short OMOKIMI.018201AE
0182019F    68 C0758D01     push OMOKIMI.018D75C0                    ; ASCII "70011C5AEBA713BD58EEB4EF9BA10FB238C354C0C3FD2BE9FD8FE5FE5967C596BCC5"

改为

01820185    2B05 20739401   sub eax,dword ptr ds:[1947320]
0182018B    3D 60EA0000     cmp eax,0EA60
01820190    E9 09010000     jmp OMOKIMI_.0182029E
01820195    90              nop
01820196    833D B0BE8A01 0>cmp dword ptr ds:[18ABEB0],0
0182019D    74 0F           je short OMOKIMI_.018201AE
0182019F    68 C0758D01     push OMOKIMI_.018D75C0                   ; ASCII "70011C5AEBA713BD58EEB4EF9BA10FB238C354C0C3FD2BE9FD8FE5FE5967C596BCC5"

SecuRom会提取系统的时间作对比的,太快不行,太慢了也不行的
直接JMP过去就可以了
还有提醒一个:
修复IAT的时候最好下个timeGetTime的断点
2005-11-18 12:20
0
雪    币: 288
活跃值: (415)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
5
刚刚再看了一下IAT:

下timeGetTime后,经过两次断就可以看到这里了
017C71A4       0000               add byte ptr ds:[eax],al
017C71A6       0000               add byte ptr ds:[eax],al
017C71A8       0091 AF063962      add byte ptr ds:[ecx+623906AF],dl
017C71AE       833D 2CAD9501 10   cmp dword ptr ds:[195AD2C],10            ; 时间不能小于0x10 ms
017C71B5       0F83 84000000      jnb OMOKIMI_.017C723F                    ; 一定不能跳
017C71BB       8B55 C0            mov edx,dword ptr ss:[ebp-40]
017C71BE       81E2 FFFF0000      and edx,0FFFF                            ; 也不能大于0xFFFF ms
017C71C4       85D2               test edx,edx
017C71C6       7E 77              jle short OMOKIMI_.017C723F              ; 也不能跳
017C71C8       66:8B45 C0         mov ax,word ptr ss:[ebp-40]
017C71CC       66:2D 0100         sub ax,1

017C72AD       33D2               xor edx,edx
017C72AF       66:8B91 2C4C8801   mov dx,word ptr ds:[ecx+1884C2C]
017C72B6       81E2 00200000      and edx,2000
017C72BC       85D2               test edx,edx
017C72BE       0F84 16020000      je OMOKIMI_.017C74DA                     ; 一定要跳
017C72C4       8D45 E0            lea eax,dword ptr ss:[ebp-20]
017C72C7       50                 push eax
017C72C8       8D4D FC            lea ecx,dword ptr ss:[ebp-4]
017C72CB       51                 push ecx
017C72CC       8D55 EC            lea edx,dword ptr ss:[ebp-14]
017C72CF       52                 push edx

017C74DA       5A                 pop edx
017C74DB       59                 pop ecx
017C74DC       8B45 CC            mov eax,dword ptr ss:[ebp-34]
017C74DF       8BF0               mov esi,eax
017C74E1       8B06               mov eax,dword ptr ds:[esi]
017C74E3       5F                 pop edi
017C74E4       5E                 pop esi
017C74E5       5B                 pop ebx
017C74E6       8BE5               mov esp,ebp
017C74E8       5D                 pop ebp
017C74E9     - FFE0               jmp eax                                  ; KERNEL32.HeapCreate
017C74EB       E9 1D000000        jmp OMOKIMI_.017C750D
就到了IAT的CALL了
2005-11-18 13:41
0
雪    币: 622
活跃值: (294)
能力值: ( LV13,RANK:410 )
在线值:
发帖
回帖
粉丝
6
谢谢Pr0Zel的分析,看来这下写PatchCode有希望了。。。
因为原来写的Patch在定位call []和调用修复都行,就是SONY太BT。
这些回去可以在写一次了。。。
不过Call的Patch就无语了,还要分析前后的字节,估计Patch会长上很多。。。

BTW:我不太敢重建PE,怕程序直接OVER,所以还是UPX一下比较简单。
2005-11-18 16:24
0
雪    币: 288
活跃值: (415)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
7
还有两种API的CALL的,一共是3种

01822D00    55              push ebp
01822D01    8BEC            mov ebp,esp
01822D03    83EC 18         sub esp,18
01822D06    53              push ebx
01822D07    56              push esi
01822D08    57              push edi
01822D09    53              push ebx
01822D0A    51              push ecx
01822D0B    52              push edx
01822D0C    56              push esi
01822D0D    57              push edi
01822D0E    50              push eax

直接往下找RETN就可以了
01822DDB    59              pop ecx
01822DDC    5B              pop ebx
01822DDD    5F              pop edi
01822DDE    5E              pop esi
01822DDF    5B              pop ebx
01822DE0    8BE5            mov esp,ebp
01822DE2    5D              pop ebp
01822DE3    C3              retn                                     ; retn到相应的API

还有一种是:
0043A94B  |.  E8 A0813E01   call OMOKIMI_.01822AF0                   ;  Kernel32.GetStartupInfoA

01822AF0    55              push ebp
01822AF1    8BEC            mov ebp,esp
01822AF3    83EC 18         sub esp,18
01822AF6    53              push ebx
01822AF7    56              push esi
01822AF8    57              push edi
01822AF9    53              push ebx
01822AFA    51              push ecx
01822AFB    52              push edx
01822AFC    56              push esi
01822AFD    57              push edi
01822AFE    8B45 04         mov eax,dword ptr ss:[ebp+4]
01822B01    8945 E8         mov dword ptr ss:[ebp-18],eax
.
.中间也有一个CALL
.
01822B9D    5F              pop edi
01822B9E    5E              pop esi
01822B9F    5A              pop edx
01822BA0    59              pop ecx
01822BA1    5B              pop ebx
01822BA2    8BE5            mov esp,ebp
01822BA4    5D              pop ebp
01822BA5    8B00            mov eax,dword ptr ds:[eax]
01822BA7    FFE0            jmp eax                                  ; 跳到相应的API里面
Kernel32.SetHandleCount

找到一部分的输入表.一共是0x43E298 - 0x43000 = 0x298字节
0043E000  510A24CC  dsound.DirectSoundCreate
0043E004  00000000
0043E008  77F41D10  GDI32.SelectObject
0043E00C  77F44DA1  GDI32.GetDeviceCaps
0043E010  77F44AA5  GDI32.CreateCompatibleDC
0043E014  77F42EC7  GDI32.DeleteObject
0043E018  77F44B1E  GDI32.DeleteDC
0043E01C  77F4AB12  GDI32.Rectangle
0043E020  77F4393C  GDI32.TextOutA
0043E024  77F4202E  GDI32.SetTextColor
0043E028  77F43EE0  GDI32.GetWindowExtEx
0043E02C  77F46ABB  GDI32.GetWindowOrgEx
0043E030  77F4507E  GDI32.CreatePen
0043E034  77F47FDF  GDI32.CreateSolidBrush
0043E038  77F42CC0  GDI32.BitBlt
0043E03C  77F4DC9C  GDI32.StretchBlt
0043E040  77F4DECD  GDI32.CreateDIBSection
0043E044  77F4E311  GDI32.EnumFontFamiliesA
0043E048  77F4CE09  GDI32.CreateFontA
0043E04C  77F42141  GDI32.SetBkColor
0043E050  00000000
0043E054  7C5B5823  KERNEL32.LCMapStringW
0043E058  7C578745  KERNEL32.SetStdHandle
0043E05C  7C586502  KERNEL32.SetEndOfFile
0043E060  7C596E6C  KERNEL32.GetEnvironmentStringsW
0043E064  7C59177F  KERNEL32.SetHandleCount
0043E068  7C578797  KERNEL32.GetStdHandle
0043E06C  7C5860D5  KERNEL32.GetFileType
0043E070  77FACCB2  ntdll.RtlUnwind
0043E074  7C586981  KERNEL32.FlushFileBuffers
0043E078  7C592D55  KERNEL32.GetDriveTypeA
0043E07C  7C59417E  KERNEL32.GetLogicalDriveStringsA
0043E080  77FCB6CA  ntdll.RtlFreeHeap
0043E084  7C58F7C1  KERNEL32.GetProcessHeap
0043E088  7C57F79D  KERNEL32.OutputDebugStringA
0043E08C  7C58C1F7  KERNEL32.CreateFileA
0043E090  7C577E6D  KERNEL32.CloseHandle
0043E094  7C5B8132  KERNEL32.GetOEMCP
0043E098  7C5B811A  KERNEL32.GetACP
0043E09C  7C5B8138  KERNEL32.GetCPInfo
0043E0A0  7C586BDE  KERNEL32.GetFileSize
0043E0A4  7C58639C  KERNEL32.WriteFile
0043E0A8  7C58658E  KERNEL32.SetFilePointer
0043E0AC  7C5875DF  KERNEL32.DeleteFileA
0043E0B0  7C58F317  KERNEL32.lstrlenA
0043E0B4  7C58F29D  KERNEL32.lstrcatA

---------------------------------------------------
这是其中一种CALL API的方法
01822D00    55              push ebp
01822D01    8BEC            mov ebp,esp
01822D03    83EC 18         sub esp,18
01822D06    53              push ebx
01822D07    56              push esi
01822D08    57              push edi
01822D09    53              push ebx
01822D0A    51              push ecx
01822D0B    52              push edx
01822D0C    56              push esi
01822D0D    57              push edi
01822D0E    50              push eax
01822D0F    8B45 04         mov eax,dword ptr ss:[ebp+4]             ; 取得CALL的retn地址
01822D12    8945 E8         mov dword ptr ss:[ebp-18],eax            ; [12F620]
01822D15    68 78563412     push 12345678
01822D1A    8BCD            mov ecx,ebp
01822D1C    2BCC            sub ecx,esp
01822D1E    8BFC            mov edi,esp
01822D20    8BF4            mov esi,esp
01822D22    83C6 04         add esi,4
01822D25    C1E9 02         shr ecx,2
01822D28    8B06            mov eax,dword ptr ds:[esi]               ; /
01822D2A    8907            mov dword ptr ds:[edi],eax               ; |
01822D2C    83C7 04         add edi,4                                ; |
01822D2F    83C6 04         add esi,4                                ; |
01822D32    49              dec ecx                                  ; |
01822D33  ^ 75 F3           jnz short OMOKIMI_.01822D28              ; \这里个循环是把栈的数值往上移1个DWORD空间,确保最后RENT到API后的堆栈是原程序PUSH的参数
01822D35    83ED 04         sub ebp,4
01822D38    A1 78729401     mov eax,dword ptr ds:[1947278]
01822D3D    83C0 03         add eax,3
01822D40    8945 F4         mov dword ptr ss:[ebp-C],eax
01822D43    8B4D E8         mov ecx,dword ptr ss:[ebp-18]
01822D46    83E9 04         sub ecx,4
01822D49    C1E9 10         shr ecx,10
01822D4C    81E1 FFFF0000   and ecx,0FFFF
01822D52    8B55 E8         mov edx,dword ptr ss:[ebp-18]
01822D55    83EA 04         sub edx,4
01822D58    81E2 FFFF0000   and edx,0FFFF
01822D5E    81E2 FFFF0000   and edx,0FFFF
01822D64    33CA            xor ecx,edx
01822D66    C1E1 03         shl ecx,3
01822D69    8B45 E8         mov eax,dword ptr ss:[ebp-18]
01822D6C    83E8 04         sub eax,4
01822D6F    C1E8 05         shr eax,5
01822D72    33D2            xor edx,edx
01822D74    BE 08000000     mov esi,8
01822D79    F7F6            div esi
01822D7B    8B45 F4         mov eax,dword ptr ss:[ebp-C]
01822D7E    0FBE1410        movsx edx,byte ptr ds:[eax+edx]
01822D82    33CA            xor ecx,edx
01822D84    8B45 E8         mov eax,dword ptr ss:[ebp-18]
01822D87    83E8 04         sub eax,4
01822D8A    33D2            xor edx,edx
01822D8C    BE 08000000     mov esi,8
01822D91    F7F6            div esi
01822D93    8B45 F4         mov eax,dword ptr ss:[ebp-C]
01822D96    0FBE1410        movsx edx,byte ptr ds:[eax+edx]
01822D9A    C1E2 07         shl edx,7
01822D9D    33CA            xor ecx,edx
01822D9F    894D FC         mov dword ptr ss:[ebp-4],ecx
01822DA2    6A 03           push 3
01822DA4    8D45 F8         lea eax,dword ptr ss:[ebp-8]
01822DA7    50              push eax
01822DA8    8B4D FC         mov ecx,dword ptr ss:[ebp-4]
01822DAB    51              push ecx
01822DAC    68 981A8A01     push OMOKIMI_.018A1A98
01822DB1    E8 FAFDFFFF     call OMOKIMI_.01822BB0                   ; 搞不懂里面的算法 :(
01822DB6    83C4 10         add esp,10
01822DB9    8945 F0         mov dword ptr ss:[ebp-10],eax
01822DBC    8B55 F0         mov edx,dword ptr ss:[ebp-10]
01822DBF    8B04D5 9C1A8A01 mov eax,dword ptr ds:[edx*8+18A1A9C]     ; 重要的地方,IAT的地址(经过加密)
01822DC6    83F0 30         xor eax,30                               ; 解密IAT地址
01822DC9    3345 FC         xor eax,dword ptr ss:[ebp-4]             ; 解密IAT地址
01822DCC    8945 EC         mov dword ptr ss:[ebp-14],eax            ; IAT地址(已解密)
01822DCF    8B75 EC         mov esi,dword ptr ss:[ebp-14]
01822DD2    8B06            mov eax,dword ptr ds:[esi]               ; 取对应的API地址了
01822DD4    8945 04         mov dword ptr ss:[ebp+4],eax             ; /放到程序CALL前
01822DD7    58              pop eax                                  ; |恢复现场
01822DD8    5F              pop edi                                  ; |
01822DD9    5E              pop esi                                  ; |
01822DDA    5A              pop edx                                  ; |
01822DDB    59              pop ecx                                  ; |
01822DDC    5B              pop ebx                                  ; |
01822DDD    5F              pop edi                                  ; |
01822DDE    5E              pop esi                                  ; |
01822DDF    5B              pop ebx                                  ; |
01822DE0    8BE5            mov esp,ebp                              ; |
01822DE2    5D              pop ebp                                  ; |
01822DE3    C3              retn                                     ; \retn到相应的API
2005-11-18 19:55
0
雪    币: 61
活跃值: (160)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
8
2005-11-18 20:03
0
雪    币: 622
活跃值: (294)
能力值: ( LV13,RANK:410 )
在线值:
发帖
回帖
粉丝
9
其实一共就只用两种API调用,一个是从171c6XX处复制过来的,还有一个和你说的那个一样,只不过call OMOKIMI_.01822BB0上面的参数是从1至5。不过游戏中只用到了第一个和另外一个的其中的三个而已。对我来说,只有PatchCode的区别,因为我也看不懂
2005-11-18 21:02
0
雪    币: 245
活跃值: (195)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
10
ÿ
2005-11-19 00:47
0
雪    币: 622
活跃值: (294)
能力值: ( LV13,RANK:410 )
在线值:
发帖
回帖
粉丝
11
手修的文件还是有修错的地方,无语。。。
努力研发PatchCode中。。。。。
2005-11-19 01:22
0
雪    币: 213
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
最初由 Pr0Zel 发布
还有两种API的CALL的,一共是3种

01822D00 55 push ebp
01822D01 8BEC mov ebp,esp
01822D03 83EC 18 sub esp,18
........

有喜欢the age of infinity系列的吗?
never7 ever17 ....在KFC社区泡了超久...
2005-11-19 06:09
0
雪    币: 622
活跃值: (294)
能力值: ( LV13,RANK:410 )
在线值:
发帖
回帖
粉丝
13
终于发现了SecuRom对函数的时间确定还真是TMD变态,不过呢,我帮它小补了一下,让它一边运行一边修复函数,所以呢,就算没全部解开,也不太会影响我现在的运行。
终于有个可用的版本了。。。。。
虽然还没完全脱了。
下面我再想,先把那些没有时间校检的函数先给修了,然后再给他补上上面那个补丁,之后呢,在需要修复的代码就会少得可怜了吧。

刚刚实践了一下,只剩80个,一下子少了2/3,而且已修复的都是正确的不会错的。挖哈哈哈哈哈。。。。

旁边一人:
2005-11-19 23:24
0
游客
登录 | 注册 方可回帖
返回
//