On USB Driver #4

November 3, 2007

Hi,

As you’ve seen, there are a series of Configuration to accomplish in order to have a fully transactional USB Driver, now is the time on I/O Configuration which sounds also as IO Implementation. Essentially we have to implement a Device IO Control Handler, in other words a mechanism that for each IO Request provides a different procedure.

This is the procedure to send an IO Request (directly taken from Microsoft USB_WDF Documentation):

  • Create the request or use a request that the framework delivered.
  • Set up the memory objects and buffers for the request.
  • Format the request.
  • Set an I/O completion callback for the request, if appropriate.
  • Send the request.

Let’s consider an InGoing requests are processed troughout In/Out Endpoints, so everything you put into In-Endpoint are pulled out the Out-Endpoint, we have the called Double Buffered Mechanism.

VOID
EvtDeviceIoWrite(
IN WDFQUEUE  Queue,
IN WDFREQUEST  Request,
IN size_t  Length
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT devCtx = NULL;
WDFMEMORY requestMem;

devCtx = GetDeviceContext(WdfIoQueueGetDevice(Queue));

status = WdfRequestRetrieveInputMemory(Request, &requestMem);

status = WdfUsbTargetPipeFormatRequestForWrite(
devCtx->UsbBulkOutPipe,
Request,
requestMem,
NULL);

WdfRequestSetCompletionRoutine(Request,
EvtIoWriteComplete,
devCtx->UsbBulkOutPipe);

status = WdfRequestGetStatus(Request);
WdfRequestComplete(Request, status);

The EvtIoWriteComplete associated with our EvtDeviceIoWrite to fix unreferenced parameters as Context and Target.

Let’s se now an Asynchronous Read Request:

VOID EvtIoReadRequest(IN WDFQUEUE         Queue,
IN WDFREQUEST       Request,
IN size_t           Length
)
{
WDFUSBPIPE          pipe;
NTSTATUS            status;
WDFMEMORY           reqMemory;
PDEVICE_CONTEXT     pDeviceContext;

pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
pipe = pDeviceContext->BulkReadPipe;
status = WdfRequestRetrieveOutputMemory(Request, &reqMemory);
status = WdfUsbTargetPipeFormatRequestForRead(pipe,
Request,
reqMemory,
NULL // Offsets
);
WdfRequestSetCompletionRoutine( Request,
EvtRequestReadCompletionRoutine,
pipe
);
if (WdfRequestSend(Request,
WdfUsbTargetPipeGetIoTarget(pipe),
WDF_NO_SEND_OPTIONS) == FALSE) {
status = WdfRequestGetStatus(Request);
goto Exit;
}
Exit:
if (!NT_SUCCESS(status)) {
WdfRequestCompleteWithInformation(Request, status, 0);
}
return;
}

[Code is taken from USB_WDF.doc]

As you’ve seen from the code, the involved Functions are WdfRequestRetrieveOutputMemory, WdfUsbTargetPipeFormatRequestForRead and WdfUsbTargetPipeGetIoTarget, for the Reading Process.

For write request we have WdfUsbTargetPipeFormatRequestForWrite and WdfUsbTargetPipeWriteSynchronously.

Here some coding reference:

http://www.microsoft.com/whdc/driver/wdf/default.mspx
http://www.microsoft.com/whdc/driver/wdf/kmdf-arch.mspx
http://go.microsoft.com/fwlink/?LinkId=80613

http://go.microsoft.com/fwlink/?LinkId=80619

With this post, ends the pure theoretical part, next post will contains 1 or 2 downloadable source code drivers, and observations about USB Security.

See you to the next post.. 🙂

http://go.microsoft.com/fwlink/?LinkId=83355


On USB Driver #3

November 1, 2007

Hi,

As you can see from the previous posts, Usb Architecture is more complex that other Serial Interfaces, due to layerization and complex packet architecture, so is necessary to have a well organized Coding Framework, to avoid and mitiagate the coding difficulties.
To implement a basical USB Device Driver, you need The latest version of the WDF DDK, Version 1.1 of the KMDF, and for professionally intersted subject in USB Coding OSR USB-FX2 learning kit.

Common WDM functions are great for USB Coding, but is any case coder needs to implements complex mechanisms, that can lead to heavy performances/working problems of the driver you coded, so Microsoft provided with KMDF an Encapsulation mechanism, that make more easy the code implementation.

The Device Descriptor

As previously said, the first operation to access an USB Device is to fill the Device Descriptor, that contains between the other settings the Number of Configurations, this field in our case is 1, because WDF supports only one onfiguration. Each Configuration has a Descriptor, that mantains trace of all Active Interfaces, these interfaces can have alternate settings, in other words various Endpoints, but at least you need for each interface Endpoint0. Pay attention to the USB Device Specifications, because many devices does not supports Multiple Alternate Settings, and your driver will deadly BSOD.

Now let’s see how to Configure our USB Device:

NTSTATUS ConfigOurUsb(WDFDEVICE Device, PDEVICE_CONTEXT DeviceContext)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT pDeviceContext;
WDF_USB_DEVICE_SELECT_CONFIG_PARAMS usbConfig;

status = WdfUsbTargetDeviceCreate(Device,
WDF_NO_OBJECT_ATTRIBUTES,
&DeviceContext->UsbDevice);

WdfUsbTargetDeviceCreate, takes as input parameters a handle to the device object and a pointer to a WDF_OBJECT_ATTRIBUTES structure and returns a handle to a WDFUSBDEVICE object, if Configuration goes ok, we can Select the Choised Configuration, we will use:

WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_SINGLE_INTERFACE

WdfUsbTargetDeviceSelectConfig, creates WDF USB interface and pipe objects, and returns information about the specified configuration. Is importanto to say that the configuration process is done by filling WDF_USB_DEVICE_SELECT_CONFIG_PARAMS structs (which have In and Out params). As you have seen we uses INIT_SINGLE_INTERFACE, but KMDF have various INIT_XXX pre setted configs, so you’ve only to choise the one you need. There are also other functions to get informations about Configuration:

WdfUsbTargetDeviceRetrieveConfigDescriptor
WdfUsbTargetDeviceGetDeviceDescriptor
WdfUsbTargetDeviceGetInterface

After Usb Configuration, we can proceed with Pipe Configuration:

The framework creates a pipe object for each pipe in the setting, and gets access for each pipe with WdfUsbInterfaceGetConfiguredPipe.

As said for each alternate setting there are one or more associated Endpoints, so our driver needs an Enumeration Procedure to identify and use these pipes:

NTSTATUS ConfigUsbPipe(PDEVICE_CONTEXT DeviceContext)
{

NTSTATUS status = STATUS_SUCCESS;
WDF_USB_PIPE_INFORMATION pipeInfo;
WDFUSBPIPE pipe = NULL;
UCHAR index;

for(index=0; index < numberConfiguredPipes; index++) {
WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
pipe = WdfUsbInterfaceGetConfiguredPipe( pDeviceContext->UsbInterface,
index, //PipeIndex,
&pipeInfo
);

if(WdfUsbPipeTypeInterrupt == pipeInfo.PipeType) {
pDeviceContext->InterruptPipe = pipe;
}
if(WdfUsbPipeTypeBulk == pipeInfo.PipeType
&& WdfUsbTargetPipeIsInEndpoint(pipe)) {
pDeviceContext->BulkReadPipe = pipe;
}
if(WdfUsbPipeTypeBulk == pipeInfo.PipeType
&& WdfUsbTargetPipeIsOutEndpoint(pipe)) {
pDeviceContext->BulkWritePipe = pipe;
}
}

Obviously, the most important function in our case is, WdfUsbInterfaceGetConfiguredPipe(), the out Struct WDF_USB_PIPE_INFORMATION mantains trace of each Pipe Configuration.

Here finishes the third part of Usb Coding, in the next days I’ll complete the coding part (probably with a full working USB Driver, and finally a we will talk about Usb Forensics.

See you to the next post.. 🙂


On USB Driver #2

October 31, 2007

Hi,

In the previous post, we talked about the General USB Architecture, that as you have seen is not easy and Highly Hierarchical, you can read that as highly Layerized.

Before talking about the foundamentals of USB Coding, is important to spent some words about Usb Protocols (not deeply handled in the previous post).

USB protocols are different from the other common interfaces, are highly layerized, but we will work only with High Level Layers, Low Level are controlled by USB Controller.

Each USB Transaction consists of a:

  • Token Packet (Header defining what it expects to follow)
  • Optional Data Packet, (Containing the payload)
  • Status Packet (Used to acknowledge transactions and to provide a means of error correction)

The first packet ( Token Packet ) is generated by the Host Controller and will cointain vital informations about the data transaction such as Device Address, Endpoints. Second packet strictly linked to the first, cointains the Payload and is called Data Packet, and finally a Status Packet is sent, works as an Handshaking Packet.

.:: Anatomy of an USB Packet ::.

USB’s data is formatted in LSB, and foundamentally USB packet is consist of various fields:

  • SYNC (All packets must start with a sync field. The sync field is 8 bits long at low and full speed or 32 bits long for igh speed and is used to synchronise the clock of the receiver with that of the transmitter. The last two bits indicatehere the PID fields starts.)
  • PID (his field is used to identify the type of packet that is being sent), Values of PID can identify 4 kind of packets: Token, Data, Handshake, Special.
  • ADDR (The address field specifies which device the packet is designated for. Being 7 bits in length allows for 127 devices to be supported. Address 0 is not valid, as any device which is not yet assigned an address must respond to packets sent to address zero.)
  • ENDP ( The Endpoint, already defined in the previous post)
  • CRC ( A classical Anti Corruption Check)
  • EOP (End Of Packet)

This is the basical composition of an USB Packet, and as said 4 types of packets, each packet have more kind of Sub-Packets:

  • Token Packets
    • In
    • Out
    • Setup
  • Data Packets
    • Data0
    • Data1
  • Handshake Packets
    • ACK
    • NAK
    • STALL
  • Start of Frame Packets (often called SOF Packet)

As you have seen, USB protocol is complicated to code directly, but fortunately we have a series of Functions that manages from low level to transation level, and only things we need to know are the error codes. Each function will have a series of buffers, typically 8 bytes long, each buffer will belong to an endpoint – EPx In, EPx

Out (we have the following numeration EP0 In/Out, EP1 In/Out, etc) , these Endpoints can be described as sources or

sinks of data, so if we send a packet to our EP1 device we will deal with EP1 In and EP1 Out. In all cases we have to ensure the support for EP0, because it receives all foundamental data about Device Control/Status.

Effective data transfer is done by Pipes, that are Logical Connections between Host and Endpoints and have some Control Parameters as Bandwidth Allocation, Transfer Type.

We can have two kind of pipes:

  • Stream Pipes: Can be sent any type of data down a stream pipe and can retrieve the data out the other end, and can support Bulk, Isochronous and Interrupt Transfer Types.
  • Message Pipes: Data is transferred in the desired direction, and is a Bidirectional Channel.

Here finishes the Architectural part, in the next part we will talk about USB Coding, and finally about Usb Forensics..

Many thanks goes to BeyondLogic Corp. for the great USB’s Arch Summary.

See you to the next post.. 🙂


On USB Driver #1

October 21, 2007

Hi,

USB Driver Coding is considered out of here something of really mystic, and too many speculations to help developers has been done, someone implemented also his own USB Development Kit, causing a lot of confusion, I’ll try to explain how to move in the USB field 😉
Here a rapid explaination of USB Architecture:

Starting out new with USB can be quite daunting, USB 2.0 documentation is 650 pages long, full of ssociated

standards as USB Class Standards such as HID Class Specifications (Human Interface Devices), and unlike RS-232 USB protocol is made up of several layers of protocols.

USB specification defines four transfer/endpoint types:

  • Control Transfers (typically used for command and status operations)
  • Interrupt Transfers (as each microcontroller, Interrupt transfers are typically non-periodic, small device initiated” communication requiring bounded latency)
  • Isochronous Transfers (sochronous transfers occur continuously and periodically. They typically contain time sensitive information, such as an audio or video stream. If there were a delay or retry of data in an audio stream)
  • Bulk Transfers (Bulk transfers can be used for large bursty data, as for printers, scanners)

All USB devices have a hierarchy of descriptors which describe to the host information such as what the device is, who makes it, what version of USB it supports, most common USB Descriptors, are:

  • Device Descriptors (The device descriptor, specifies some basic, important informations such as the supported USB version, maximum packet size, vendor and product IDs)
  • Configuration Descriptors (USB Supports different configurations although the majority of devices are simple and only have one, this descriptor specifies how the device is powered, what the maximum power consumption is, thenumber of interfaces it has)
  • Interface Descriptors (The interface descriptor could be seen as a header or grouping of the endpoints into a functional group performing a single feature of the device)
  • Endpoint Descriptors (Endpoint descriptors are used to describe endpoints other than endpoint zero)
  • String Descriptors (String descriptors provide human readable information and are optional)

Every USB device must respond to Setup Packets on the default pipe. The setup packets are used for detection and configuration of the device and carry out common functions such as setting the USB device’s address, requesting a device descriptor or checking the status of a endpoint.

Enumeration is the process of determining what device has just been connected to the bus and what parameters it requires such as power consumption, number and type of endpoint(s), class of product etc. The host will then assign the device an address and enable a configuration allowing the device to transfer data on the bus.

As you can see, USB driver coding is not so easy, is necessary to know:

  • General USB driver issues
  • USB Interrupt handling
  • Read, write, and IO control operations
  • General power management issues
  • Device suspend and wakeup

Obviously the only best way to write a good usb driver is to use WDF and KMDF, here some good link:

USB

BeyondLogic

UsbDeveloper

UsbCentral

UsbInformation

See you to the next post.. 🙂


KMDF’s NTSTATUS Return Values

September 29, 2007

Frequently happens that, KMDF Functions returns strange status values, that can’t be founded into NtStatus.h, this causes to Newbie KMDF Coders some confusion, the solution is easy, just take a look at \inc\wdf\kmdf\10\wdfstatus.h 😉

See you to the next post 🙂


News From Microsoft

September 5, 2007

USB devices store standard descriptors in firmware for the device, and its interfaces and endpoints. Independent Hardware Vendors (IHVs) can also store class and vendor-specific descriptors. However, the types of information that these descriptors can contain is limited.

So Microsoft implemented OS Descriptors, to enlarge potentialities of IHVs. These descriptors can be used by IHVs to store in firmware much of the information that is now typically provided to customers separately.

Here you can download OS Descriptors.

Measuring Windows Vista Performances
This paper provides information about measuring performance on Windows Vista. It provides guidelines for technical users and professionals who are creating benchmark tests to create accurate, repeatable workloads and measurements.

Optimizing Windows Vista Platforms for Energy Efficiency

This paper explains how to evaluate system energy efficiency and demonstrates example power policy settings to favor power savings or performance. Best practices for energy-efficient platform design are also covered.

Have a nice Day,

Evilcry


Something about Firewall hooking and Packet Filtering #2

August 27, 2007

Hi,

Here the second and last part of my little paper..
First of all, let’s introduce some more specification, to make previous blog entry more clear
The last struct showed, is the _FIREWALL_CONTEXT_T, and as can be seen there is DIRECTION_E that could be a little obscure, so here is reported:

typedef enum _IP_DIRECTION_E {
IP_TRANSMIT,
IP_RECEIVE
} DIRECTION_E, *PDIRECTION_E;

Represents easly a packet is Receiver or Transmitted.

The return values by the filter-routine can be:

FORWARD = 0
DROP = 1
ICMP_ON_DROP = 2

that are proper of FORWARD_ACTION

As previously said, to implement IP_SET_FIREWALL_HOOK_INFO, it’s necessary to write a filter function for \device\IP, so the pointer (to IP) self can be obtained easly by calling IoGetDeviceObjectPointer( )

Now can be installed the filter function, by passing througout IP’s pointer the address of the filtering function self, with IoBuildDeviceIoControlRequest(IOCTL_IP_SET_FIREWALL_HOOK, IpDeviceObject,…..)
It’s important to say also (according to DDK documentation) that IOCTL_PF_SET_EXTENSION_POINTERregisters filter-hook callback to the IP filter driver, to “make known” \device\IP to reroute every packet received or transmitted, and finally this same IOCTL clears the filter function from IP device. All these specifications could be made, by filling up the proper structure of this IOCTL, that will go to constitute the InputBuffer of IoBuildDeviceIoControlRequest:

PF_SET_EXTENSION_HOOK_INFO, that inside have another struct PacketFilterExtensionPtr which specifies the pointer to the filter hook callback, and when ins FALSE clears the filter.


typedef PF_FORWARD_ACTION (*PacketFilterExtensionPtr)(
IN unsigned char *PacketHeader, //Pointer to Ip header of packet
IN unsigned char *Packet, //Points a buffer with informations in the packet
//that filter-hook receives
IN unsigned int PacketLength , //Length of the packet
IN unsigned int RecvInterfaceIndex,//Index number for the interface adapter (InGoing)
IN unsigned int SendInterfaceIndex,//Index number for the interface adapter (OutGoing)
IN IPAddr RecvLinkNextHop, //IP address for the interface adapter that received the packet
IN IPAddr SendLinkNextHop //IP address for the interface adapter that will transmit the packet
);

It’s also important to notice that only on filter function per time can be installed, if others resides functions are stil working this one will not work.

See you to the next post! 🙂


Something about Firewall hooking and Packet Filtering

August 26, 2007

Hi,

Firewall hooking is a task in major part not well documented, MS doesn’t provides a clear and exaustive documentation about structures and development, so the only mode to have more knowledge is the RCE method.

These filter-hooks obviously works only at kernel mode, installing a callback function, and the driver installs a callback into \device\IP (which can be seen with WinObj) but let’s also parse \system32\Drivers

Fortunately, no extreme binary analysis is needed, we can study directly some header file from DDK, and precisely ipfirewall.h, so let’s take a deeper look to this file. Immediately we can see two intersing structs, the first is IPPacketFirewallPtr that works as a callout routine, and the most interesting _IP_SET_FIREWALL_HOOK_INFO
First Struct:

First Struct: typedef FORWARD_ACTION (*IPPacketFirewallPtr)(
VOID **pData, //can be pMdl or pRcvBuf
UINT RecvInterfaceIndex, //Received Data
UINT *pSendInterfaceIndex, //Index where data is sent
UCHAR *pDestinationType, //Can be Local Network, Remote, Broadcast, Multicast.
VOID *pContext, //Points to _FIREWALL_CONTEXT_T
UINT ContextLength, //sizeof(FIREWALL_CONTEXT_T)
struct IPRcvBuf **pRcvBuf
);

Second Struct:

_IP_SET_FIREWALL_HOOK_INFO {
IPPacketFirewallPtr FirewallPtr; // Packet filter callout.
UINT Priority; // Priority of the hook
BOOLEAN Add; // if TRUE then ADD else DELETE
} IP_SET_FIREWALL_HOOK_INFO, *PIP_SET_FIREWALL_HOOK_INFO;

This is the heart structure necessary to set-up the filter-hook, which can be done by sending a IOCTL to \device\Ip


#define IOCTL_IP_SET_FIREWALL_HOOK \
_IP_CTL_CODE(12, METHOD_BUFFERED, FILE_WRITE_ACCESS)

IP_SET_FIREWALL_HOOK_INFO will be the Input Structure to be filled for the IOCTL.

By observing IPPacketFirewallPtr, we can see _FIREWALL_CONTEXT_T which is:


typedef struct _FIREWALL_CONTEXT_T {
DIRECTION_E Direction;
void *NTE;
void *LinkCtxt;
NDIS_HANDLE LContext1;
UINT LContext2;
} FIREWALL_CONTEXT_T, *PFIREWALL_CONTEXT_T;

After installing the filter-hook, can be powered up a set of rules to FORWARD or DROP a packet.

Thanks to Jesus O.


Good Driver Links

August 24, 2007

Hi,

Here I inserted some link, just to open thi section 🙂 other links and suggestions are welcome..

Latest WDK :
http://www.microsoft.com/whdc/DevTools/WDK/betawdk.mspx

WDK Documentation:

http://www.microsoft.com/whdc/DevTools/WDK/WDKdocs.mspx

A bit different from Vista’s Documentation, cause the DTM stuff that this WDK-Doc don’t have.

Debugging Tools for 32 bits:

http://msdl.microsoft.com/download/symbols/debuggers/dbg_x86_6.7.05.1.exe

Debugging Tools for 64 bits, Native Itanium:

http://msdl.microsoft.com/download/symbols/debuggers/dbg_ia64_6.7.05.1.exe

Debugging Tools for 64 bits, Native x64:

http://msdl.microsoft.com/download/symbols/debuggers/dbg_amd64_6.7.05.1.exe

Virtual Address Space Usage In Windows Game Development

http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/WDDM_VA.doc

Suggestions for new links are welcome

Best Regards,

Evilcry