• VMP3.6的反调试和反虚拟机


    背景

    看雪上有人泄露了3.6.0.1406,第一时间先下载下来,然后加壳之后扔进x32dbg,A debugger has been found.......

     还能怎么办?右键回收站。

     分析

    正准备放弃的时候,想了想要不在看看,好吧那就在看看,结果一段瞎分析之后定位到了scylla没有处理完善的函数NtQueryInformationThread和QueryInformationProcess

    1. HookNtQueryInformationThread ThreadHideFromDebugger
    2. HookNtQueryInformationProcess ProcessDebugPort
    3. HookNtQueryInformationProcess ProcessDebugObjectHandle
    4. HookNtQueryInformationProcess ProcessDebugPort

    你问我怎么定位的,全是某牛姓男子给我说的,还有需要注意的是这些api下执行是不会断下的,因为它自己shadow了一份systemcall。

    R3的反调试,在scylla配置如下的情况下,添加下面的代码(不管你是inline,vt,ifhook都可以,反正蓝的也不是我的电脑)

    在内核的处理逻辑如下(都是最简单的返回,有的情况下返回是错误的)

    1. NTSTATUS HookNtQueryInformationProcess(
    2. HANDLE ProcessHandle,
    3. PROCESSINFOCLASS ProcessInformationClass,
    4. PVOID ProcessInformation,
    5. ULONG ProcessInformationLength,
    6. PULONG ReturnLength
    7. ) {
    8. UCHAR* fileName = PsGetProcessImageFileName(PsGetCurrentProcess());
    9. if (memcmp((const char*)fileName, "SuperKiller",strlen("SuperKiller")) == 0 && ExGetPreviousMode() == UserMode)//最新的3.6
    10. {
    11. if (ProcessInformationLength != 0)
    12. {
    13. __try
    14. {
    15. ProbeForRead(ProcessInformation, ProcessInformationLength, 4);
    16. if (ReturnLength != 0)
    17. ProbeForWrite(ReturnLength, 4, 1);
    18. }
    19. __except (EXCEPTION_EXECUTE_HANDLER)
    20. {
    21. return GetExceptionCode();
    22. }
    23. }
    24. if (ProcessInformationClass == ProcessDebugObjectHandle)
    25. {
    26. DbgPrint("HookNtQueryInformationProcess ProcessDebugObjectHandle \n");
    27. PEPROCESS TargetProcess;
    28. NTSTATUS Status = ObReferenceObjectByHandle(ProcessHandle, 0x0400, *PsProcessType, UserMode, (PVOID*)& TargetProcess, NULL);
    29. if (NT_SUCCESS(Status) == TRUE)
    30. {
    31. __try
    32. {
    33. *(ULONG64*)ProcessInformation = NULL;
    34. if (ReturnLength != NULL)* ReturnLength = sizeof(ULONG64);
    35. Status = STATUS_PORT_NOT_SET;
    36. }
    37. __except (EXCEPTION_EXECUTE_HANDLER)
    38. {
    39. Status = GetExceptionCode();
    40. }
    41. ObDereferenceObject(TargetProcess);
    42. return Status;
    43. }
    44. return Status;
    45. }
    46. else if (ProcessInformationClass == ProcessDebugPort)
    47. {
    48. DbgPrint("HookNtQueryInformationProcess ProcessDebugPort \n");
    49. if (ProcessInformationLength != sizeof(ULONG64))
    50. return STATUS_INFO_LENGTH_MISMATCH;
    51. PEPROCESS TargetProcess;
    52. NTSTATUS Status = ObReferenceObjectByHandle(ProcessHandle, 0x0400, *PsProcessType, UserMode, (PVOID*)& TargetProcess, NULL);
    53. if (NT_SUCCESS(Status) == TRUE)
    54. {
    55. __try
    56. {
    57. *(ULONG64*)ProcessInformation = 0;
    58. if (ReturnLength != 0)
    59. * ReturnLength = sizeof(ULONG64);
    60. }
    61. __except (EXCEPTION_EXECUTE_HANDLER)
    62. {
    63. Status = GetExceptionCode();
    64. }
    65. ObDereferenceObject(TargetProcess);
    66. return Status;
    67. }
    68. return Status;
    69. }
    70. else if (ProcessInformationClass == ProcessDebugFlags)
    71. {
    72. DbgPrint("HookNtQueryInformationProcess ProcessDebugFlags \n");
    73. if (ProcessInformationLength != 4)
    74. return STATUS_INFO_LENGTH_MISMATCH;
    75. PEPROCESS TargetProcess;
    76. NTSTATUS Status = ObReferenceObjectByHandle(ProcessHandle, 0x0400, *PsProcessType, UserMode, (PVOID*)& TargetProcess, NULL);
    77. if (NT_SUCCESS(Status) == TRUE)
    78. {
    79. __try
    80. {
    81. *(ULONG*)ProcessInformation = 0;
    82. if (ReturnLength != 0)
    83. * ReturnLength = sizeof(ULONG);
    84. }
    85. __except (EXCEPTION_EXECUTE_HANDLER)
    86. {
    87. Status = GetExceptionCode();
    88. }
    89. ObDereferenceObject(TargetProcess);
    90. return Status;
    91. }
    92. return Status;
    93. }
    94. else if (ProcessInformationClass == ProcessBreakOnTermination)
    95. {
    96. DbgPrint("HookNtQueryInformationProcess ProcessBreakOnTermination \n");
    97. if (ProcessInformationLength != 4)
    98. return STATUS_INFO_LENGTH_MISMATCH;
    99. PEPROCESS TargetProcess;
    100. NTSTATUS Status = ObReferenceObjectByHandle(ProcessHandle, 0x1000, *PsProcessType, UserMode, (PVOID*)& TargetProcess, NULL);
    101. if (NT_SUCCESS(Status) == TRUE)
    102. {
    103. __try
    104. {
    105. *(ULONG*)ProcessInformation = 0;
    106. if (ReturnLength != 0)
    107. * ReturnLength = sizeof(ULONG);
    108. }
    109. __except (EXCEPTION_EXECUTE_HANDLER)
    110. {
    111. Status = GetExceptionCode();
    112. }
    113. ObDereferenceObject(TargetProcess);
    114. return Status;
    115. }
    116. return Status;
    117. }
    118. }
    119. return ((PNtQueryInformationProcess)g_jmpNtQueryInformationProcess)(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength);
    120. }
    121. NTSTATUS HookNtQueryInformationThread(
    122. HANDLE ThreadHandle,
    123. THREADINFOCLASS ThreadInformationClass,
    124. PVOID ThreadInformation,
    125. ULONG ThreadInformationLength,
    126. PULONG ReturnLength
    127. ) {
    128. UCHAR* fileName = PsGetProcessImageFileName(PsGetCurrentProcess());
    129. if (memcmp((const char*)fileName, "SuperKiller", strlen("SuperKiller")) == 0 && ExGetPreviousMode() == UserMode)//最新的3.6
    130. {
    131. if (ThreadInformationLength != 0)
    132. {
    133. __try
    134. {
    135. ProbeForRead(ThreadInformation, ThreadInformationLength, 4);
    136. if (ReturnLength != 0)
    137. ProbeForWrite(ReturnLength, 4, 1);
    138. }
    139. __except (EXCEPTION_EXECUTE_HANDLER)
    140. {
    141. return GetExceptionCode();
    142. }
    143. }
    144. if (ThreadInformationClass == ThreadHideFromDebugger)
    145. {
    146. DbgPrint("HookNtQueryInformationThread ThreadHideFromDebugger \n");
    147. if (ThreadInformationLength != 1)
    148. return STATUS_INFO_LENGTH_MISMATCH;
    149. PETHREAD TargetThread;
    150. NTSTATUS Status = ObReferenceObjectByHandle(ThreadHandle, 0x40, *PsThreadType, UserMode, (PVOID*)& TargetThread, NULL);
    151. if (NT_SUCCESS(Status) == TRUE)
    152. {
    153. __try
    154. {
    155. *(BOOLEAN*)ThreadInformation =0;
    156. if (ReturnLength != 0)* ReturnLength = 1;
    157. }
    158. __except (EXCEPTION_EXECUTE_HANDLER)
    159. {
    160. Status = GetExceptionCode();
    161. }
    162. ObDereferenceObject(TargetThread);
    163. return Status;
    164. }
    165. return Status;
    166. }
    167. }
    168. return ((PNtQueryInformationThread)g_jmpNtQueryInformationThread)(ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength, ReturnLength);
    169. }

    R0的反调试,都是直接返回失败

    1. NTSTATUS HookNtQuerySystemInformation(
    2. SYSTEM_INFORMATION_CLASS SystemInformationClass,
    3. PVOID SystemInformation,
    4. ULONG SystemInformationLength,
    5. PULONG ReturnLength
    6. ) {
    7. if(SystemInformationClass == SystemKernelDebuggerInformation || SystemInformationClass == SystemKernelDebuggerInformationEx || SystemCodeIntegrityInformation == SystemInformationClass || ProcessDebugObjectHandle == SystemInformationClass)
    8. return STATUS_UNSUCCESSFUL;
    9. return ((PNtQuerySystemInformation)g_jmpNtQuerySystemInformation)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
    10. }

    反虚拟机

    1、需要处理的是cpuid,代码是抄的别人写的vt,随便改改

    Registers->Rcx = (ULONG_PTR)dwCpuidRegisters.ecx & 0xFFFFFFFF7FFFFFFF;//绕过vmp的虚拟机检测

    2、需要注意中断,如果用的vthook,需要判断当前的tf标志位

    1. if (GuestRflag.fields.tf)
    2. {
    3. ULONG64 info = 0;
    4. // 注入一个硬件调试中断
    5. InjectInterruption(kHardwareException, EXCEPTION_VECTOR_DEBUG, false, 0);
    6. info = VmxCsRead(GUEST_INTERRUPTIBILITY_INFO);
    7. info &= ~2;
    8. VmxCsWrite(GUEST_INTERRUPTIBILITY_INFO, info);
    9. }

    3、NtQuerySystemInformation的处理,比3.5多了一个BMSR

    1. NTSTATUS HookNtQuerySystemInformation(
    2. SYSTEM_INFORMATION_CLASS SystemInformationClass,
    3. PVOID SystemInformation,
    4. ULONG SystemInformationLength,
    5. PULONG ReturnLength
    6. ) {
    7. if (SystemInformationClass == SystemFirmwareTableInformation && SystemInformation)
    8. {
    9. __try
    10. {
    11. if (*(PULONG)SystemInformation == 0x4649524d || *(PULONG)SystemInformation == 0x52534d42)//MRIF BMSR
    12. {
    13. return STATUS_UNSUCCESSFUL;
    14. }
    15. }
    16. __except (EXCEPTION_EXECUTE_HANDLER) {}
    17. }
    18. return ((PNtQuerySystemInformation)g_jmpNtQuerySystemInformation)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
    19. }

    结束

    做完上面的准备工作,vmp3.6就能在虚拟机正常被调试了,这些都是某牛姓男子教的,我啥也不会!我是真菜啊!

  • 相关阅读:
    近期的一些小总结(关于TCP/IP协议相关的)
    Rancher清理节点
    python列表操作
    [附源码]java毕业设计ssm酒店综合管理平台
    视频通话中的Camera操作
    Pycharm配置Git以及Gitee实现代码管理(全网最详细)
    Spring依赖注入的简介说明
    深度学习——嵌入矩阵and学习词嵌入andWord2Vec
    高通导航器软件开发包使用指南(7)
    概率论的一些知识
  • 原文地址:https://blog.csdn.net/lyshark_lyshark/article/details/126792454