Verifying the processes identity from inside an IOCTL queue

Inside my IOCTL callback function I need a way to determine the identity of the process that is trying to communicate with me so I can restrict communication to only my client side application. My thought process was to check the file name or the token key name since those should not be changed (the client verifies the file name is the same name it was shipped with). If you have a better idea please let me know but for now I am trying to figure out how to get the file name of the process that is sending an IOCTL request. To start off with I am using HANDLE ProcessId = PsGetCurrentProcessId(); inside my queue to get the process but I am not sure where to go from there. I can use ‘PsLookupProcessByProcessId’ to get the EPROCESS but Microsoft never fully documented this which is sad considering I know it contains the ImageFileName but I dont want to provide a struct for every Windows version since it would make maintenance a nightmare. So what other ways can I query the processes name?

You are not guaranteed to be in the context of the calling app in your WDFQUEUE callback. You should check for the calling app in EvtFileCreate and then set the appropriate state in the WDFFILEOBJECT context. You can then check for this state in the queue callback (retrieve the file object from the request). I don’t have any recommendations on how to check for the app’s identity.

@Doron_Holan said:
You are not guaranteed to be in the context of the calling app in your WDFQUEUE callback. You should check for the calling app in EvtFileCreate and then set the appropriate state in the WDFFILEOBJECT context. You can then check for this state in the queue callback (retrieve the file object from the request).

I don’t have any recommendations on how to check for the app’s identity.

Alright interesting even with that though do you know if its possible to get the file name?

remember that any check that you can create to ensure that the UM caller is your super special process, I can circumvent given time and effort. If you want to put in a check to protect against accidental access, something simple like the .exe filename could work.

if you want to protect your driver from a determined attack / malware, use an ACL and run your UM program in a different security context. Although if the UM program ever needs to interact with a user, eventually, some part of it has to be exposed

@MBond2 said:
remember that any check that you can create to ensure that the UM caller is your super special process, I can circumvent given time and effort. If you want to put in a check to protect against accidental access, something simple like the .exe filename could work.

if you want to protect your driver from a determined attack / malware, use an ACL and run your UM program in a different security context. Although if the UM program ever needs to interact with a user, eventually, some part of it has to be exposed

Yea I know it can be circumvented but it was just one check idea and I also needed it for something else but its fine I could just use RSA to ensure I am talking to the correct client.

How will using RSA be better?

If I am an admin user and have the time, inclination and skill, you can’t stop me from sending IO from my program to your driver.

So unless you are worried about accidental access, don’t bother

@MBond2 said:
How will using RSA be better?

If I am an admin user and have the time, inclination and skill, you can’t stop me from sending IO from my program to your driver.

So unless you are worried about accidental access, don’t bother

I don’t need to stop you from sending IO to my driver I just need to stop your IO from doing anything inside the driver.

You missed the point. Any IO that you can identify as being from your super special safe process, can be made to be indistinguishable from IO from my super bad nasty bad process. If I care enough, and have the same permissions (maybe a few more) as the ‘safe’ process, I can always do that no matter what protection you want to employ

@MBond2 said:
You missed the point. Any IO that you can identify as being from your super special safe process, can be made to be indistinguishable from IO from my super bad nasty bad process. If I care enough, and have the same permissions (maybe a few more) as the ‘safe’ process, I can always do that no matter what protection you want to employ

Well I am sure with enough experience you could reverse engineer the private key from the driver but doing that is not that easy to do.

You might also consider to modify your private key dynamically based on the system time. The delay might be a few milliseconds. If it’s based on seconds or 10 seconds it should be safe, just an idea to make it harder for the evil attacker.

@pwilly said:
You might also consider to modify your private key dynamically based on the system time. The delay might be a few milliseconds. If it’s based on seconds or 10 seconds it should be safe, just an idea to make it harder for the evil attacker.

Since kernel drivers cant talk to the web what I am planning on doing is having the private key be located inside the driver and have a server hold the public key. Then when a user logs into a desktop app the server takes a password and concatenates a time stamp with it and sends it to the client. The client then saves it locally to reuse. Then when the client tries to communicate with my driver it sends this encrypted data and my driver decodes it and verifies the time stamp is still valid and then compares the password to a saved password in my driver. Essentially disabling replay attacks and making the client non vulnerable since it wont contain any secret information.

The only issue I am facing now is getting RSA 2048 to work between C# and my C driver. I did manage to get BCrypt to work inside the kernel and the functions seem to be working (since BCryptOpenAlgorithmProvider succeeded) but I am getting a 0x80090005 aka NTE_BAD_DATA error from the ‘BCryptDecrypt’ function.

unsigned char g_privateKeyBlob[] = { 0x32, 0x41, 0x53, 0x52, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0xBA, 0x51, 0xD9, 0x5F, 0x95, 0x6D, 0x91, 0xCD, 0x58, 0xAE, 0xCC, 0x74, 0xE1, 0xEC, 0x70, 0x08, 0x58, 0x1D, 0xF5, 0x1A, 0xDD, 0x02, 0xAB, 0x77, 0xD3, 0x8E, 0xD7, 0x45, 0x8F, 0x59, 0x50, 0xBF, 0xAA, 0x29, 0x40, 0x43, 0xCC, 0xFB, 0x10, 0x11, 0x95, 0x77, 0xDA, 0x65, 0x80, 0xDC, 0xEA, 0x78, 0xAD, 0xF1, 0x96, 0x34, 0xA2, 0xC8, 0x6A, 0x94, 0xF9, 0x81, 0x9E, 0x5B, 0x03, 0x1B, 0x24, 0xB3, 0xD6, 0xB2, 0x71, 0xB5, 0x55, 0x90, 0x96, 0x1A, 0xE9, 0xE9, 0x4F, 0x70, 0xBB, 0x9D, 0xFF, 0xD9, 0x4B, 0x53, 0x7C, 0x98, 0xF7, 0x72, 0x44, 0xCA, 0x67, 0x9B, 0x4E, 0xDF, 0x34, 0x85, 0x47, 0x13, 0xDF, 0x3E, 0xDD, 0xE6, 0x44, 0x61, 0x96, 0x87, 0x00, 0x8B, 0xFA, 0xE3, 0x01, 0x06, 0x48, 0x4B, 0x7C, 0xF8, 0x92, 0x82, 0x2B, 0x6F, 0xCB, 0x01, 0x4F, 0x2D, 0xEA, 0xF5, 0x96, 0xEF, 0xE2, 0x16, 0xED, 0xBB, 0x5E, 0x6F, 0xCB, 0x8E, 0xE2, 0xEE, 0xBE, 0xE3, 0xF8, 0xF5, 0xAB, 0xA1, 0xCE, 0xA9, 0x98, 0x69, 0xA3, 0x80, 0xD0, 0xF2, 0xBF, 0xF1, 0xC4, 0xEF, 0xBB, 0x12, 0xD2, 0x26, 0x74, 0x44, 0xBA, 0xD6, 0xCF, 0x64, 0x9B, 0x29, 0xD9, 0x69, 0xBF, 0xF4, 0x32, 0xE3, 0x0C, 0xA1, 0x5F, 0xBE, 0x90, 0x0A, 0x9C, 0xDB, 0xB8, 0xE5, 0x0B, 0x89, 0x13, 0xC7, 0xA6, 0x6D, 0x7D, 0x70, 0xFD, 0xE1, 0x27, 0x3A, 0xA1, 0x98, 0x9D, 0x7A, 0x3B, 0x70, 0xE1, 0x82, 0x66, 0x7D, 0x83, 0x37, 0x59, 0x75, 0xF2, 0xE7, 0xDB, 0xE9, 0xAE, 0x6A, 0x05, 0x6A, 0x40, 0xDE, 0xC0, 0x7C, 0x88, 0x10, 0xAF, 0x2E, 0xE5, 0xCC, 0x44, 0x0D, 0x7C, 0x7C, 0x99, 0x7F, 0x45, 0x8B, 0x11, 0x46, 0x89, 0xE2, 0xAF, 0xA5, 0xC4, 0x66, 0xAF, 0xE8, 0xE7, 0xC1, 0xA1, 0x69, 0x15, 0x38, 0x36, 0xD6, 0x28, 0xDB, 0xE4, 0xC9, 0xD5, 0xA1, 0xAE, 0x69, 0x1F, 0x09, 0x50, 0xC6, 0xF6, 0xCE, 0xA0, 0x92, 0xFF, 0xB5, 0x34, 0x5F, 0x88, 0x06, 0x49, 0x0E, 0x54, 0xA6, 0xF2, 0xD5, 0xEF, 0xCB, 0x6A, 0xB2, 0x01, 0x2E, 0x5A, 0x29, 0xE7, 0x91, 0x1D, 0xA9, 0x1A, 0xF1, 0xFE, 0x9E, 0xA8, 0xE1, 0xB7, 0xAB, 0xAB, 0xE3, 0xBD, 0xE7, 0xB0, 0x5A, 0xE1, 0xFD, 0x3C, 0xA0, 0x8E, 0x45, 0xCF, 0xB7, 0x95, 0x18, 0x2A, 0x85, 0xD7, 0x8E, 0x1B, 0x18, 0xF1, 0xB7, 0xAF, 0x7F, 0xB7, 0x63, 0x6D, 0xDE, 0x1B, 0x21, 0x42, 0x68, 0xF9, 0x59, 0xF4, 0x64, 0x5A, 0x1F, 0x99, 0xF9, 0x25, 0xFA, 0x81, 0x3F, 0x90, 0xA2, 0x1C, 0x27, 0x73, 0x0A, 0x5B, 0x0E, 0xDF, 0xDB, 0x28, 0xBB, 0xB1, 0x7E, 0x7D, 0xA2, 0x9B, 0x0B, 0x64, 0x9B, 0x77, 0xDA, 0xC6, 0x81, 0x66, 0x08, 0x09, 0xB2, 0x62, 0x87, 0x79, 0xB0, 0x0D, 0x2C, 0xF0, 0xBF, 0x67, 0xE3, 0xDF, 0x45, 0x83, 0xA8, 0x16, 0x6A, 0x95, 0xF0, 0x96, 0x30, 0x63, 0x94, 0x8C, 0xF6, 0x25, 0x4A, 0x47, 0x82, 0x35, 0x5B, 0x7B, 0xB8, 0x36, 0x9E, 0xF1, 0x45, 0x27, 0x28, 0x7B, 0x47, 0xA9, 0x4C, 0x3C, 0x19, 0x85, 0x3C, 0xB4, 0x21, 0xB1, 0x0E, 0x55, 0x8D, 0x94, 0xB9, 0x14, 0xEF, 0x38, 0x70, 0x1C, 0x30, 0x77, 0xD0, 0x11, 0x7B, 0xDC, 0xBA, 0x41, 0xDB, 0x79, 0xB2, 0xE1, 0xED, 0xBA, 0x75, 0x64, 0x14, 0xEC, 0xFE, 0x9F, 0x1C, 0x38, 0x4A, 0xEF, 0x6A, 0x6F, 0x86, 0xE5, 0x0D, 0xE2, 0xFC, 0x0B, 0x29, 0x22, 0x24, 0x77, 0x79, 0x77, 0x99, 0x72, 0x04, 0x6A, 0x48, 0xE8, 0xC4, 0x0C, 0x5F, 0xD6, 0xF6, 0x65, 0x24, 0x94, 0xF9, 0x43, 0x33, 0x60, 0x9D, 0x85, 0xB4, 0x79, 0x82, 0xEB, 0xAF, 0x65, 0xDB, 0xFE, 0x18, 0xA1, 0x62, 0x8D, 0x4B, 0x78, 0x08, 0x2A, 0xED, 0x99, 0x5B, 0xE8, 0x63, 0x65, 0x12, 0x0F, 0x50, 0x10, 0xAC, 0xF9, 0x98, 0x88, 0x60, 0x0D, 0xBC, 0x3E, 0x5A, 0x5E, 0xA2, 0xEB, 0xD9, 0xFD, 0x6A, 0x58, 0x46, 0x7C, 0x11, 0x17, 0x58, 0x27, 0xEC, 0x7B, 0x7E, 0x90, 0x8D, 0xCE, 0xCE, 0xEB, 0x37, 0x7C, 0x56, 0x0D, 0x5E, 0xC7, 0x0B, 0xB3, 0x37, 0xF7, 0x24, 0xD2, 0x4D, 0xF1, 0x33, 0xAE, 0x43, 0x7F, 0x11, 0x7E, 0xFE, 0x2C, 0x5D, 0xF0, 0x9D, 0xF4, 0x50, 0x4A, 0x41, 0x23, 0x34, 0xD3, 0xF7, 0x51, 0x82, 0x9D, 0x22, 0xDF, 0x71, 0xFB, 0x67, 0xEA, 0xE1, 0x7B, 0x47, 0x41, 0xC6, 0xD0, 0x94, 0xAE, 0xE6, 0x1F, 0x3F, 0xBB, 0x32, 0x75, 0x9D, 0x1C, 0xB0, 0xD5, 0x4E, 0x8A, 0xF2, 0x28, 0x9A, 0xA9, 0x54, 0xD3, 0x8E, 0xC2, 0xA5, 0xD1, 0xB0, 0xBC, 0x32, 0x89, 0xAB, 0xE9, 0xCA, 0x82, 0x99, 0x3E, 0xED, 0x34, 0x8C, 0x5F, 0xD8, 0x19, 0x03, 0xB0, 0x0A, 0xFE, 0x7D, 0x17, 0xD7, 0x3E, 0x65, 0xB6, 0x6F, 0x0F, 0x2F, 0xAF, 0x79, 0xDF, 0x48, 0x3F, 0x7D, 0x11, 0x22, 0x4B, 0x5C, 0x76, 0x02, 0x1C, 0xC5, 0xE0, 0xDF, 0x3B, 0xF8, 0x1C, 0x64, 0x50, 0x35, 0xA8, 0xB8, 0x41, 0x3A, 0xA0, 0x65, 0x88, 0xFE, 0x87, 0xFF, 0x75, 0xD7, 0x36, 0x68, 0x44, 0xF9, 0xFE, 0x56, 0xCA, 0x4B, 0xCA, 0x9F, 0x67, 0x1E, 0x88, 0xC5, 0x42, 0xBF, 0x02, 0xD1, 0xBD, 0x1A, 0x3B, 0x6C, 0xC9, 0x91, 0x0A, 0x75, 0x6D, 0xDB, 0xFF, 0x8E, 0xD0, 0xDD, 0xD6, 0xA6, 0xDA, 0xD2, 0x8E, 0xC8, 0x47, 0x10, 0xCF, 0x5A, 0x81, 0x7F, 0x70, 0xEB, 0xEB, 0xA6, 0xD9, 0x0A, 0x8C, 0x00, 0x53, 0x29, 0xF0, 0xB4, 0x42, 0xBC, 0x93, 0x43, 0xC2, 0x8F, 0x3B, 0xE3, 0xD6, 0x21, 0x1D, 0x50, 0x83, 0x86, 0x29, 0x24, 0x42, 0x8F, 0xB2, 0xBB, 0xE9, 0x46, 0x83, 0xBC, 0xAB, 0x88, 0xCF, 0x75, 0x66, 0xED, 0x61, 0xF2, 0x29, 0x3C, 0xC8, 0xA7, 0x75, 0x56, 0x36, 0xA1, 0xC5, 0x62, 0x0E, 0xF9, 0x4E, 0xAE, 0x36, 0x0C, 0x66, 0x0E, 0x62, 0x89, 0x58, 0xB3, 0xC7, 0xF9, 0x51, 0xB2, 0xEC, 0x6F, 0xFC, 0xA6, 0xD2, 0x10, 0x56, 0xD8, 0xBC, 0x0B, 0x77, 0x02, 0x50, 0x7D, 0x9A, 0x81, 0x3F, 0x02, 0x34, 0xD4, 0xAC, 0x17, 0xAB, 0x1E, 0x7F, 0x48, 0x18, 0x83, 0x34, 0x6B, 0xD7, 0xC1, 0xE7, 0x85, 0x3F, 0x33, 0x3F, 0xA9, 0x31, 0xA1, 0xE0, 0x2A, 0xE1, 0x03, 0x31, 0xE3, 0x46, 0x62, 0xB0, 0x9C, 0xD3, 0xDC, 0x20, 0x4D, 0x34, 0xF4, 0xA9, 0x4C, 0x80, 0x0B, 0xA8, 0x2F, 0xBC, 0x1E, 0x9E, 0x17, 0x2A, 0x12, 0x19, 0xEA, 0x4F, 0x5E, 0xA2, 0x9B, 0x20, 0x36, 0x53, 0x95, 0x45, 0x1E, 0xB4, 0x33, 0x92, 0x21, 0x0A, 0xC3, 0xC3, 0xCC, 0x5E, 0x3D, 0xA8, 0xBE, 0x4C, 0xC5, 0x0A, 0x88, 0x3B, 0x2A, 0xEE, 0xE4, 0x25, 0x03, 0x3B, 0x76, 0x64, 0x7D, 0xD6, 0xB7, 0xFF, 0x45, 0x02, 0x32, 0xB9, 0xEA, 0xB9, 0x3A, 0xBF, 0x1E, 0x7C, 0x61, 0x70, 0xC4, 0x26, 0x01, 0xF0, 0xD1, 0xF0, 0x6B, 0xCE, 0x15, 0x45, 0x18, 0x3E, 0x1A, 0x61, 0xBC, 0xD6, 0x4C, 0x8D, 0x9D, 0xA0, 0x9E, 0xA5, 0x91, 0x02, 0x6F, 0x60, 0x58, 0xC6, 0xDD, 0x36, 0x24, 0x90, 0xAD, 0xD5, 0x96, 0x70, 0x96, 0x52, 0x39, 0xEC, 0x3D, 0x09, 0x26, 0x7C, 0xA1, 0x08, 0x3B, 0xA8, 0x9A, 0xC7, 0x66, 0xE3, 0x4E, 0xC8, 0xCC, 0x31, 0x49, 0x2A, 0xD9, 0x24, 0xC0, 0x9A, 0x00, 0xDD, 0x2F, 0x23, 0x01, 0x3E, 0x61, 0xB8, 0xE2, 0x58, 0x51, 0x9D, 0x94, 0x12, 0x06, 0x30, 0x18, 0x9D, 0x3E, 0xF1, 0xA3, 0x31, 0xF5, 0x9C, 0xCA, 0x59, 0x9A, 0xC0, 0xE3, 0xD6, 0x18, 0x9F, 0x2A, 0x22, 0xAC, 0xDB, 0x9C, 0x0F, 0xF9, 0xA4, 0x32, 0x53, 0x60, 0xA5, 0xFD, 0xE7, 0x43, 0x26, 0xE9, 0x47, 0x52, 0x67, 0x06, 0x23, 0xF0, 0x42, 0xBD, 0x6B, 0xA3, 0x34, 0x0C, 0xD7, 0xFF, 0xF9, 0xD9, 0x3E, 0xF1, 0x12, 0xB5, 0x0E, 0xA3, 0x77, 0x51, 0xCC, 0x9B, 0xF7, 0x5C, 0xE2, 0xE5, 0x10, 0x95, 0xC3, 0xBF, 0x27, 0x5D, 0x6A, 0xE8, 0x16, 0xCD, 0xC2, 0x0B, 0x68, 0x1E, 0xD4, 0xF9, 0x43, 0xFD, 0xEA, 0x32, 0x9E, 0xC9, 0x78, 0xD9, 0xAF, 0xC1, 0xC2, 0x46, 0x65, 0x96, 0x2B, 0xDB, 0x15, 0x1F, 0xD5, 0xE1, 0x0D, 0x15, 0xC0, 0x24, 0xAA, 0x4A, 0x11, 0x27, 0x04, 0xF4, 0x42, 0xE8, 0x92, 0x15, 0x99, 0x40, 0x00, 0xAD, 0xAE, 0xCE, 0xEF, 0x2E, 0x7F, 0xE9, 0xF4, 0x3A, 0x54, 0x28, 0x54, 0xE4, 0x8B, 0x20, 0xA7, 0xD9, 0x72, 0x0A, 0x8E, 0x0B, 0x82, 0xB5, 0xC5, 0x14, 0xBA, 0x38, 0x26, 0x88, 0xC9, 0x9C, 0xD8, 0xCE, 0x65, 0x90, 0xF8, 0xAE, 0x96, 0xD3, 0xD4, 0xED };

                ULONG privateKeyBlobLength = sizeof(g_privateKeyBlob); // Get the size of your private key blob
                PUCHAR decryptedData = NULL;
                ULONG decryptedDataLength = 0;

                NTSTATUS stat = DecryptRsaData(handshakeData->EncryptedData, 256, g_privateKeyBlob, privateKeyBlobLength, &decryptedData, &decryptedDataLength);

NTSTATUS DecryptRsaData(
    PUCHAR encryptedData, ULONG encryptedDataLength,
    PUCHAR privateKeyBlob, ULONG privateKeyBlobLength,
    PUCHAR* decryptedData, PULONG decryptedDataLength) {

    BCRYPT_ALG_HANDLE algHandle = NULL;
    BCRYPT_KEY_HANDLE keyHandle = NULL;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    DebugMessage("DecryptRsaData 1 \n");
    // Open an algorithm provider for RSA.
    status = BCryptOpenAlgorithmProvider(&algHandle, BCRYPT_RSA_ALGORITHM, NULL, 0);
    if (!NT_SUCCESS(status)) {
        return status;
    }
    DebugMessage("DecryptRsaData 2 \n");
    // Import the private key.
    status = BCryptImportKeyPair(algHandle, NULL, BCRYPT_RSAPRIVATE_BLOB, &keyHandle,
        privateKeyBlob, privateKeyBlobLength, 0);
    if (!NT_SUCCESS(status)) {
        BCryptCloseAlgorithmProvider(algHandle, 0);
        return status;
    }

Based on that I assume my private key conversion is just wrong. Right now I am using C# to create a private and a public key then I convert the private key into a byte form then pasting it inside my driver before then pasting the public key inside the C# code. Also dont worry ill regenerate the keys again after I get this working since pasting the private key here would just be dumb otherwise. I know this might be a bit out of scope from my original question but if anyone knows how to properly covert my private key into byte form I would greatly appreciate it!

This seems like a candidate for Intel SGX, as otherwise any privileged code can find this private key from memory (As already pointed by MBond2.

Yea thats a good point but SGX is not a good solution since its not universal any other ideas?