天天看點

隐藏技術之程序僞裝

// 簡單的程序僞裝就是修改程序名稱,比如svchost.exe、services.exe等系統程序。
// 進階的程序僞裝就是修改程序的PEB資料,也就是在任務管理器中看到的程序的名稱、啟動路徑等資訊。

// NtQueryInformationProcess函數
// 作用:擷取指定程序的資訊。
// 原型:NSTATUS WINAPI NtQueryInformationProcess(
//        _In_ HANLDE hProcess;
//        _In_ PROCESSINFOCLASS ProcessInformationClass,
//        _Out_ PVOID ProcesInformation,
//        _In_ ULONG ProcessInformationLength,
//        _Out_opt_ PULONG ReturnLength      
//      )
// 參數:hProcess:程序句柄,由OpenProcess函數擷取。
//       ProcessInformationClass:程序資訊的類型,為以下枚舉值之一:
//          ProcessBasicInformation:檢索指向PEB結構的指針。
//          ProcessDebugPort:擷取作為程序調試器端口号的DWORD_PTR值。
//          ProcessWow64Information:确定程序是否在Wow64環境中運作。
//          ProcessImageFileName:檢索包含該程序映像檔案名稱的UNICODE_STRING值。
//          ProcessBreakOnTermination:檢索訓示程序是否被視為關鍵的ULONG值。
//          ProcessSubsystemInformation:檢索訓示程序子系統類别的SUBSYSTEM_INFORMATION_TYPE值。
//       ProcessInformation:接收值,
//       ProcessInformationLength:指定接收資料緩沖區的大小。
//       ReturnLength:接收傳回所請求資訊的大小。
// 結果:傳回一個NTSTATUS成功或錯誤代碼。

// PROCESS_BASIC_INFORMATION結構體
// 定義: typedef struct _PROCESS_BASIC_INFORMATION {
//           PVOID Reserved1;
//           PPEB PebBaseAddress,
//           PVOID Reserved2[2];
//           ULONG_PTR UniqueProcessId;
//           PVOID Reserved3;
//        } PROCESS_BASIC_INFORMATION;
// 參數:PebBaseAddress成員指向PEB結構。

// 實作原理:就是修改指定程序環境塊(PEB)中的程序路徑以及指令行資訊,進而達到程序僞裝的效果。

// PS:NtQueryInformationProcess這個函數不是公開的,需要從ntdll.dll中擷取函數位址。

// 示例代碼:

BOOL DisguiseProcess(DWORD dwProcessId, wchar_t* lpwszPath, wchar_t* lpwszCmd)
{
    // 打開程序,擷取程序句柄
    HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    if (NLL == hProcess)
    {
        ShowError("OpenProcess");
        return FALSE;
    }

    typedef_NtQueryInformationProcess NtQueryInformationProcess = NULL;
    PROCESS_BASIC_INFORMATION pbi = {0};
    PEB peb = {0};
    RTL_USER_PROCESS_PARAMETERS Param = {0};
    USHORT usCmdLen = 0;
    USHORT usPathLen = 0;

    // 需要通過LoadLibrary、GetProcessAddress從ntdll.dll中擷取位址
    NtQueryInformationProcess = ::GetProcAddress(::LoadLibrary("ntdll.dll"), "NtQueryInformationProcess");
    if (NULL == NtQueryInformationProcess)
    {
        ShowError("GetProcAddress");
        return FALSE;
    }

    // 擷取指定程序的基本資訊
    NTSATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
    if (!NT_SUCCESS(status))
    {
        ShowError("NtQueryInformationProcess");
        return FALSE;
    }

    // 擷取指定程序基本資訊結構中的PebBaseAddress
    ::ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), NULL);
    // 擷取指定程序環境塊結構中的ProcessParameters
    ::ReadProcessMemory(hProcess, peb.ProcessParameters, &Param, sizeof(Param), NULL);
    // 修改指定PEB中指令行資訊
    usCmdLen = 2 + 2 * ::wcslen(lpwszCmd);
    ::WriteProcessMemory(hProcess, Param.CommandLine.Buffer, lpwszCmd, usCmdLen, NULL);
    ::WriteProcessMemory(hProcess, Param.CommandLine.Length, &usCmdLen, sizeof(usCmdLen), NULL);
    // 修改指定PEB中的路徑資訊
    usPathLen = 2 + 2 * wcslen(lpwszPath);
    ::WriteProcessMemory(hProcess, Param.ImagePathName.Buffer, lpwszPath, usPathLen, NULL);
    ::WriteProcessMemory(hProcess, Param.ImagePathName.Length, &usPathLen, sizeof(usPathLen), NULL);

    return TRUE;
}




           

繼續閱讀