A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #13567  by AlexCasual
 Thu May 31, 2012 11:01 am
Hello guys!
I'm writting Usb LowFilters driver and in AddDevice routine i want send directly to usb mass storage device some scsi command :
(before this I configurate usb mass storage device and get pipes handles - pipeIn/pipeOut)
Code: Select all
...
typedef struct  _CBW                           //command block wrapper
{
	unsigned int Signature;
	unsigned int Tag;
	unsigned int dataTransferLength;
	unsigned char Flags;
	unsigned char Lun;
	unsigned char cbdLength;		//scsi command block length
	unsigned char cbd[16];		//scsi command block data
} CBW, * PCBW;
...
typedef struct _CSW                 //command status wrapper
{
	unsigned int Signature;
	unsigned int Tag;
	unsigned int dataResidue;
	unsigned char Status;
} CSW, * PCSW;
Code: Select all
URB urb;
NTSTATUS ntStatus = STATUS_SUCCESS;

PCBW commandBlock;
PCSW statusBlock;
char*       buffer; 
int          dataLen = 36; //INQURY data len

commandBlock  = (PCBW *)ExAllocatePool(PagedPool,sizeof(CBW ));
statusBlock       = (PCSW *)ExAllocatePool(PagedPool,sizeof(CSW));
buffer               = (char*) ExAllocatePool(PagedPool,sizeof(char)*dataLen );

commandBlock->Signature = 0x43425355;  // command block signature 'USBC'
commandBlock->Flags        = 0x80;//80->data in
commandBlock->Lun          = 0; //default Logical Unit Number

RtlZeroMemory(commandBlock->cbd,16);

//[b]now i try get INQURY iinfo from device[/b]

commandBlock->Tag                         = - TAG_INQUIRY; // TAG_INQUIRY = 18
commandBlock->dataTransferLength = 36;   //INQUIRY_REPLY_LENGTH
commandBlock->Flags                      = 0x80; //inquiry data will flow In
commandBlock->cbdLength              = 6;    //inquiry command length 

[i]//scsi command block[/i]
commandBlock->cbd[0] = 0x12; //inquiry operation code
commandBlock->cbd[1] = 0;  //lun/reserved
commandBlock->cbd[2] = 0;    //page code
commandBlock->cbd[3] = 0;    //reserved
commandBlock->cbd[4] = 36;   //inquiry reply length
commandBlock->cbd[5] = 0;    //reserved/flag/link/

//[b]start mass storage transaction - CBW-DATA-CSW[/b]

[i]//scsi command block[/i]
UsbBuildInterruptOrBulkTransferRequest(&urb, 
							    sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
							    pipeOut, 
							    block, 
							    NULL, 
							   31,
							   USBD_TRANSFER_DIRECTION_OUT,
							   NULL);

ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);

[i]//data[/i]
if (NT_SUCCESS(ntStatus))
{
    UsbBuildInterruptOrBulkTransferRequest(&urb, 
								sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
								pipeIn,
								buffer,
								NULL, 
								dataLen, 
								USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
								NULL);

   ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
}
[i]//status command block[/i]
statusBlock->Signature      = 0x53425355 // 'USBS'
statusBlock->Tag              = -TAG_CSW; // TAG_CSW = 37
statusBlock->dataResidue = 0;//residue;
statusBlock->Status          = 0;

if (NT_SUCCESS(ntStatus))
{
    UsbBuildInterruptOrBulkTransferRequest(&urb,
			                                        sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),
								pipeIn,
								packet,
								NULL,
								13,
								USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
								NULL);

     ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
}

ASSERT(statusBlock->Status == 0); [b]//FINE!Info recived![/b]
.....
And it work fine ((statusBlock->Status == 0 and buffer include inqury info)! But if I want to get TEST UNIT READY command or REPORT LUNS command it failed...
May be I don't undestan transaction mechanism?
This code for TEST UNIT READY :
Code: Select all
URB urb;
NTSTATUS ntStatus = STATUS_SUCCESS;

PCBW commandBlock;
PCSW statusBlock;
char*       buffer; 
commandBlock  = (PCBW *)ExAllocatePool(PagedPool,sizeof(CBW ));
statusBlock       = (PCSW *)ExAllocatePool(PagedPool,sizeof(CSW));

commandBlock->Signature = 0x43425355;  // command block signature 'USBC'
commandBlock->Flags        = 0x80;//80->data in
commandBlock->Lun          = 0; //Logical Unit Number

RtlZeroMemory(commandBlock->cbd,16);

//[b]now i try send TEST UNIT READY[/b]

commandBlock->Tag                         = - TAG_UNIT_READY; // TAG_INQUIRY = 25
commandBlock->dataTransferLength = 0;   //INQUIRY_REPLY_LENGTH
commandBlock->Flags                      = 0x80; //inquiry data will flow In
commandBlock->cbdLength              = 6;    //test unit ready command length 

[i]//scsi command block[/i]
commandBlock->cbd[0] = 0x0; //inquiry operation code
commandBlock->cbd[1] = 0;  //lun/reserved
commandBlock->cbd[2] = 0;    //page code
commandBlock->cbd[3] = 0;    //reserved
commandBlock->cbd[4] = 0;   //inquiry reply length
commandBlock->cbd[5] = 0;    //reserved/flag/link/

//[b]start mass storage transaction - CBW-DATA-CSW[/b]

[i]//scsi command block[/i]
UsbBuildInterruptOrBulkTransferRequest(&urb, 
							    sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
							    pipeOut, 
							    block, 
							    NULL, 
							   31,
							   USBD_TRANSFER_DIRECTION_OUT,
							   NULL);

ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);

[i]//status command block[/i]
statusBlock->Signature      = 0x53425355 // 'USBS'
statusBlock->Tag              = -TAG_CSW; // TAG_CSW = 37
statusBlock->dataResidue = 0;//residue;
statusBlock->Status          = 0;

if (NT_SUCCESS(ntStatus))
{
    UsbBuildInterruptOrBulkTransferRequest(&urb,
			                                        sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),
								pipeIn,
								packet,
								NULL,
								13,
								USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
								NULL);

     ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
}

ASSERT(statusBlock->Status == 0); // [b]status always return 1 for LUN =0 and other LUN (0...256), but sometimes return 0 for LUN = 0 and etc. - it's WRONG [/b]
...
Usb mass storage device 'A' hase 1 LUN - 0,but TEST UNIT READY return 1 for this,usb mass storage device 'B' hase 2 LUNs,but TEST UNIT READY 1 for each lun...

And when I try to read some info from device :
Code: Select all
URB urb;
NTSTATUS ntStatus = STATUS_SUCCESS;

PCBW commandBlock;
PCSW statusBlock;
char*       buffer; 
int          dataLen = 128;

commandBlock  = (PCBW *)ExAllocatePool(PagedPool,sizeof(CBW ));
statusBlock       = (PCSW *)ExAllocatePool(PagedPool,sizeof(CSW));
buffer               = (char*) ExAllocatePool(PagedPool,sizeof(char)*dataLen );

commandBlock->Signature = 0x43425355;  // command block signature 'USBC'
commandBlock->Flags        = 0x80;//80->data in
commandBlock->Lun          = 0; //Logical Unit Number

RtlZeroMemory(commandBlock->cbd,16);

//[b]now i try get INQURY iinfo from device[/b]

commandBlock->Tag                         = - TAG_READ_6; // TAG_INQUIRY = 14
commandBlock->dataTransferLength = dataLen ;   //READ LEN
commandBlock->Flags                      = 0x80; //read data will flow In
commandBlock->cbdLength              = 6;    //read command length 

[i]//scsi command block[/i]
commandBlock->cbd[0] = 0x28; //read 6 operation code
commandBlock->cbd[1] = 0;  //lun/reserved
commandBlock->cbd[2] = 0;    //page code
commandBlock->cbd[3] = 0;    //try read first sector
commandBlock->cbd[4] = dataLen;   //readreply length
commandBlock->cbd[5] = 0;    //reserved/flag/link/

//[b]start mass storage transaction - CBW-DATA-CSW[/b]

[i]//scsi command block[/i]
UsbBuildInterruptOrBulkTransferRequest(&urb, 
							    sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
							    pipeOut, 
							    block, 
							    NULL, 
							   31,
							   USBD_TRANSFER_DIRECTION_OUT,
							   NULL);

ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);

[i]//read data[/i]

if (NT_SUCCESS(ntStatus))
{
    UsbBuildInterruptOrBulkTransferRequest(&urb, 
								sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
								pipeIn,
								buffer,
								NULL, 
								dataLen, 
								USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
								NULL);

   ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE);
   [b][i]//now buffer contain 'USBS' signature in first bytes![/i][/b]
}
[i]//status command block[/i]
statusBlock->Signature      = 0x53425355 // 'USBS'
statusBlock->Tag              = -TAG_CSW; // TAG_CSW = 37
statusBlock->dataResidue = 0;//residue;
statusBlock->Status          = 0;

if (NT_SUCCESS(ntStatus))
{
    UsbBuildInterruptOrBulkTransferRequest(&urb,
			                                        sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER),
								pipeIn,
								packet,
								NULL,
								13,
								USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
								NULL);

     ntStatus = SendAndWaitUrb(deviceObject, &urb,TRUE); // ***
}

[b][i]//and now i'm don't return from SendAndWaitUrb(***)....deadlock [/i][/b]
.....
In this case (read 6 command) after send command block I'm recived in buffer 'USBS' signature,but WHY?

Please guys help me!