Ring3枚举进程

2024-06-17 01:08
文章标签 进程 枚举 ring3

本文主要是介绍Ring3枚举进程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在Ring3枚举进程通常有一下几种方法:
  • ToolHelper32
  • Psapi
  • ZwQuerySystemInformation
  • WTSEnumerateProcesses

一、ToolHelper32

头文件:TlHelp32.h
关键函数:CreateToolhelp32Snapshot,Process32Next

BOOL EnumProcessesByToolHelper32()
{
    PROCESSENTRY32 ProcessEntry32 = { 0 };
    HANDLE hSnapshot = INVALID_HANDLE_VALUE;
    BOOL IsOk = FALSE;
    
    hSnapshot = CreateToolhelp32Snapshot(2, 0);
    if (INVALID_HANDLE_VALUE == hSnapshot)
    {
        return FALSE;
    }
    //不添加这句会出现 0x0018 错误
    ProcessEntry32.dwSize = sizeof(ProcessEntry32);
    //遍历名字查找
    _tprintf(TEXT("ProcessID\tProcessImageName\r\n"));
    if (Process32First(hSnapshot, &ProcessEntry32))
    {
        do
        {
            _tprintf(TEXT("%d\t%s\r\n"), ProcessEntry32.th32ProcessIDProcessEntry32.szExeFile);
        } while (Process32Next(hSnapshot, &ProcessEntry32));
    }
    CloseHandle(hSnapshot);
    getchar();
}

二、Psapi

头文件:Psapi.h
关键函数:EnumProcessesOpenProcess,EnumProcessModules,GetProcessImageFileName,GetModuleBaseName
总结:由于该方法需要进程句柄,如果得不到进程句柄,什么信息都得不到,不建议使用。

// 注意:32位程序只能枚举32位程序,枚举不出64位程序
BOOL  EnumProcessByPsapi()
{
    TCHAR ProcessDosPath[0x200] = {};
    TCHAR ProcessNtPath[MAX_PATH];
    TCHAR ProcessName[MAX_PATH];
    DWORD ProcessID[1024];
    DWORD ProcessesCount;
    DWORD CbNeeded;
    
    HANDLE ProcessHandle = NULL;
    HMODULE hMod = NULL;
    if (!EnumProcesses(ProcessIDsizeof(ProcessID), &CbNeeded))
    {
        return FALSE;
    }
    ProcessesCount = CbNeeded / sizeof(DWORD);
    _tprintf(TEXT("ProcessID\t ProcessImageName\t ProcessImageFullPath\r\n"));
    for (size_t i = 0; i < CbNeededi++)
    {
        if (0 != ProcessID[i])
        {
            // 没有PROCESS_VM_READ 权限是枚举不出来的
            ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                FALSEProcessID[i]);
            if (ProcessHandle != NULL)
            {
                // 完整路径
                if (GetProcessImageFileName(ProcessHandleProcessDosPath_countof(ProcessDosPath)) > NULL)
                {
                    // The GetProcessImageFileName function returns the path in device form, rather than drive letters.
                    // For example, the file name C:\Windows\System32\Ctype.nls would look as follows in 
                    // device form :\Device\Harddisk0\Partition1\Windows\System32\Ctype.nls
                    DosPathToNtPath(ProcessDosPathProcessNtPathMAX_PATH);
                }
                //进程名称()
                if (EnumProcessModules(ProcessHandle, &hModsizeof(hMod), &CbNeeded))
                {
                    GetModuleBaseName(ProcessHandlehModProcessNamesizeof(ProcessName) / sizeof(TCHAR));
                }
                else
                {
                    _stprintf_s(ProcessNameTEXT("%s"), TEXT("<unknow>"));
                }
                _tprintf(TEXT("%d\t%s\t%s\r\n"), ProcessID[i], ProcessNameProcessNtPath);
                CloseHandle(ProcessHandle);
            }
        }
    }
    return TRUE;
}
BOOL DosPathToNtPath(IN LPTSTR DosPathOUT LPTSTR NtPath,IN ULONG CchNtPath)
{
    // DosPath: \Device\HarddiskVolume2\Windows\System32\sihost.exe
    TCHAR DosPathOfVolume[0x200];
    TCHAR DeviceName[3] = TEXT("A:");
    
    TCHAR COMDeviceName[5] = TEXT("COM0");
    ULONG StringLength = 0;
    while (DeviceName[0] <= 'Z')  //Z
    {
        // 如果指定DeviceName为NULL,那么该函数将输出所有存在的 MS-DOS device names 
        if (QueryDosDevice(DeviceNameDosPathOfVolume, 0x100 /sizeof(TCHAR)))
        {
            // C: 对应的DosPath是 \Device\HarddiskVolume2
            StringLength = lstrlen(DosPathOfVolume);
            // \Device\HarddiskVolume2 --> \Device\HarddiskVolume2\Windows\System32\sihost.exe
            lstrcat(DosPathOfVolumeDosPath + StringLength);
            // 判断是否是待转换的路径
            if (lstrcmpi(DosPathOfVolumeDosPath) == NULL)
            {
                lstrcpy(NtPathDeviceName);  // D:
                lstrcat(NtPathDosPath + StringLength);  // D:\Windows\system32
                return TRUE;
            }
        }
        DeviceName[0]++;
    }
    while (COMDeviceName[3] <= '9')  //9
    {
        if (QueryDosDevice(COMDeviceNameDosPathOfVolumeMAX_PATH * 2) > NULL)
        {
            StringLength = lstrlen(DosPathOfVolume);
            lstrcat(DosPathOfVolume, (DosPath + StringLength));
            if (lstrcmpi(DosPathOfVolumeDosPath) == NULL)
            {
                lstrcpy(NtPathCOMDeviceName);
                lstrcat(NtPath, (DosPath + StringLength));
                return TRUE;
            }
        }
        COMDeviceName[3]++;
    }
    return FALSE;
}

三、NtQuerySystemInformation

头文件:Winternl.h(头文件中的结构体都是不全的,需要自己定义,通常都是从ntdll.dll 中 Get 到函数地址)
关键函数:NtQuerySystemInformation
关键宏:SystemProcessInformation
关键结构:SYSTEM_PROCESS_INFORMATION

BOOL EnumProcessByZwQuerySystemInformation()
{
    LPFN_NtQuerySystemInformation __NtQuerySystemInformation;
    HMODULE hNtdll = LoadLibraryW(L"ntdll.dll");
    if (!hNtdll)
    {
        return FALSE;
    }
    __NtQuerySystemInformation = (LPFN_NtQuerySystemInformation)GetProcAddress(hNtdll"NtQuerySystemInformation");
    if (!__NtQuerySystemInformation)
    {
        return FALSE;
    }
    PSYSTEM_PROCESS_INFORMATION SystemProcessInfo = NULL;
    DWORD ReturnLength = 0;
    DWORD BufferLength = 1;
    // 将BufferLength置位1,查询需要的缓冲区大小
    if (STATUS_INFO_LENGTH_MISMATCH == __NtQuerySystemInformation(SystemProcessInformation, &SystemProcessInfoBufferLength, &ReturnLength))
    {
        BufferLength = ReturnLength;
        SystemProcessInfo = (PSYSTEM_PROCESS_INFORMATION)malloc(BufferLength);
        
        if (!SystemProcessInfo)
        {
            return FALSE;
        }
        if (__NtQuerySystemInformation(SystemProcessInformationSystemProcessInfoBufferLength, &ReturnLength) != STATUS_SUCCESS)
        {
            GetLastError();
            return FALSE;
        }
        while (SystemProcessInfo->NextEntryOffset != 0)
        {
            wprintf(L"%d\t%s\r\n"SystemProcessInfo->UniqueProcessIdSystemProcessInfo->ImageName.Buffer);
            SystemProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((PUINT8)SystemProcessInfo + SystemProcessInfo->NextEntryOffset);
        }
    }
}

四、WTSEnumerateProcesses

头文件:Wtsapi32.h(该方法需要获得计算机名,局域网内的其它计算机应该也能枚举)
关键函数:GetComputerName,WTSOpenServer,WTSEnumerateProcesses
关键结构:PWTS_PROCESS_INFO 

int EnumProcessByWTSEnumerateProcesses()
{
    TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 2];
    DWORD BufferSize;
    BufferSize = sizeof ComputerName - 1;
    GetComputerName(ComputerName, &BufferSize);
    PWTS_PROCESS_INFO wts;
    DWORD dwCount;
    HANDLE hWtsServer = WTSOpenServer(ComputerName);
    if (!WTSEnumerateProcesses(hWtsServer, 0, 1, &wts, &dwCount))
        return 0;
    for (DWORD i = 0; i < dwCounti++)
    {
        printf("%d\t%s\n"wts[i].ProcessIdwts[i].pProcessName);
    }
    getchar();
    return 0;
}

这篇关于Ring3枚举进程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1068068

相关文章

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

Kotlin 枚举类使用举例

《Kotlin枚举类使用举例》枚举类(EnumClasses)是Kotlin中用于定义固定集合值的特殊类,它表示一组命名的常量,每个枚举常量都是该类的单例实例,接下来通过本文给大家介绍Kotl... 目录一、编程枚举类核心概念二、基础语法与特性1. 基本定义2. 带参数的枚举3. 实现接口4. 内置属性三、

C#之枚举类型与随机数详解

《C#之枚举类型与随机数详解》文章讲解了枚举类型的定义与使用方法,包括在main外部声明枚举,用于表示游戏状态和周几状态,枚举值默认从0开始递增,也可手动设置初始值以生成随机数... 目录枚举类型1.定义枚举类型(main外)2.使用生成随机数总结枚举类型1.定义枚举类型(main外)enum 类型名字

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1

一文解密Python进行监控进程的黑科技

《一文解密Python进行监控进程的黑科技》在计算机系统管理和应用性能优化中,监控进程的CPU、内存和IO使用率是非常重要的任务,下面我们就来讲讲如何Python写一个简单使用的监控进程的工具吧... 目录准备工作监控CPU使用率监控内存使用率监控IO使用率小工具代码整合在计算机系统管理和应用性能优化中,监

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存