Пользоваться просто:
2: kd> !py ctlcode 0x1401c8 Device type: FILE_DEVICE_NETWORK_FILE_SYSTEM Function: 0x72(114) Method: BUFFERED Access: FILE_ANY_ACCESSВзять можно здесь.
2: kd> !py ctlcode 0x1401c8 Device type: FILE_DEVICE_NETWORK_FILE_SYSTEM Function: 0x72(114) Method: BUFFERED Access: FILE_ANY_ACCESSВзять можно здесь.
Начиная с Windows Vista MS упорно продвигает свой фреймворк WFP ( Windows Filtering Platform ). В предверии Windows 8 Microsoft еще более закручивают гайки: теперь продукт не может получить логотип о совместимоcти с Windows 8, если он содержит TDI или LSP фильтры. Между нами, скажу по секрету шепотом свое мнение: WFP - это полное говно, писать на нем определенные вещи крайне неудобно. Но это все эмоции, говно - не говно, отлаживать драйвера надо. Кто знаком с WFP, тот помнит, что там все делает через одно место, а именно через функцию classsifyFn. В зависимости от версии WFP, эта функция может имееть разные сигнатуры, но в любом случае, они содержат параметеры inFixedValues и inMetaValues в которых, собственно, и содержится вся информация о сетевом событии. И конечно, при отладке хочется посмотреть, что содержат эти переменные. Но это не так просто, inFixedValues - это массив переменной длины, а в inMetaValues доступность полей регулируется флагами. Поэтому, я решил написать python скрипт, который будет выводить эту информацию.
Сам скрипт можно взять здесь: wfp.py download.
Использовать его довольно просто: Ставим брейкпойнт на интересующей нас ф. classifyFn. При срабатывании брейкпойнта, вводим команду:
!py wfp /fixed poi(inFixedValues).
Примерный вывод команды:
FWPS_INCOMING_VALUES0: Layer: FWPS_LAYER_STREAM_V4 Value: 7 FWPS_FIELD_STREAM_V4_IP_LOCAL_ADDRESS Type: FWP_UINT32 Value: 0xaf4087c FWPS_FIELD_STREAM_V4_IP_LOCAL_ADDRESS_TYPE Type: FWP_UINT8 Value: 0x1 FWPS_FIELD_STREAM_V4_IP_REMOTE_ADDRESS Type: FWP_UINT32 Value: 0x40040b19 FWPS_FIELD_STREAM_V4_IP_LOCAL_PORT Type: FWP_UINT16 Value: 0xc02b FWPS_FIELD_STREAM_V4_IP_REMOTE_PORT Type: FWP_UINT16 Value: 0x50 FWPS_FIELD_STREAM_V4_DIRECTION Type: FWP_UINT32 Value: 0x0 FWPS_FIELD_STREAM_V4_FLAGS Type: FWP_UINT32 Value: 0x0Для 64 битной платформы, потребуется указать регистр rcx ( именно через него передается inFixedValues ):
FWPS_INCOMING_METADATA_VALUES0: FWPS_METADATA_FIELD_FLOW_HANDLE: 0x210 FWPS_METADATA_FIELD_SYSTEM_FLAGS: 0x1
Теперь на примере данного скрипта рассмотрим некоторые приемы написания скрипта для pykd. Первым делом, нам нужно получить доступ к полям переменной inFixedValues. Это делается так:
inFixedValue = typedVar( "FWPS_INCOMING_VALUES0_", addr ) dprintln( " Layer: " + fwpsLayer[ inFixedValue.layerId ] ) dprintln( " Value: %d" % inFixedValue.valueCount )Класс typedVar позволяет осуществить удобный доступ к полям стурктур - просто как к аттрибутам. Именно так выводится количество записей в массиве:
dprintln( " Value: %d" % inFixedValue.valueCount )Поле inFixedValue.layerId содержит численный идентификатор уровня фильтрации. Но мы хотим получить его символьное представление, которое задается энумератором FWPS_BUILTIN_LAYERS_. И тут нам приходит на помощь новый функционал pykd версии 0.1.x:
fwpsLayer = typeInfo( "FWPS_BUILTIN_LAYERS_" ).asMap()Вызов typeInfo( "FWPS_BUILTIN_LAYERS_" ) возвращает информацию о типе FWPS_BUILTIN_LAYERS_. А метод asMap() конвертирует его в словарь вида: { число : "имя" }. Таким образом, зная идентификатор уровня фильтрации мы легко конвертируем его в символьное представление:
dprintln( " Layer: " + fwpsLayer[ inFixedValue.layerId ] )Теперь нам необходимо вывести информацию о каждом элементе массива inFixedValue.incomingValue. Это можно было бы сделать с помощью цикла:
values = [] for i in range( 0, inFixedValue.valueCount ): values.append( typedVar( "FWPS_INCOMING_VALUE0_", inFixedValue.incommingValue + typeInfo("FWPS_INCOMING_VALUE0_").size() * i ).value )Но есть способ гораздо проще, через специальный метод для работы с массивами:
values = [ x.value for x in typedVarArray( inFixedValue.incomingValue, "FWPS_INCOMING_VALUE0_", inFixedValue.valueCount ) ]typedVarArray возвращает список переменных типа typedVar с inFixedValue.valueCount элементов и начинающийся с адреса inFixedValue.incomingValue. Далее мы используем генератор списков, чтобы трансформировать список. Ну вот, собственно и все. Надеюсь данный скрипт будет полезен в работе и в качестве примера работы c pykd.