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

相关文章

Java枚举类型深度详解

《Java枚举类型深度详解》Java的枚举类型(enum)是一种强大的工具,它不仅可以让你的代码更简洁、可读,而且通过类型安全、常量集合、方法重写和接口实现等特性,使得枚举在很多场景下都非常有用,本文... 目录前言1. enum关键字的使用:定义枚举类型什么是枚举类型?如何定义枚举类型?使用枚举类型:2.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

一文解析C#中的StringSplitOptions枚举

《一文解析C#中的StringSplitOptions枚举》StringSplitOptions是C#中的一个枚举类型,用于控制string.Split()方法分割字符串时的行为,核心作用是处理分割后... 目录C#的StringSplitOptions枚举1.StringSplitOptions枚举的常用

C#使用SendMessage实现进程间通信的示例代码

《C#使用SendMessage实现进程间通信的示例代码》在软件开发中,进程间通信(IPC)是关键技术之一,C#通过调用WindowsAPI的SendMessage函数实现这一功能,本文将通过实例介绍... 目录第一章:SendMessage的底层原理揭秘第二章:构建跨进程通信桥梁2.1 定义通信协议2.2

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 并