首页
社区
课程
招聘
[分享]x64 antidebug 不触发PG
发表于: 2015-8-5 12:13 10465

[分享]x64 antidebug 不触发PG

2015-8-5 12:13
10465
不说啥= =  语文不好 直接放码
.H
#include <ntddk.h>

typedef struct _SYSTEM_SERVICE_TABLE{
        PVOID ServiceTableBase;
        PVOID ServiceCounterTableBase;
        SIZE_T NumberOfServices;
        PVOID ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
typedef NTSTATUS(__fastcall * pfnEnumObjectTable)(PVOID64 HANDLETABLE, PVOID CALLback, ULONG64 unKonw);
typedef BOOLEAN(__fastcall *ENUMPROCESSCALLBACK)(ULONG64 EPROCESS);
typedef struct _SERVICE_DESCRIPTOR_TABLE{
        SYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe (native api)
        SYSTEM_SERVICE_TABLE win32k; // win32k.sys (gdi/user)
        SYSTEM_SERVICE_TABLE Table3; // not used
        SYSTEM_SERVICE_TABLE Table4; // not used
} SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;
typedef struct _KAPC_STATE
{
        LIST_ENTRY ApcListHead[2];
        PVOID Process;
        BOOLEAN KernelApcInProgress;
        BOOLEAN KernelApcPending;
        BOOLEAN UserApcPending;
}KAPC_STATE, *PKAPC_STATE;

typedef struct _OBJECT_HANDLE_FLAG_INFORMATION{
        BOOLEAN Inherit;
        BOOLEAN ProtectFromClose;
}OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION;
NTKERNELAPI CHAR* PsGetProcessImageFileName(PEPROCESS Process);
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process);
NTKERNELAPI NTSTATUS PsLookupThreadByThreadId(HANDLE Id, PETHREAD *Thread);
NTKERNELAPI PEPROCESS IoThreadToProcess(PETHREAD Thread);
NTKERNELAPI NTSTATUS ObSetHandleAttributes(HANDLE Handle, POBJECT_HANDLE_FLAG_INFORMATION HandleFlags, KPROCESSOR_MODE PreviousMode);
NTKERNELAPI VOID KeStackAttachProcess(PEPROCESS PROCESS, PKAPC_STATE ApcState);
NTKERNELAPI VOID KeUnstackDetachProcess(PKAPC_STATE ApcState);
typedef struct _HANDLE_TABLE_ENTRY{
        union{
                PVOID64 Object;
                ULONG32 ObAttributes;
                PVOID64 InfoTable;
                ULONG64 Value;

        };

        union{

                ULONG32 GrantedAccess;
                struct{

                        UINT8  GrantedAccessIndex;
                        UINT8 CreatorBackTraceIndex;

                };
                ULONG32        NextFreeTableEntry;
        };

}HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;

ULONGLONG GetKeServiceDescriptorTable64()
{
        char KiSystemServiceStart_pattern[13] = "\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x25\xFF\x0F\x00\x00";
        ULONGLONG CodeScanStart = (ULONGLONG)&_strnicmp;
        ULONGLONG CodeScanEnd = (ULONGLONG)&KdDebuggerNotPresent;
        UNICODE_STRING Symbol;
        ULONGLONG i, tbl_address, b;
        for (i = 0; i < CodeScanEnd - CodeScanStart; i++)
        {
                if (!memcmp((char*)(ULONGLONG)CodeScanStart + i, (char*)KiSystemServiceStart_pattern, 13))
                {
                        for (b = 0; b < 50; b++)
                        {
                                tbl_address = ((ULONGLONG)CodeScanStart + i + b);
                                if (*(USHORT*)((ULONGLONG)tbl_address) == (USHORT)0x8d4c)
                                        return ((LONGLONG)tbl_address + 7) + *(LONG*)(tbl_address + 3);
                        }
                }
        }
        return 0;
}
ULONGLONG GetSSDTFuncCurAddr(ULONG id, PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable)
{
        LONG dwtmp = 0;
        PULONG ServiceTableBase = NULL;
        ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
        dwtmp = ServiceTableBase[id];
        dwtmp = dwtmp >> 4;
        return dwtmp + (ULONGLONG)ServiceTableBase;
}
ULONG GetOffsetAddress(ULONGLONG FuncAddr, PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable)
{
        LONG dwtmp = 0;
        PULONG ServiceTableBase = NULL;
        ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;
        dwtmp = (LONG)(FuncAddr - (ULONGLONG)ServiceTableBase);

        return dwtmp << 4;
}

SRC
#include <ntddk.h>
#include<struct.h>

pfnEnumObjectTable EnumObjectTable;
ULONG64 targetprocess;
ULONG64 targetDebugprocess;
ULONG64 Targethandle;

ULONG64 SreachFunctionAddress(ULONG64 uAddress, UCHAR *Signature)
{
        ULONG64        index;
        UCHAR        *p;
        ULONG64        uRetAddress;

        if (uAddress == 0){ return 0; }

        p = (UCHAR*)uAddress;
        for (index = 0; index<0x3000; index++)
        {
                if (*p == Signature[0] &&
                        *(p + 1) == Signature[1] &&
                        *(p + 2) == Signature[2] &&
                        *(p + 3) == Signature[3] &&
                        *(p + 4) == Signature[4])
                {

                        uRetAddress = p + 4;
                        uRetAddress = *(ULONG*)(uRetAddress + 1) + uRetAddress + 5;
                        return uRetAddress;
                }
                p++;
#if defined(_DEBUG)
                DbgPrint("++ %p ", p);
#endif
        }
        return 0;
}

//用于搜索进程 编码仅限于win7X64
ULONG64 Search64Process(char *szProcessName, ULONG64 callBackFUNC)
{
        ULONG64 pEprocess, LastProcess;
        ULONG64 Current_Pid;
        ULONG64 Start_Pid;
        int          index;
        PLIST_ENTRY64 pList_Active_Process;

        if (!MmIsAddressValid(szProcessName))
                return 0;

        index = 0;

        pEprocess = (ULONG64)PsGetCurrentProcess();
        Start_Pid = *(ULONG64*)(pEprocess + 0x180);
        Current_Pid = Start_Pid;

        while (TRUE)
        {
                LastProcess = pEprocess;
                pList_Active_Process = (PLIST_ENTRY)(pEprocess + 0x188);
                pEprocess = (ULONG64)pList_Active_Process->Flink;
                pEprocess = pEprocess - 0x188;
                Current_Pid = *(ULONG64*)(pEprocess + 0x180);
                if (MmIsAddressValid(callBackFUNC) && callBackFUNC != 0){
                        ((ENUMPROCESSCALLBACK)callBackFUNC)(LastProcess);

                }
                if ((Current_Pid == Start_Pid) && index>0)
                {
                        return 0;
                }
                else if (strstr((char*)LastProcess + 0x2e0, szProcessName) != 0)
                {

                        return LastProcess;
                }
                index++;
        }
        return 0;
}
VOID __fastcall ForceCloseHandle(PEPROCESS Process, ULONG64 HandleValue)
{
        HANDLE h;
        KAPC_STATE ks;
        OBJECT_HANDLE_FLAG_INFORMATION ohfi;
        if (Process == NULL)
                return;
        if (!MmIsAddressValid(Process))
                return;
        KeStackAttachProcess(Process, &ks);
        h = (HANDLE)HandleValue;
        ohfi.Inherit = 0;
        ohfi.ProtectFromClose = 0;
        ObSetHandleAttributes(h, &ohfi, KernelMode);
        ZwClose(h);
        KeUnstackDetachProcess(&ks);
}
BOOLEAN __fastcall enumObjectCallBack(PHANDLE_TABLE_ENTRY object, PHANDLE handle, ULONG64 Unkonw){

        ULONG32 debugobject;
        debugobject = (ULONG32)*(UINT8*)((ULONG64)(object->Object) + 0x18);
#if defined(_DEBUG)
        DbgPrint("type :%d", debugobject);
#endif
       

        if (debugobject == 0xb)
        {
#if defined(_DEBUG)
                DbgPrint("~ Targetprocess :%p ,ProcessName: %s", targetprocess, PsGetProcessImageFileName(targetprocess));
#endif
               
                targetDebugprocess = targetprocess;
                Targethandle = handle;
               
        }

        return FALSE;

}

ENUMPROCESSCALLBACK ex_ENUMPROCESSCALLBACK(ULONG64 EPROCESS){
        ULONG64 temp64;
       
        if (MmIsAddressValid(EPROCESS)){
                targetprocess = EPROCESS;

                temp64 = *(ULONG64*)((ULONG64)EPROCESS + 0x200);
                if (MmIsAddressValid(temp64)){

                        EnumObjectTable(temp64, enumObjectCallBack, 1);

                }

        }

}
void DriverUnload(PDRIVER_OBJECT pDriverObject)
{

        __asm{xor eax,eax}
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pReg)
{        UCHAR  opcode[5] = { 0x89, 0x6c, 0x24, 0x30, 0xe8 };
NTSTATUS state = STATUS_SUCCESS;
UNICODE_STRING64 ObFindHandleForObjectsign;
PSYSTEM_SERVICE_TABLE systable;
ULONG64 temp64 = 0;
DbgPrint("Super game protect loading~\n");
pDriverObject->DriverUnload = DriverUnload;
RtlInitUnicodeString(&ObFindHandleForObjectsign, L"ObFindHandleForObject");//ObFindHandleForObject PAGE 0000000140319DB0 000000B4 00000048 00000028 R . . . . . .
temp64 = (ULONG64)MmGetSystemRoutineAddress(&ObFindHandleForObjectsign);

if (!MmIsAddressValid(temp64))
return state;
EnumObjectTable = (pfnEnumObjectTable)SreachFunctionAddress(temp64, opcode);
if (!MmIsAddressValid(EnumObjectTable))
return state;
DbgPrint("Super game protect start~\n");
Search64Process("xxxaaass.exe", ex_ENUMPROCESSCALLBACK);
ForceCloseHandle(targetDebugprocess, Targethandle);
systable=GetKeServiceDescriptorTable64();
DbgPrint("NTSuspendProcess address : %p\n", GetSSDTFuncCurAddr(378, systable));
return state;
}

enumprocesshandle ==debugobject    xxxxx

下面是 KIUSER

__declspec(naked)void KiUserExceptionDispatcher(){

                __asm{
                        cld
                                push[esp + 4]
                                push[esp]
                               
                                call KiUserExceptionDispatcher_BT
                       
       
                               

                }

}

DWORD dwoldKiuserExceptionDispatcher = NULL;

__declspec(naked)void KiUserExceptionDispatcher_asm(){
        __asm{

               
                        cld
                                pushfd
                                push ecx

                        mov ecx, [esp + 0xc]
                        mov pc, ecx
                        pop ecx
                        popfd

                        pushfd
                        push ebx
                        mov ebx, [esp+0x8]
                        mov px, ebx
                pop ebx
                popfd
                       
        }
       

        pc->Dr0 = 0;
        pc->Dr1 = 0;
        pc->Dr2 = 0;
        pc->Dr3 = 0;
        pc->Dr7 = 0;

        __asm{
                pushfd
                        pushad
        }
       

                __asm{
               
mov edx, dword ptr[px]
mov edx, dword ptr[edx+0xc]
mov ebx, dword ptr[dllsize]
add ebx, dword ptr[dllbase]

cmp dword ptr[dllbase],edx
ja xxxx
cmp ebx, edx
jb xxxx

popad
popfd
       
               
                        __asm        jmp dword ptr[dwoldKiuserExceptionDispatcher]
        }

       
        __asm{

                xxxx:
                popad
                        popfd

                cld
                        mov ecx, [esp + 4]
                        mov ebx, [esp]
                        mov px, ebx
                        push ecx
                        push ebx
                        call PfnCall97B
                        or al,al
                        jz loc_53
                        pop ebx
                        pop ecx
                        push 0
                        push ecx
                        call NtContinue
                loc_53:
                pop ebx
                        pop ecx
                        push 0
                        push ecx
                        push ebx
                        call NtRaiseException
                        add     esp, 0FFFFFFECh
                        mov[esp],eax
                        mov[esp+4],1
                        mov[esp+8],ebx
                        mov[esp+10],0
                        push    esp; ExceptionRecord
                        call    dwRtlRaiseException
                        ret 8
                        lea ecx, [ecx+0]

        }

}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (15)
雪    币: 101
活跃值: (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感觉 antiantidebug 直接禁用PG 会更方便...

如过可以 HOOK ring0->ring3 调用 kiuserdispatcherException 时把地址改到自己的
kiuserdispatcherException 处理代码
代码中判断不是调试器产生的异常就跳回原始的 kiuserdispatcherException
这样就不会被 ring3 的代码校验发现
2015-8-5 12:57
0
雪    币: 719
活跃值: (777)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
3
int 1的陷阱帧 的EIP设置为kiuser....而已改了就是
(所以没返回地址)
2015-8-5 13:02
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
怎么确定是调试器产生的异常呢?
2015-8-5 15:58
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
据我所知,调试异常发生后,就直接被调试端口接管了,并不会走kiuserdispatcherException吧?
2015-8-5 16:01
0
雪    币: 62
活跃值: (971)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
至少OD下的断点在第一轮就被处理了,根本轮不到kiuserdispatcherException
2015-8-5 16:08
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
不管是Hook还是反Hook kiuserdispatcherException
然并卵
2015-8-5 16:15
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
我来纠正一下,只要一个进程存在调试端口,不管是WinDbg,OD,CE...还是别的什么调试器
调试异常只会走调试端口,int 3也好,硬断执行或读写访问也罢,压根儿不会执行到KiUserExceptionDispatcher里面去
进程自身的SEH和VEH才会进KiUserExceptionDispatcher,例如try语句块之类的...
很多同学都容易陷入这个误区,就以为KiUserExceptionDispatcher可以拦截到调试行为
再别误导人了,拜托
2015-8-5 18:39
0
雪    币: 719
活跃值: (777)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
9
= =你说到哪里去了,这个只是防止在里面取出context中的dr0-dr7来检测硬件断点~~~~ 和调试流程都扯上关系了
2015-8-5 18:53
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
清除dr0-dr7即可
2015-8-5 21:41
0
雪    币: 70
活跃值: (72)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
到底是 antiDebug 还是 antiantiDebug 呢?
2015-8-5 22:33
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
LZ的意思是,既可以检测硬件断点,也可以反检测硬件断点,至于方法嘛,这可就千变万化了
2015-8-5 23:25
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
LZ技术好,但语文水平看起来有点费劲。。。
2015-8-6 11:27
0
雪    币: 35
活跃值: (627)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
我只想知道 楼主说的代码 那么多天过去了 还是没看到 = =!

也没看懂楼主的意思。不少专业俗语滴 。

KiUserExceptionDispatcher 可以获取线程dr寄存器值  但调试器的异常都ret完了 轮不到KiUserExcepti执行了

硬件占坑。对方肯定也用线程来实现的 自己不可能主线程实现吧 不然不卡死了。

OD硬件断是对目标进程线程枚举全部出来吧 然后一个一个SetThreadContext .

如果我们自己做的硬件断 只对主线程 SetThreadContext  是不是就没触碰到 占坑线程了
2015-8-15 21:29
0
雪    币: 719
活跃值: (777)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
15
不说啥了 直接码
2015-8-26 21:04
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
擦除句柄表都用上了呢
2015-8-26 22:37
0
游客
登录 | 注册 方可回帖
返回
//