网络安全参考 | UNIX参考 | GPS参考 | 无线参考 | 在线手册 | OSBUG.ORG | SUNNY-NETWORK.COM
网站地图 RSS订阅
高级搜索 收藏本站
Home | 业界动态 | 防火墙 | IDS/IPS | VPN | PKI | Honeypot | Hacker/Intruder | 黑客技术 | 破解技术 | 加密技术 | 病毒防护 | 木马 | 反垃圾邮件 | 反流氓软件 | 漏洞 | 无线安全 | UNIX | Windows | 安全编程 | 安全软件 | TPM/TCG | 数据恢复 | 企业信息安全 | 个人信息安全
 当前位置: Home > Windows > 文章  
检测并禁用隐藏服务
文章来源: xfocus.net 文章作者: linux2linux 发布时间: 2006-07-07   字体: [ ]
 

  创建时间:2005-05-30
  文章属性:原创
  文章提交:linux2linux (linux2linux_at_163.com)

  隐藏服务的概念是由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_MACHINE\SYSTEM\ControlSet001\Services"的子项都转储为Hive格式文件(使用DumpServiceInfo函数),存放在C:\tmp.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:\tmp2.hiv文件中,此时提供用户一个选择“是否要禁用隐藏服务”,默认的选择是“否”,如果用户确实想要禁用,可输入“Yes”或“Y",接着使用RestoreServiceInfo函数将C:\tmp2.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 can't work well in windows.
    //while it read 0x1a from the opened file, the function read will stop there.
    //I don't know the reason why, it work well in linux envoriment.
    // read the dumped hive file to fill hive struct.
    // return the point

  struct hive *My_openHive(char *filename, int mode)
  {
    HANDLE hFile;
    int szread;
    struct hive *hdesc;
    int vofs;
    unsigned long pofs;
    char *c;
    struct hbin_page *p;
    struct regf_header *hdr;
    int verbose = (mode & HMODE_VERBOSE);
    CREATE(hdesc, struct hive, 1);

    hdesc->filename = str_dup(filename);
    hdesc->state = 0;
    hdesc->size = 0;
    hdesc->buffer = NULL;
    hFile = CreateFile(hdesc->filename, GENERIC_READ, // open for reading
         0,  // do not share
         NULL, // no security
         OPEN_ALWAYS, // existing file only
         FILE_ATTRIBUTE_NORMAL, // normal file
         NULL); // no attr. template

    if (hFile == INVALID_HANDLE_VALUE)
    {
      printf("Could not open hive file."); // process error
      return 0;
    }

    /* Read the whole file */
    hdesc->size = GetFileSize(hFile, NULL);
    ALLOC(hdesc->buffer, 1, hdesc->size);
    ReadFile(hFile, (void *) hdesc->buffer, hdesc->size, &szread, NULL);
    CloseHandle(hFile);

    if (szread < hdesc->size)
    {
      printf("Could not read file, got %d bytes while expecting %d\n", szread, hdesc->size);
      My_closeHive(hdesc);
      return (NULL);
    }

    /* Now run through file, tallying all pages */
    /* NOTE/KLUDGE: Assume first page starts at offset 0x1000 */
    pofs = 0x1000;
    hdr = (struct regf_header *) hdesc->buffer;

    if (hdr->id != 0x66676572)
    {
      printf("openHive(%s): File does not seem to be a registry hive!\n", filename);
      return (hdesc);
    }
    for (c = hdr->name; *c && (c < hdr->name + 64); c += 2)
      putchar(*c);

    hdesc->rootofs = hdr->ofs_rootkey + 0x1000;

    while (pofs < hdesc->size)
    {
  #ifdef LOAD_DEBUG
      if (verbose)
        hexdump(hdesc->buffer, pofs, pofs + 0x20, 1);
  #endif

      p = (struct hbin_page *) (hdesc->buffer + pofs);

      if (p->id != 0x6E696268)
      {
        printf("Page at 0x%lx is not 'hbin', assuming file contains garbage at end", pofs);
        break;
      }

      hdesc->pages++;
  #ifdef LOAD_DEBUG
      if (verbose)
        printf("\n###### Page at 0x%0lx has size 0x%0lx, next at 0x%0lx ######\n", pofs, p->len_page, p->ofs_next);
  #endif

      if (p->ofs_next == 0)
      {
  #ifdef LOAD_DEBUG
        if (verbose)
   printf("openhive debug: bailing out.. pagesize zero!\n");
  #endif
        return (hdesc);
      }

  #if 0
      if (p->len_page != p->ofs_next)
      {
  #  ifdef LOAD_DEBUG
        if (verbose)
   printf("openhive debug: len & ofs not same. HASTA!\n");
  #  endif
        exit(0);
      }

  #endif

      vofs = pofs + 0x20;  /* Skip page header */
  #if 1
      while (vofs - pofs < p->ofs_next)
      {
        vofs += parse_block(hdesc, vofs, verbose);
      }

  #endif
      pofs += p->ofs_next;
    }

    return (hdesc);
  }

  void My_closeHive(struct hive *hdesc)
  {
    FREE(hdesc->filename);
    FREE(hdesc->buffer);
    FREE(hdesc);
  }

  int My_writeHive(struct hive *hdesc)
  {
    HANDLE hFile;
    DWORD dwBytesWritten;

    hFile = CreateFile("C:\\tmp2.hiv", GENERIC_WRITE, // open for writing
         0,  // do not share
         NULL, // no security
         CREATE_ALWAYS, // open or create
         FILE_ATTRIBUTE_NORMAL, // normal file
         NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
      printf("Can't open dump file");
      return 0;
    }

    WriteFile(hFile, hdesc->buffer, hdesc->size, &dwBytesWritten, NULL);

    if (dwBytesWritten != hdesc->size)
    {
      printf("WriteHive error\n");
    }

    CloseHandle(hFile);

    return 0;
  }

  void CleanPatterns()
  {
    int i;

    if (pattern != NULL)
    {
      for (i = 0; i < pattern_count; i++)
      {
        if (pattern[i] != NULL)
   free(pattern[i]);
      }

      free(pattern);
    }
  }

  void GetPatterns()
  {
    HANDLE hService;
    CHAR achKey[MAX_PATH];
    DWORD i;
    DWORD retCode;
    int Nohide = 1;
    DWORD SubKeyNum = 0;

    pattern_count = 0;
    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, // handle to open key
       "SYSTEM\\ControlSet001\\Services", // subkey name
       NULL, // reserved
       KEY_ALL_ACCESS, // security access mask
       &hService // handle to open key
        ) != ERROR_SUCCESS)
    {
      printf("sorry %d\n", GetLastError());
      return;
    }
    RegQueryInfoKey(hService, NULL, NULL, NULL, &SubKeyNum, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
    //Before it don't work well , because i set the wrong premission of HKEY
    //KEY_ALL_ACCESS is needed
    if (SubKeyNum == 0)
    {
      printf("SubKey's Number is NULL, it's too strange.\n");
      return;
    }
    pattern = malloc(sizeof(char *) * SubKeyNum);
    for (i = 0, retCode = ERROR_SUCCESS; retCode == ERROR_SUCCESS; i++)
    {
      retCode = RegEnumKey(hService, // handle to key to query
      i, // index of subkey to query
      achKey, // buffer for subkey name
      MAX_PATH // size of subkey name buffer
        );

      if (retCode == (DWORD) ERROR_SUCCESS)
      {
        //What i add to get pattern Services Table.
        pattern[pattern_count] = strdup(achKey);
        pattern_count++;
      }

    }

    CloseHandle(hService);
  }

  void ShowPathImage(struct hive *hdesc, int nkofs, char *path)
  {
    void *data;
    int len, i, type;
    char string[SZ_MAX + 1];

    type = get_val_type(hdesc, nkofs, path);
    if (type == -1)
    {
      printf("No such value <%s>\n", path);
      return;
    }

    len = get_val_len(hdesc, nkofs, path);
    if (!len)
    {
      printf("Value <%s> has zero length\n", path);
      return;
    }

    data = (void *) get_val_data(hdesc, nkofs, path, 0);
    if (!data)
    {
      printf("Value <%s> references NULL-pointer (bad boy!)\n", path);
      abort();
      return;
    }

    switch (type)
    {
      case REG_SZ:
      case REG_EXPAND_SZ:
      case REG_MULTI_SZ:
        cheap_uni2ascii(data, string, len);
        for (i = 0; i < (len >> 1) - 1; i++)
        {
   if (string[i] == 0)
     string[i] = '\n';
   if (type == REG_SZ)
     break;
        }

        puts(string);
        break;
      case REG_DWORD:
        printf("0x%08x", *(unsigned short *) data);
        break;
      default:
        printf("Don't know how to handle type yet!\n");
      case REG_BINARY:
        hexdump((char *) data, 0, len, 1);
    }
  }

  void EnablePriv(LPCTSTR lpName)
  {
    HANDLE hToken;
    LUID sedebugnameValue;
    TOKEN_PRIVILEGES tkp;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
      printf("open process error\n");
      return;
    }

    if (!LookupPrivilegeValue(NULL, lpName, &sedebugnameValue))
    {
      printf("can't find privilege error\n");
      CloseHandle(hToken);
      return;
    }

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = sedebugnameValue;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL))
    {
      printf("adjust error\n");
      CloseHandle(hToken);
    }
  }

  int DumpServiceInfo()
  {
    HKEY hService;

    EnablePriv(SE_BACKUP_NAME);
    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, // handle to open key
       "SYSTEM\\ControlSet001\\Services", // subkey name
       NULL, // reserved
       KEY_ALL_ACCESS, // security access mask
       &hService // handle to open key
        ) != ERROR_SUCCESS)
    {
      printf("can't get key handle\n");
      return 0;
    }

    if (RegSaveKey(hService, "C:\\tmp.hiv", NULL) != ERROR_SUCCESS)
    {
      printf("Can't dump Service info\n");
      CloseHandle(hService);

      return 0;
    }

    CloseHandle(hService);

    return 1;
  }

  void ShowHideService(struct hive *hdesc, char *path, int vofs, int type)
  {
    struct nk_key *key;
    int nkofs;
    struct ex_data ex;
    int count = 0, countri = 0;

    //wHAT I ADD
    void *data;
    int nkofs_cat;
    int serviceno;

    serviceno = 1;
    nkofs = trav_path(hdesc, vofs, path, 0);
    if (!nkofs)
    {
      printf("nk_ls: Key <%s> not found\n", path);
      abort();
      return;
    }

    nkofs += 4;
    key = (struct nk_key *) (hdesc->buffer + nkofs);
    if (key->id != 0x6b6e)
    {
      printf("Error: Not a 'nk' node!\n");
      debugit(hdesc->buffer, hdesc->size);
    }

    if (key->no_subkeys)
    {
      while ((ex_next_n(hdesc, nkofs, &count, &countri, &ex) > 0))
      {
        if (!CompareHive(ex.name))
        {
   nohideservice = 0;

   if (!(serviceno - 1))
     printf("Hide Service List:\n");

   printf("\n%d.------------------------------------------------------------\n", serviceno++);
   printf("Hide Service : %s\n", ex.name);
   nkofs_cat = trav_path(hdesc, vofs, ex.name, 0);
   printf("Image Path   : ");
   ShowPathImage(hdesc, nkofs_cat + 4, "ImagePath");
   data = (void *) get_val_data(hdesc, nkofs_cat + 4, "Start", 0);

   if (data != NULL)
   {
     printf("Start Type   : ");
     switch (*(unsigned short *) data)
     {
       case 0:
         printf("SERVICE_BOOT_START");
         break;
       case 1:
         printf("SERVICE_SYSTEM_START");
         break;
       case 2:
         printf("SERVICE_AUTO_START");
         break;
       case 3:
         printf("SERVICE_DEMAND_START");
         break;
       case 4:
         printf("SERVICE_DISABLED");
         break;
       default:
         printf("UNKOWN START TYPE");
     }

     //disable the service
     if (*(unsigned short *) data != 4)
     {
       printf("(Will be set to Disabled)");
       put_dword(hdesc, nkofs_cat + 4, "Start", 4);
       ischange = 1;
     }

     printf("\n");
   }

   data = (void *) get_val_data(hdesc, nkofs_cat + 4, "Type", 0);
   printf("Service Type : ");
   if (data != NULL)
   {
     if (*(unsigned short *) data & 1)
       printf("SERVICE_KERNEL_DRIVER ");
     if (*(unsigned short *) data & 2)
       printf("SERVICE_FILE_SYSTEM_DRIVER ");
     if (*(unsigned short *) data & 8)
       printf("SERVICE_RECOGNIZER_DRIVER ");
     if (*(unsigned short *) data & 16)
       printf("SERVICE_WIN32_OWN_PROCESS ");
     if (*(unsigned short *) data & 32)
       printf("SERVICE_WIN32_SHARE_PROCESS ");
     if (*(unsigned short *) data & 256)
       printf("SERVICE_INTERACTIVE_PROCESS ");
     printf("\n");
   }
        }

        FREE(ex.name);
      }
    }

    if (nohideservice)
      printf("There are no hide services.\n");
    else
      printf("\nTotal Hide Services is %d\n\n", serviceno - 1);
  }

  int RestoreServiceInfo()
  {
    HKEY hService;
    LONG tmp;

    EnablePriv(SE_RESTORE_NAME);
    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, // handle to open key
       "SYSTEM\\ControlSet001\\Services", // subkey name
       NULL, // reserved
       KEY_ALL_ACCESS, // security access mask
       &hService // handle to open key
        ) != ERROR_SUCCESS)
    {
      printf("Can't open Service key\n");
      return 0;
    }

    //The first time to Restore always fail even you set the Force flag
    //The second time will success.

    for (;;)
    {
      if ((tmp = RegRestoreKey(hService, "C:\\tmp2.hiv", 8)) == ERROR_SUCCESS)
      {
        break;
      }

    }

    CloseHandle(hService);
    return 1;
  }

  int main(int argc, char *argv[])
  {
    struct hive *pHive;
    char c;

    nohideservice = 1;
    ischange = 0;
    printf("KHS - kill hide services 0.1 by linux2linux, 2005/5/26.\n");
    printf("Take notes from knlsc and FHS.                         \n\n");
    if (!DumpServiceInfo())
      return 0;
    pHive = My_openHive("C:\\tmp.hiv", HMODE_RW);
    if (pHive == NULL)
    {
      printf("Open Hive fail\n");
      return 0;
    }

    GetPatterns();
    ShowHideService(pHive, "", pHive->rootofs + 4, 0);
    CleanPatterns();

    if (!nohideservice && ischange)
    {
      My_writeHive(pHive);
      printf("Do you want Disable the hide Services ( Yes / No )? [ No ]:");
      c = getchar();

      if ((c == 'Y') || c == 'y')
      {
        if (RestoreServiceInfo())
   printf("Success Restore\n");
      }

      else
      {
        printf("Quit without Restore.\n");
      }

      DeleteFile("C:\\tmp2.hiv");
    }

    DeleteFile("C:\\tmp.hiv");
    My_closeHive(pHive);

    return 0;
  }

  参考资源

  1.The Offline NT Password Editor 源程序 - Petter Nordahl-Hagen http://home.eunet.no/~pnordahl/ntpasswd/
  2.<<Windows NT/2000 Native API Reference>> - Gary Nebbett
  3.Knlsc, FHS, IceSword 使用说明

--
※ 链接: http://www.nsfocus.net/index.php?act=sec_doc&do=view&doc_id=961
※ 出处:http://www.xfocus.net/articles/200505/802.html

 
推荐文章
·谁在误导群众 Vista评分工具深入
·100%中招 亲身“体验”Vista蓝屏
·BIOS引发的血案 10分钟完美破解V
·轻松应对偷偷跑进来的自启动程序
·普通人不知道的20个WinXP秘密
·防范非法用户入侵Win 2K/XP系统
·Vista发布 对SOA带来什么影响
·安全性不是购买Vista的理由
·Vista并不安全 九成以上病毒均可
·Windows Vista操作系统安全性能
·Vista的安全措施有何具体意义?
·专家问诊 排除网上邻居使用4大常
·Vista被曝重大隐患 电脑极易被远
·几种Windows系统实现远程控制完
 
 
↑返回顶部   打印本页   关闭窗口↓  

Google
 
Web oldhand.org unixreference.net meshmea.org
热点文章
·BIOS引发的血案 10分钟
·如何删掉“删不掉”的文
·几种Windows系统实现远
·谁在误导群众 Vista评分
·零起步搞定DNS(网络域名
·Windows Vista兼容性问
·防止黑客入侵 网络端口
·100%中招 亲身“体验”V
相关分类
相关文章
·WinXP和2003又现安全漏
·对微软施压 16岁少年发
·十大Windows服务隐患重
·专家建议封杀Google桌面
·防止黑客入侵 网络端口
·菜鸟安全加倍:精通防火
·不用密码怎样进入Window
·Windows中用注销脚本自
更多...
 
 

Copyright(c) 2001-2008 OLDHAND ORGANIZATION, All Rights reserved.
Power by DedeCms 织梦内容管理系统
$Id: article_article.html,v 1.3 2007/02/10 12:00:37 yjs Exp $