locked
Getting the process id from an ALE callout is mostly 0 RRS feed

  • Question

  • I have written a callout driver that filters at the ALE layer. It passes certain values back to user mode for a policy decision and yet one of the most important values, the process ID from FWPS_INCOMING_METADATA_VALUES0 is almost always zero.

    Any idea why?

    I would like to know which application or process is involved in the network chat.

    Friday, May 27, 2011 12:15 PM

Answers

  • Even if it's largely based on Inspect it's not Inspect. I would recommend recompiling the sample in the same way you compile your code (using the exactly same settings or even better using the exactly same command prompt) and check the PID via a breakpoint in your test environment.

     


    QmQ
    • Marked as answer by suityou01 Tuesday, May 31, 2011 2:47 PM
    Tuesday, May 31, 2011 2:19 PM

All replies

  • I have callouts at the ALE_CONNECT_REDIRECT/ALE_FLOW_ESTABLISHED layers (both IPv4 and IPv6) and I've never had such problems. Do you verify that the PID is in fact available using the FWPS_IS_METADATA_FIELD_PRESENT macro? I imagine it can be zero either because it's not available or explicitly set to zero which makes a difference. What OS/WDK are you using? What about other values from the inMetaValues structure?

     

    Here's a quick n' dirty snippet I use to verify what I have available at which layer:

    #define BLABLA(name) if(FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, name)) DbgPrint(#name "\n");
    void NTAPI DumpMeta(IN const FWPS_INCOMING_METADATA_VALUES* inMetaValues)
    {
    	BLABLA(FWPS_METADATA_FIELD_DISCARD_REASON);
    	BLABLA(FWPS_METADATA_FIELD_FLOW_HANDLE);
    	BLABLA(FWPS_METADATA_FIELD_IP_HEADER_SIZE);
    	BLABLA(FWPS_METADATA_FIELD_PROCESS_PATH);
    	BLABLA(FWPS_METADATA_FIELD_TOKEN);
    	BLABLA(FWPS_METADATA_FIELD_PROCESS_ID);
    	BLABLA(FWPS_METADATA_FIELD_SYSTEM_FLAGS);
    	BLABLA(FWPS_METADATA_FIELD_RESERVED);
    	BLABLA(FWPS_METADATA_FIELD_SOURCE_INTERFACE_INDEX);
    	BLABLA(FWPS_METADATA_FIELD_DESTINATION_INTERFACE_INDEX);
    	BLABLA(FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE);
    	BLABLA(FWPS_METADATA_FIELD_COMPARTMENT_ID);
    	BLABLA(FWPS_METADATA_FIELD_FRAGMENT_DATA);
    	BLABLA(FWPS_METADATA_FIELD_PATH_MTU);
    	BLABLA(FWPS_METADATA_FIELD_COMPLETION_HANDLE);
    	BLABLA(FWPS_METADATA_FIELD_TRANSPORT_ENDPOINT_HANDLE);
    	BLABLA(FWPS_METADATA_FIELD_TRANSPORT_CONTROL_DATA);
    	BLABLA(FWPS_METADATA_FIELD_REMOTE_SCOPE_ID);
    	BLABLA(FWPS_METADATA_FIELD_PACKET_DIRECTION);
    	BLABLA(FWPS_METADATA_FIELD_PACKET_SYSTEM_CRITICAL);
    	BLABLA(FWPS_METADATA_FIELD_FORWARD_LAYER_OUTBOUND_PASS_THRU);
    	BLABLA(FWPS_METADATA_FIELD_FORWARD_LAYER_INBOUND_PASS_THRU);
    	BLABLA(FWPS_METADATA_FIELD_ALE_CLASSIFY_REQUIRED);
    	BLABLA(FWPS_METADATA_FIELD_TRANSPORT_HEADER_INCLUDE_HEADER);
    	BLABLA(FWPS_METADATA_FIELD_DESTINATION_PREFIX);
    	BLABLA(FWPS_METADATA_FIELD_ETHER_FRAME_LENGTH);
    	BLABLA(FWPS_METADATA_FIELD_PARENT_ENDPOINT_HANDLE);
    	BLABLA(FWPS_METADATA_FIELD_ICMP_ID_AND_SEQUENCE);
    	BLABLA(FWPS_METADATA_FIELD_LOCAL_REDIRECT_TARGET_PID);
    	BLABLA(FWPS_METADATA_FIELD_ORIGINAL_DESTINATION);
    }
    

     

    Use with caution - a lot of DbgPrint()s can make the kernel angry ;)

     

    Regards,


    QmQ
    Friday, May 27, 2011 12:27 PM
  • I have callouts at the ALE_CONNECT_REDIRECT/ALE_FLOW_ESTABLISHED layers (both IPv4 and IPv6) and I've never had such problems. Do you verify that the PID is in fact available using the FWPS_IS_METADATA_FIELD_PRESENT macro? I imagine it can be zero either because it's not available or explicitly set to zero which makes a difference. What OS/WDK are you using? What about other values from the inMetaValues structure?

    Use with caution - a lot of DbgPrint()s can make the kernel angry ;)

     

    Regards,


    QmQ

    Do you verify that the PID is in fact available using the FWPS_IS_METADATA_FIELD_PRESENT macro?

     

    Yes, I have tried with and without. 

     

    What OS/WDK are you using?

     

    Vista Home Basic, SP1

     

    WinDDK 7600.16385.0

    Friday, May 27, 2011 12:41 PM
  • You can only use the PID if that flag is set. Otherwise you're looking for trouble.

    I'm using Windows7 and WinDDK 7600.16385.1. Maybe there's been an update?

     

    What layers have you tried? Not all are available on Vista...

     

     

    Regards,


    QmQ
    Friday, May 27, 2011 12:55 PM
  • Hi QmQ,

     

    Thanks for your reply. Sorry for not getting back sooner. The ALE layers I am using are :

     

    FWPM_LAYER_ALE_AUTH_CONNECT_V4/V6

    FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4/V6

     

    Thanks

     

    SY01

    Saturday, May 28, 2011 8:23 AM
  • I also note that I can use inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_ALE_APP_ID].value.byteBlob->data

     

    Will this give me what I need given that processId in the meta values is not actually working?

     

    Where is the documentation on what this Blob actually is? What do I have to cast it to to get to the APP_ID?

     

    Or better yet can someone suggest why the meta values process Id is blank? It should be available at the ALE RECV_ACCEPT layer, the DDK says so.

    Very confused.

    Saturday, May 28, 2011 2:50 PM
  • It's odd that you get zeros in the meta values processId field... I don't know why that is.

     

    I would recommend trying the ALE_FLOW_ESTABLISHED layer. Using it you should be able to capture both inbound and outbound traffic via a single callout (unless you explicitly require the ones you mentioned). Have you tried to write another, very simple callout just to test this?

    I have no experience using inFixedValues->incomingValue - can't help you there. But it doesn't seem like the correct way. I would focus on unveiling the mystery of the zero PIDs. Could you show us your callout implementation? What conditions do you use?

     

     


    Best regards, QmQ
    Saturday, May 28, 2011 8:22 PM
  • Also, do please use my meta values dumping code and paste the results here.
    QmQ
    Saturday, May 28, 2011 8:24 PM
  • It's odd that you get zeros in the meta values processId field... I don't know why that is.

     

    I would recommend trying the ALE_FLOW_ESTABLISHED layer. Using it you should be able to capture both inbound and outbound traffic via a single callout (unless you explicitly require the ones you mentioned). Have you tried to write another, very simple callout just to test this?

    I have no experience using inFixedValues->incomingValue - can't help you there. But it doesn't seem like the correct way. I would focus on unveiling the mystery of the zero PIDs. Could you show us your callout implementation? What conditions do you use?

     

     


    Best regards, QmQ


    Hi,

    Callout implementation function is as below :

     

    NTSTATUS
    
    TLInspectRegisterALEClassifyCallouts(
    
     IN const GUID* layerKey,
    
     IN const GUID* calloutKey,
    
     IN void* deviceObject,
    
     OUT UINT32* calloutId
    
     )
    
    /* ++
    
    
    
     This function registers callouts and filters at the following layers
    
     to intercept inbound or outbound connect attempts.
    
    
    
     FWPM_LAYER_ALE_AUTH_CONNECT_V4
    
     FWPM_LAYER_ALE_AUTH_CONNECT_V6
    
     FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4
    
     FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6
    
    
    
    -- */
    
    {
    
    	NTSTATUS status = STATUS_SUCCESS;
    
    	FWPS_CALLOUT0 sCallout = {0};
    
    	FWPM_CALLOUT0 mCallout = {0};
    
    	FWPM_DISPLAY_DATA0 displayData = {0};
    
    	BOOLEAN calloutRegistered = FALSE;
    
    
    
    	sCallout.calloutKey = *calloutKey;
    
    
    
    	if (IsEqualGUID(layerKey, &FWPM_LAYER_ALE_AUTH_CONNECT_V4) ||
    
    		IsEqualGUID(layerKey, &FWPM_LAYER_ALE_AUTH_CONNECT_V6))
    
    	{
    
    		sCallout.classifyFn = TLInspectALEConnectClassify;//The callout function
    
    		sCallout.notifyFn = TLInspectALEConnectNotify;//The notification function
    
    	}
    
    	else
    
    	{
    
    		sCallout.classifyFn = TLInspectALERecvAcceptClassify;//The callout function
    
    		sCallout.notifyFn = TLInspectALERecvAcceptNotify;//The notification function
    
    	}
    
    
    
    	//The FwpsCalloutRegister0 function registers a callout with the filter engine.
    
    	status = FwpsCalloutRegister0(
    
    		deviceObject,
    
    		&sCallout,
    
    		calloutId
    
    	);
    
    
    
    	if (!NT_SUCCESS(status))
    
    	{
    
    		//DbgPrint the error if Debugging is turned on
    
    		#ifdef DEBUG_OUTPUT
    
    			DbgPrint("A problem occurred in function TLInspectRegisterALEClassifyCallouts. The wfp function FwpsCalloutRegister0 returned a fail code");
    
    		#endif
    
    		goto Exit;
    
    	}
    
    	calloutRegistered = TRUE;
    
    
    
    	displayData.name = L"Port Knox ALE Classify Callout";
    
    	displayData.description =
    
    		L"Intercepts inbound or outbound connect attempts";
    
    
    
    	mCallout.calloutKey = *calloutKey;
    
    	mCallout.displayData = displayData;
    
    	mCallout.applicableLayer = *layerKey;
    
    
    
    	//Add the callout to the WFP engine
    
    	status = FwpmCalloutAdd0(
    
    		gEngineHandle,
    
    		&mCallout,
    
    		NULL,
    
    		NULL
    
    	);
    
    
    
    	if (!NT_SUCCESS(status))
    
    	{
    
    		//DbgPrint the error if Debugging is turned on
    
    		#ifdef DEBUG_OUTPUT
    
    			DbgPrint("A problem occurred in function TLInspectRegisterALEClassifyCallouts. The wfp function FwpmCalloutAdd0 returned a fail code");
    
    		#endif
    
    		goto Exit;
    
    	}
    
    
    
    	//Add the filter to which the callout function depends
    
    	status = TLInspectAddFilter(
    
    		L"Transport Inspect ALE Classify",
    
    		L"Intercepts inbound or outbound connect attempts",
    
    		(IsEqualGUID(layerKey, &FWPM_LAYER_ALE_AUTH_CONNECT_V4) ||
    
    		IsEqualGUID(layerKey, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4)) ?
    
    		configInspectRemoteAddrV4 : configInspectRemoteAddrV6,
    
    		0,
    
    		layerKey,
    
    		calloutKey
    
    	);
    
    
    
    	//Add the filter to which the callout function depends
    
    		status = TLInspectAddInboundFilter(
    
    			L"Transport Inspect ALE Classify",
    
    			L"Intercepts inbound or outbound connect attempts",
    
    			(IsEqualGUID(layerKey, &FWPM_LAYER_ALE_AUTH_CONNECT_V4) ||
    
    			IsEqualGUID(layerKey, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4)) ?
    
    			configInspectRemoteAddrV4 : configInspectRemoteAddrV6,
    
    			0,
    
    			layerKey,
    
    			calloutKey
    
    		);
    
    
    
    	if (!NT_SUCCESS(status))
    
    	{
    
    		//DbgPrint the error if Debugging is turned on
    
    		#ifdef DEBUG_OUTPUT
    
    			DbgPrint("A problem occurred in function TLInspectRegisterALEClassifyCallouts. The custom driver function TLInspectAddFilter returned a fail code");
    
    		#endif
    
    		goto Exit;
    
    	}
    
    
    
    Exit:
    
    	if (!NT_SUCCESS(status))
    
    	{
    
    		if (calloutRegistered)
    
    		{
    
    			FwpsCalloutUnregisterById0(*calloutId);
    
    			*calloutId = 0;
    
    		}
    
     }
    
     return status;
    
    }
    
    
    
    
    
    
    NTSTATUS
    TLInspectAddFilter(
     IN const wchar_t* filterName,
     IN const wchar_t* filterDesc,
     IN const UINT8* localAddr,
     IN UINT64 context,
     IN const GUID* layerKey,
     IN const GUID* calloutKey
    )
    {
    	NTSTATUS status = STATUS_SUCCESS; //Optimistic start!
    
    	FWPM_FILTER0 filter = {0};
    	FWPM_FILTER_CONDITION0 filterConditions[3] = {0};
    	UINT conditionIndex;
    
    	//Initialise the filter object settings
    	filter.layerKey = *layerKey;
    	filter.displayData.name = (wchar_t*)filterName;
    	filter.displayData.description = (wchar_t*)filterDesc;
    
    	filter.action.type = FWP_ACTION_CALLOUT_TERMINATING;
    	filter.action.calloutKey = *calloutKey;
    	filter.filterCondition = filterConditions;
    	filter.subLayerKey = TL_INSPECT_SUBLAYER;
    	filter.weight.type = FWP_EMPTY; // auto-weight.
    	filter.rawContext = context;
    
    	conditionIndex = 0;
    
    	if (localAddr != NULL)
    	{
    		//Add the filter where the local address matches the local ip of the packet
    		filterConditions[conditionIndex].fieldKey =
      FWPM_CONDITION_IP_LOCAL_ADDRESS;
    		filterConditions[conditionIndex].matchType = FWP_MATCH_EQUAL;
    
    		if (IsEqualGUID(layerKey, &FWPM_LAYER_ALE_AUTH_CONNECT_V4) ||
       IsEqualGUID(layerKey, &FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4) ||
       IsEqualGUID(layerKey, &FWPM_LAYER_INBOUND_TRANSPORT_V4) ||
       IsEqualGUID(layerKey, &FWPM_LAYER_OUTBOUND_TRANSPORT_V4))
    		{
    			filterConditions[conditionIndex].conditionValue.type = FWP_UINT32;
    			filterConditions[conditionIndex].conditionValue.uint32 =
       *(UINT32*)localAddr;
    		}
    		else
    		{
    			filterConditions[conditionIndex].conditionValue.type =
       FWP_BYTE_ARRAY16_TYPE;
    			filterConditions[conditionIndex].conditionValue.byteArray16 =
       (FWP_BYTE_ARRAY16*)localAddr;
    		}
    
    		conditionIndex++;
    	}
    	else
    	{
    		//Local address is null, can't continue
    		//DbgPrint the error if Debugging is turned on
    		#ifdef DEBUG_OUTPUT
    			DbgPrint("A problem occurred in function TLInspectAddFilter. The local IP Address passed in was NULL.");
    		#endif
    	}
    
    	filter.numFilterConditions = conditionIndex;
    
    	//Add the filter
    	status = FwpmFilterAdd0(
        gEngineHandle,
        &filter,
        NULL,
        NULL);
    
    	if (NT_SUCCESS(status)){
    		//Successfully added the filter
    		return STATUS_SUCCESS;
    	}
    	else
    	{
    		//DbgPrint the error if Debugging is turned on
    		#ifdef DEBUG_OUTPUT
    			DbgPrint("A problem occurred in function TLInspectAddFilter. The wfp function FwpmFilterAdd0 returned a fail code");
    		#endif
    		return STATUS_UNSUCCESSFUL;
    	}
    }
    

    configInspectRemoteAddrV4  is the IP4 address of the local machine, retrieved from the registry on driver startup.

    I will add your debug code to the driver next and report back.

    Thanks

     

    SY01


    Edit : Code for

    TLInspectAddFilter added.

     


    Tuesday, May 31, 2011 9:33 AM

  • Also, do please use my meta values dumping code and paste the results here.
    QmQ


    The response was :

    00000037	27.74569130	FWPS_METADATA_FIELD_PROCESS_PATH	
    00000038	27.74569321	FWPS_METADATA_FIELD_TOKEN	
    00000039	27.74569702	FWPS_METADATA_FIELD_PROCESS_ID	
    00000040	27.74570084	FWPS_METADATA_FIELD_RESERVED	
    00000041	27.74570274	FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE	
    00000042	27.74570465	FWPS_METADATA_FIELD_COMPARTMENT_ID	
    00000043	27.74570656	FWPS_METADATA_FIELD_COMPLETION_HANDLE	
    00000044	27.74571037	FWPS_METADATA_FIELD_TRANSPORT_ENDPOINT_HANDLE	
    00000045	27.74577904	FWPS_METADATA_FIELD_SYSTEM_FLAGS	
    00000046	27.74578094	FWPS_METADATA_FIELD_RESERVED	
    00000047	27.74578476	FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE	
    00000048	27.74578857	FWPS_METADATA_FIELD_COMPARTMENT_ID	
    00000049	27.74579048	FWPS_METADATA_FIELD_TRANSPORT_ENDPOINT_HANDLE

    Although I had to edit your code slightly as the last 6 identifiers were not recognised.

     

    Tuesday, May 31, 2011 10:21 AM
  • Well it looks as if you should have the PID available. I have added a DbgPrint in my code at the ALE_AUTH_CONNECT (v4) layer and the PID's just fine.

    Have you tried using the Inspect sample from the DDK? It uses the ALE_AUTH_CONNECT layer. Try debugging that and see if it has the PID or not. If it does it means there's something wrong with your code. If it has not...well, that would be an issue for Microsoft to resolve...

     


    QmQ
    Tuesday, May 31, 2011 1:35 PM
  • This code is largely based on the inspect example.

     

    I am currently using ALE_AUTH_CONNECT (v4) and this was also in one of my previous answers.

    I wonder if as you suggest Microsoft want to comment here?

    Tuesday, May 31, 2011 1:42 PM
  • Even if it's largely based on Inspect it's not Inspect. I would recommend recompiling the sample in the same way you compile your code (using the exactly same settings or even better using the exactly same command prompt) and check the PID via a breakpoint in your test environment.

     


    QmQ
    • Marked as answer by suityou01 Tuesday, May 31, 2011 2:47 PM
    Tuesday, May 31, 2011 2:19 PM
  • Hi,

     

    I did this. Inspect example works. Back to the drawing board for me. :(

     

    Thanks for your help.

     

    SY01

    Tuesday, May 31, 2011 2:47 PM