為何需要 Thunking
內核模式驅動程式必須驗證從使用者模式應用程式傳入的任何 I/O 緩衝區大小。 如果 32 位應用程式將包含指標有效位數數據類型的緩衝區傳遞至 64 位驅動程式,而且不會發生任何 Thunking,則驅動程式會預期緩衝區大於實際值。 這是因為指標精確度是 32 位 Microsoft Windows 上的 32 位,而 64 位 Windows 上的 64 位。 例如,請考慮下列結構定義:
typedef struct _DRIVER_DATA
{
HANDLE Event;
UNICODE_STRING ObjectName;
} DRIVER_DATA;
在 32 位 Windows 上,DRIVER_DATA 結構的大小為 12 個字節。 下表顯示 DRIVER_DATA結構之 Event 成員和 ObjectName 成員的大小:
事件 | ObjectName (USHORT Length) | ObjectName (USHORT 最大長度) | ObjectName (PWSTR Buffer) |
---|---|---|---|
32 位元 | 16 位元 | 16 位元 | 32 位元 |
(4 個字節) | (2 個字節) | (2 個字節) | (4 個字節) |
在 64 位 Windows 上,DRIVER_DATA 結構的大小為 24 個字節。 (需要 4 個字節的結構填補,才能在 8 位元組界限上對齊 Buffer 成員。)
事件 | ObjectName (USHORT Length) | ObjectName (USHORT 最大長度) | 空 (結構填補) | ObjectName (PWSTR Buffer) |
---|---|---|---|---|
64 位元 | 16 位元 | 16 位元 | 32 位元 | 64 位元 |
(8 個字節) | (2 個字節) | (2 個字節) | (4 個字節) | (8 個字節) |
如果 64 位驅動程式在預期為 24 個字節時收到 12 個字節的 DRIVER_DATA,大小驗證將會失敗。 若要避免這種情況,驅動程式必須偵測 32 位應用程式是否傳送DRIVER_DATA結構,如果是的話,請在執行驗證之前適當地叫用它。
例如,上述DRIVER_DATA結構的 Thunked 版本可以定義如下:
typedef struct _DRIVER_DATA32
{
VOID *POINTER_32 Event;
UNICODE_STRING32 ObjectName;
} DRIVER_DATA32;
因為它只包含固定有效位數數據類型,所以這個新結構在32位Windows和64位 Windows 上的大小相同。
事件 | ObjectName (USHORT Length) | ObjectName (USHORT 最大長度) | ULONG 緩衝區 |
---|---|---|---|
32 位元 | 16 位元 | 16 位元 | 32 位元 |
(4 個字節) | (2 個字節) | (2 個字節) | (4 個字節) |