I have the following code which is responsible to receive and send data between my mini-filter driver and user-mode:
NTSTATUS MiniSendRecv(PVOID portcookie, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, PULONG RetLength) {
PCHAR msg = "Hi User";
PCHAR userData = (PCHAR)InputBuffer;
DbgPrintEx(0, 0, "User said: %d:%s\n", strlen(userData), userData);
DbgPrintEx(0, 0, "Before comparing strings\n");
if (RtlCompareString(userData, (PCHAR)"status=stop", TRUE) == 0) {
DbgPrintEx(0, 0, "stop requested\n");
}
//if((PCHAR)InputBuffer.contains("status=stopservice"))
if (strlen(msg) > OutputBufferLength) {
DbgPrintEx(0, 0, "message length too big\n");
return STATUS_SUCCESS;
}
strncpy((PCHAR)OutputBuffer, msg, 500);
return STATUS_SUCCESS;
}
WinDBG output:
User said: 11:status=stop
Before comparing strings
KDTARGET: Refreshing KD connection
*** Fatal System Error: 0x0000003b
(0x00000000C0000005,0xFFFFF8046D001E82,0xFFFF8580E9924C20,0x0000000000000000)
Break instruction exception - code 80000003 (first chance)
A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.
A fatal system error has occurred.
nt!DbgBreakPointWithStatus:
fffff804`6cdffc70 cc int 3
As you can see the data is received just fine, but as soon as it hit RtlCompareString
, the driver crashes causing the OS to crash as well.
Also prior to using PCHAR userData
, I was doing if (RtlCompareString((PCHAR)InputBuffer, (PCHAR)"status=stop", TRUE) == 0)
but that didn't do any good as well.
Can anyone tell me what is wrong here? when I call RtlCompareString
against OutputBuffer, it works just fine.
CodePudding user response:
RtlCompareString
compares counted strings. What you have are null terminated strings. Just use the regular strcmp
function, or since you seem to be trying to do a case insensitive string comparison you could try the non-standard _stricmp
function.
CodePudding user response:
Try something like this (I always try to implement in terms of standard C i.o. winapi calls). string_view is a nice lightweight class to make views on buffers which has hardly any overhead but gives you things like a compare function.
#include <Windows.h>
#include <array>
#include <string>
#include <iostream>
NTSTATUS MiniSendRecv(PVOID portcookie, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, PULONG RetLength)
{
// you can make msg static it will not vary from call to call
static const std::string_view msg{ "Hi User" };
// create a string_view on the input, using the passed input length
const std::string_view input{ static_cast<const char*>(InputBuffer), static_cast<std::size_t>(InputBufferLength) };
// and now you can just use string_view compare instead of awkward win api call
if (msg == input)
{
std::cout << "messages are equal\n";
}
return ERROR_SUCCESS;
}
int main()
{
std::array hi_buffer{ 'H','i',' ','U','s','e','r' }; // Note : NO trailing '\0` in hi_buffer
std::array<char, 16> output_buffer;
ULONG ret_buffer_size{ 0ul };
MiniSendRecv
(
nullptr,
static_cast<PVOID>(hi_buffer.data()), hi_buffer.size(),
static_cast<PVOID>(output_buffer.data()), output_buffer.size(),
&ret_buffer_size
);
return 0;
}