当前位置:编程学习 > 网站相关 >>

检测并禁用隐藏服务

隐藏服务的概念是由hxdef 和rootkit这些后门工具提出的。这些后门工具通过挂钩系统本地调用来隐藏自己,原本通过调用Windows API调用查看系统服务的企图都是徒劳的。所以这时的系统是不可靠的,不值得信任的。目前针对查找隐藏服务的工具已经有很多,比如IceSword,knlsc,FHS等等。虽然这些软件都是免费的,但是它们到目前为止都不是开源,所以将自己的实现版本展示出来,正如knlsc的作者所说的那样,这是一个简单的小程序。

    Knlsc是通过将%SystemRoot%/System32/Config/System这个Hive文件转储出来,提取出ControlSet001/Services的子项再与RegEnumKeyEx的输出结果进行比对,发现若是在RegEnumKeyEx的输出结果中没有的子项就可以认为是一个隐藏的服务。当然knlsc还认为隐藏服务必须同时拥有ImagePath,Start,Type三个键值。据说knlsc运行时还将从资源段中放出一个驱动程序,但是估计这个驱动是假的。将knlsc托壳后用VC从资源段中导出的文件是一个没有EntryPoint但有MZ标志的驱动,没有办法进行反汇编。或许作者使用了SMC技术,放出资源文件后在进行修改,在执行文件中也有NtLoadDriver的调用片段,但是同一作者的knlps中的资源驱动却未作任何的处理。要实现检测隐藏服务的功能其实没有必要使用驱动程序,即使可以验证knlsc驱动的真实性。直接对Hive文件的转储也不是必须的,虽然这只要通过修改Gary Nebbett的示例代码就可做到。

    Hive文件的转储可以通过RegSaveKey函数来进行,rootkitrevealer就是使用这个API的扩充函数RegSaveKeyEx工作的,至少到目前为止还没有挂钩这类函数的后门,但是世上没有永远的安全,在理论上是可行的,可能不得不对该函数的输出文件进行处理,这将在一定程度上影响该函数的执行时间。使用该函数时还必须赋予调用进程以SE_BACKUP_NAME权限。

    在实现中将“HKEY_LOCAL_MACHINESYSTEMControlSet001Services"的子项都转储为Hive格式文件(使用DumpServiceInfo函数),存放在C: mp.hive,在C盘下不可有同名文件,否则会发生Dump错误。现在的问题是如何对Hive格式文件进行处理,在这一点上必须感谢Petter Nordahl-Hagen所写的NT Registry Hive access library,它是The Offline NT Password Editor的一部分。本人的实现很大程度上就是参照他的程序,然而这个库工作在Linux环境,但是它向VC编译器移植的工作量是极少的,只需稍加修改。

1.将 #include <unistd.h> 去掉

2.将程序中三处的

#define D_OFFS(o) ( (void *)&(key->o)-(void *)hdesc->buffer-vofs )    

改为 

#define D_OFFS(o) ( (int *)&(key->o)-(int *)hdesc->buffer-vofs )

因为在VC中无法打印void * 类型,只得改为int * 。

3.将程序中唯一的一处使用snprintf函数该为_snprintf,即

snprintf(path,maxlen,"(...)%s",tmp);改为

_snprintf(ptth,maxlen,”(…)%s”,tmp);

4.添加两个VC不支持的函数来使编译通过

void bzero(void *s,int n)

{    

memset(s,0,n);      

}

int strncasecmp(const char *s1, const char *s2, size_t n)

{

return _stricmp(s1,s2);

}

    为了表示对Petter Nordahl-Hagen的尊重,我不再修改他的库文件ntreg.c和ntreg.h(除了以上移植的需要),而是将所有需要重写和添加的函数放到KHS.C文件中,这样可以使原来的库文件保持其独立性。

    由于在Petter库中openHive函数使用open 和 read 函数来进行hive文件的读取,在VC条件下的read函数有一个问题,每当文件中存在一个0x1a的二进制数值时,read函数就会在那儿终止,这样就会导致hive文件无法完全导入。所以就使用了Windows API重写openHive,命名为My_openHive。相应的还重写了closeHive,writeHive并加上了前缀My_。

    随后GetPatterns函数将使用RegEnumKey枚举的服务键值名称保存在pattern的全局变量指针中,为以后的匹配作准备。ShowHideService函数是由nk_ls函数改写的,将由Hive文件导出的buffer中的服务名称与pattern[I]作比较,这个比较过程使用CompareHive函数。若比较结果为相同,CompareHive会将pattern[I]置为NULL,以提高匹配速度,或许有更好的匹配算法,但在这个小程序中也不使用了。若结果不同,则说明该服务是隐藏的,显示出该隐藏服务的名称,文件路径(ShowPathImage是由cat_vk改写的),启动类型和服务类型,并将该隐藏服务的启动类型改为SERVICE_DISABLED。如果存在隐藏服务并且禁止了该隐藏服务(仅在buffer中的修改),通过调用My_writeHive将修改过的hive 的buffer保存在C: mp2.hiv文件中,此时提供用户一个选择“是否要禁用隐藏服务”,默认的选择是“否”,如果用户确实想要禁用,可输入“Yes”或“Y",接着使用RestoreServiceInfo函数将C: mp2.hiv文件导回原来的%SystemRoot%/System32/Config/System这个Hive文件中,这一步由系统自己来完成,值得一提的是Win32函数RegRestoreKey即使在dwFlags参数中使用了REG_FORCE_RESTORE (8) ,在第一次调用时往往会错误返回,一般在第二次调用就会成功,所以就使用了一个循环直到它成功后为止,并且调用它的进程需要有SE_RESTORE_NAME的权限。

    至于让隐藏服务真正失去作用,仍然需要重新启动计算机之后。

 

下面给出KHS.C的完整源代码:

/*

* KHS.cpp - Kill Hide Services v0.1

* Copyright (c) 2005 linux2linux.

*

* It takes notes from knlsc and FHS.

* Thank you, Petter Nordahl-Hagen, for your "NT Registry Hive access library"

*

* Freely distributable in source or binary for noncommercial purposes.

* THIS SOFTWARE IS PROVIDED BY PETTER NORDAHL-HAGEN `AS IS AND

* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

* ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE

* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS

* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT

* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY

* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF

* SUCH DAMAGE.

*

*/

        

#include "ntreg.h"

#include <windows.h>

 

char **pattern;

int pattern_count;

 

int nohideservice;

int ischange;

 

extern char *val_types[REG_MAX+1];

 

struct hive *My_openHive(char *filename, int mode);

void My_closeHive(struct hive *hdesc);

 

int CompareHive(char *sample)

{

      int i;

      for(i = 0; i < pattern_count ; i++)

      {         

           if(pattern[i]!=NULL)

           {

                 if( strcmp ( sample , pattern[ i ] ) == 0 )

                 {

                      free(pattern[i]);

                      pattern[i]=NULL;

                      return 1;

                 }

           }

      }

      return 0;

}

 

//Because read cant work well in windows.

//while it read 0x1a from the opened file, the function read will stop there.

//I dont know the reason why, it work well in linux envoriment.

 

// read the dumped hive file to fill hive struct.

补充:综合编程 , 安全编程 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,