0xAA55 发表于 2015-1-15 19:46:38

【转】RING3直接读写磁盘扇区

FROM: http://www.kernelmode.info/forum/viewtopic.php?f=15&t=3677
Author: EP_X0FF#include <windows.h>
#include "prtl.h"

#define IOCTL_SCSI_BASE               FILE_DEVICE_CONTROLLER
#define FILE_DEVICE_CONTROLLER          0x00000004
#define IOCTL_ATA_PASS_THROUGH_DIRECT   CTL_CODE(IOCTL_SCSI_BASE, 0x040c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define ATA_FLAGS_DRDY_REQUIRED         (1 << 0)
#define ATA_FLAGS_DATA_IN               (1 << 1)
#define ATA_FLAGS_DATA_OUT            (1 << 2)
#define ATA_FLAGS_48BIT_COMMAND         (1 << 3)
#define ATA_FLAGS_USE_DMA               (1 << 4)
#define ATA_FLAGS_NO_MULTIPLE         (1 << 5)

typedef struct _ATA_PASS_THROUGH_DIRECT
{
    USHORT Length;
    USHORT AtaFlags;
    UCHAR PathId;
    UCHAR TargetId;
    UCHAR Lun;
    UCHAR ReservedAsUchar;
    ULONG DataTransferLength;
    ULONG TimeOutValue;
    ULONG ReservedAsUlong;
    PVOID DataBuffer;
    UCHAR PreviousTaskFile;
    UCHAR CurrentTaskFile;
} ATA_PASS_THROUGH_DIRECT, *PATA_PASS_THROUGH_DIRECT;

#define INBUFFER_SIZE 1024*1024

int IsFileInfested(LPCTSTR FileName, LPVOID RawData, DWORD BufferSize)
{
   ATA_PASS_THROUGH_DIRECT      dio, dioOut;
   STARTING_VCN_INPUT_BUFFER   base;
   RETRIEVAL_POINTERS_BUFFER   *ptrs;
   VOLUME_DISK_EXTENTS         ext;
   LARGE_INTEGER            ofs, lofs;
   __int64                  i, k;

   HANDLE   f = INVALID_HANDLE_VALUE;
   DWORD   iobytes, SectorsPerCluster = 0, BytesPerSector = 0, c, p = 0;
   TCHAR   drive = TEXT("\\\\.\\X:\\");
   WORD    DevId = {0};
   USHORTAtaFlags;
   UCHAR   AtaCommand;

   drive = FileName;
   if ( !GetDiskFreeSpace(&drive, &SectorsPerCluster, &BytesPerSector, NULL, NULL) )
      return -1;

   ptrs = (RETRIEVAL_POINTERS_BUFFER *)VirtualAlloc(NULL, INBUFFER_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
   while ( ptrs != NULL ) {
      f = CreateFile(FileName, GENERIC_READ | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
      if ( f == INVALID_HANDLE_VALUE )
         break;
      base.StartingVcn.QuadPart = 0;
      if ( !DeviceIoControl(f, FSCTL_GET_RETRIEVAL_POINTERS, &base, sizeof(base), ptrs, INBUFFER_SIZE, &iobytes, NULL) )
         break;
      CloseHandle(f);

      drive = 0;
      f = CreateFile(drive, GENERIC_READ | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
      if ( f == INVALID_HANDLE_VALUE )
         break;
      if ( !DeviceIoControl(f, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &ext, sizeof(ext), &iobytes, NULL) )
         break;
      CloseHandle(f);

      f = CreateFile(TEXT("\\\\.\\PHYSICALDRIVE0"), GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
      if ( f == INVALID_HANDLE_VALUE )
         break;

      ext.Extents.StartingOffset.QuadPart /= BytesPerSector;
      lofs.QuadPart = 0;

      memset(&DevId, 0, sizeof(DevId));
      memset(&dio, 0, sizeof(dio));
      dio.Length = sizeof(dio);
      dio.AtaFlags = ATA_FLAGS_DRDY_REQUIRED | ATA_FLAGS_DATA_IN;
      dio.DataTransferLength = 512;
      dio.TimeOutValue = 1;
      dio.DataBuffer = &DevId;
      dio.CurrentTaskFile = 0xEC;
      DeviceIoControl(f, IOCTL_ATA_PASS_THROUGH_DIRECT, &dio, sizeof(dio), &dioOut, sizeof(dioOut), &iobytes, NULL);

      if ((DevId & 0x400) != 0) {
         AtaCommand = 0x25;
         AtaFlags = ATA_FLAGS_DRDY_REQUIRED | ATA_FLAGS_USE_DMA | ATA_FLAGS_DATA_IN | ATA_FLAGS_48BIT_COMMAND;
      } else {
         AtaCommand = 0xC8;
         AtaFlags = ATA_FLAGS_DRDY_REQUIRED | ATA_FLAGS_USE_DMA | ATA_FLAGS_DATA_IN;
      }


      for (c=0; c<ptrs->ExtentCount; c+=1) {
         ofs.QuadPart = ext.Extents.StartingOffset.QuadPart + (ptrs->Extents.Lcn.QuadPart*SectorsPerCluster);
         k = ptrs->Extents.NextVcn.QuadPart - lofs.QuadPart;

         if ( p+(BytesPerSector*SectorsPerCluster) > BufferSize )
            break;

         for (i=0; i<k; i+=1) {
            if ( p+(BytesPerSector*SectorsPerCluster) > BufferSize )
               break;
            lofs.QuadPart = ofs.QuadPart + i*SectorsPerCluster;

            memset(&dio, 0, sizeof(dio));
            dio.Length = sizeof(dio);
            dio.AtaFlags = AtaFlags;
            dio.DataTransferLength = BytesPerSector*SectorsPerCluster;
            dio.TimeOutValue = 1;
            dio.DataBuffer = ((LPBYTE)RawData)+p;

            dio.PreviousTaskFile = (lofs.QuadPart >> 24) & 0xff;
            dio.PreviousTaskFile = (lofs.QuadPart >> 32) & 0xff;
            dio.PreviousTaskFile = (lofs.QuadPart >> 40) & 0xff;

            dio.CurrentTaskFile = (UCHAR)SectorsPerCluster;
            dio.CurrentTaskFile = lofs.QuadPart & 0xff;
            dio.CurrentTaskFile = (lofs.QuadPart >> 8) & 0xff;
            dio.CurrentTaskFile = (lofs.QuadPart >> 16) & 0xff;
            
            if (AtaCommand == 0xC8) {
               dio.CurrentTaskFile = 0x40 | ((lofs.QuadPart >> 24) & 0x0f);
            } else {
               dio.CurrentTaskFile = 0x40;
            }
            
            dio.CurrentTaskFile = 0x40;

            dio.CurrentTaskFile = AtaCommand;
            DeviceIoControl(f, IOCTL_ATA_PASS_THROUGH_DIRECT, &dio, sizeof(dio), &dioOut, sizeof(dioOut), &iobytes, NULL);
            p+=(BytesPerSector*SectorsPerCluster);
         }
         lofs.QuadPart = ptrs->Extents.NextVcn.QuadPart;
      }
      CloseHandle(f);

      VirtualFree(ptrs, 0, MEM_RELEASE);
      return 0;
   }

   if ( f != INVALID_HANDLE_VALUE )
      CloseHandle(f);
   if ( ptrs != NULL )
      VirtualFree(ptrs, 0, MEM_RELEASE);
   return -1;
}

#define sFileName TEXT("C:\\WINDOWS\\system32\\drivers\\fltmgr.sys")

void main()
{
   LPVOID buffer;
   HANDLE   f;
   DWORD   iobytes, fsize = 0;

   

   f = CreateFile(sFileName, GENERIC_READ | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
   if ( f != INVALID_HANDLE_VALUE ) {
      fsize = GetFileSize(f, NULL);
      CloseHandle(f);
   }

   buffer = VirtualAlloc(NULL, fsize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
   memset(buffer, 0xcc, fsize);

   IsFileInfested(sFileName, buffer, fsize);
   f = CreateFile(TEXT("Z:\\TEMP\\4321.dmp"), GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
   if (f != INVALID_HANDLE_VALUE) {
      WriteFile(f, buffer, fsize, &iobytes, NULL);
      CloseHandle(f);
   }
   Sleep(0);
}但EP_X0FF表示:Do you understrand with current hardware + newest Windows installed in EFI mode all legacy BIOS bootkits are no longer work? And after few years computers with BIOS you can only see in the scrapyard?

翻译过来就是:现在的硬件+最新的Windows在EFI模式下,所有的BIOS bootkit将不再有效你造吗?几年后,你只能在废料厂找到有BIOS的电脑。(他说的BIOS指的是Legacy方式引导的电脑。)

0xAA55 发表于 2015-1-21 03:51:31

我觉得……现在“坚持”用XP的人还是很多,恐怕完全淘汰Legacy Boot要很久以后喽

stlcours 发表于 2016-6-3 17:15:15

ring3说明是用户级别的程序?这样也可读写磁盘扇区?

话说谢谢楼主的搬运,不搬运压根不知道有这回事,知道了或许可以自己研究一下~

tx7790 发表于 2017-2-22 10:59:47

谢谢楼主分享,意思就是UEFI的不起作用了吗?
页: [1]
查看完整版本: 【转】RING3直接读写磁盘扇区