首页
社区
课程
招聘
[原创]奇虎360第1题 hook WRITE_PORT_UCHAR
2008-12-19 10:57 60751

[原创]奇虎360第1题 hook WRITE_PORT_UCHAR

2008-12-19 10:57
60751
收藏
点赞7
打赏
分享
最新回复 (41)
雪    币: 198
活跃值: (13)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
曾定国 1 2008-12-19 23:04
26
0
本想写写 lba48 代码,测试一下再发上来,以后终归是要写的,但身体不太舒服,明天还要考四级... 只好下次了
雪    币: 709
活跃值: (2230)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 25 2008-12-19 23:17
27
0
LZ很厉害啊.

学习,现在的学生都这么厉害啊~~
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
weolar 10 2008-12-19 23:22
28
0
写好了一定要发上来~~~我在线等了,嘿嘿。明天下午我也要考………………痛苦啊!!!!!
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
weolar 10 2008-12-19 23:22
29
0
                                             ·
雪    币: 198
活跃值: (13)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
曾定国 1 2008-12-21 09:06
30
0
看了老v  io硬盘的代码, 用的是 CHS 寻址,最大可以访问 8G 硬盘 不存在只能访问头几个扇区的情况。不过我觉得吧,老v 的代码只在传输数据的时候关了中断,那么如果在传输数据之前发生了任务切换,并且切换的过程中 windows 访问了硬盘...那么当切换回来时 硬盘的状态已经发生改变了。其实也就是一个同步的问题

下面是 DeviceIoControl 访问硬盘的代码 , lba48 没有经过测试 ,weolar  能帮忙测一下不? (超过128 G 的硬盘 才用 lba48,不然一般不支持lba48)

直接 io 硬盘的代码就不发了(不想方便干坏事的人)。DeviceIoControl 的代码无法穿透我做一题的那个bin,所以还是可以发一下地。代码有什么错误的 一定要告诉俺,俺感激不尽,俺不想再做硬盘分区了。

#include <Windows.h>
#include <stdio.h>
#include <Winioctl.h>
#include "ntddscsi.h"

#define REG_PRECOMP            0       
#define REG_COUNT            1       
#define REG_SECTOR            2
#define REG_CYL_LO            3       
#define REG_CYL_HI            4       
#define REG_LDH                    5       
#define REG_COMMAND            6       

#define   LDH_DEFAULT                0xA0       
#define   LDH_LBA                0x40       

#define          CMD_WRITE_EXT                0x34
#define   CMD_WRITE                0x30       

#define   CMD_READ_EXT                0x24       
#define   CMD_READ                0x20       

typedef __int64 LONGLONG;

char * write_disk(LONGLONG sec,int cnt,void * buff,int is_lba48 )
{//sec :扇区号; cnt : 扇区数; is_lba48 :是否使用 lba48 ;不使用lba48 可寻址 128G
        HANDLE hDevice;               // handle to the drive to be examined
        BOOL bResult;                 // results flag
        DWORD junk;
        ATA_PASS_THROUGH_DIRECT  rigs;   //
                /*author: zdg102 */
        hDevice = CreateFile("\\\\.\\PhysicalDrive0",  // drive to open
                           GENERIC_ALL,                //
                            FILE_SHARE_READ | // share mode
                            FILE_SHARE_WRITE,
                            NULL,             // default security attributes
                            OPEN_EXISTING,    // disposition
                            0,                // file attributes
                            NULL);            // do not copy file attributes
                           
        if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
        {
                return "cannot open the drive";
        }
       
        rigs.Length = sizeof(rigs);
        rigs.AtaFlags = ATA_FLAGS_DATA_OUT  | ATA_FLAGS_DRDY_REQUIRED  ;//| ATA_FLAGS_USE_DMA;
        if(is_lba48)
                rigs.AtaFlags |= ATA_FLAGS_48BIT_COMMAND;
        rigs.PathId = 0;
        rigs.TargetId = 0 ;
        rigs.Lun = 0;  
        rigs.ReservedAsUchar = 0 ;
        rigs.DataTransferLength = cnt*512;
        rigs.TimeOutValue = 10;
        rigs.ReservedAsUlong = 0;
        rigs.DataBuffer = buff;
       
        rigs.CurrentTaskFile[REG_PRECOMP] = 0;
        rigs.CurrentTaskFile[REG_COUNT] =(char) cnt & 0xff;
        rigs.CurrentTaskFile[REG_SECTOR] =(char) sec & 0xff;
        rigs.CurrentTaskFile[REG_CYL_LO] =(char) (sec>>=8) & 0xff;
        rigs.CurrentTaskFile[REG_CYL_HI] =(char) (sec>>=8) & 0xff;

        rigs.CurrentTaskFile[REG_LDH] = LDH_DEFAULT | LDH_LBA;
        sec>>=8;
        if(!is_lba48)
                rigs.CurrentTaskFile[REG_LDH] |= (char) sec&0xf;

        if(is_lba48)
                rigs.CurrentTaskFile[REG_COMMAND] = CMD_WRITE_EXT;
        else
                rigs.CurrentTaskFile[REG_COMMAND] = CMD_WRITE;

        rigs.CurrentTaskFile[7] = 0;
       
        rigs.PreviousTaskFile[REG_PRECOMP] = 0;
        rigs.PreviousTaskFile[REG_COUNT] =(char) (cnt>>=8)&0xff;
        rigs.PreviousTaskFile[REG_SECTOR] =(char) (sec)&0xff;
        rigs.PreviousTaskFile[REG_CYL_LO] =(char) (sec>>=8)&0xff;
        rigs.PreviousTaskFile[REG_CYL_HI] =(char) (sec>>=8)&0xff;   
        rigs.PreviousTaskFile[REG_LDH] = LDH_DEFAULT | LDH_LBA;
        rigs.PreviousTaskFile[REG_COMMAND] = CMD_WRITE_EXT;
        rigs.PreviousTaskFile[7] = 0;
       
        bResult = DeviceIoControl(hDevice,  // device to be queried
        IOCTL_ATA_PASS_THROUGH_DIRECT,  // operation to perform
                             &rigs, sizeof(rigs), // no input buffer
                            &rigs, sizeof(rigs),     // output buffer
                            &junk,                 // # bytes returned
                            (LPOVERLAPPED) NULL);  // synchronous I/O
       
        if(!bResult)
        {
                bResult = GetLastError();
                return "call DeviceIoControl error\n";
        }
        CloseHandle(hDevice);

        return 0;
}

char * read_disk(LONGLONG sec,int cnt,void * buff,int is_lba48 )
{
        HANDLE hDevice;               // handle to the drive to be examined
        BOOL bResult;                 // results flag
        DWORD junk;
        ATA_PASS_THROUGH_DIRECT  rigs;   //
                /*author: zdg102 */
        hDevice = CreateFile("\\\\.\\PhysicalDrive0",  // drive to open
                           GENERIC_ALL,                //
                            FILE_SHARE_READ | // share mode
                            FILE_SHARE_WRITE,
                            NULL,             // default security attributes
                            OPEN_EXISTING,    // disposition
                            0,                // file attributes
                            NULL);            // do not copy file attributes
                           
        if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
        {
                return "cannot open the drive";
        }
       
        rigs.Length = sizeof(rigs);
        rigs.AtaFlags = ATA_FLAGS_DATA_IN  | ATA_FLAGS_DRDY_REQUIRED  ;//| ATA_FLAGS_USE_DMA;
        if(is_lba48)
                rigs.AtaFlags |= ATA_FLAGS_48BIT_COMMAND;
        rigs.PathId = 0;
        rigs.TargetId = 0 ;
        rigs.Lun = 0;  
        rigs.ReservedAsUchar = 0 ;
        rigs.DataTransferLength = cnt*512;
        rigs.TimeOutValue = 10;
        rigs.ReservedAsUlong = 0;
        rigs.DataBuffer = buff;
       
        rigs.CurrentTaskFile[REG_PRECOMP] = 0;
        rigs.CurrentTaskFile[REG_COUNT] =(char) cnt & 0xff;
        rigs.CurrentTaskFile[REG_SECTOR] =(char) sec & 0xff;
        rigs.CurrentTaskFile[REG_CYL_LO] =(char) (sec>>=8) & 0xff;
        rigs.CurrentTaskFile[REG_CYL_HI] =(char) (sec>>=8) & 0xff;

        rigs.CurrentTaskFile[REG_LDH] = LDH_DEFAULT | LDH_LBA;
        sec>>=8;
        if(!is_lba48)
                rigs.CurrentTaskFile[REG_LDH] |= (char) sec&0xf;

        if(is_lba48)
                rigs.CurrentTaskFile[REG_COMMAND] = CMD_READ_EXT;
        else
                rigs.CurrentTaskFile[REG_COMMAND] = CMD_READ;

        rigs.CurrentTaskFile[7] = 0;
       
        rigs.PreviousTaskFile[REG_PRECOMP] = 0;
        rigs.PreviousTaskFile[REG_COUNT] =(char) (cnt>>=8)&0xff;
        rigs.PreviousTaskFile[REG_SECTOR] =(char) (sec)&0xff;
        rigs.PreviousTaskFile[REG_CYL_LO] =(char) (sec>>=8)&0xff;
        rigs.PreviousTaskFile[REG_CYL_HI] =(char) (sec>>=8)&0xff;   
        rigs.PreviousTaskFile[REG_LDH] = LDH_DEFAULT | LDH_LBA;
        rigs.PreviousTaskFile[REG_COMMAND] = CMD_READ_EXT;
        rigs.PreviousTaskFile[7] = 0;
       
        bResult = DeviceIoControl(hDevice,  // device to be queried
        IOCTL_ATA_PASS_THROUGH_DIRECT,  // operation to perform
                             &rigs, sizeof(rigs), // no input buffer
                            &rigs, sizeof(rigs),     // output buffer
                            &junk,                 // # bytes returned
                            (LPOVERLAPPED) NULL);  // synchronous I/O
       
        if(!bResult)
        {
                bResult = GetLastError();
                return "call DeviceIoControl error\n";
        }
        CloseHandle(hDevice);

        return 0;
}

char data[1024] = "fuck your disk";

int main()
{
        int i,j,k;
        i=0;

        write_disk(1,1,data,0);

        do
        {
                read_disk(i,1,data,0);
                for(k=0;k<0x20;k++)
                {
                        for(j=0;j<16;j++)
                        {
                                printf("%2X ",data[j+k*16]&0xff);
                        }
                        printf("   ");
                        for(j=0;j<16;j++)
                        {
                                if( (data[j+k*16]&0xff) > 0x20 && (data[j+k*16]&0xff) < 0x7f)
                                        printf("%c",data[j+k*16]&0xff);
                                else
                                        printf(".");
                        }
                        printf("\n");
                }
                scanf("%d",&i);
        }while(i>=0);
       
       
        printf("ok");
       
        return 0;
}
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
qihoocom 9 2008-12-21 09:41
31
0
ata pass through没意思,早被guard field拦了~
老V那个代码纯属意淫,完全没法用的 试试就知道
雪    币: 581
活跃值: (149)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 14 2008-12-21 09:52
32
0
汗....正想ata pass through呢/....
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
weolar 10 2008-12-21 10:23
33
0
呵呵,我测试在大硬盘上没问题
雪    币: 204
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wdsm 2008-12-21 12:12
34
0
好东西,来看看。这题我中招了。
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
weolar 10 2008-12-28 13:25
35
0
贴个老点的lba48资料:

LBA HDD Access via PIO
Every operating system will eventually find a need for reliable, long-term storage. There are only a handful of commonly used storage devices:

Floppy

Flash media

CD-ROM

Hard drive

Hard drives are by far the most widely used mechanism for data storage, and this tutorial will familiarize you with a practical method for accessing them. In the past, a method known as CHS was used. With CHS, you specified the cylinder, head, and sector where your data was located. The problem with this method is that the number of cylinders that could be addressed was rather limited. To solve this problem, a new method for accessing hard drives was created: Linear Block Addressing (LBA). With LBA, you simply specify the address of the block you want to access. Blocks are 512-byte chunks of data, so the first 512 bytes of data on the disk are in block 0, the next 512 bytes are in block 1, etc. This is clearly superior to having to calculate and specify three separate bits of information, as with CHS. However, there is one hitch with LBA. There are two forms of LBA, which are slightly different: LBA28 and LBA48. LBA28 uses 28 bits to specify the block address, and LBA48 uses 48 bits. Most drives support LBA28, but not all drives support LBA48. In particular, the Bochs emulator supports LBA28, and not LBA48. This isn't a serious problem, but something to be aware of. Now that you know how LBA works, it's time to see the actual methods involved.

To read a sector using LBA28:

Send a NULL byte to port 0x1F1: outb(0x1F1, 0x00);

Send a sector count to port 0x1F2: outb(0x1F2, 0x01);

Send the low 8 bits of the block address to port 0x1F3: outb(0x1F3, (unsigned char)addr);

Send the next 8 bits of the block address to port 0x1F4: outb(0x1F4, (unsigned char)(addr >> 8);

Send the next 8 bits of the block address to port 0x1F5: outb(0x1F5, (unsigned char)(addr >> 16);

Send the drive indicator, some magic bits, and highest 4 bits of the block address to port 0x1F6: outb(0x1F6, 0xE0 | (drive << 4) | ((addr >> 24) & 0x0F));

Send the command (0x20) to port 0x1F7: outb(0x1F7, 0x20);

To write a sector using LBA28:

Do all the same as above, but send 0x30 for the command byte instead of 0x20: outb(0x1F7, 0x30);

To read a sector using LBA48:

Send two NULL bytes to port 0x1F1: outb(0x1F1, 0x00); outb(0x1F1, 0x00);

Send a 16-bit sector count to port 0x1F2: outb(0x1F2, 0x00); outb(0x1F2, 0x01);

Send bits 24-31 to port 0x1F3: outb(0x1F3, (unsigned char)(addr >> 24));

Send bits 0-7 to port 0x1F3: outb(0x1F3, (unsigned char)addr);

Send bits 32-39 to port 0x1F4: outb(0x1F4, (unsigned char)(addr >> 32));

Send bits 8-15 to port 0x1F4: outb(0x1F4, (unsigned char)(addr >> 8));

Send bits 40-47 to port 0x1F5: outb(0x1F5, (unsigned char)(addr >> 40));

Send bits 16-23 to port 0x1F5: outb(0x1F5, (unsigned char)(addr >> 16));

Send the drive indicator and some magic bits to port 0x1F6: outb(0x1F6, 0x40 | (drive << 4));

Send the command (0x24) to port 0x1F7: outb(0x1F7, 0x24);

To write a sector using LBA48:

Do all the same as above, but send 0x34 for the command byte, instead of 0x24: outb(0x1F7, 0x34);

Once you've done all this, you just have to wait for the drive to signal that it's ready:

while (!(inb(0x1F7) & 0x08)) {}

And then read/write your data from/to port 0x1F0:

// for read:

for (idx = 0; idx < 256; idx++)

{

tmpword = inw(0x1F0);

buffer[idx * 2] = (unsigned char)tmpword;

buffer[idx * 2 + 1] = (unsigned char)(tmpword >> 8);

}

// for write:

for (idx = 0; idx < 256; idx++)

{

tmpword = buffer[8 + idx * 2] | (buffer[8 + idx * 2 + 1] << 8);

outw(0x1F0, tmpword);

}

Of course, all of this is useless if you don't know what drives you actually have hooked up. Each IDE controller can handle 2 drives, and most computers have 2 IDE controllers. The primary controller, which is the one I have been dealing with thus-far has its registers located from port 0x1F0 to port 0x1F7. The secondary controller has its registers in ports 0x170-0x177. Detecting whether controllers are present is fairly easy:

Write a magic value to the low LBA port for that controller (0x1F3 for the primary controller, 0x173 for the secondary): outb(0x1F3, 0x88);

Read back from the same port, and see if what you read is what you wrote. If it is, that controller exists.

Now, you have to detect which drives are present on each controller. To do this, you simply select the appropriate drive with the drive/head select register (0x1F6 for the primary controller, 0x176 for the secondary controller), wait a small amount of time (I wait 1/250th of a second), and then read the status register and see if the busy bit is set:

outb(0x1F6, 0xA0); // use 0xB0 instead of 0xA0 to test the second drive on the controller

sleep(1); // wait 1/250th of a second

tmpword = inb(0x1F7); // read the status port

if (tmpword & 0x40) // see if the busy bit is set

{

printf("Primary master exists\n");

}

And that about wraps it up. Note that I haven't actually tested my LBA48 code, because I'm stuck with Bochs, which only supports LBA28. It should work, according to the ATA specification.

If any of this is inaccurate or unclear, just email me at marsdragon88@gmail.com.
雪    币: 581
活跃值: (149)
能力值: ( LV12,RANK:600 )
在线值:
发帖
回帖
粉丝
Sysnap 14 2008-12-28 18:31
36
0
嗯....读写扇区走到IN/OUT指令...下面的就是在ox1f0-0x1f7下断点了..
雪    币: 198
活跃值: (13)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
曾定国 1 2008-12-29 20:28
37
0
咳!怎么我就没找到这么详细的资料啊,悲痛,早看到就不用去纯dos 跟踪 int 13 了

weolar 在哪找到的 ?
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
weolar 10 2008-12-29 20:30
38
0

你说lba48,我就到处搜索lba48 io 、port等关键字,无意中找到的
雪    币: 198
活跃值: (13)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
曾定国 1 2008-12-29 20:32
39
0
前几天在代码里发现了一个错误

if((at_rig[REG_CYL_HI] == 0)&& (at_rig[REG_CYL_LO] == 0) &&

(at_rig[REG_SECTOR] == 1) && ((at_rig[REG_LDH]&0x10) == 0))

要改成

if((at_rig[REG_CYL_HI] == 0)&& (at_rig[REG_CYL_LO] == 0) &&

(at_rig[REG_SECTOR] == 1) && ((at_rig[REG_LDH]&0x1f) == 0))
雪    币: 198
活跃值: (13)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
曾定国 1 2008-12-29 20:33
40
0
不是 lba48,而是 io 硬盘的方法
雪    币: 198
活跃值: (13)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
曾定国 1 2008-12-29 20:42
41
0
网上 也又很多 io硬盘的方法 ,但是执行起来总是有问题,也没有什么检测硬盘存在的问题,经常都是虚拟机上正常,真机子上就不行了。
后来还是跟踪 int 13h + atapi 文档 解决的
雪    币: 364
活跃值: (152)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
weolar 10 2008-12-29 20:50
42
0
呵呵,牛!
io硬盘也得看是什么接口的,很麻烦啊
游客
登录 | 注册 方可回帖
返回