Search code examples
c++stringkerneldriver

Why is my driver only reading part of the string?


I'm attempting to read a string from a dummy program with a kernel driver. But only the first 4 char's are being read, I can't figure out why.

Part of the IOCTL code for reading the string:

else if (ControlCode = IO_READ_STRING_REQUEST)
{
    PREAD_REQUEST Values = (PREAD_REQUEST)buffer;
    PREAD_REQUEST ValuesOutput = (PREAD_REQUEST)buffer;
    PEPROCESS process;

    if (NT_SUCCESS(PsLookupProcessByProcessId(PID, &process)))
    {
        KeReadProcessMemory(process, Values->Address, &ValuesOutput->buffer, Values->Size);
        DbgPrint((PCSTR)Values->buffer);
        status = STATUS_SUCCESS;
    }
    else
        status = STATUS_INVALID_PARAMETER;

    BytesIO = sizeof(READ_REQUEST);
}

This is the read struct:

typedef struct ReadStruct
{
    ULONGLONG Address;
    ULONGLONG Response;
    ULONGLONG Size;
    char buffer[128];

} READ_REQUEST, *PREAD_REQUEST;

The DbgPrint always prints stri when it's supposed to print stringChar, and stri is returned to the usermode.

This is how it's called from usermode:

void ReadString(std::string *string, DWORD64 address)
{
    ReadValues Values;
    std::memset(Values.buffer, '\0', 128);
    Values.Address = address;
    Values.Response = 0;    
    Values.Size = sizeof(128);

    if (!(DeviceIoControl(hDriver, IO_READ_STRING_REQUEST, &Values, sizeof(Values), &Values, sizeof(Values), 0, 0)))
    {
        std::cout << "RPM Failed!\n";
        exit(1);
    }

    *string = (std::string)Values.buffer;
}

The struct is the same:

struct ReadValues
{
    ULONGLONG Address;
    ULONGLONG Response;
    ULONGLONG Size;
    char buffer[128];
};

I thought it was the size, but when I specified the size to 11 (10 + \0) it also read only 4 chars.


Solution

  • The problem is here:

    Values.Size = sizeof(128);
                  ^^^^^^^^^^^
    

    This is the same as sizeof(int) (which, I would guess, is 4 in your platform).

    Either use 128 or sizeof(buffer) (the latter is arguably better since you won't be hard-coding the same constant in several places).