镜之边缘第四关破解补丁TlsGetValue 导致的Bug解决方法
来源:互联网 发布:php 字符串比较 编辑:程序博客网 时间:2024/06/05 16:01
年前把镜之边缘下回来玩,可惜玩到第四关的时候会冻结住,人物动不了。按照网上的说法需要打上第四关补丁,不过所谓的第四关补丁同学的电脑可以,我的机器打上了就连程序也打不开了……这几天又非常想玩镜之边缘,终于痛下决心,自己动手,丰衣足食。
分别载入可以玩的和不可以玩的版本。可以发现多了这么几条指令:
03D60576 FF15 1C28B202 CALL DWORD PTR DS:[<&KERNEL32.GetProcess>; kernel32.GetProcessHeap03D6057C A3 3C899902 MOV DWORD PTR DS:[299893C],EAX03D60581 A1 60DAA801 MOV EAX,DWORD PTR DS:[<&USER32.SendMessa>03D60586 A3 B105D603 MOV DWORD PTR DS:[3D605B1],EAX03D6058B C705 60DAA801 9>MOV DWORD PTR DS:[<&USER32.SendMessageW>>03D60595 - E9 D12C5BFD JMP MirrorsE.0131326B03D6059A B8 2A010600 MOV EAX,6012A03D6059F 3E:394424 04 CMP DWORD PTR DS:[ESP+4],EAX03D605A4 75 05 JNZ SHORT MirrorsE.03D605AB03D605A6 - E9 A5465FFE JMP MirrorsE.02354C5003D605AB FF25 B105D603 JMP DWORD PTR DS:[3D605B1]
可以看到第四关补丁在程序刚开始的地方把SendMessageW的地址给改了。同时写了4个字节的数据。先不管,跑一下发现出错了:
024A3238 8951 14 MOV DWORD PTR DS:[ECX+14],EDX
此时的ECX = 8BEC8B55 不出错才怪呢……
往上看到底是什么地方给ECX赋的值找到这里:
024A31E2 E8 9071FFFF CALL MirrorsE.0249A377024A31E7 85C0 TEST EAX,EAX024A31E9 59 POP ECX024A31EA 8947 44 MOV DWORD PTR DS:[EDI+44],EAX024A31ED B9 B0289202 MOV ECX,MirrorsE.029228B0024A31F2 74 03 JE SHORT MirrorsE.024A31F7024A31F4 8B4F 44 MOV ECX,DWORD PTR DS:[EDI+44]
可见ECX的值是跟0249A377这个地址的函数有关,跟踪下发现执行的是MOV ECX,DWORD PTR DS:[EDI+44],但内部没有关于EDI的操作,那么在向前看看。
024A31C8 E8 AAC4FFFF CALL MirrorsE.0249F677024A31CD 85F6 TEST ESI,ESI024A31CF 8BF8 MOV EDI,EAX
调用了0249F677,跟进:
0249F677 53 PUSH EBX0249F678 56 PUSH ESI0249F679 FF15 9425B202 CALL DWORD PTR DS:[<&KERNEL32.GetLastErr>; ntdll.RtlGetLastWin32Error0249F67F FF35 5C93A202 PUSH DWORD PTR DS:[2A2935C]0249F685 8BD8 MOV EBX,EAX0249F687 FF15 A427B202 CALL DWORD PTR DS:[<&KERNEL32.TlsGetValu>; kernel32.TlsGetValue0249F68D 8BF0 MOV ESI,EAX0249F68F 85F6 TEST ESI,ESI0249F691 75 49 JNZ SHORT MirrorsE.0249F6DC0249F693 68 8C000000 PUSH 8C0249F698 6A 01 PUSH 10249F69A E8 41E5FFFF CALL MirrorsE.0249DBE00249F69F 8BF0 MOV ESI,EAX0249F6A1 85F6 TEST ESI,ESI0249F6A3 59 POP ECX0249F6A4 59 POP ECX0249F6A5 74 2D JE SHORT MirrorsE.0249F6D40249F6A7 56 PUSH ESI0249F6A8 FF35 5C93A202 PUSH DWORD PTR DS:[2A2935C]0249F6AE FF15 5827B202 CALL DWORD PTR DS:[<&KERNEL32.TlsSetValu>; kernel32.TlsSetValue0249F6B4 85C0 TEST EAX,EAX0249F6B6 74 1C JE SHORT MirrorsE.0249F6D40249F6B8 C746 54 A895A20>MOV DWORD PTR DS:[ESI+54],MirrorsE.02A29>0249F6BF C746 14 0100000>MOV DWORD PTR DS:[ESI+14],10249F6C6 FF15 A025B202 CALL DWORD PTR DS:[<&KERNEL32.GetCurrent>; kernel32.GetCurrentThreadId0249F6CC 834E 04 FF OR DWORD PTR DS:[ESI+4],FFFFFFFF0249F6D0 8906 MOV DWORD PTR DS:[ESI],EAX0249F6D2 EB 08 JMP SHORT MirrorsE.0249F6DC0249F6D4 6A 10 PUSH 100249F6D6 E8 4AC0FFFF CALL MirrorsE.0249B7250249F6DB 59 POP ECX0249F6DC 53 PUSH EBX0249F6DD FF15 2C28B202 CALL DWORD PTR DS:[<&KERNEL32.SetLastErr>; ntdll.RtlSetLastWin32Error0249F6E3 8BC6 MOV EAX,ESI0249F6E5 5E POP ESI0249F6E6 5B POP EBX0249F6E7 C3 RETN
这里就是关键了,可以看到ESI和EAX唯一被修改的地方是CALL DWORD PTR DS:[<&KERNEL32.TlsGetValu>,执行到这一步,EAX变成了7C82209E。也就是FlsGetValue的地址。接下来程序的走法就是就直接跳走,读取非法内存然后挂掉。
找到问题去同学家跑一下,发现正常的程序执行到这一步TlsGetValue的返回值是0,然后JNZ不跳转。这样的话我们稍微改下,把MOV ESI,EAX改成XOR ESI,ESI就可以达到效果。试试瞧,果然界面弹出来了,哈哈哈……
可惜执行到一半还是出错了……看看反汇编发现是PhysxCore.dll跑飞了……看下堆栈
发现返回到07723E01。重启程序跟进看看。发现是CALL EAX,而CALL上面那句还是个CALL,看样子是直接跳到了返回值里面,跟进发现EAX竟然是TlsGetValue的返回值……又是这个阴魂不散的家伙……
仔细分析刚才我们做的操作,想起来了吗?我们的TlsGetValue的值本来是FlsGetValue,但由于CALL DWORD PTR DS:[<&KERNEL32.TlsSetValu>; kernel32.TlsSetValue而被修改了,所以这个补丁可能没那么简单。
虽然我们不能直接执行TlsSetValue把值给改了,但我们的目的仅仅是让EDI的值正常,来保障接下来的ECX正常。看看我们分析清楚问题那么就动手吧。看看我们刚才分析到的正确EDI的值:00087E38貌似是会变的,但是之前的CALL 0249DBE0似乎被EA做了手脚,只有在这里才能成功调用,所以就不管会变不会变了,直接赋值给EDI。
找一块空地址,我找的是0281CD20,先跳过来,由于不知道其他地方会不会调用这个函数所以仅修改EDI为FlsGetValue的情况。
0281CD20 FF15 A427B202 CALL DWORD PTR DS:[<&KERNEL32.TlsGetValu>; kernel32.TlsGetValue0281CD26 3D 9E20827C CMP EAX,kernel32.FlsGetValue0281CD2B 75 05 JNZ SHORT MirrorsE.0281CD320281CD2D B8 387E0800 MOV EAX,87E380281CD32 ^ E9 5629C8FF JMP MirrorsE.0249F68D
然后修改原来的CALL DWORD PTR DS:[<&KERNEL32.TlsGetValu>改成JMP 0281CD20
保存下,跑跑试试!大功告成!
- 镜之边缘第四关破解补丁TlsGetValue 导致的Bug解决方法
- .net 2.0的URL重写导致的Bug及其解决方法
- 非正常关机时,innodb故障导致mysql无法启动的解决方法
- if导致的bug
- snprintf 导致的bug
- 粗心导致的bug
- munmap导致的BUG
- ICON边缘锯齿的解决方法
- 【BUG】ExtJS3.4.0的Grid中垂直滚动条导致列错位的解决方法
- IE6中用了float:left之后导致margin-left双倍边距的BUG解决方法
- IE6中用了float:left之后导致margin-left双倍边距的BUG解决方法
- IE6中用了float:left之后导致margin-left双倍边距的BUG解决方法
- IE6中用了float:left之后导致margin-left双倍边距的BUG解决方法
- IE6中用了float:left之后导致margin-left双倍边距的BUG解决方法
- 锁表导致的BUG
- jdk版本导致的bug
- 经验问题导致的bug
- 依赖包导致的bug
- How to remove an ASM instance and its corresponding database(s) on WINDOWS
- pthread_cond_wait的工作机制
- Die young at 80
- Struts 2的拦截器原理和核心
- How to remove an ASM instance and its corresponding database(s) on UNIX
- 镜之边缘第四关破解补丁TlsGetValue 导致的Bug解决方法
- HTTP协议及其POST与GET操作差异 & C#中如何使用POST、GET等
- QQ农场耕种计划
- 一个多线程实例
- poj 1782
- 预防数据库攻击的PHP函数一例子 mysql_real_escape_string()
- 表达式计算器(MFC)
- 海龟画图(Windows API及C++)
- AVL树的描绘(Java)