Hide your DebugPort in ring0

来源:互联网 发布:淘宝增加权重 编辑:程序博客网 时间:2024/06/01 13:05

标 题: 【原创】Hide your DebugPort in ring0
作 者: wowelf
时 间: 2009-01-26,11:00
链 接: http://bbs.pediy.com/showthread.php?t=80971

一个程序被ring3调试器调试时,有很多的调试特征可以检测,本论坛也有专门的帖子详细论述,但有个非常根本的标志ring3也是可以检测的比较少人提及,那就是_EPROCESS.DebugPort。DebugPort对于ring3调试器来说非常重要,没有它正常的ring3调试是无法进行的。当然要检测这个标志的前提是程序能够读取ring0内存,在XP以上的系统有个非常简单的方法就是使用ZwSystemDebugControl的SysDbgReadVirtualMemory方法,我们也可以map physicalmemory来操作。检测DebugPort之前首先要得到进程的eprocess地址,这可以通过ZwQuerySystemInformation的SystemHandleInformation方法得到,也可以直接搜索ring0内存的eprocess结构。

   对于ring3直接检测DebugPort,我们可以通过禁止该进程访问ring0内存来对付,但是目标一旦使用驱动来检测,那么就非常麻烦了。下面介绍一种隐藏_EPROCESS.DebugPort的方法,这种方法的基本思路是,将一个正常被调试进程的DebugPort置零后,修正所有受影响的函数,使我们的调试器能够正常进行。这些函数如下:
    PspCreateProcess、MmCreatePeb 进程创建,设置DebugPort
    DbgkCreateThread 发送线程或者进程创建的调试信息
    KiDispatchException、DbgkForwardException和DbgkpQueueMessage 发送异常调试信息
    PspExitThread、DbgkExitThread和DbgkExitProcess 发送线程退出、进程退出的调试信息
    DbgkMapViewOfSection和DbgkUnMapViewOfSection 发送映像装载卸载调试信息
    DbgkpSetProcessDebugObject和DbgkpMarkProcessPeb 当调试器附加进程时设置DebugPort   

     这类函数非常多的,如果都HOOK处理的话,那太恐怖了,这里使用一个非常简单的办法:偷龙转凤。我们看系统访问DebugPort的代码都是这样的(XP)
         8b89bc000000    mov     ecx,dword ptr [ecx+0BCh] //0BCh就是DebugPort的偏移

     我们可以把DebugPort转移到_EPROCESS的另外一个地方,比如我使用+0x070 CreateTime,它是纪录进程创建时间的,进程创建之后,在进程退出前系统不会对它进行任何修改,而且我们修改后对系统或进程没有任何影响。这样我们可以把上面的代码改成这样
         8b8970000000    mov     ecx,dword ptr [ecx+070h] //指向CreateTime,实际的DebugPort已经被移到这里
     只需要修改一个字节,非常简单。

     当然这种方法最麻烦的地方就是定位引用到DebugPort的函数(本人仅仅针对不同的XP系统制作特征码都累到吐血),这些函数都是不导出的,如果是特定系统,最简单的方法就是WinDbg->uf *** 直接找地址硬编码,只需要几分钟时间。
    

代码:
BOOLEAN InitHackAddress(){  _SEH_TRY  {    g_KernelBase = GetKernelBaseAndSize( &g_KernelSize );          g_HackPspCreateProcess = SearchHackPspCreateProcess( &g_NopPspCreateProcess.Address );    g_HackKiDispatchException = SearchKiDispatchException( g_KernelBase,g_KernelSize );      g_HackDbgkpQueueMessage = SearchDbgkpQueueMessage( g_KernelBase,g_KernelSize );    g_HackDbgkCreateThread = SearchDbgkCreateThread( g_KernelBase,g_KernelSize );        SearchDbgkNotifyRoutine( g_KernelBase,g_KernelSize );    g_HackPspExitThread = SearchPspExitThread();      g_HackMmCreatePeb = SearchMmCreatePeb( g_HackPspCreateProcess );    SearchDbgkpSetProcessDebugObject( g_KernelBase,g_KernelSize );    if( g_HackDbgkpSetProcessDebugObject[3] )      g_HackDbgkpMarkProcessPeb = SearchDbgkpMarkProcessPeb( g_HackDbgkpSetProcessDebugObject[3] ) ;        if( g_NopPspCreateProcess.Address != 0 ){      RtlFillMemory( g_NopPspCreateProcess.NopCode,sizeof(g_NopPspCreateProcess.NopCode),0x90 );       g_NopPspCreateProcess.Size = 9;      RtlCopyMemory( g_NopPspCreateProcess.OrigCode,(PVOID)g_NopPspCreateProcess.Address,g_NopPspCreateProcess.Size );    }    if( g_NopDbgkForwardException.Address != 0 ){            RtlFillMemory( g_NopDbgkForwardException.NopCode,sizeof(g_NopDbgkForwardException.NopCode),0x90 );      RtlCopyMemory( g_NopDbgkForwardException.OrigCode,(PVOID)g_NopDbgkForwardException.Address,g_NopDbgkForwardException.Size );    }    if( g_NopDbgkExitThread.Address != 0 ){            RtlFillMemory( g_NopDbgkExitThread.NopCode,sizeof(g_NopDbgkExitThread.NopCode),0x90 );      RtlCopyMemory( g_NopDbgkExitThread.OrigCode,(PVOID)g_NopDbgkExitThread.Address,g_NopDbgkExitThread.Size );    }    if( g_NopDbgkExitProcess.Address != 0 ){      RtlFillMemory( g_NopDbgkExitProcess.NopCode,sizeof(g_NopDbgkExitProcess.NopCode),0x90 );      RtlCopyMemory( g_NopDbgkExitProcess.OrigCode,(PVOID)g_NopDbgkExitProcess.Address,g_NopDbgkExitProcess.Size );    }    if( g_NopDbgkMapViewOfSection.Address != 0){      RtlFillMemory( g_NopDbgkMapViewOfSection.NopCode,sizeof(g_NopDbgkMapViewOfSection.NopCode),0x90 );      RtlCopyMemory( g_NopDbgkMapViewOfSection.OrigCode,(PVOID)g_NopDbgkMapViewOfSection.Address,g_NopDbgkMapViewOfSection.Size );    }    if( g_NopDbgkUnMapViewOfSection.Address != 0 ){      RtlFillMemory( g_NopDbgkUnMapViewOfSection.NopCode,sizeof(g_NopDbgkUnMapViewOfSection.NopCode),0x90 );      RtlCopyMemory( g_NopDbgkUnMapViewOfSection.OrigCode,(PVOID)g_NopDbgkUnMapViewOfSection.Address,g_NopDbgkUnMapViewOfSection.Size );    }               }  _SEH_HANDLER  {        DbgPrint( "InitHackAddress Exception!/n" );  }  return ( g_HackPspCreateProcess != 0 &&         g_HackKiDispatchException != 0 &&       g_HackDbgkForwardException != 0 &&       g_HackDbgkpQueueMessage != 0 &&        g_NopPspCreateProcess.Address != 0 &&       g_NopDbgkForwardException.Address != 0 &&       g_HackDbgkCreateThread != 0 &&       g_HackDbgkExitThread != 0 &&       g_NopDbgkExitThread.Address != 0 &&       g_HackDbgkExitProcess != 0 &&       g_NopDbgkExitProcess.Address != 0 &&       g_HackDbgkMapViewOfSection != 0 &&       g_NopDbgkMapViewOfSection.Address != 0 &&       g_HackDbgkUnMapViewOfSection != 0 &&       g_NopDbgkUnMapViewOfSection.Address != 0 &&       g_HackPspExitThread != 0 &&       g_HackMmCreatePeb != 0 &&       g_HackDbgkpSetProcessDebugObject[0] != 0 &&       g_HackDbgkpSetProcessDebugObject[1] != 0 &&       g_HackDbgkpSetProcessDebugObject[2] != 0 &&       g_HackDbgkpSetProcessDebugObject[3] != 0 &&       g_HackDbgkpMarkProcessPeb != 0 );}
代码:
//修改已经运行进程的DebugPort位置BOOLEAN ChangeProcessDebugPort( BOOLEAN Hide ){  ULONG eProcess = (ULONG)PsInitialSystemProcess;  PLIST_ENTRY pListHead,pListWalk;  ULONG DebugObject;  if( !g_bIsAddressStartup ){    return FALSE;  }  pListHead = (PLIST_ENTRY)( eProcess + ACTIVE_LINKS_OFFSET );  pListWalk = pListHead;  _SEH_TRY  {        do{      if( pListWalk == NULL || eProcess == 0 )        break;      eProcess = ( (ULONG)pListWalk - ACTIVE_LINKS_OFFSET );          if( Hide ){        DebugObject = *(ULONG*)( eProcess + DEBUG_PORT_OFFSET );        *(ULONG*)( eProcess + CREATE_TIME_OFFSET ) = DebugObject;        *(ULONG*)( eProcess + DEBUG_PORT_OFFSET ) = 0;      }else{        DebugObject = *(ULONG*)( eProcess + CREATE_TIME_OFFSET );        *(ULONG*)( eProcess + DEBUG_PORT_OFFSET ) = DebugObject;      }      pListWalk = pListWalk->Flink;    }while( pListWalk != pListHead );  }  _SEH_HANDLER  {    DbgPrint( "ChangeProcessDebugPort exception!/n" );  }    return TRUE;}
代码:
BOOLEAN ModifyDebugFunction(){  if( !g_bIsAddressStartup ){    return FALSE;  }  __asm{    cli    mov  eax,cr0    and  eax,not 10000h    mov  cr0,eax  }  *(ULONG*)g_HackPspCreateProcess = CREATE_TIME_OFFSET;  *(ULONG*)g_HackKiDispatchException = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkForwardException = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkpQueueMessage = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkCreateThread = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkExitThread = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkExitProcess = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkMapViewOfSection = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkUnMapViewOfSection = CREATE_TIME_OFFSET;  *(ULONG*)g_HackPspExitThread = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkpMarkProcessPeb = CREATE_TIME_OFFSET;  *(ULONG*)g_HackMmCreatePeb = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkpSetProcessDebugObject[0] = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkpSetProcessDebugObject[1] = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkpSetProcessDebugObject[2] = CREATE_TIME_OFFSET;  *(ULONG*)g_HackDbgkpSetProcessDebugObject[3] = CREATE_TIME_OFFSET;      RtlCopyMemory( (PVOID)g_NopPspCreateProcess.Address,g_NopPspCreateProcess.NopCode,g_NopPspCreateProcess.Size );  RtlCopyMemory( (PVOID)g_NopDbgkForwardException.Address,g_NopDbgkForwardException.NopCode,g_NopDbgkForwardException.Size );  RtlCopyMemory( (PVOID)g_NopDbgkExitThread.Address,g_NopDbgkExitThread.NopCode,g_NopDbgkExitThread.Size );  RtlCopyMemory( (PVOID)g_NopDbgkExitProcess.Address,g_NopDbgkExitProcess.NopCode,g_NopDbgkExitProcess.Size );  RtlCopyMemory( (PVOID)g_NopDbgkMapViewOfSection.Address,g_NopDbgkMapViewOfSection.NopCode,g_NopDbgkMapViewOfSection.Size );  RtlCopyMemory( (PVOID)g_NopDbgkUnMapViewOfSection.Address,g_NopDbgkUnMapViewOfSection.NopCode,g_NopDbgkUnMapViewOfSection.Size );  __asm{    mov  eax,cr0    or   eax,10000h    mov  cr0,eax    sti  }  return TRUE;}BOOLEAN WriteBackDebugFunction(){  if( !g_bIsAddressStartup ){    return FALSE;  }  __asm{    cli    mov  eax,cr0    and  eax,not 10000h    mov  cr0,eax  }  *(ULONG*)g_HackPspCreateProcess = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackKiDispatchException = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkForwardException = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkpQueueMessage = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkCreateThread = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkExitThread = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkExitProcess = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkMapViewOfSection = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkUnMapViewOfSection = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackPspExitThread = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkpMarkProcessPeb = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackMmCreatePeb = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkpSetProcessDebugObject[0] = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkpSetProcessDebugObject[1] = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkpSetProcessDebugObject[2] = DEBUG_PORT_OFFSET;  *(ULONG*)g_HackDbgkpSetProcessDebugObject[3] = DEBUG_PORT_OFFSET;  RtlCopyMemory( (PVOID)g_NopPspCreateProcess.Address,g_NopPspCreateProcess.OrigCode,g_NopPspCreateProcess.Size );  RtlCopyMemory( (PVOID)g_NopDbgkForwardException.Address,g_NopDbgkForwardException.OrigCode,g_NopDbgkForwardException.Size );  RtlCopyMemory( (PVOID)g_NopDbgkExitThread.Address,g_NopDbgkExitThread.OrigCode,g_NopDbgkExitThread.Size );  RtlCopyMemory( (PVOID)g_NopDbgkExitProcess.Address,g_NopDbgkExitProcess.OrigCode,g_NopDbgkExitProcess.Size );  RtlCopyMemory( (PVOID)g_NopDbgkMapViewOfSection.Address,g_NopDbgkMapViewOfSection.OrigCode,g_NopDbgkMapViewOfSection.Size );  RtlCopyMemory( (PVOID)g_NopDbgkUnMapViewOfSection.Address,g_NopDbgkUnMapViewOfSection.OrigCode,g_NopDbgkUnMapViewOfSection.Size );  __asm{    mov  eax,cr0    or   eax,10000h    mov  cr0,eax    sti  }  return TRUE;}
     我想再啰嗦一下,上面代码大家看到很多函数有个NOPCode,这个实际上是对付线程PS_CROSS_THREAD_FLAGS_HIDEFROMDBG的,NOP掉相关地方后,就算线程被设置为ThreadHideFromDebugger也无法阻挡调试器接收调试信息。

****************************************************************
祝大家牛年技术越来越牛,愿我等小菜在牛年可以望得见牛人项背!

原创粉丝点击