Windows任务管理器开发原理与实现

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Windows任务管理器开发原理与实现

Windows2000/XP内含的任务管理器(Taskmgr)相信大家都熟悉吧,相比之下XP里的要比2000功能更加强大,返回的信息也更加的详细,不过您是否觉得还有很多希望获得的消息没有包含在里面吗?您是否觉得 Windows的系统管理工具箱里的东西太分散了吗?下面就让我们看看它们的开发原理,并动手实现一个真正的任务管理器。现在我们是调用Win32API来实现这些功能的,但是大家都说MS隐藏了太多的细节,以后我们将讨论更多关于Windows内核的东东。

 可能大家对任务管理器里最熟悉的功能要数进程管理了,常常我们在怀疑中了病毒/木马的时候都会看看任务管理器里有没有什么特别的进程在运行,所以进程查看器应该是一个非常重要的功能。我们除了需要获得进程的名称外,还有什么呢?当然包括它的进程标识符(ProcessID),用户信息(UserName),CPU使用时间(CPUTime)和存储器的使用情况(MemoryUsage),还有它的优先权(BasePriority)。CPU和Memory信息可以帮助我们分析进程的运行情况,而优先权可以表示进程在CPU分配处理器使用时的优先情况。这些都是通用的进程信息,让我们再看看其他的信息吧。进程的父进程标识符(Parent Process ID),创建时间(Create Time),程序名称等在很多情况下也是我们关心的信息。我们再看看进程相关的性能信息。在Windows下通常有两种模式:内核模式(Kernel: Level 0)和用户模式(User: Level 3),进程往往在两种模式中来回切换,所以可以获得进程在内核模式和用户模式各自的使用时间。同时还包括进程相关的工作集(WorkingSet),分页池(PagedPool),非分页池(NonePagedPool)和页面文件(PageFile)信息。进程相关的I/O操作包括读/写/其他等动作,我们可以获得这些操作的次数和传送数据的数量。

 如果您怀疑某个进程是木马,那您还想获得哪些信息呢?简单的进程名称应该是不够的吧!我们希望获得进程的实际程序的路径,这样可以帮助我们判断究竟是那个程序在运行。前段时间不是在讨论什么进程隐藏的,其中一种就是“创建远程线程”,而注体往往又是以动态链接库(DLL)的形式存在的,我们就希望看到某个具体进程所包含的所有模块(Module),常常是DLL也。“线程”是一个大家熟悉的名字,它是Windows系统中的实现体,而进程则是线程运行的环境。一个进程到底创建了多少线程了?我们同样可以枚举进程内部的所有线程信息。如果您发现一个木马进程,下面的动作就应该是分析它的运行机制(如果您对它感兴趣),不过最终您还是要将它结束吧。在Windows2k下,很多系统关键进程在TaskMgr里是不能被结束的,不过现在您不用担心了。好的,对进程的操作当然就包括结束进程。如果您用过中文的XP,您是否常常遇到任务栏“假死”的情况,虽然您的电脑没有挂掉,但却动弹不得,那好我们也同样可以将任意的进程挂起来,不管您对它做什么动作(除了结束),它都不会有任何的反应。有了挂起进程,同样我们也可以将进程从“挂起”状态激活。

 系统性能是每个用户关心的话题。它包括整个系统当前创建的句柄,进程以及线程的数目。还有物理存储器(Physical Memory)的总量和使用情况,系统高速缓存(System Cache)的大小,存储器保留与提交(Commit Charge)状况,当然还有核心分页/非分页池(Kernel Memory)的使用情况。几乎包括了Windows系统下存储器管理的大部分信息。

 虽然现在硬盘的价格已经很低了,不过我还是在用6.4G的小东东,所以常常遇到“Low Disk”!我们常常要看看硬盘的使用情况,不过每次都要进入我的电脑,太麻烦了。而我们现在可以一次了解所有磁盘的容量和当前使用情况,同时还有它们的格式类型(如FAT,NTFS,CDFS等)和磁盘标签。

 说到环境块,或许不是那么熟悉吧,它包含一些环境变量,而每个环境变量对应一个/多个字符串,您可以在控制面板的SYSTEM/Advanced(系统/高级)里对它们进行设置,包括添加新的环境变量,删除和编辑系统环境变量。

 事件记录对我们分析系统的使用情况有很大的帮助。事件记录分为三种:应用程序,系统和安全。而对应的每种事件又可以分为几种类型,它们分别是常规信息,警告和错误。其中包括记录序号(Record Number),事件类型(Type),标识符(Event ID),来源(Source),产生时间(Time Generated),用户名(User)和相关描述信息(Description)。有时间大家可以多看看事件信息,当然每个网络管理员对它们应该是很熟悉的,不过还包括其他的事件日志信息。

 Windows系统下的ipconfig /all这个命令我是常常用,因为我们使用的是DHCP,没事看看自己的IP地址变了没有。其中包括详细的网络适配器的信息,包括适配器名称,描述,硬件地址和类型,IP地址及相应的子网掩码,网关与DHCP服务器地址等。不过您是否对网络流量也感兴趣呢?我们当然可以获得主机接受/发送了多少(非)广播数据报,出现了多少错误,一共接受/发送了多少信息,这些对每个网友都是有用的信息哟。

 网络共享往往是大家注意的地方,您究竟共享了多少信息,它们的文件路径是什么,还有它们的共享类型信息。我们在不需要某些共享资料时,当然不要忘了将其删除,以免泄露自己的机密信息。

 Windows的NT是一个多用户的系统,允许多种类型用户的存在。我们希望获得用户账号的使用期限(Password Expired),记住要不定时的修改用户的密码哟,以及用户标识符(User ID),组标识符(Group ID),还有用户账号的类型(Type),不同的类型有不同的权限,我们当然希望有最High的权力哟!看看系统对某个账号的磁盘空间使用情况是否有限制(Max Storage),账号登录的次数(Number Of Logon)和登录时间信息(Logon Hours)等,对我们分析用户的使用情况也有帮助的。

 系统的Win32服务和设备驱动信息也是很重要的,我们希望探测每个服务/设备启动程序的具体路径,状态,类型,启动方式等等信息。我们还希望对服务进行控制,比如停止,启动和删除操作。

 关机也不是那么的单调的,您可以注销自己的系统,如果您要离开当然就需要锁定了。最近大家都不喜欢关机,太麻烦了,所以都习惯使用冬眠,系统将会为我们保留当前信息,不过还有支持电源管理的关机和休眠。Windows2000的用户注意了,我们同样可以使用XP系统下的带有到记时与消息提示的关机和重启功能了。

 系统的版本信息是比较固定的,主要包括操作系统的指纹,注册组织/用户,主机名和系统相关目录等信息。  

 说了这么多,我们也该谈谈如何实现了。

 1.窗口信息

 MS为我们提供了打开特定桌面和枚举桌面窗口的函数。

 hDesk=OpenDesktop(lpszDesktop,0,FALSE,DESKTOP_ENUMERATE);

 //打开我们默认的Default桌面;

 EnumDesktopWindows(hDesk,(WNDENUMPROC)EnumWindowProc,0);

 //枚举打开桌面上的所有窗口,由回调函数实现。

 BOOL __stdcall EnumWindowProc(HWND, LPARAM);

 //在回调函数中,我们可以获得窗口的标题和相关进程,线程信息;

 GetWindowText(hWnd,szWindowText,dwMaxCount);

 GetWindowThreadProcessId(hWnd,&dwPID);

 2.设备驱动器信息(服务和设备驱动器差不多,在此不做重复)

 设备驱动信息有服务控制管理器(SCM)来管理的,我要打开服务控制管理器,并枚举所有的设备驱动器。

 OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

 //以所有权限打开服务控制管理器;

 EnumServicesStatus(schManager,dwDeviceType,dwDeviceState,

       EnumStatus,dwBufSize,&dwBytesNeeded,

      &dwDevicesReturned,&dwResumeHandle))

 //枚举所有设备的当前状态;

 CloseServiceHandle(schManager);

 //记住,在结束访问后要关闭服务句柄;

 OpenService(schManager,szDeviceName,SERVICE_ALL_ACCESS);

 //打开特定的设备驱动器;

 QueryServiceConfig(schDevice,lpDeviceConfig,

            1024*8,&dwBytesNeeded);

 //查询驱动器的服务配置信息;

 QueryServiceStatus(schDevice,&DeviceStatus);

 //查询设备驱动器的当前状态;

 QueryServiceConfig2(schDevice,SERVICE_CONFIG_DESCRIPTION,

 (LPBYTE)lpDeviceDescription,8*1024,&dwBytesNeeded)

 //查询设备的描述信息;

 StartService(schDevice,0,NULL);

 //启动设备;

 ControlService(schDevice,SERVICE_CONTROL_STOP,&DeviceStatus);

 //停止设备;

 DeleteService(schDevice);

 //删除设备;

 3.磁盘信息

 我们希望获得系统所有磁盘的信息,包括软盘,硬盘,光盘等等;

 GetLogicalDriveStrings(dwBufferLength,lpBuffer);

 //获得逻辑设备的信息;

 GetVolumeInformation(lpRootPathName,lpVolumeNameBuffer,

  dwVolumeNameSize,&dwVolumeSerialNumber,

  &dwMaximumComponentLength,&dwFileSystemFlags,

     lpFileSystemNameBuffer,dwFileSystemNameSize);

 //获得磁盘卷信息,包括卷名称和格式类型;

 GetDiskFreeSpaceEx(lpRootPathName,&FreeBytesAvailable,

         &TotalNumberOfBytes,&TotalNumberOfFreeBytes);

 //探测磁盘的空间使用情况;

 4.环境变量

 我们可以从注册表中获得环境块的信息:HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/Environment,当然要使用注册表的函数。

 RegOpenKeyEx(HKEY_LOCAL_MACHINE,RegKey,0,KEY_QUERY_VALUE,&hKey);

 //打开注册表的键;

 RegEnumValue(hKey,dwIndex,EnvironVariable,

        &dwVariableLength,NULL,NULL,NULL,NULL);

 //查询我们需要的信息值;

 GetEnvironmentVariable(EnvironVariable,EnvironString,1024);

 //获得环境变量的字符串信息;

 5.事件记录信息

 OpenEventLog(NULL,szLog);

 //打开时间日志记录;

 GetOldestEventLogRecord(hEvent,&dwThisRecord);

 //获得最新的日志信息,以便继续查找;

 ReadEventLog(hEvent,EVENTLOG_FORWARDS_READ │ EVENTLOG_SEQUENTIAL_READ,

  0,pEventLogRecord,1024*32,&dwRead,&dwNeeded)

 //读去日志信息;

 LookupAccountSid(NULL,pSid,szName,&dwName,szDomain,&dwDomain,&SNU);

 //获取账户的SID,以便获得账户的用户名称;

 GetNumberOfEventLogRecords(hEvent,&dwTotal);

 //获得事件日志的总数;

 CloseEventLog(hEvent);

 //不要忘记关闭事件句柄;

 

 6.网络共享

 我们使用第二等级的网络共享搜索;

 NetShareEnum(NULL,dwLevel,(PBYTE *)&pBuf,MAX_PREFERRED_LENGTH,&entriesread,&totalentries,&resume);

 //列举所有的共享目录及相关信息;

 NetApiBufferFree(pBuf);

 //释放缓冲区;

 NetShareDel(NULL,(char *)lpShareNameW,0);

 //删除网络共享目录;

 

 7.网络适配器信息

 我们要探测NIC的信息和网络流量;

 GetAdaptersInfo(&AdapterInfo,&OutBufLen);

 //获取适配器信息;

 

 8.系统性能

 获取系统的存储器使用情况;

 GetPerformanceInfo(&PerfInfo,sizeof(PERFORMACE_INFORMATION))

 //获取系统性能信息;

 9.进程/线程/模块信息

 在此我们使用工具帮助函数(ToolHelp32)和系统

 OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY │ TOKEN_ADJUST_PRIVILEGES,&hToken);

 //打开进程的令牌,提升权限;

 AdjustTokenPrivileges(hToken,FALSE,&TokenPrivileges,sizeof(TOKEN_PRIVILEGES),NULL,NULL);

 //将进程的权限提升到支持调试(Debug);

 CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

 //创建进程的快照;

 Process32First(hProcessSnap,&ProcessEntry32);

 Process32First(hProcessSnap,&ProcessEntry32);

 //枚举所有进程;

 OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,ProcessEntry32.th32ProcessID);

 //打开特定进程,以查询进程相关信息;

 GetProcessTimes(hProcess,&CreateTime,&ExitTime,&KernelTime,&UserTime);

 //获取进程的时间信息;

 GetProcessMemoryInfo(hProcess,&PMCounter,sizeof(PMCounter));

 //获取进程的存储区信息;

 GetPriorityClass(hProcess);

 //获取进程的优先权;

 GetProcessIoCounters(hProcess,&IoCounters);

 //获取进程的IO使用情况;

 CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID);

 //创建模块快照;

 Module32First(hModuleSnap, &ModuleEntry32);

 Module32Next(hModuleSnap, &ModuleEntry32);

 //枚举进程模块信息;

 CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

 //创建线程快照;

 Thread32First(hThreadSnap, &ThreadEntry32);

 Thread32Next(hThreadSnap, &ThreadEntry32);

 //枚举线程信息;

 OpenThread(THREAD_ALL_ACCESS,FALSE,ThreadEntry32.th32ThreadID);

 //打开线程,须自己获得此函数地址;

 TerminateProcess(hProcess,0);

 //终止进程;

 SuspendThread(hThread);

 //悬挂线程;

 ResumeThread(hThread);

 //激活线程;

 10.关机

 AdjustTokenPrivileges(hToken,FALSE,&TokenPrivileges,sizeof(TOKEN_PRIVILEGES),NULL,NULL);

 //调整进程令牌,使其支持关机;

 ExitWindowsEx(EWX_LOGOFF,0);

 //注销系统;

 LockWorkStation();

 //锁定系统;

 InitiateSystemShutdown(NULL,szMessage,dwTimeout,FALSE,bSig);

 //支持到记时和消息显示的关机/重启;

 SetSystemPowerState(bSig,FALSE);

 //系统休眠/冬眠;

 11.用户信息

 NetUserEnum(NULL,dwLevel,FILTER_NORMAL_ACCOUNT,(LPBYTE*)&pBuf,       dwPrefMaxLen,&dwEntriesRead,&dwTotalEntries,&dwResumeHandle);

 //枚举系统用户信息;

 NetUserDel(NULL,lpUserNameW);

 //删除指定用户;

 

 12.系统版本信息

 GetVersionEx((LPOSVERSIONINFO)&osviex);

 //获取操作系统的版本信息;

 我们也可以通过注册表(HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion)获取相关信息:

 GetTickCount();

 //获取开机时间;

 GetComputerName(szInfo,&dwInfo);

 //获取计算机名称;

 GetUserName(szInfo,&dwInfo);

 //获取计算机用户名;

 GetWindowsDirectory(szInfo,MAX_PATH+1);

 //获取Windows目录;

 GetSystemDirectory(szInfo,MAX_PATH+1);

 //获取系统目录;

 小结:

 虽然我们现在已经实现了任务管理器的各项功能,甚至比Windows自带的功能还要强大,不过却没有什么兴奋的感觉。因为看看我们的代码,您就会发现那些都是直接调用的Win32API函数,但是我们清楚系统底层究竟是怎么实现的吗?不管我们是否只是为了实现一个功能,还是对操作系统感兴趣,我们都应该更多的对系统底层进行研究,而不仅仅是只会使用高层函数的程序员。虽然微软为我们隐藏了很多的内部细节,但正是这种底层的秘密激发了我们对其进行深入研究的兴趣和动力。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
6月前
|
IDE 关系型数据库 开发工具
使用Visual Basic进行Windows窗体开发
【4月更文挑战第27天】本文介绍了使用Visual Basic进行Windows窗体(WinForms)开发的步骤,从搭建开发环境到创建、设计用户界面,再到编写事件驱动的代码和数据绑定。Visual Basic结合WinForms提供了一种易学易用的桌面应用开发方案。通过调试、优化、部署和维护,开发者可以构建专业应用程序。随着技术发展,掌握最新UI设计和开发工具对于保持竞争力至关重要。本文为初学者提供了基础指导,鼓励进一步探索和学习。
202 0
|
7天前
|
安全 前端开发 Windows
Windows Electron 应用更新的原理是什么?揭秘 NsisUpdater
本文介绍了 Electron 应用在 Windows 中的更新原理,重点分析了 `NsisUpdater` 类的实现。该类利用 NSIS 脚本,通过初始化、检查更新、下载更新、验证签名和安装更新等步骤,确保应用的更新过程安全可靠。核心功能包括差异下载、签名验证和管理员权限处理,确保更新高效且安全。
18 4
Windows Electron 应用更新的原理是什么?揭秘 NsisUpdater
|
29天前
|
监控 关系型数据库 MySQL
PowerShell 脚本编写 :自动化Windows 开发工作流程
PowerShell 脚本编写 :自动化Windows 开发工作流程
26 0
|
1月前
|
API Windows
Windows之窗口原理
这篇文章主要介绍了Windows窗口原理和如何使用Windows API创建和管理窗口。
52 0
|
1月前
|
Ubuntu Linux Python
如何利用wsl-Ubuntu里conda用来给Windows的PyCharm开发
如何在WSL(Windows Subsystem for Linux)的Ubuntu环境中使用conda虚拟环境来为Windows上的PyCharm开发设置Python解释器。
63 0
|
3月前
|
开发者 C# Windows
WPF与游戏开发:当桌面应用遇见游戏梦想——利用Windows Presentation Foundation打造属于你的2D游戏世界,从环境搭建到代码实践全面解析新兴开发路径
【8月更文挑战第31天】随着游戏开发技术的进步,WPF作为.NET Framework的一部分,凭借其图形渲染能力和灵活的UI设计,成为桌面游戏开发的新选择。本文通过技术综述和示例代码,介绍如何利用WPF进行游戏开发。首先确保安装最新版Visual Studio并创建WPF项目。接着,通过XAML设计游戏界面,并在C#中实现游戏逻辑,如玩家控制和障碍物碰撞检测。示例展示了创建基本2D游戏的过程,包括角色移动和碰撞处理。通过本文,WPF开发者可更好地理解并应用游戏开发技术,创造吸引人的桌面游戏。
182 0
|
3月前
|
开发者 iOS开发 C#
Uno Platform 入门超详细指南:从零开始教你打造兼容 Web、Windows、iOS 和 Android 的跨平台应用,轻松掌握 XAML 与 C# 开发技巧,快速上手示例代码助你迈出第一步
【8月更文挑战第31天】Uno Platform 是一个基于 Microsoft .NET 的开源框架,支持使用 C# 和 XAML 构建跨平台应用,适用于 Web(WebAssembly)、Windows、Linux、macOS、iOS 和 Android。它允许开发者共享几乎全部的业务逻辑和 UI 代码,同时保持原生性能。选择 Uno Platform 可以统一开发体验,减少代码重复,降低开发成本。安装时需先配置好 Visual Studio 或 Visual Studio for Mac,并通过 NuGet 或官网下载工具包。
274 0
|
4月前
|
Linux Apache C++
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
该文介绍了如何在Windows环境下为FFmpeg集成SRT协议支持库libsrt。首先,需要安装Perl和Nasm,然后编译OpenSSL。接着,下载libsrt源码并使用CMake配置,生成VS工程并编译生成srt.dll和srt.lib。最后,将编译出的库文件和头文件按照特定目录结构放置,并更新环境变量,重新配置启用libsrt的FFmpeg并进行编译安装。该过程有助于优化直播推流的性能,减少卡顿问题。
118 2
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
|
5月前
|
网络安全 C++ Windows
【Windows驱动开发】(主机)VS2017+(虚拟机)win10系统------双机调试
【Windows驱动开发】(主机)VS2017+(虚拟机)win10系统------双机调试
|
5月前
|
Windows
【Windows驱动开发】注册表的基本操作(创建、打开、修改、读取、枚举)(附源码)
【Windows驱动开发】注册表的基本操作(创建、打开、修改、读取、枚举)(附源码)