看流星社区

 找回密码
 注册账号
查看: 2370|回复: 0

初步实现系统级拦截应用程序取硬盘物理序列号

[复制链接]

该用户从未签到

发表于 2014-3-19 15:52:22 | 显示全部楼层 |阅读模式
【详细过程】
  以前想模拟某个程序取硬盘系列号,就将一个DLL注入进去,拦截DeviceIoControl的返回值,将其修改为目标硬盘的值。
  后来看到REGMON 从SSDT着手拦截注册表操作,可以看到任何程序的读写操作,就仿着改了一下程序。经测试可以欺骗相当
  一部分程序读硬盘序列号,包括ASPROTECT及用其加密算法的子孙:)。
  
  我的思路是这样的:
   
  1、首先用程序取自己的真正的硬盘序列号,假设为XXXX
  
  2、拦截系统的ZwDeviceIoControlFile,并判断入口参数中的IoControlCode ,只有某几个特定的值用来取序列号的,
     目前在所有的程序中取硬盘序列号的,我只发现两个值,一个是0x7c088,另外一个是什么忘了。
     
     如果IoControlCode为上面的值,读取系统原有的ZwDeviceIoControlFile返回BUFFER,并用串匹配方法查找这个返回值中存在
     不存在XXXX,如果存在,替换为你要欺骗的值.
  
  代码很简单:
  
  UCHAR __DiskSerial[DISK_SERIAL_BUFF_LENGTH]={0};
  UCHAR __ChangeTo  [DISK_SERIAL_BUFF_LENGTH]={0};
  
  //一个简单的低率串匹配算法 ,判断一个串S1是不是另外一个串S2的子串
  PUCHAR IsSubString(PUCHAR String, PUCHAR SubString ,ULONG StringLength ,ULONG SubStringLength)
  {
      ULONG i,j;
      for(i=0;i<StringLength - SubStringLength +1 ;i++){
          for(j=0;j<SubStringLength;j++){
              if(String[i+j]!=SubString[j])
                  break;
          }
          if(j==SubStringLength)  //match a substring
              return String+i;
      }
      return NULL;
  }
  
  //----------------------------------------------------------------------
  //
  //  Our own routine for ZwDeviceIocontrolFile
  //  We change the hard disk serial number value requested by user
  //
  //----------------------------------------------------------------------
  NTSTATUS HookZwDeviceIoControlFile(
                                    IN HANDLE FileHandle,
                                    IN HANDLE Event OPTIONAL,
                                    IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
                                    IN PVOID ApcContext OPTIONAL,
                                    OUT PIO_STATUS_BLOCK IoStatusBlock,
                                    IN ULONG IoControlCode,
                                    IN PVOID InputBuffer OPTIONAL,
                                    IN ULONG InputBufferLength,
                                    OUT PVOID OutputBuffer OPTIONAL,
                                    IN ULONG OutputBufferLength
                                    )
  {
      NTSTATUS rc;
  
      rc = RealZwDeviceIoControlFile (
          FileHandle,
          Event,
          ApcRoutine,
          ApcContext,
          IoStatusBlock,
          IoControlCode,
          InputBuffer,
          InputBufferLength,
          OutputBuffer,
          OutputBufferLength
      );
      //判断IoControlcode是不是取序列号的值
      if((0x7c088 ==IoControlCode) && OutputBufferLength >DISK_SERIAL_BUFF_LENGTH){
  
          //判断返回值中是否包含当前的硬盘序列号,是的话用假的替换
          PUCHAR Locate = IsSubString(OutputBuffer,__DiskSerial,OutputBufferLength,DISK_SERIAL_BUFF_LENGTH);
          if(Locate){
              UCHAR i;
              for(i=0;i<20;i++){
                  Locate[i]= __ChangeTo[i];
              }
          }
      }
      return(rc);
  }
  
  
  目前,驱动只处理了简单的几个应用层的消息,包括停止欺骗,开始欺骗,设置新的欺骗值。
  
  BOOLEAN  HDHookDeviceControl( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait,
                                IN PVOID InputBuffer, IN ULONG InputBufferLength,
                                OUT PVOID OutputBuffer, IN ULONG OutputBufferLength,
                                IN ULONG IoControlCode, OUT PIO_STATUS_BLOCK IoStatus,
                                IN PDEVICE_OBJECT DeviceObject ) {
      BOOLEAN                 retval = FALSE;
      ULONG i;
  
      // Its a message from our GUI!
      IoStatus->Status      = STATUS_SUCCESS; // Assume success
      IoStatus->Information = 0;              // Assume nothing returned
  
  
      switch ( IoControlCode ) {
  
      //  开始欺骗
  
      case HDHOOK_HOOK:
          HookStart();
          break;
  
      // 停止欺骗
  
      case HDHOOK_UNHOOK:
          HookStop();
          break;
  
      // 告诉驱动当前自己硬盘的序列号值为多少
  
      case HDHOOK_SETSELFVALUE:
        if( InputBufferLength < DISK_SERIAL_BUFF_LENGTH || InputBuffer == NULL){
          IoStatus->Status = STATUS_INVALID_PARAMETER;
          break;
        }
        for(i=0; i< DISK_SERIAL_BUFF_LENGTH ;i++)
          __DiskSerial[i] = ((UCHAR *)InputBuffer)[i];
  
          break;
  
      // 设置新的欺骗的硬盘序列号
  
      case HDHOOK_SETEMULABLEVALUE:
        if( InputBufferLength < DISK_SERIAL_BUFF_LENGTH || InputBuffer == NULL){
          IoStatus->Status = STATUS_INVALID_PARAMETER;
          break;
        }
  
        for(i=0;i< DISK_SERIAL_BUFF_LENGTH ;i++)
          __ChangeTo[i] = ((UCHAR *)InputBuffer)[i];
  
          break;
  
    //返回驱动的版本号
  
    case HDHOOK_VERSION:
          if ( OutputBufferLength < sizeof(ULONG) ||
               OutputBuffer == NULL ) {
              IoStatus->Status = STATUS_INVALID_PARAMETER;
              break;
          }
  
          *(ULONG *)OutputBuffer = REGMONVERSION;
          IoStatus->Information = sizeof(ULONG);
          break;
  
      default:
          IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
          break;
      }
      return TRUE;
  }
  
  
  ////////////////////////////////////////////////
  应用层程序可以通过如下简单代码与驱动进行通信:
  
  #define HDHOOK_HOOK                  (ULONG) CTL_CODE( FILE_DEVICE_REGMON, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS )
  #define HDHOOK_UNHOOK                (ULONG) CTL_CODE( FILE_DEVICE_REGMON, 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS )
  #define HDHOOK_VERSION               (ULONG) CTL_CODE( FILE_DEVICE_REGMON, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS )
  #define HDHOOK_SETSELFVALUE          (ULONG) CTL_CODE( FILE_DEVICE_REGMON, 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS )
  #define HDHOOK_SETEMULABLEVALUE      (ULONG) CTL_CODE( FILE_DEVICE_REGMON, 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS )
  
  #define DISK_SERIAL_BUFF_LENGTH      20
  
  //设置新的序列号模拟值
  DeviceIoControl(__SysHandle,HDHOOK_SETEMULABLEVALUE,szEmulSerial,DISK_SERIAL_BUFF_LENGTH, NULL, 0, &dwDummy, NULL) ;
  
  //告诉驱动自己的硬盘序列号
  DeviceIoControl(__SysHandle,HDHOOK_SETSELFVALUE,szBuffer,DISK_SERIAL_BUFF_LENGTH, NULL, 0, &dwDummy, NULL) ;
  
  //开始拦截
  DeviceIoControl(__SysHandle,HDHOOK_HOOK,NULL,0,NULL,0,&dwDummy,NULL) ;
  
  
  //停止拦截
  DeviceIoControl(__SysHandle,HDHOOK_UNHOOK,NULL,0,NULL,0,&dwDummy,NULL) ;
  
  其中__SysHandle是安装驱动的句柄
  
  
  这篇文章的思路来自regmon(regmon版权申明我保留在文件中),写出来是方便调试那些有正版注册号且以硬盘序列号生成注册码的程序,方便一下大家。
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-5-14 20:03

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表