A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #31346  by sharpmddr
 Sun Mar 18, 2018 5:28 am
I am a newer programme developer of Windows Kernel project.Recently,I am having trouble in Windows kernel programme about UNICODE_STRINGS. I am writing a driver that writes an output file instead of having the name of the file hard-coded inside the driver source code, I would like to send it a file name from a user application. I using buffered I/O send the file name to driver. The user application send code is:

void Transfile(CString FileNamePath)
{
HANDLE device = NULL;
ULONG ret_len;
CString PreStr="\\\\??\\\\";
CString TranStr = "";
TranStr.Format(_T("%s%s"), PreStr, FileNamePath); //TranStr="\\??\\c:\\test.txt"
char *msg = (LPSTR)(LPCSTR)TranStr;

device = CreateFile("\\\\.\\micksysTestr", GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);

DeviceIoControl(device, Com_Send, msg, strlen(msg)+1, NULL, 0, &ret_len, 0)
CloseHandle(device);
}


And then the driver do buffered I/O using DeviceIoControl code is:

NTSTATUS DeviceIoControl(PDEVICE_OBJECT DeviceObject, PIRP irp)
{
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp);
NTSTATUS status = STATUS_SUCCESS;
PWSTR b = L"\\??\\c:\\test.txt";
PWSTR pWstr = NULL;
UNREFERENCED_PARAMETER(DeviceObject);
PAGED_CODE();
switch (irpsp->Parameters.DeviceIoControl.IoControlCode)
{
case Com_Send:

pWstr = (PWSTR)irp->AssociatedIrp.SystemBuffer; //DbgPrint(pWstr) is \\??\\c:\\test.txt
OutFile(pWstr); //OutFile(b)
status = irp->IoStatus.Status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
break;
......
}

VOID OutFile(IN PWSTR FileName)
{
NTSTATUS status;
HANDLE hFileHandle;
UNICODE_STRING uFile;
WCHAR FilePath[256] = { 0 };
wcscpy(FilePath, FileName);
hFileHandle = CDelOpenFile(FilePath, FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE);
......
}

The display of Debug View is correct from "DbgPrint(pWstr)", the pWstr is "\\??\\c:\\test.txt". But the function of OutFile(pWstr) is not correct, however when I used the variante "b" instead of "pWstr", and then the function of OutFile(b) is right. Now I don't know how to programme the code to realize the pWstr to b? Is it right of the knowlege about ANSI to UNICODE_STRING? Thanks in advance for any assistance
 #31349  by Vrtule
 Sun Mar 18, 2018 7:26 pm
Yes, you seem to send an ANSI-character string to the driver, not the wide-character one. UNICODE_STRING is just a structure that contains:
* a pointer to the wide-character string (i.e. PWSTR),
* string length, in bytes
* maximum possible string length that fits into the buffer (the PWSTR), required only for modifying operations.

If you have a wide-character string (PWSTR), RtlInitUnicodeString initializes an UNICODE_STRING structure pointing to that string. If you have an ANSI-character string, you can similarly use RtlInitAnsiString to initialize an ANSI_STRING structure pointing to it. RtlAnsiStringToUnicodeString and RtltUnicodeStringToAnsiString sort of converts between ANSI_STRING and UNICODE_STRING structures, howerver, they can allocate and copy the ansi-character and wide-character strings which is important since you may need to free them (RtlFreeAnsiString, RtlFreeUnicodeString).

I would discourage you from passing the strings in their C form (PSTR, PWSTR) since a malicious application may simply send such as string and omit the null-terminating character. It is better to send the length of the string together with its characters, which is exactly why the UNICODE_STRING and ANSI_STRING structures exist.