上一篇:一个跨表查询的例子 >>
剖析Windows任务管理器开发原理与实现
e-mail: brief@fz5fz.org
homepage: www.fz5fz.org && www.safechina.net
date: 05-01-2003
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,您是否常常遇到任务栏“假死”的情况,虽然您的电脑没有挂掉,但却动弹不得,那好我们也同样可以将任意的进程挂起来,不管您对它做什么动作(除了结束),它都不会有任何的反应。有了挂起进程,同样我们也可以将进程从“挂起”状态激活哈。
桌面窗口是大家接触得最多的交互界面了,您是否想获得每个窗口的标题信息呢?当然我们还可以获得与窗口关联的进程,线程与窗口句柄属性。如果大家对vc比较熟悉,就应该知道其中的一个spy++工具吧,它就可以获得桌面窗口,进程和线程的详细信息,不过现在就不用打开这个,打开那个了,通通搞定了!
系统性能是每个用户关心的话题。它包括整个系统当前创建的句柄,进程以及线程的数目。还有物理存储器(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服务与后门技术》获得更多关于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函数,但是我们清楚系统底层究竟是怎么实现的吗?不管我们是否只是为了实现一个功能,还是对操作系统感兴趣,我们都应该更多的对系统底层进行研究,而不仅仅是只会使用高层函数的程序员。虽然微软为我们隐藏了很多的内部细节,但正是这种底层的秘密激发了我们对其进行深入研究的兴趣和动力。
注:
本文相关程序代码过长,所以不在此一并给出,如果你对其比较感兴趣,请到fz5fz主页下载~
()
下一篇:强制访问你的广告才能进入你的站点的script >>
相关文章:
- · Winodws下IIS/Apache+PHP+MySQL的安装配置
- · sql的sa空口令漏洞怎么补
- · SQL Server 2000的安全配置
- · VC里一些容易混淆的地方
- · VC Studio 使用技巧大全
- · 用PHP 4.2书写安全的脚本
- · 限制只能中文输入的方法
- · 程序设计中的一些感悟
- · 编写高质量的VB代码
- · dvbbs绝对背后的微笑
- · 5.PHP的其他功能
- · 4.与数据库的连接
- · 3.从实例开始
- · 2.PHP入门
- · 1.PHP简介
- · 随机头像PHP版
- · 自动跳转中英文页面
- · 从IIS到SQL Server数据库安全
- · 通用数据库显示程序
- · ASP实用函数库
- · 漂亮但不安全的CTB
- · 无组件图片与文本同步存入数据库的最简单的办法
- · 利用PHP创建动态图像
- · 精妙SQL语句
- · 用ASP动态生成JS表单验证代码
- · 用ASP编写网上调查投票系统
- · 轮换的logo显示
- · ip签名探针
- · ASP下载系统防盗链方法
- · ASP开发网页牢记注意事项
- · IIS6.0下ASP的新增功能
- · 图片或banner的随机显示
- · 判断Cookies是否处于开启状态
- · 主页javascript特效19则
- · Script经典文章
- · 用ASP做全文检索
- · WEB应用中报表打印的实现
- · 控制输出字符串长度区别中英文
