关于Win7 x64下过TP保护(应用层)(转)

调试对象:DXF
调试工具:CE、OD、PCHunter、Windbg
调试先言:TP的应用层保护做得比较多,包括对调试器的检测,比如CE工具会被DXF报非法。有的保护还是内核与应用层交替保护。

应用层:
1、TP让调试器卡死(内核互动)
 
如图,TP会检测调试器让调试器暂停运行,实际上就是暂停了调试器所有的线程而已。
这个保护是今年7月份新出的,所以我这里重点分析下,我刚开始调试的时候就发现OD会莫名其妙地卡死。
打开PCHunter发现OD的进程线程全部被暂停了。
开始我认为是TP调用了SuspendThread(函数:暂停指定线程)来让调试器卡死的。
于是我就打开Windbg附加并在这个函数上下断点,发现没有断下来。
然后我认为是调用了接口函数NtSuspendThread(函数:暂停指定线程<内核接口>)
但是还是没有断下。所以排除了DXF在Ring3调用了暂停线程让OD卡死。
于是我思考了一下,打开虚拟机,简单过了双机调试保护(一段时间后还是会蓝屏),在DXF启动之后,
在Windbg输入!process OD的进程ID 来查看线程的调用堆载,我发现了很有意思的东西。
SuspendCount被置为了1,再看看调用堆载。
原来TP在Ring0中调用了KiSuspendThread来暂停OD的线程啊。怪不得断不下来。
于是我在KiSuspendThread头部下断点,发现当OD打开的时候会断下,
这个是它的函数开头
0: kd> u KiSuspendThread
nt!KiSuspendThread:
fffff800`03e6cc60 48895c2408      mov     qword ptr [rsp+8],rbx
fffff800`03e6cc65 4889742410      mov     qword ptr [rsp+10h],rsi
fffff800`03e6cc6a 57              push    rdi
fffff800`03e6cc6b 4883ec30        sub     rsp,30h
fffff800`03e6cc6f 8364245800      and     dword ptr [rsp+58h],0
fffff800`03e6cc74 65488b1c2588010000 mov   rbx,qword ptr gs:[188h]
fffff800`03e6cc7d 4885db          test    rbx,rbx
它还保留着用__stdcall的调用约定,在64位下一般都是__fastcall
通过对参数的分析,我发现这个函数的第一个参数也就是rbx,里面存的是线程对象。
我在网上也没有找到相关的信息,于是我自己在头部改成了ret。
之后运行OD就不会卡死了。
继续深究,原来TP创建了一个内核回调,就是CreateProcess的回调,
自己可以打开PCHunter查看。
当发现是OD的进程被创建时,就会调用这个函数让进程暂停。
哦,原来是这样,那我们有什么办法解决它呢?怎么才能让调试器正常运行呢?
方案:1、自己恢复调试器的进程(推荐) 2、删除内核回调(驱动推荐)3、Hook KiSuspendThread 绕过(稍难)
在这里我推荐第一种,因为我们是要在应用层下操作。
方法很简单,当我们打开OD工具时,打开PCHunter选择OD的进程,右键恢复进程运行即可。
也可以自己做一个工具,恢复OD的进程,但是你要确保自己的程序不会进入黑名单。
至此,我们的调试器能正常打开了。

2、函数钩子(Hook)
这个保护不能说是新鲜了的吧,在应用层里很多游戏都这么干。
其实就是把一些重要的调试函数进行钩子,导致程序崩溃或者无法调试。
我们打开PCHunter,来到如图的位置,选择DXF的进程->右键选择扫描。
 
现在你只需要坐下等大约5分钟吧,好像有一千多个钩子(笑),要有耐心。
看到图中3个钩子了吗,它就是我们要说的。
我这里来说明下这3个函数的用途。

DbgUiRemoteBreakin:远程中断,附加调试器时调试器会发送信息让进程走这里。
KiUserExceptionDispatcher:UEF异常处理函数,梦老大讲解过的,这个我们不能随便恢复,干脆不用管它
因为DXF自己制造异常自己处理。
LdrInitalizeThunk:映像文件链入口,当DLL载入时会经过这里,如果我们不恢复它将无法注入DLL。

这3个钩子有两个是我们必须恢复的,就是一和三。
第三个比较好处理,PCHunter中已经给出了函数原来的机器码。我们之间用PCHunter恢复也可以自己写个程序恢复
但是第一个就不好了,我们必须用程序自己来恢复,因为:
 
红线部分是需要重定位的,机器每次开机都会不同,我们可以通过获取自己程序的这个位置的代码来恢复。
具体怎么恢复这里就不说了,我会贴出代码给大家。
那么2个Hook搞定后我们就要来解决崩溃问题了。

3、异常崩溃
大家可以发现OD附加DXF后运行,游戏会莫名其妙地崩溃,你可能会认为OD被DXF检测到了,其实它是个通用
的反调试的手法。
自己给自己制造异常,自己处理,如果OD抢着处理这个异常,反而会使进程崩溃。
这个就是它异常崩溃的原理。
其实是一个线程在自发异常的,怎么把它揪出来呢?
打开Windbg,附加DXF,运行,可以发现一段时间后,Windbg断下
如图所示:
 
线程ID:F08 发送了一个内存访问异常(0x80000002)它故意让Windbg断下。
它需要试探是否有调试器,于是我们就找到它了,把f08换成十进制发现是
3848的线程发送异常的,在PCHunter中可以看到,如图所示,它是由ntdll.dll发送的。
唯一的办法就是结束这个线程,右键->结束线程,搞定,OD附加DXF不会崩溃了。
但是你得自己做个程序来找到这条线程然后来结束掉,可以通过搜索线程入口特征码的方式来
找到它。
那么现在,我们调试DXF再也没有问题了。但是CE工具开启久了也会被提示非法,怎么办?

4、检测非法工具
也许大家非常想要知道怎么办。
它检测非法工具的原理是:
使用ReadProcessMemory(函数:读取进程内存)搜索进程特征码,找到属于非法工具的特征码后游戏消失,提示非法重启。
若想解决它,我们有以下方案:
1、删除工具中的特征码 2、在内核中拦截NtReadVirtualMemory或KeStackAttachProcess来绕过搜索
3、找到搜索的线程,结束该线程。

其实我发现第3种是一劳永逸,所以我在这里说下第三种方法。
打开PCHunter找到如下几条线程。选择后同时右键结束,OK,CE再也不会非法了。
 
这几条线程都是TenSLX.dll模块里的,其实这个方法在腾Xun游戏里面通用。
别问我是怎么知道的,其实我是一个个试过的(笑)。

5、关于CRC代码自校验
通过上面的说明,大家应该可以总结一个结论
在应用层中游戏若想保护自己都是采用走线程或Hook方式。
所以大家可以自己找到CRC代码自校验的线程吧?结束掉,OK,可以下软件断点(int 3)了。

结束语:
别以为这样就能在DXF里为所欲为了,还有三方检测等着你呢!
这些还需要靠大家自己多去练习,总结规律,其实你会发现,
再难的保护还都是这样子的了(笑)......

附赠代码(部分):

  1. void CAnitTP_AppDlg::OnBnClickedButtonAnit()
  2. {
  3. DWORD pid = GetProcessIdByProcName(TEXT("DNF.exe"));
  4. if (pid==0)
  5. {
  6. MessageBox(TEXT("对不起,没有找到指定游戏进程.(DNF.exe)"), TEXT("操作失败"), MB_OK | MB_ICONERROR);
  7. return;
  8. }
  9. const BYTE code[8] = {0x90,0x90,0x90,0x90,0x90,0x55,0x8b,0xec};
  10. const BYTE code2[13] = { 0xC3, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 ,0xE9};
  11. DWORD trds[521];
  12. int trdcount=0;
  13. trdcount=GetProcessThreadId(pid, trds);
  14. LPVOID pEntryPoint=NULL;
  15. BYTE buf[13];
  16. HANDLE hThread;
  17. for (int i = 0; i < trdcount;i++)
  18. {
  19. pEntryPoint=GetThreadEntryPointById(trds[i]);
  20. ReadProcessMemoryEx(pid, pEntryPoint, buf, 8);
  21. TCHAR ModuleName[256];
  22. GetProcessThreadModuleNameByTid(pid, trds[i], ModuleName);
  23. if (memcmp(buf, code, 8) == 0 || lstrcmp(ModuleName, L"TenSLX.dll")==0)
  24. {
  25. hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, trds[i]);
  26. if (!hThread)continue;
  27. TerminateThread(hThread,0);
  28. CloseHandle(hThread);
  29. }
  30. ReadProcessMemoryEx(pid, (LPVOID)((int)pEntryPoint - 0xc), buf, 13);
  31. if (memcmp(buf, code2, 13) == 0)
  32. {
  33. hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, trds[i]);
  34. if (!hThread)continue;
  35. SuspendThread(hThread);
  36. CloseHandle(hThread);
  37. }
  38. }
  39. byte code3[7] = { 0x6A, 0x08, 0x68, 0x00, 0x00, 0x00, 0x00 };
  40. LPVOID pDbgUiRemoteBreakin = (LPVOID)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "DbgUiRemoteBreakin");   //调试用
  41. memcpy(&code3[3], (LPVOID)((int)pDbgUiRemoteBreakin + 3), 4);
  42. WriteProcessMemoryEx(pid, pDbgUiRemoteBreakin, code3, 7);
  43. byte code4[6] = { 0x8b, 0xff, 0x55, 0x8b, 0xec, 0xff };
  44. LPVOID pLdrInitializeThunk = (LPVOID)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "LdrInitializeThunk");  //DLL注入用
  45. WriteProcessMemoryEx(pid, pLdrInitializeThunk, code4, 6);
  46. MessageBox(TEXT("操作完毕,开始调试吧!"),TEXT("OK"),MB_OK|MB_ICONINFORMATION);
  47. }

复制代码

功能函数头文件:

  1. #ifndef HANSHU
  2. #define HANSHU
  3. #include <TlHelp32.h>
  4. #include <psapi.h>
  5. #pragma comment(lib,"psapi.lib")
  6. typedef enum _THREADINFOCLASS {
  7. ThreadBasicInformation,
  8. ThreadTimes,
  9. ThreadPriority,
  10. ThreadBasePriority,
  11. ThreadAffinityMask,
  12. ThreadImpersonationToken,
  13. ThreadDescriptorTableEntry,
  14. ThreadEnableAlignmentFaultFixup,
  15. ThreadEventPair_Reusable,
  16. ThreadQuerySetWin32StartAddress,
  17. ThreadZeroTlsCell,
  18. ThreadPerformanceCount,
  19. ThreadAmILastThread,
  20. ThreadIdealProcessor,
  21. ThreadPriorityBoost,
  22. ThreadSetTlsArrayAddress,
  23. ThreadIsIoPending,
  24. ThreadHideFromDebugger,
  25. ThreadBreakOnTermination,
  26. MaxThreadInfoClass
  27. } THREADINFOCLASS;
  28. typedef struct _CLIENT_ID {
  29. HANDLE UniqueProcess;
  30. HANDLE UniqueThread;
  31. } CLIENT_ID;
  32. typedef CLIENT_ID *PCLIENT_ID;
  33. typedef struct _THREAD_BASIC_INFORMATION { // Information Class 0
  34. LONG     ExitStatus;
  35. PVOID    TebBaseAddress;
  36. CLIENT_ID ClientId;
  37. LONG AffinityMask;
  38. LONG Priority;
  39. LONG BasePriority;
  40. } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
  41. typedef LONG (__stdcall *fZwQueryInformationThread) (
  42. IN HANDLE ThreadHandle,
  43. IN THREADINFOCLASS ThreadInformationClass,
  44. OUT PVOID ThreadInformation,
  45. IN ULONG ThreadInformationLength,
  46. OUT PULONG ReturnLength OPTIONAL
  47. );
  48. fZwQueryInformationThread  ZwQueryInformationThread;
  49. DWORD GetProcessPidByWndName(LPCTSTR szWndName)
  50. {
  51. HWND hWnd = FindWindow(NULL,szWndName);
  52. if (IsWindow(hWnd))
  53. {
  54. DWORD pid;
  55. GetWindowThreadProcessId(hWnd,&pid);
  56. return pid;
  57. }
  58. return 0;
  59. }
  60. DWORD GetProcessIdByProcName(LPCTSTR szProcName)
  61. {
  62. HANDLE hSnapshot= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  63. PROCESSENTRY32 pro;
  64. pro.dwSize=sizeof(pro);
  65. BOOL bMore=Process32First(hSnapshot,&pro);
  66. while (bMore)
  67. {
  68. if (lstrcmp(szProcName,pro.szExeFile)==0)
  69. {
  70. CloseHandle(hSnapshot);
  71. return pro.th32ProcessID;
  72. }
  73. bMore=Process32Next(hSnapshot,&pro);
  74. }
  75. CloseHandle(hSnapshot);
  76. return 0;
  77. }
  78. BOOL ReadProcessMemoryEx(DWORD pid,LPVOID addr,LPVOID buffer,DWORD size)
  79. {
  80. HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
  81. if (hProcess==0)
  82. {
  83. return FALSE;
  84. }
  85. BOOL bResult=ReadProcessMemory(hProcess,addr,buffer,size,NULL);
  86. CloseHandle(hProcess);
  87. return bResult;
  88. }
  89. BOOL WriteProcessMemoryEx(DWORD pid,LPVOID addr,LPVOID buffer,DWORD size)
  90. {
  91. HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
  92. if (hProcess==0)
  93. {
  94. return FALSE;
  95. }
  96. BOOL bResult=WriteProcessMemory(hProcess,addr,buffer,size,NULL);
  97. CloseHandle(hProcess);
  98. return bResult;
  99. }
  100. int GetProcessThreadId(DWORD pid,DWORD *trds)
  101. {
  102. HANDLE hSnapshot= CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,pid);
  103. if (hSnapshot==INVALID_HANDLE_VALUE)
  104. return 0;
  105. THREADENTRY32 trd;
  106. trd.dwSize=sizeof(trd);
  107. BOOL bMore=Thread32First(hSnapshot,&trd);
  108. int i=0;
  109. while (bMore)
  110. {
  111. if (trd.th32OwnerProcessID==pid)
  112. {
  113. trds[i]=trd.th32ThreadID;
  114. i++;
  115. }
  116. bMore=Thread32Next(hSnapshot,&trd);
  117. }
  118. CloseHandle(hSnapshot);
  119. return i;
  120. }
  121. LPVOID GetThreadEntryPointById(DWORD tid)
  122. {
  123. HANDLE hThread=OpenThread(THREAD_ALL_ACCESS,FALSE,tid);
  124. if (hThread==0)
  125. {
  126. return NULL;
  127. }
  128. LPVOID Addr=NULL;
  129. ZwQueryInformationThread=(fZwQueryInformationThread)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")),"ZwQueryInformationThread");
  130. ZwQueryInformationThread(hThread,ThreadQuerySetWin32StartAddress,&Addr,4,NULL);
  131. CloseHandle(hThread);
  132. return Addr;
  133. }
  134. BOOL GetProcessThreadModuleNameByTid(DWORD pid, DWORD tid, LPWSTR pszModuleName)
  135. {
  136. HANDLE hProcess = NULL;
  137. LPVOID pStart = NULL;
  138. TCHAR tmpStr[256];
  139. hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
  140. if (!hProcess)return FALSE;
  141. pStart = GetThreadEntryPointById(tid);
  142. if (!pStart) return FALSE;
  143. GetMappedFileName(hProcess, pStart, tmpStr, 256);
  144. for (int i = lstrlen(tmpStr); i >0; i--)
  145. {
  146. if (tmpStr[i]== '\\')
  147. {
  148. lstrcpy(pszModuleName, &tmpStr[i+1]);
  149. break;
  150. }
  151. }
  152. CloseHandle(hProcess);
  153. return TRUE;
  154. }
  155. void TerminateThreadEx(DWORD tid,DWORD exitcode=0)
  156. {
  157. HANDLE hThread=OpenThread(THREAD_ALL_ACCESS,FALSE,tid);
  158. if (hThread!=NULL)
  159. {
  160. TerminateThread(hThread,exitcode);
  161. CloseHandle(hThread);
  162. }
  163. }
  164. BOOL EnableDebugPrivilege()
  165. {
  166. HANDLE token;
  167. //提升权限
  168. if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&token))
  169. {
  170. return FALSE;
  171. }
  172. TOKEN_PRIVILEGES tkp;
  173. tkp.PrivilegeCount = 1;
  174. ::LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid);
  175. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  176. if(!AdjustTokenPrivileges(token,FALSE,&tkp,sizeof(tkp),NULL,NULL))
  177. {
  178. return FALSE;
  179. }
  180. CloseHandle(token);
  181. return TRUE;
  182. }
  183. #endif

关于Win7 x64下过TP保护(应用层)相关推荐

  1. 关于Win7 x64下过TP保护(应用层)(转)

    非常感谢大家那么支持我上一篇教程. Win10 快出了,所以我打算尽快把应用层的部分说完. 调试对象:DXF 调试工具:CE.OD.PCHunter.Windbg 调试先言:TP的应用层保护做得比较多 ...

  2. [转载] 关于Win7 x64下过TP保护的一些思路,内核层过保护,驱动过保护

    首先特别感谢梦老大,本人一直没搞懂异常处理机制,看了他的教程之后终于明白了. 在他的教程里我学到了不少东西. 第一次在论坛发帖,就说说Win7 x64位下怎么过TP保护.如果有讲错的地方,还望指出. ...

  3. 关于Win7 x64下过TP保护(内核层)(转)

    首先特别感谢梦老大,本人一直没搞懂异常处理机制,看了他的教程之后终于明白了. 在他的教程里我学到了不少东西. 第一次在论坛发帖,就说说Win7 x64位下怎么过TP保护.如果有讲错的地方,还望指出. ...

  4. (转)完美解决中国工商银行第一代网银U盾(NETPASS)在WIN7 x64下的使用问题

    http://bbs.pcbeta.com/viewthread.php?tid=591837 http://bbs.pcbeta.com/archiver/tid-591837.html 远景论坛  ...

  5. WIN7 X64下成功安装HP LASERJET 3015网络打印机驱动

    困扰多时的在WIN7 X64下成功装上了HP LASERJET 3015的网络打印机驱动终于搞掂. 打印机:HP LASERJET 3015 server:WINXP X86 client: WIN7 ...

  6. Dell D630 win7 x64 下 风扇控制程序 I8kfanGUI 解决方法

    Dell D630 经典商务机 打算升级win7 x64程序 内存已升级4G 遇到的问题:D630经典"显卡门"A2改良版也会出温度过高的问题!所以I8kfanGUI 是大家常用的 ...

  7. win7 x64下安装 KB958559 出现 0x80240037 错误解决方法(win7 x64 安装VB6、Media Studio 8)

    想在win7 X64下运行以前的一些32位程序,比如 VB6 .Media Studio Pro 8 等好用的软件,之前在win7 x86下还勉强能安装运行,但是 win7 x64 下是直接连安装都安 ...

  8. Win7 x64下内核池溢出覆盖配额进程指针(Quota Process Pointer Overwrite)

    0x0 简介 在 Win7 x64位下,内核池的头部结构如下: nt!_POOL_HEADER+0x000 PreviousSize : Pos 0, 8 Bits // 前一个内核堆块大小除以0x1 ...

  9. win7 X64下安装CAD 2013

    环境: AMD 740 , 8G 内存 使用完整版光盘安装 win7 X64 金山毒霸新悟空Sp2.5 杀毒 第1个问题: 安装NDP40-KB2468871补丁时,进度条到头了,仍然很长时间没有结束 ...

  10. intel I7平台Win7 x64 下wpf、silverlight 与aero特效动画缓慢故障排除一则

    *貌似是炫耀博?* 卑鄙本周新入一台  inter i7 平台 gts250 12g内存的主机  自己折腾用. win7 评分 cpu 内存7.5 显示7.9 硬盘5.8 ----------出问题了 ...

最新文章

  1. 语言舒尔特方格程序_注意力训练神器——舒尔特方格(成人、孩子均适用)
  2. lnmp之php5.6.29安装
  3. 操作RadGrid1,RadAjaxLoadingPanel1不出现
  4. Android开发之APP唤醒小程序,打开小程序,调起小程序以及传参数的实现方法(附加源码)
  5. python进阶10 MySQL补充 编码、别名、视图、数据库修改
  6. UVA-1045 - The Great Wall Game(二分图最佳匹配)
  7. Java基础——Java NIO详解(一)
  8. mutilprocess模块的用法
  9. Linux Polkit 中的pkexec 组件存在的本地权限提升漏洞(CVE-2021-4034)修复方法及centos6和centos7的安装包
  10. flex socket java_使用Java编写Socket服务器,并且与Flex通信(二)
  11. 转: DH密钥交换和ECDH原理
  12. Apache整合Tomcat(转)
  13. CsharpVB教程下载
  14. c#打包安装程序[VS2010]
  15. 消防工程师 5.气体灭火系统
  16. 计算机专业高数学科难度,大学里极其有难度的4个专业,挂科率很高,不是学霸学不明白...
  17. python读取微博文本数据,对微博文本进行分句(分句主要以特定的标点符号为主)。...
  18. 2011年系统架构师考试题详解
  19. 2021-2027全球与中国电池冷却板市场现状及未来发展趋势
  20. Echarts常用组件

热门文章

  1. linux识别罗兰声卡,罗兰系列声卡直播K歌模式调试方法
  2. Java后端开发实习记录
  3. 大文件下载插件webupload插件
  4. 3DEC离散元数值模拟技术与应用
  5. java 获取视频时长
  6. DataStudio 编辑器快捷键列表
  7. CDR话单主要字段介绍
  8. c语言自动计费工作,c语言编程实现话单计费实例
  9. 我是游戏设计师——《游戏设计艺术》
  10. SVN客户端安装与使用