WIN32和Kernel)直接讀寫硬盤扇區


第一篇寫技術的文章哦,以前好少寫文章,我的文字表達很差勁,大家不要笑哦.
前幾天仙劍4通關了,感覺好惆悵,什么都不想去做.今天看了一下書發現一篇比較好玩的文章,於是自己靜靜地實踐一番.文章是<基於硬盤保留扇區的軟件保護方法(作者:熊志勇)>,內容是介紹了怎么讀寫硬盤保留扇區.以下是我的學習日記.

這里是摘自文章里的一個表:硬盤的總體結構
***********************************************************************
編號       名稱                                     備注
1          主引導扇區(含硬盤分區表)            占用一個扇區空間(一個扇區空間為512字節)
2          保留扇區(操作系統不使用的扇區)    占用62個扇區空間
3          第一個分區                              C:
4          擴展主引導扇區(含擴展分區表)       一個扇區空間(只有存在擴展分區是才存在)
5          保留扇區                                占用62個扇區空間
6          2個分區                               D:
7          下一個擴展主引導扇區                 只有分區鏈沒結束才存在
8          ......                                    ......
***********************************************************************

通常的軟件保護都會向編號為2的保留扇區寫一些軟件注冊信息呀,等等的東西.
而要讀寫這個沒被操作系統利用的部分作者已經給出了代碼(幸福呀,不用自己找).

//以下是已經做好的一個函數

BOOL ReadPhysicalSector(unsigned long SectorStart, unsigned long SectorCount, unsigned char *p)

{

    unsigned long BytesPerSector = 512;

    unsigned long nBytes;

    char Drive[] = "////.//PHYSICALDRIVE0";

    BOOL result = FALSE;

    HANDLE hDeviceHandle = CreateFile(Drive,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,0);

    if(hDeviceHandle)

    {

        long pointer;

        long phigh;

        pointer = SectorStart;

        pointer = pointer*BytesPerSector;

        phigh = pointer>>32;

        SetFilePointer(hDeviceHandle,(unsigned long)pointer,&phigh,FILE_BEGIN);

        if(ReadFile(hDeviceHandle,p,SectorCount*BytesPerSector,&nBytes,NULL))

            result = TRUE;

        CloseHandle(hDeviceHandle);

    }

    return result;

}

 

//調用就這樣

int main(int argc, char* argv[])

{

    unsigned long SectorStart = 0;//比如我要讀的是編號為的那個扇區開始的數據,這里寫

                                  //如果讀的是從第扇區開始后的數據這里就寫

    unsigned long SectorCount = 1;//讀多少個扇區,這里是個

    unsigned char p[512];//一個扇區數據量是字節呀

    ReadPhysicalSector(SectorStart, SectorCount, p);

    for(int i=0;i<512;i++)//輸出的

    {

        printf("%02X ",p[i]);

        if(i%26==0)

            printf(" ");

    }

    return 0;

}

以上的代碼都是讀的,那如果要寫就把ReadFile改成WriteFile呀.要注意的是別亂寫了分區表了,很難恢復的.小心用WriteFile呀.

以上的我就實現了,其實也是抄人家的代碼,5555555沒意思,突然間想把這些功能用驅動來實現.
想就快呀,第一時間上網找ZwWriteFile,ZwReadFile的使用啦,想不到在baidu搜的都是怎么hook ZwWriteFile,ZwReadFile他們的文章,555555那個簡單啦,不就改改SSDT然后自己定義函數嘛
.
但是......ZwWriteFile,ZwReadFile怎么用的文章幾乎沒有的.天呀!好慘!

接着我看好久的DDK文檔,看了很久ZwWriteFile,ZwReadFile的函數原型,就一步步寫出以下的代碼出來,經過了n的n次方次的失敗后終於......成功讀取了第一個扇區的數據了.

#include<ntddk.h>

 

//--------------------------------------------------------------------

VOID ReadPhysicalSector(unsigned long SectorCount, unsigned char *p)

{

    unsigned long BytesPerSector = 512;

    WCHAR* name = L"//??//PHYSICALDRIVE0";//這個找了好久呀,原來要這樣寫的

 

    NTSTATUS ntStatus;

    HANDLE hDeviceHandle;

    IO_STATUS_BLOCK IoStatusBlock;

    IO_STATUS_BLOCK IoStatusBlockR;

    OBJECT_ATTRIBUTES ObjectAttributesL;

    UNICODE_STRING UniFileNameL;

 

    LARGE_INTEGER ByteOffset;

 

    RtlInitUnicodeString(&UniFileNameL,name);

    InitializeObjectAttributes( &ObjectAttributesL,

                                &UniFileNameL,

                                OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,

                                NULL,

                                NULL);

 

    ntStatus = ZwCreateFile(&hDeviceHandle,

                            GENERIC_READ,

                            &ObjectAttributesL,

                            &IoStatusBlock,

                            NULL,

                            0,

                            FILE_SHARE_READ,

                            FILE_OPEN,

                            FILE_SYNCHRONOUS_IO_ALERT,

                            NULL,

                            0);

   

    if( NT_SUCCESS(ntStatus) )

    {

        DbgPrint("Open Success");

 

        ByteOffset.LowPart = FILE_USE_FILE_POINTER_POSITION;

        ByteOffset.HighPart = -1;

 

        ntStatus = ZwReadFile(  hDeviceHandle,

                                NULL,

                                NULL,

                                NULL,

                                &IoStatusBlockR,

                                p,

                                SectorCount*BytesPerSector,

                                &ByteOffset,

                                NULL);

 

        if( NT_SUCCESS(ntStatus) )

        {

            DbgPrint("Read Success");

        }

    }

 

    ZwClose(hDeviceHandle);

}

//--------------------------------------------------------------------

VOID OnUnload(IN PDRIVER_OBJECT DriverObject)

{

    DbgPrint("     88  ");

}

 

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)

{

    unsigned long SectorCount = 1;

    unsigned char p[512];

    int i;

   

    DriverObject->DriverUnload = OnUnload;

 

    DbgPrint("Hi");

 

    ReadPhysicalSector(SectorCount, p);

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

        DbgPrint("%02X ",p[i]);

 

    return STATUS_SUCCESS;

}

終於讀取成功了,寫就Read改成Write呀,哎....其實我都是剛剛學什么都不會,看了好久DDK文檔才擠出上面幾行代碼.....但是現在我最不明白的就是ZwReadFile中怎么定位指針的位置呢,比如我想在第2個扇區開始讀應該怎么寫呢?55555555不想啦,很煩啊.....有高手路過就批一下啦,最好教一下我.

好啦今天一起床,想了想,又看了看DDK終於將以上的問題解決了,可以任意讀取某一個扇區了~~~~~~~~~~~心情當然非常激動啦~~~啦~~~啦~

原來錯誤就在這兩句里面,DDK誤導人的,還是我的英文差呢~~~~~~好啦~~~其實DDK是這么說的:

ByteOffset

Pointer to a variable that specifies the starting byte offset in the file where the read operation will begin. If an attempt is made to read beyond the end of the file, ZwReadFile returns an error.

If the call to ZwCreateFile set either of the CreateOptions flags FILE_SYNCHRONOUS_IO_ALERT or FILE_SYNCHRONOUS_IO_NONALERT, the I/O Manager maintains the current file position. If so, the caller ofZwReadFile can specify that the current file position offset be used instead of an explicit ByteOffset value. This specification can be made by using one of the following methods:

● Specify a pointer to a LARGE_INTEGER value with the HighPart member set to -1 and the LowPartmember set to the system-defined value FILE_USE_FILE_POINTER_POSITION.

● Pass a NULL pointer for ByteOffset.

ZwReadFile updates the current file position by adding the number of bytes read when it completes the read operation, if it is using the current file position maintained by the I/O Manager.

Even when the I/O Manager is maintaining the current file position, the caller can reset this position by passing an explicit ByteOffset value to ZwReadFile. Doing this automatically changes the current file position to that ByteOffset value, performs the read operation, and then updates the position according to the number of bytes actually read. This technique gives the caller atomic seek-and-read service.

 

//今天不按照它說的來做,

ByteOffset.LowPart = FILE_USE_FILE_POINTER_POSITION;

ByteOffset.HighPart = -1;

//改成:

ByteOffset.QuadPart = //第幾個字節;

//終於成功了:

代碼如下:

#include<ntddk.h>

 

//--------------------------------------------------------------------

VOID ReadPhysicalSector(unsigned long SectorStart,unsigned long SectorCount,unsigned char *p)

{

    unsigned long BytesPerSector = 512;

    WCHAR* name = L"//??//PHYSICALDRIVE0";//這個找了好久呀,原來要這樣寫的

 

    NTSTATUS ntStatus;

    HANDLE hDeviceHandle;

    IO_STATUS_BLOCK IoStatusBlock;

    IO_STATUS_BLOCK IoStatusBlockR;

    OBJECT_ATTRIBUTES ObjectAttributesL;

    UNICODE_STRING UniFileNameL;

 

    LARGE_INTEGER ByteOffset;

 

    RtlInitUnicodeString(&UniFileNameL,name);

    InitializeObjectAttributes( &ObjectAttributesL,

                                &UniFileNameL,

                                OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,

                                NULL,

                                NULL);

 

    ntStatus = ZwCreateFile(&hDeviceHandle,

                            GENERIC_READ,

                            &ObjectAttributesL,

                            &IoStatusBlock,

                            NULL,

                            0,

                            FILE_SHARE_READ,

                            FILE_OPEN,

                            FILE_SYNCHRONOUS_IO_ALERT,

                            NULL,

                            0);

   

    if( NT_SUCCESS(ntStatus) )

    {

        DbgPrint("Open Success");

 

//      ByteOffset.LowPart = FILE_USE_FILE_POINTER_POSITION;

//      ByteOffset.HighPart = -1;不要用這兩句換成下面一句,DDK誤導人啊~~~~~

        ByteOffset.QuadPart = SectorStart*BytesPerSector;//是這句了

 

        ntStatus = ZwReadFile(  hDeviceHandle,

                                NULL,

                                NULL,

                                NULL,

                                &IoStatusBlockR,

                                p,

                                SectorCount*BytesPerSector,

                                &ByteOffset,

                                NULL);

 

        if( NT_SUCCESS(ntStatus) )

        {

            DbgPrint("Read Success");

        }

    }

 

    ZwClose(hDeviceHandle);

}

//--------------------------------------------------------------------

VOID OnUnload(IN PDRIVER_OBJECT DriverObject)

{

    DbgPrint("     88  ");

}

 

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)

{

    unsigned long SectorStart = 63;//現在是讀扇區啦

    unsigned long SectorCount = 1;

    unsigned char p[512];

    int i;

   

    DriverObject->DriverUnload = OnUnload;

 

    DbgPrint("Hi");

 

    ReadPhysicalSector(SectorStart ,SectorCount, p);

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

        DbgPrint("%02X ",p[i]);

 

    return STATUS_SUCCESS;

}

 

http://blog.csdn.net/cooblily/article/details/1737703


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM