背景
看雪上有人泄露了3.6.0.1406,第一时间先下载下来,然后加壳之后扔进x32dbg,A debugger has been found.......
还能怎么办?右键回收站。
分析
正准备放弃的时候,想了想要不在看看,好吧那就在看看,结果一段瞎分析之后定位到了scylla没有处理完善的函数NtQueryInformationThread和QueryInformationProcess
HookNtQueryInformationThread ThreadHideFromDebugger
HookNtQueryInformationProcess ProcessDebugPort
HookNtQueryInformationProcess ProcessDebugObjectHandle
HookNtQueryInformationProcess ProcessDebugPort
你问我怎么定位的,全是某牛姓男子给我说的,还有需要注意的是这些api下执行是不会断下的,因为它自己shadow了一份systemcall。
R3的反调试,在scylla配置如下的情况下,添加下面的代码(不管你是inline,vt,ifhook都可以,反正蓝的也不是我的电脑)
在内核的处理逻辑如下(都是最简单的返回,有的情况下返回是错误的)
NTSTATUS HookNtQueryInformationProcess(
HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength
) {
UCHAR* fileName = PsGetProcessImageFileName(PsGetCurrentProcess());
if (memcmp((const char*)fileName, "SuperKiller",strlen("SuperKiller")) == 0 && ExGetPreviousMode() == UserMode)//最新的3.6
{
if (ProcessInformationLength != 0)
{
__try
{
ProbeForRead(ProcessInformation, ProcessInformationLength, 4);
if (ReturnLength != 0)
ProbeForWrite(ReturnLength, 4, 1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
if (ProcessInformationClass == ProcessDebugObjectHandle)
{
DbgPrint("HookNtQueryInformationProcess ProcessDebugObjectHandle \n");
PEPROCESS TargetProcess;
NTSTATUS Status = ObReferenceObjectByHandle(ProcessHandle, 0x0400, *PsProcessType, UserMode, (PVOID*)& TargetProcess, NULL);
if (NT_SUCCESS(Status) == TRUE)
{
__try
{
*(ULONG64*)ProcessInformation = NULL;
if (ReturnLength != NULL)* ReturnLength = sizeof(ULONG64);
Status = STATUS_PORT_NOT_SET;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = GetExceptionCode();
}
ObDereferenceObject(TargetProcess);
return Status;
}
return Status;
}
else if (ProcessInformationClass == ProcessDebugPort)
{
DbgPrint("HookNtQueryInformationProcess ProcessDebugPort \n");
if (ProcessInformationLength != sizeof(ULONG64))
return STATUS_INFO_LENGTH_MISMATCH;
PEPROCESS TargetProcess;
NTSTATUS Status = ObReferenceObjectByHandle(ProcessHandle, 0x0400, *PsProcessType, UserMode, (PVOID*)& TargetProcess, NULL);
if (NT_SUCCESS(Status) == TRUE)
{
__try
{
*(ULONG64*)ProcessInformation = 0;
if (ReturnLength != 0)
* ReturnLength = sizeof(ULONG64);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = GetExceptionCode();
}
ObDereferenceObject(TargetProcess);
return Status;
}
return Status;
}
else if (ProcessInformationClass == ProcessDebugFlags)
{
DbgPrint("HookNtQueryInformationProcess ProcessDebugFlags \n");
if (ProcessInformationLength != 4)
return STATUS_INFO_LENGTH_MISMATCH;
PEPROCESS TargetProcess;
NTSTATUS Status = ObReferenceObjectByHandle(ProcessHandle, 0x0400, *PsProcessType, UserMode, (PVOID*)& TargetProcess, NULL);
if (NT_SUCCESS(Status) == TRUE)
{
__try
{
*(ULONG*)ProcessInformation = 0;
if (ReturnLength != 0)
* ReturnLength = sizeof(ULONG);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = GetExceptionCode();
}
ObDereferenceObject(TargetProcess);
return Status;
}
return Status;
}
else if (ProcessInformationClass == ProcessBreakOnTermination)
{
DbgPrint("HookNtQueryInformationProcess ProcessBreakOnTermination \n");
if (ProcessInformationLength != 4)
return STATUS_INFO_LENGTH_MISMATCH;
PEPROCESS TargetProcess;
NTSTATUS Status = ObReferenceObjectByHandle(ProcessHandle, 0x1000, *PsProcessType, UserMode, (PVOID*)& TargetProcess, NULL);
if (NT_SUCCESS(Status) == TRUE)
{
__try
{
*(ULONG*)ProcessInformation = 0;
if (ReturnLength != 0)
* ReturnLength = sizeof(ULONG);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = GetExceptionCode();
}
ObDereferenceObject(TargetProcess);
return Status;
}
return Status;
}
}
return ((PNtQueryInformationProcess)g_jmpNtQueryInformationProcess)(ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength);
}
NTSTATUS HookNtQueryInformationThread(
HANDLE ThreadHandle,
THREADINFOCLASS ThreadInformationClass,
PVOID ThreadInformation,
ULONG ThreadInformationLength,
PULONG ReturnLength
) {
UCHAR* fileName = PsGetProcessImageFileName(PsGetCurrentProcess());
if (memcmp((const char*)fileName, "SuperKiller", strlen("SuperKiller")) == 0 && ExGetPreviousMode() == UserMode)//最新的3.6
{
if (ThreadInformationLength != 0)
{
__try
{
ProbeForRead(ThreadInformation, ThreadInformationLength, 4);
if (ReturnLength != 0)
ProbeForWrite(ReturnLength, 4, 1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
if (ThreadInformationClass == ThreadHideFromDebugger)
{
DbgPrint("HookNtQueryInformationThread ThreadHideFromDebugger \n");
if (ThreadInformationLength != 1)
return STATUS_INFO_LENGTH_MISMATCH;
PETHREAD TargetThread;
NTSTATUS Status = ObReferenceObjectByHandle(ThreadHandle, 0x40, *PsThreadType, UserMode, (PVOID*)& TargetThread, NULL);
if (NT_SUCCESS(Status) == TRUE)
{
__try
{
*(BOOLEAN*)ThreadInformation =0;
if (ReturnLength != 0)* ReturnLength = 1;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = GetExceptionCode();
}
ObDereferenceObject(TargetThread);
return Status;
}
return Status;
}
}
return ((PNtQueryInformationThread)g_jmpNtQueryInformationThread)(ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength, ReturnLength);
}
R0的反调试,都是直接返回失败
NTSTATUS HookNtQuerySystemInformation(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
) {
if(SystemInformationClass == SystemKernelDebuggerInformation || SystemInformationClass == SystemKernelDebuggerInformationEx || SystemCodeIntegrityInformation == SystemInformationClass || ProcessDebugObjectHandle == SystemInformationClass)
return STATUS_UNSUCCESSFUL;
return ((PNtQuerySystemInformation)g_jmpNtQuerySystemInformation)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
}
反虚拟机
1、需要处理的是cpuid,代码是抄的别人写的vt,随便改改
Registers->Rcx = (ULONG_PTR)dwCpuidRegisters.ecx & 0xFFFFFFFF7FFFFFFF;//绕过vmp的虚拟机检测
2、需要注意中断,如果用的vthook,需要判断当前的tf标志位
if (GuestRflag.fields.tf)
{
ULONG64 info = 0;
// 注入一个硬件调试中断
InjectInterruption(kHardwareException, EXCEPTION_VECTOR_DEBUG, false, 0);
info = VmxCsRead(GUEST_INTERRUPTIBILITY_INFO);
info &= ~2;
VmxCsWrite(GUEST_INTERRUPTIBILITY_INFO, info);
}
3、NtQuerySystemInformation的处理,比3.5多了一个BMSR
NTSTATUS HookNtQuerySystemInformation(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
) {
if (SystemInformationClass == SystemFirmwareTableInformation && SystemInformation)
{
__try
{
if (*(PULONG)SystemInformation == 0x4649524d || *(PULONG)SystemInformation == 0x52534d42)//MRIF BMSR
{
return STATUS_UNSUCCESSFUL;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {}
}
return ((PNtQuerySystemInformation)g_jmpNtQuerySystemInformation)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
}
结束
做完上面的准备工作,vmp3.6就能在虚拟机正常被调试了,这些都是某牛姓男子教的,我啥也不会!我是真菜啊!