S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

[转] hook PsCreateSystemThread

Posted on 2009-09-17 21:59 S.l.e!ep.¢% 阅读(780) 评论(0)  编辑 收藏 引用 所属分类: Windows WDM

hook PsCreateSystemThread

很多RootKit在ring0下利用PsCreateSystemThread来创建系统线程做某些WS的事情,我们平时不利用ARK工具的话,是很难发现这些线程,在某些情况下,需要anti一些特定的rootkit,这里给出一个简单的示例:

.h:
#pragma once

#include 
<ntddk.h> 

typedef 
long LONG;
typedef unsigned 
char  BOOL, *PBOOL;
typedef unsigned 
char  BYTE, *PBYTE;
typedef unsigned 
long  DWORD, *PDWORD;
typedef unsigned 
short WORD, *PWORD;

typedef 
void  *HMODULE;
typedef 
long NTSTATUS, *PNTSTATUS;
typedef unsigned 
long DWORD;
typedef DWORD 
* PDWORD;
typedef unsigned 
long ULONG;
typedef unsigned 
long ULONG_PTR;
typedef ULONG 
*PULONG;
typedef unsigned 
short WORD;
typedef unsigned 
char BYTE; 
typedef unsigned 
char UCHAR;
typedef unsigned 
short USHORT;
typedef 
void *PVOID;
typedef BYTE BOOLEAN;
#define SEC_IMAGE    0x01000000

NTSTATUS
  PsLookupProcessByProcessId(
    IN HANDLE ProcessId,
    OUT PEPROCESS 
*Process
    );

.c:
#include "HookPsThread.h"
/******************************************************************************

    Hook PsCreateSystemThread
    out adress

*****************************************************************************
*/


//=============================================================================
//        Version Define
//=============================================================================
#define EPROCESS_SIZE            1
#define PEB_OFFSET                2   
#define FILE_NAME_OFFSET        3   
#define PROCESS_LINK_OFFSET     4   
#define PROCESS_ID_OFFSET       5 
#define EXIT_TIME_OFFSET        6 
//=============================================================================
//        Logic Define
//=============================================================================
ULONG PsCreateSystemThreadAddr = 0;
char PsCreateSystemThreadData[5= {0};

DWORD  ProcessNameOffset;

//-----------------------------------------------------------------------------
//        GetPlantformDependentInfo
//-----------------------------------------------------------------------------
DWORD GetPlantformDependentInfo( DWORD dwFlag )    
{     
    DWORD current_build;     
    DWORD ans 
= 0;     
   
    PsGetVersion(NULL, NULL, 
&current_build, NULL);     
   
    
switch ( dwFlag )    
    
{     
    
case EPROCESS_SIZE:     
        
if (current_build == 2195) ans = 0 ;        // 2000,当前不支持2000,下同    
        if (current_build == 2600) ans = 0x25C;     // xp    
        if (current_build == 3790) ans = 0x270;     // 2003    
        break;     
    
case PEB_OFFSET:     
        
if (current_build == 2195)  ans = 0;     
        
if (current_build == 2600)  ans = 0x1b0;     
        
if (current_build == 3790)  ans = 0x1a0;    
        
break;     
    
case FILE_NAME_OFFSET:     
        
if (current_build == 2195)  ans = 0;     
        
if (current_build == 2600)  ans = 0x174;     
        
if (current_build == 3790)  ans = 0x164;    
        
break;     
    
case PROCESS_LINK_OFFSET:     
        
if (current_build == 2195)  ans = 0;     
        
if (current_build == 2600)  ans = 0x088;     
        
if (current_build == 3790)  ans = 0x098;    
        
break;     
    
case PROCESS_ID_OFFSET:     
        
if (current_build == 2195)  ans = 0;     
        
if (current_build == 2600)  ans = 0x084;     
        
if (current_build == 3790)  ans = 0x094;    
        
break;     
    
case EXIT_TIME_OFFSET:     
        
if (current_build == 2195)  ans = 0;     
        
if (current_build == 2600)  ans = 0x078;     
        
if (current_build == 3790)  ans = 0x088;    
        
break;     
    }
     
    
return ans;     
}



//-----------------------------------------------------------------------------
//        GetFunctionAddr
//-----------------------------------------------------------------------------
ULONG GetFunctionAddr( IN PCWSTR FunctionName)
{
    UNICODE_STRING UniCodeFunctionName;
    RtlInitUnicodeString( 
&UniCodeFunctionName, FunctionName );
    
return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   
}


//-----------------------------------------------------------------------------
//        _PsCreateSystemThread
//-----------------------------------------------------------------------------
NTSTATUS _PsCreateSystemThread(IN PKSTART_ROUTINE  StartRoutine)
{
    ULONG RAddr 
= (ULONG)StartRoutine;  //Routine Address
    
//Get Process Info
    LPTSTR   CurProc;
    PEPROCESS EProcess;
    PsLookupProcessByProcessId(PsGetCurrentProcessId(), 
&EProcess);
    CurProc 
=(LPTSTR)EProcess;
    CurProc 
=CurProc+ProcessNameOffset;

    
if (strncmp((char*)CurProc,"System",6!= 0)
    
{
        DbgPrint(
"Current Process : %s, StartRoutine : %X\n", (char *)CurProc, StartRoutine);
    }

    
return 0;
}


//-----------------------------------------------------------------------------
//        MyPsCreateSystemThread
//-----------------------------------------------------------------------------
__declspec (naked)void MyPsCreateSystemThread()
{
    _asm
    
{
        pushad
        push [esp
+20h+18h]
        call _PsCreateSystemThread
        popad
        
        mov edi,edi
        push ebp
        mov ebp,esp
        jmp PsCreateSystemThreadAddr
    }

}


//-----------------------------------------------------------------------------
//        Install Hook
//-----------------------------------------------------------------------------
VOID InHook()
{
    PsCreateSystemThreadAddr 
= GetFunctionAddr(L"PsCreateSystemThread");

    __asm
    
{
        push    eax
        mov        eax, CR0
        and        eax, 0FFFEFFFFh
        mov        CR0, eax
        pop        eax
    }


    
//Save asmCode
    memcpy(PsCreateSystemThreadData, (PVOID)PsCreateSystemThreadAddr, 5);
    (ULONG)PsCreateSystemThreadAddr 
+= 5;

    
//Inline PsCreateSystemThread
    __asm
    
{
        mov esi, PsCreateSystemThreadAddr
        sub esi, 
5
        mov 
byte ptr[esi], 0xE9
        lea eax, [MyPsCreateSystemThread]
        sub eax, esi
        sub eax, 
5
        mov dword ptr [esi
+1],eax
    }


    __asm
    
{
        push    eax
        mov        eax, CR0
        or        eax, NOT 0FFFEFFFFh
        mov        CR0, eax
        pop        eax
    }


    DbgPrint(
"Hooked OK.\n");
    
return;
}


//-----------------------------------------------------------------------------
//        Uninstall Hook
//-----------------------------------------------------------------------------
VOID UnHook()
{
    __asm
    
{
        push    eax
        mov        eax, CR0
        and        eax, 0FFFEFFFFh
        mov        CR0, eax
        pop        eax
    }

    (ULONG)PsCreateSystemThreadAddr 
-= 5;
    memcpy((PVOID)PsCreateSystemThreadAddr, PsCreateSystemThreadData, 
5);
    __asm
    
{
        push    eax
        mov        eax, CR0
        or        eax, NOT 0FFFEFFFFh
        mov        CR0, eax
        pop        eax
    }

    DbgPrint(
"UnHook OK.\n");
    
return;
}


//-----------------------------------------------------------------------------
//        Driver UnLoad
//-----------------------------------------------------------------------------
void OnUnload(PDRIVER_OBJECT pDriverObj)
{
    UnHook();
    DbgPrint(
"UnLoading Driver");
}


//-----------------------------------------------------------------------------
//        Driver LoadEntry
//-----------------------------------------------------------------------------
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
    pDriverObj
->DriverUnload = OnUnload;

    DbgPrint(
"Loading Driver");
    ProcessNameOffset 
= GetPlantformDependentInfo(FILE_NAME_OFFSET);
    InHook();
    
return STATUS_SUCCESS;
}
很多RootKit在ring0下利用PsCreateSystemThread来创建系统线程做某些WS的事情,我们平时不利用ARK工具的话,是很难发现这些线程,在某些情况下,需要anti一些特定的rootkit,这里给出一个简单的示例:

.h:
#pragma once

#include 
<ntddk.h> 

typedef 
long LONG;
typedef unsigned 
char  BOOL, *PBOOL;
typedef unsigned 
char  BYTE, *PBYTE;
typedef unsigned 
long  DWORD, *PDWORD;
typedef unsigned 
short WORD, *PWORD;

typedef 
void  *HMODULE;
typedef 
long NTSTATUS, *PNTSTATUS;
typedef unsigned 
long DWORD;
typedef DWORD 
* PDWORD;
typedef unsigned 
long ULONG;
typedef unsigned 
long ULONG_PTR;
typedef ULONG 
*PULONG;
typedef unsigned 
short WORD;
typedef unsigned 
char BYTE; 
typedef unsigned 
char UCHAR;
typedef unsigned 
short USHORT;
typedef 
void *PVOID;
typedef BYTE BOOLEAN;
#define SEC_IMAGE    0x01000000

NTSTATUS
  PsLookupProcessByProcessId(
    IN HANDLE ProcessId,
    OUT PEPROCESS 
*Process
    );

.c:
#include "HookPsThread.h"
/******************************************************************************

    Hook PsCreateSystemThread
    out adress

*****************************************************************************
*/


//=============================================================================
//        Version Define
//=============================================================================
#define EPROCESS_SIZE            1
#define PEB_OFFSET                2   
#define FILE_NAME_OFFSET        3   
#define PROCESS_LINK_OFFSET     4   
#define PROCESS_ID_OFFSET       5 
#define EXIT_TIME_OFFSET        6 
//=============================================================================
//        Logic Define
//=============================================================================
ULONG PsCreateSystemThreadAddr = 0;
char PsCreateSystemThreadData[5= {0};

DWORD  ProcessNameOffset;

//-----------------------------------------------------------------------------
//        GetPlantformDependentInfo
//-----------------------------------------------------------------------------
DWORD GetPlantformDependentInfo( DWORD dwFlag )    
{     
    DWORD current_build;     
    DWORD ans 
= 0;     
   
    PsGetVersion(NULL, NULL, 
&current_build, NULL);     
   
    
switch ( dwFlag )    
    
{     
    
case EPROCESS_SIZE:     
        
if (current_build == 2195) ans = 0 ;        // 2000,当前不支持2000,下同    
        if (current_build == 2600) ans = 0x25C;     // xp    
        if (current_build == 3790) ans = 0x270;     // 2003    
        break;     
    
case PEB_OFFSET:     
        
if (current_build == 2195)  ans = 0;     
        
if (current_build == 2600)  ans = 0x1b0;     
        
if (current_build == 3790)  ans = 0x1a0;    
        
break;     
    
case FILE_NAME_OFFSET:     
        
if (current_build == 2195)  ans = 0;     
        
if (current_build == 2600)  ans = 0x174;     
        
if (current_build == 3790)  ans = 0x164;    
        
break;     
    
case PROCESS_LINK_OFFSET:     
        
if (current_build == 2195)  ans = 0;     
        
if (current_build == 2600)  ans = 0x088;     
        
if (current_build == 3790)  ans = 0x098;    
        
break;     
    
case PROCESS_ID_OFFSET:     
        
if (current_build == 2195)  ans = 0;     
        
if (current_build == 2600)  ans = 0x084;     
        
if (current_build == 3790)  ans = 0x094;    
        
break;     
    
case EXIT_TIME_OFFSET:     
        
if (current_build == 2195)  ans = 0;     
        
if (current_build == 2600)  ans = 0x078;     
        
if (current_build == 3790)  ans = 0x088;    
        
break;     
    }
     
    
return ans;     
}



//-----------------------------------------------------------------------------
//        GetFunctionAddr
//-----------------------------------------------------------------------------
ULONG GetFunctionAddr( IN PCWSTR FunctionName)
{
    UNICODE_STRING UniCodeFunctionName;
    RtlInitUnicodeString( 
&UniCodeFunctionName, FunctionName );
    
return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   
}


//-----------------------------------------------------------------------------
//        _PsCreateSystemThread
//-----------------------------------------------------------------------------
NTSTATUS _PsCreateSystemThread(IN PKSTART_ROUTINE  StartRoutine)
{
    ULONG RAddr 
= (ULONG)StartRoutine;  //Routine Address
    
//Get Process Info
    LPTSTR   CurProc;
    PEPROCESS EProcess;
    PsLookupProcessByProcessId(PsGetCurrentProcessId(), 
&EProcess);
    CurProc 
=(LPTSTR)EProcess;
    CurProc 
=CurProc+ProcessNameOffset;

    
if (strncmp((char*)CurProc,"System",6!= 0)
    
{
        DbgPrint(
"Current Process : %s, StartRoutine : %X\n", (char *)CurProc, StartRoutine);
    }

    
return 0;
}


//-----------------------------------------------------------------------------
//        MyPsCreateSystemThread
//-----------------------------------------------------------------------------
__declspec (naked)void MyPsCreateSystemThread()
{
    _asm
    
{
        pushad
        push [esp
+20h+18h]
        call _PsCreateSystemThread
        popad
        
        mov edi,edi
        push ebp
        mov ebp,esp
        jmp PsCreateSystemThreadAddr
    }

}


//-----------------------------------------------------------------------------
//        Install Hook
//-----------------------------------------------------------------------------
VOID InHook()
{
    PsCreateSystemThreadAddr 
= GetFunctionAddr(L"PsCreateSystemThread");

    __asm
    
{
        push    eax
        mov        eax, CR0
        and        eax, 0FFFEFFFFh
        mov        CR0, eax
        pop        eax
    }


    
//Save asmCode
    memcpy(PsCreateSystemThreadData, (PVOID)PsCreateSystemThreadAddr, 5);
    (ULONG)PsCreateSystemThreadAddr 
+= 5;

    
//Inline PsCreateSystemThread
    __asm
    
{
        mov esi, PsCreateSystemThreadAddr
        sub esi, 
5
        mov 
byte ptr[esi], 0xE9
        lea eax, [MyPsCreateSystemThread]
        sub eax, esi
        sub eax, 
5
        mov dword ptr [esi
+1],eax
    }


    __asm
    
{
        push    eax
        mov        eax, CR0
        or        eax, NOT 0FFFEFFFFh
        mov        CR0, eax
        pop        eax
    }


    DbgPrint(
"Hooked OK.\n");
    
return;
}


//-----------------------------------------------------------------------------
//        Uninstall Hook
//-----------------------------------------------------------------------------
VOID UnHook()
{
    __asm
    
{
        push    eax
        mov        eax, CR0
        and        eax, 0FFFEFFFFh
        mov        CR0, eax
        pop        eax
    }

    (ULONG)PsCreateSystemThreadAddr 
-= 5;
    memcpy((PVOID)PsCreateSystemThreadAddr, PsCreateSystemThreadData, 
5);
    __asm
    
{
        push    eax
        mov        eax, CR0
        or        eax, NOT 0FFFEFFFFh
        mov        CR0, eax
        pop        eax
    }

    DbgPrint(
"UnHook OK.\n");
    
return;
}


//-----------------------------------------------------------------------------
//        Driver UnLoad
//-----------------------------------------------------------------------------
void OnUnload(PDRIVER_OBJECT pDriverObj)
{
    UnHook();
    DbgPrint(
"UnLoading Driver");
}


//-----------------------------------------------------------------------------
//        Driver LoadEntry
//-----------------------------------------------------------------------------
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
    pDriverObj
->DriverUnload = OnUnload;

    DbgPrint(
"Loading Driver");
    ProcessNameOffset 
= GetPlantformDependentInfo(FILE_NAME_OFFSET);
    InHook();
    
return STATUS_SUCCESS;
}

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理