首页
社区
课程
招聘
[旧帖] 分享一下最新过TP DebugPort清零的方法 0.00雪花
2013-7-31 15:58 10655

[旧帖] 分享一下最新过TP DebugPort清零的方法 0.00雪花

2013-7-31 15:58
10655
众所周知
TP 系统全称 TenProtect,是由腾讯自主研发推出的安全系统,可以有效保护游戏不受外挂侵犯,同时具备反木马盗号功能,
能有效的防止用户游戏帐号和虚拟财产被窃取。腾讯 TP 系统主要作用为外挂检测、反盗号、反非法工作室、防非法消息。

文章写的有点赶,没有带图,代码可能也有点乱,各位将就看看吧!

首先要提出的是,我现在所做的过 TP 驱动保护只支持 32 位 XP,在所有的 32 位 XP 上都可以正常运行,
不过 Win7 的话还不行,因为里面用到了搜索特征码来定位未导出 API,而我只针对 XP 做了处理。

首先我们先分析一下TP所做的保护:
1、 NtOpenProcess 中的 Deep InLine Hook:
2、 NtOpenThread 中的 Deep InLine Hook:
3、 NtReadVirtualMemory 中的 InLine Hook:
4、 NtWriteVirtualMemory 中的 InLine Hook:
5、 KiAttachProcess和KeStackAttachProcess的 InLine Hook:
6、 NtGetContextThread 中的 InLine Hook:
7、 NtSetContextThread 中的 InLine Hook:
8 、DebugPort清零:
大概主要的函数就是以上这些了,一些小HOOK就不写了。

我相信前7个函数的处理方法在网上应该已经被人讲过一遍又一遍了,所以我直接从DebugPort清零说起。

首先我们又虚拟机进行双机调试 下游戏基址+0xbc 的访问断点
可以发现现在最新的TP 有四处清零和一处检测
他们分别是

TesSafe基址:   B13AF000
进程基址:        829FFDA0

Breakpoint 0 hit
<Unloaded_TesSafe.sys>+0x6ef1:
b1117ef1 8b4624          mov     eax,dword ptr [esi+24h]

Breakpoint 0 hit
<Unloaded_TesSafe.sys>+0x22a2:
b11132a2 8b09            mov     ecx,dword ptr [ecx]

Breakpoint 0 hit
<Unloaded_TesSafe.sys>+0xba4cc:
b11cb4cc e9a8350000      jmp     <Unloaded_TesSafe.sys>+0xbda79 (b11cea79)

Breakpoint 0 hit
<Unloaded_TesSafe.sys>+0xbb0f2:
b11cc0f2 e9c5f1ffff      jmp     <Unloaded_TesSafe.sys>+0xba2bc (b11cb2bc

一处检测: TesSafe.sys +0x4082

在处理清零之前我们要先处理掉检测,不然要是直接把清零函数ret掉了,检测函数发现后就会重启我们的电脑。
我们要先通过IDA的逆向找出清零函数和检测函数的首地址

第一处清零首地址:TesSafe+0x6ea8;
第二处清零首地址:TesSafe+0x222e;

以下是两处VM的清零代码的地址:

第三处清零:TesSafe+0xbb0f0;
第四处清零:TesSafe+0xba4ca;

CRC检测首地址:TesSafe+0x4082;

知道这些信息后我们就开始写代码过了他吧!

void HandleDebugZero(ULONG uImageBase) //主要清零处理函数
{
                ULONG uAddr_1=uImageBase + 0x4082;//清零CRC检测首地址

	ULONG uAddr_2=uImageBase + 0x6ea8;//清零处1首地址
	ULONG uAddr_3=uImageBase + 0x2228;//清零处2首地址

	GetDnfEprocessAddr(uImageBase);   //取得DNF 进程基址
           //这个进程基址在处理第三和第四处清零的时候用到

           if(uImageBase==0)
	{
		return;
	}

	DisableWP();   //清除CR0

	*(PUSHORT)uAddr_1=0xc3;
                 //由于这个检测函数没压入参数,所以直接ret
         	
    
	//0x6ea8 //第一处清零首地址,也是直接ret
           *(PUCHAR)(uAddr_2)=0xc3;

	//0x2228 //第二处清零首地址,还是直接ret
	*(PUCHAR)(uAddr_3)=0xc3;


	EnableWP();//恢复CR0
	

                g_uDebugPortOffset=g_uDebugPortOffset+0xbc;
                //取到清零位置的地址

	HandleDebugPortPop(true,uImageBase);//处理第三处清零
	HandleDebugPortPush(true,uImageBase);//处理第四处清零
}


打字打到手都累了,下面就不加那么清楚的注释了,各位自己看下吧

void HandleDebugPortPop(BOOLEAN bHook,ULONG uImageBase)
{
        if(bHook)
        {
                //hook pop
                if(uImageBase==0)
                {
                        return ;
                }
                g_uDebugPortPopHookAddr=uImageBase+0xbb0f0;//pop hook地址

                g_uDebugPortPopRetAddr=uImageBase+0xba2bc;//pop retn 地址

                if(g_uDebugPortPopHookAddr==0)
                {
                        return;
                }
                RtlCopyMemory((PVOID)g_szBackupDebugPortPop,
                                  (PVOID)g_uDebugPortPopHookAddr,
                                         5);//保存hook地址,用于恢复
               
                InLineHookEngine(g_uDebugPortPopHookAddr,(int)FuckDebugPortPop);
                //__asm int 3
        }
        else
        {
                if(g_uDebugPortPopHookAddr==0)
                {
                        return;
                }
                // 最好判断下 TP是否 已经卸载
                int TesSafe=GetTesSafeBassAddr();
                if(TesSafe!=0)
                {
                //KIRQL Irql=KeRaiseIrqlToDpcLevel();
                DisableWP();
        RtlCopyMemory((PVOID)g_uDebugPortPopHookAddr,
                                  (PVOID)g_szBackupDebugPortPop,
                                         5);//保存hook地址,用于恢复
                EnableWP();
                }
        }

}

void HandleDebugPortPush(BOOLEAN bHook,ULONG uImageBase)
{
        if(bHook)
        {
                //hook pop
                if(uImageBase==0)
                {
                        return ;
                }
                g_uDebugPortPushHookAddr=uImageBase+0xba4ca;//push hook地址

                g_uDebugPortPushRetAddr=uImageBase+0xba2bc;//push retn 地址

                if(g_uDebugPortPushHookAddr==0)
                {
                        return;
                }
                RtlCopyMemory((PVOID)g_szBackupDebugPortPush,
                                  (PVOID)g_uDebugPortPushHookAddr,
                                         5);//保存hook地址,用于恢复
               
                InLineHookEngine(g_uDebugPortPushHookAddr,(int)FuckDebugPortPush);
                //__asm int 3
        }
        else
        {
                if(g_uDebugPortPushHookAddr==0)
                {
                        return;
                }
                // 最好判断下 TP是否 已经卸载
                int TesSafe=GetTesSafeBassAddr();
                if(TesSafe!=0)
                {
                //KIRQL Irql=KeRaiseIrqlToDpcLevel();
                DisableWP();
                                RtlCopyMemory((PVOID)g_uDebugPortPushHookAddr,
                                  (PVOID)g_szBackupDebugPortPush,
                                         5);//保存hook地址,用于恢复
                EnableWP();
                }
        }

}

__declspec(naked)void FuckDebugPortPop()
{
        //DbgPrint("Pop");
        __asm
        {
                pushfd
                cmp edx,g_uDebugPortOffset //判断入栈的参数是否是清零位置的地址
                jnz POPLABLE
                popfd
                add esp,0x4
                jmp g_uDebugPortPopRetAddr
POPLABLE:
                popfd
                pop dword ptr [edx]
                jmp g_uDebugPortPopRetAddr

        }

}

__declspec(naked)void FuckDebugPortPush()
{
        //DbgPrint("Push");
        __asm
        {
                pushfd
                cmp edx,g_uDebugPortOffset//判断入栈的参数是否是清零位置的地址

                jnz PUSHLABLE
                popfd
                push 0
                jmp g_uDebugPortPushRetAddr
PUSHLABLE:
                popfd
                push dword ptr [edx]
                jmp g_uDebugPortPushRetAddr
        }

}

最后提一点以下这两个函数要在驱动卸载的时候加到Unload函数中
HandleDebugPortPop(false,0);
HandleDebugPortPush(false,0);

最后在自己的机子成功过了TP后,CE 可以读写内存,OD可以附加。

但是测试一段时间后发现还有以下很多问题
1、CE 打开进程的时候没问题,但一扫描内存就非法。
2、驱动加载一段时间后,保护虽然过了,但一阵子后系统就重启了,只要过了保护一段时间就算没做任何操作也会重启。求大牛解答下

[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞3
打赏
分享
最新回复 (18)
雪    币: 1904
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jioushizhu 2013-7-31 16:30
2
0
此帖不错,必火。
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
BMXDN 2013-7-31 16:33
3
0
我的是用syser调试找debugPort清零的。
后来必须开着syser,才不会重启。
雪    币: 115
活跃值: (46)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
IDGHOST 2013-7-31 16:58
4
0
FuckDebugPortPush挺有个性的

个人怀疑是R3与驱动通信,引起的检测并重启,检测当然不只这四处。
而且R3进程本身就会对调试器脱离,可以停了驱动试下;昨天不知怎么的,附上游戏后居然没断开,还能下断。
TP还有一处工作,检测是否内存被读写(Driver层的Attach)。
雪    币: 3110
活跃值: (143)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
sorrywyb 2013-7-31 17:32
5
0
嗯 这个还是老的地址吧
雪    币: 50
活跃值: (101)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
charwin 2013-7-31 21:56
6
0
请问楼主用的虚拟机版本是什么呢..我试了两个版本..全部到载入完快要选频道时就退出了..
另外..楼主关于重启.是否有处理过NtQueryInformationProcess??
雪    币: 54
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
getxxx 2013-7-31 21:58
7
0
必火,赶紧马克之!!
雪    币: 11
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
pcmyth 2013-7-31 22:40
8
0
火前留名~~~~~~~~~~~~
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
学雄 1 2013-7-31 22:52
9
0
老得掉牙的文章,还有一堆人盲目.....
雪    币: 37
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
averycheng 2013-7-31 22:53
10
0
Mark之后研究
雪    币: 149
活跃值: (71)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
萧遥法外 2013-7-31 23:07
11
0
我的虚拟机版本是VMware7破解版,TP没有修改NtQueryInformationProcess
吧,需要处理么?
雪    币: 50
活跃值: (101)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
charwin 2013-7-31 23:30
12
0
不知道你调的驱动是否是1.16.0.36655(2013-5-15)这个版本..如果是的话.他有调用该函数对dbgport端口检查..但是感觉着你好像不是这个版本的驱动..你所发的地址和这个驱动的地址不太一样..
雪    币: 50
活跃值: (101)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
charwin 2013-7-31 23:37
13
0
弱弱的问下...Driver层的Attach我怎么样去发现呢...
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yuhb 2013-8-1 00:36
14
0
弱弱的问一句,这代码是以前的吧?过不了清0吧?
雪    币: 64
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
逆帅 2013-8-1 09:47
15
0
重启,TP本来就会对几乎整个代码进行效验,只是比较慢而已
大概是3-5分钟才检测到的样子,甚至更久
雪    币: 64
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
逆帅 2013-8-1 09:51
16
0
还有push
pop清零在最新版的TP里面已经取消了吧,我没看到么。。。
还有没过另一种清零你是怎么附加的
你游戏多久没更新了额
雪    币: 115
活跃值: (46)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
IDGHOST 2013-8-1 10:17
17
0
暂时不了解TP玩的哪样,是不扫描就一直都不提示环境异常吗
同样HS也有这样检测,那个就恶多了。
雪    币: 38
活跃值: (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Shhh 2013-8-9 13:24
18
0
大侠jmp g_uDebugPortPopRetAddr为什么要跳到g_uDebugPortPopRetAddr这个地址,那个push压栈不是才2 byte 吗?还有就是现在的清零有两处检测代码哦,一处被VM了,跟第3、4处的差不多处理,但是我看不懂你3、4处为什么要跳到g_uDebugPortPopRetAddr这个地址,求解释~~~
雪    币: 21
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
豆浆蟹蟹 2013-8-9 15:01
19
0
mark下看看
游客
登录 | 注册 方可回帖
返回