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


    首先特别感谢梦老大,本人一直没搞懂异常处理机制,看了他的教程之后终于明白了。
    在他的教程里我学到了不少东西。
    第一次在论坛发帖,就说说Win7 x64位下怎么过TP保护。如果有讲错的地方,还望指出。
    说不定我发帖后一星期TP就会大更新呢。
    打字排版好辛苦。 
    先说说内核层,看大家的反应后再说说应用层的保护。(包括解决CE非法问题)

    调试对象:DXF
    调试工具:OD、Windbg
    调试环境:Win7 SP1 X64

    调试先言:我记得TP最近的一次大更新是在去年的暑假,在那之前的ring0保护和现在的已经大有不同了。
    不过还是少不了DebugPort清零。


    内核层部分:
    x64下因为有PatchGuard的限制,很多保护都被巨硬给抹掉了。
    比如SSDT Hook Inline Hook 所以TP无法继续使用这些保护手段了。
    除非腾Xun冒着被巨硬吊销数字签名的风险来阻止我们调试。
    我曾经在看雪论坛里看过有个人写的文章,它亲自测试在x64环境下清零调试端口,结果发生了蓝屏,
    所以在x64下TP是不会清零的。这样就省了不少的事情。
    但是自从那次TP大更新后新加入了ValidAccessMask清零。
    那么在ring0中 TP除了ValidAccessMask清零,还有反双机调试,这里不是我们讨论的范畴。
    我们只是讨论如何才能正常调试游戏,于是在内核层我们只要解决ValidAccessMask清零就可以了。

    调试权限(ValidAccessMask)的清零
    这个标志位其实是DebugObject (调试对象)的权限,如果为0将导致无法创建调试对象(缺少权限)。
    常见的情况就是OD无法附加任何进程,这个保护刚刚出的时候很多菜鸟都没搞懂,包括我自己(知道被我师傅说我等级太低时的心情是什么?)。
    这个DebugObject在很多调试函数中都有用到 ,比如NtCreateDebugObject就有需要访问调试对象。
    所以要想办法恢复这个标志位。
    我们有三种选择:1、自己恢复原来的值 2、找到TP清零的位置Nop掉 3、移位(重建DebugObject)
    这里我选择了第一种。

    具体步骤如下:
    ①定位DebugObject:
    在NtCreateDebugObject里就有DebugObject的地址。
    1: kd> uf NtCreateDebugObject
    nt!NtCreateDebugObject:
    fffff800`042697a0 48895c2408      mov     qword ptr [rsp+8],rbx
    fffff800`042697a5 4889742410      mov     qword ptr [rsp+10h],rsi
    fffff800`042697aa 57              push    rdi
    fffff800`042697ab 4883ec70        sub     rsp,70h
    fffff800`042697af 418bf9          mov     edi,r9d
    fffff800`042697b2 8bf2            mov     esi,edx
    fffff800`042697b4 488bd9          mov     rbx,rcx
    fffff800`042697b7 65488b042588010000 mov   rax,qword ptr gs:[188h]
    fffff800`042697c0 448a90f6010000  mov     r10b,byte ptr [rax+1F6h]
    fffff800`042697c7 4584d2          test    r10b,r10b
    fffff800`042697ca 7414            je      nt!NtCreateDebugObject+0x40 (fffff800`042697e0)
    nt!NtCreateDebugObject+0x2c:
    fffff800`042697cc 488b052d38e5ff  mov     rax,qword ptr [nt!MmUserProbeAddress (fffff800`040bd000)]
    fffff800`042697d3 483bc8          cmp     rcx,rax
    fffff800`042697d6 480f43c8        cmovae  rcx,rax
    fffff800`042697da 488b01          mov     rax,qword ptr [rcx]
    fffff800`042697dd 488901          mov     qword ptr [rcx],rax
    nt!NtCreateDebugObject+0x40:
    fffff800`042697e0 48832300        and     qword ptr [rbx],0
    fffff800`042697e4 41f7c1feffffff  test    r9d,0FFFFFFFEh
    fffff800`042697eb 740a            je      nt!NtCreateDebugObject+0x57 (fffff800`042697f7)
    nt!NtCreateDebugObject+0x4d:
    fffff800`042697ed b80d0000c0      mov     eax,0C000000Dh
    fffff800`042697f2 e9e4000000      jmp     nt!NtCreateDebugObject+0x13b (fffff800`042698db)
    nt!NtCreateDebugObject+0x57:
    fffff800`042697f7 488d442450      lea     rax,[rsp+50h]
    fffff800`042697fc 4889442440      mov     qword ptr [rsp+40h],rax
    fffff800`04269801 8364243800      and     dword ptr [rsp+38h],0
    fffff800`04269806 8364243000      and     dword ptr [rsp+30h],0
    fffff800`0426980b c744242868000000 mov     dword ptr [rsp+28h],68h
    fffff800`04269813 488364242000    and     qword ptr [rsp+20h],0
    fffff800`04269819 458aca          mov     r9b,r10b
    fffff800`0426981c 488b158dd3daff  mov     rdx,qword ptr [nt!DbgkDebugObjectType (fffff800`04016bb0)]
    fffff800`04269823 418aca          mov     cl,r10b
    fffff800`04269826 e84572f1ff      call    nt!ObCreateObject (fffff800`04180a70)
    fffff800`0426982b 4c8b4c2450      mov     r9,qword ptr [rsp+50h]
    fffff800`04269830 4c894c2460      mov     qword ptr [rsp+60h],r9
    fffff800`04269835 85c0            test    eax,eax
    fffff800`04269837 0f889e000000    js      nt!NtCreateDebugObject+0x13b (fffff800`042698db)
    这个红字就是了 
    继续定位ValidAccessMask的地址。

    1: kd> dq fffff800`04016bb0
    fffff800`04016bb0  fffffa80`00c33200 00000000`00000000
    fffff800`04016bc0  fffff8a0`0009a010 0000002a`00000012
    fffff800`04016bd0  00000024`000000a1 fffff880`0119d9a0
    fffff800`04016be0  00000002`00000001 fffff880`095deacc
    fffff800`04016bf0  fffff800`03f873f0 00000000`00000007
    fffff800`04016c00  00000003`00000000 fffff800`03e10448
    fffff800`04016c10  fffffa80`01bae060 00000000`00000000
    fffff800`04016c20  00000000`00000000 00000003`00000101

    1: kd> dt _OBJECT_TYPE fffffa80`00c33200
    nt!_OBJECT_TYPE
       +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`00c33200 - 0xfffffa80`00c33200 ]
       +0x010 Name             : _UNICODE_STRING "DebugObject"
       +0x020 DefaultObject    : (null) 
       +0x028 Index            : 0xb ''
       +0x02c TotalNumberOfObjects : 0
       +0x030 TotalNumberOfHandles : 0
       +0x034 HighWaterNumberOfObjects : 0
       +0x038 HighWaterNumberOfHandles : 0
      +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
       +0x0b0 TypeLock         : _EX_PUSH_LOCK
       +0x0b8 Key              : 0x75626544
       +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffffa80`00c332c0 - 0xfffffa80`00c332c0 ]

    1: kd> dt _OBJECT_TYPE_INITIALIZER fffffa80`00c33200+40
    nt!_OBJECT_TYPE_INITIALIZER
       +0x000 Length           : 0x70
       +0x002 ObjectTypeFlags  : 0x8 ''
       +0x002 CaseInsensitive  : 0y0
       +0x002 UnnamedObjectsOnly : 0y0
       +0x002 UseDefaultObject : 0y0
       +0x002 SecurityRequired : 0y1
       +0x002 MaintainHandleCount : 0y0
       +0x002 MaintainTypeList : 0y0
       +0x002 SupportsObjectCallbacks : 0y0
       +0x002 CacheAligned     : 0y0
       +0x004 ObjectTypeCode   : 0
       +0x008 InvalidAttributes : 0
       +0x00c GenericMapping   : _GENERIC_MAPPING
       +0x01c ValidAccessMask  : 0x1f000f
       +0x020 RetainAccess     : 0
       +0x024 PoolType         : 0 ( NonPagedPool )
       +0x028 DefaultPagedPoolCharge : 0
       +0x02c DefaultNonPagedPoolCharge : 0x58
       +0x030 DumpProcedure    : (null) 
       +0x038 OpenProcedure    : (null) 
       +0x040 CloseProcedure   : 0xfffff800`042b18e0     void  nt!DbgkpCloseObject+0
       +0x048 DeleteProcedure  : 0xfffff800`04105200     void  nt!xHalEndOfBoot+0
       +0x050 ParseProcedure   : (null) 
       +0x058 SecurityProcedure : 0xfffff800`04170530     long  nt!SeDefaultObjectMethod+0
       +0x060 QueryNameProcedure : (null) 
       +0x068 OkayToCloseProcedure : (null) 

    于是我们就定位到了VaildAccessMask的地址了。

    ②恢复工作
    它的默认值是0x1F000F
    当我们自己手动修改成0时。
    使用OD附加任意进程。


    <ignore_js_op> 
    无法附加,那我们就要手动恢复成0x1F000F。
    具体方式我采用开DPC定时器的方法恢复,恢复的频率不会和TP的冲突。
    代码我贴出一部分,部分函数需要自己手动编写,因为在64位下编写驱动寻找SSDT等都比较麻烦。
    这些函数大家可以去网上一些x64驱动编写的教程里面抄下。
    我在这里推荐下Tesla.Angela的教程《WIN64驱动编程基础教程》

      1. #ifndef PROC
      2. #define PROC
      3. PVOID pNtCreateDebugObject;
      4. PVOID pDbgkDebugObject;
      5. PVOID pDebugObject;
      6. PVOID pValidMask;
      7. KTIMER PassObjTimer;
      8. KDPC PassObjDpc;
      9. LARGE_INTEGER PassObjTime;
      10. PVOID pKeStackAttachProcess;
      11. PVOID pKeStackAttachProcessJmpAddr;
      12. byte  bufKeStackAttachProcess[13];
      13. VOID
      14. PassObj(
      15. __in struct _KDPC  *Dpc,
      16. __in_opt PVOID  DeferredContext,
      17. __in_opt PVOID  SystemArgument1,
      18. __in_opt PVOID  SystemArgument2
      19. )
      20. {
      21.         __try
      22.         {
      23.                 WriteProtectOff();
      24.                 *((ULONG*)pValidMask) = 0x1F000F;
      25.                 WriteProtectOn();
      26.         }
      27.         __except (1)
      28.         {
      29.                 KeCancelTimer(&PassObjTimer);
      30.                 return;
      31.         }
      32.         KeSetTimer(&PassObjTimer, PassObjTime, &PassObjDpc);
      33.         return;
      34. }
      35. VOID PassObjectMask()
      36. {
      37.         PVOID pTargetAddr;
      38.         pNtCreateDebugObject = (PVOID)GetSSDTFunctionAddress(144);
      39.         pTargetAddr = (PVOID)(((ULONG64)pNtCreateDebugObject) + 0x7C);
      40.         pDbgkDebugObject=(PVOID)(MAKE_TARGETADDR((*((ULONG*)(((ULONG64)pTargetAddr) + 3))), (ULONG64)pTargetAddr));
      41.         pDebugObject = (PVOID)(*((ULONG64*)pDbgkDebugObject));
      42.         pValidMask = (PVOID)(((ULONG64)pDebugObject) + 0x40 + 0x1c);
      43.         PassObjTime.QuadPart = -10000 * 100;
      44.         KeInitializeTimer(&PassObjTimer);
      45.         KeInitializeDpc(&PassObjDpc, &PassObj, NULL);
      46.         KeSetTimer(&PassObjTimer, PassObjTime, &PassObjDpc);
      47. }
      48. VOID UnPassObjectMask()
      49. {
      50.         KeCancelTimer(&PassObjTimer);
      51. }
      52. #endif

    非常感谢大家那么支持我上一篇教程。
    Win10 快出了,所以我打算尽快把应用层的部分说完。


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

    应用层:
    1、TP让调试器卡死(内核互动)
    现象: <ignore_js_op> 
    如图,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的进程->右键选择扫描。
    <ignore_js_op> 
    现在你只需要坐下等大约5分钟吧,好像有一千多个钩子(笑),要有耐心。
    看到图中3个钩子了吗,它就是我们要说的。
    我这里来说明下这3个函数的用途。

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

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

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

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

    其实我发现第3种是一劳永逸,所以我在这里说下第三种方法。
    打开PCHunter找到如下几条线程。选择后同时右键结束,OK,CE再也不会非法了。
    <ignore_js_op> 
    这几条线程都是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.         
    12.         DWORD trds[521];
    13.         int trdcount=0;
    14.         trdcount=GetProcessThreadId(pid, trds);
    15.         LPVOID pEntryPoint=NULL;
    16.         BYTE buf[13];
    17.         HANDLE hThread;
    18.         for (int i = 0; i < trdcount;i++)
    19.         {
    20.                 pEntryPoint=GetThreadEntryPointById(trds[i]);
    21.                 ReadProcessMemoryEx(pid, pEntryPoint, buf, 8);
    22.                 TCHAR ModuleName[256];
    23.                 GetProcessThreadModuleNameByTid(pid, trds[i], ModuleName);
    24.                 
    25.                 if (memcmp(buf, code, 8) == 0 || lstrcmp(ModuleName, L"TenSLX.dll")==0)
    26.                 {
    27.                         hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, trds[i]);
    28.                         if (!hThread)continue;
    29.                         TerminateThread(hThread,0);
    30.                         CloseHandle(hThread);
    31.                         
    32.                 }
    33.                 
    34.                 ReadProcessMemoryEx(pid, (LPVOID)((int)pEntryPoint - 0xc), buf, 13);
    35.                 if (memcmp(buf, code2, 13) == 0)
    36.                 {
    37.                         hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, trds[i]);
    38.                         if (!hThread)continue;
    39.                         SuspendThread(hThread);
    40.                         CloseHandle(hThread);
    41.                 }
    42.         }
    43.         
    44.         byte code3[7] = { 0x6A, 0x08, 0x68, 0x00, 0x00, 0x00, 0x00 };
    45.         LPVOID pDbgUiRemoteBreakin = (LPVOID)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "DbgUiRemoteBreakin");   //调试用
    46.         memcpy(&code3[3], (LPVOID)((int)pDbgUiRemoteBreakin + 3), 4);
    47.         WriteProcessMemoryEx(pid, pDbgUiRemoteBreakin, code3, 7);
    48.         byte code4[6] = { 0x8b, 0xff, 0x55, 0x8b, 0xec, 0xff };
    49.         LPVOID pLdrInitializeThunk = (LPVOID)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "LdrInitializeThunk");  //DLL注入用
    50.         WriteProcessMemoryEx(pid, pLdrInitializeThunk, code4, 6);
    51.         MessageBox(TEXT("操作完毕,开始调试吧!"),TEXT("OK"),MB_OK|MB_ICONINFORMATION);
    52. }
    复制代码

    功能函数头文件:

    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. }
    165. BOOL EnableDebugPrivilege()  
    166. {  
    167.         HANDLE token;  
    168.         //提升权限   
    169.         if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&token))  
    170.         {   
    171.                 return FALSE;  
    172.         }  
    173.         TOKEN_PRIVILEGES tkp;  
    174.         tkp.PrivilegeCount = 1;  
    175.         ::LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid);  
    176.         tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;  
    177.         if(!AdjustTokenPrivileges(token,FALSE,&tkp,sizeof(tkp),NULL,NULL))  
    178.         {  
    179.                 return FALSE;  
    180.         }  
    181.         CloseHandle(token);  
    182.         return TRUE;  
    183. }  
    184. #endif
  • 相关阅读:
    小小小康
    GC日志补充
    一次GC问题定位
    mycat1.5~1.6的一个bug
    [转] java Statement和PreparedStatement批量更新
    java 中的instanceof 运算符
    Java学习篇之数组方法
    iOS7适配的一点小技巧
    iOS 中正确切换摄像头&正确实现设置帧率的方式
    iOS 音量键事件监控响应
  • 原文地址:https://www.cnblogs.com/csnd/p/11587490.html
Copyright © 2020-2023  润新知