A forum for reverse engineering, OS internals and malware analysis 

Ask your beginner questions here.
 #32014  by Paul
 Tue Aug 21, 2018 11:45 am
Hi,

I use RtlUnicodeStringCat to concatenate two UnicodeStrings and this "randomly" fails with GetLastError 0x80000005.
I do this in order to get a full objectname for a filepath. My code reads like this:
Code: Select all
UNICODE_STRING prefix;
RtlInitUnicodeStringEx(&prefix, L"\\DosDevices\\");

UNICODE_STRING fullPathObjectName; // TODO: How much space is really needed?
fullPathObjectName.Buffer = ExAllocatePoolWithTag(NonPagedPool, (prefix.Length * sizeof(WCHAR)) + (path.Length * sizeof(WCHAR)) + 2, 'tGAT');

if (fullPathObjectName.Buffer == NULL)
{
	DbgPrint("Could not allocate memory for the dlls object name.");
	return STATUS_INSUFFICIENT_RESOURCES;
}

RtlCopyUnicodeString(&fullPathObjectName, &prefix);
status = RtlUnicodeStringCat(&fullPathObjectName, &path);

if (!NT_SUCCESS(status))
{
	DbgPrint("Could not append this unicode strings: \"%wZ\" + \"%wZ\" - Result string is \"%wZ\" - Status 0x%X\n", prefix, path, fullPathObjectName, status);
	return status;
}
0x80000005 means STATUS_BUFFER_OVERFLOW in this case which would mean that i did not allocate enough memory for the result string. This doesn't really make sense to me because the strings are always the same (prefix is static, path comes from userinput but i do always input the same string and handle its size dynamically).

Nearly forgot the output of my debug print.
Could not append this unicode strings: "\DosDevices\" + "C:\Users\somebody\source\repos\someProject\Release\x64\someFile.dll" - Result string is "" - Status 0x80000005

So dear masters of kernel development:
Teach me please!
 #32020  by EP_X0FF
 Wed Aug 22, 2018 5:31 am
AFAIK STATUS_BUFFER_OVERFLOW comes from RtlWideCharArrayCopyWorker in this strsafe.

Does this also fail?
Code: Select all
USHORT sz = (prefix.Length * sizeof(WCHAR)) +
        (path.Length * sizeof(WCHAR)) +
        2;

fullPathObjectName.Buffer = ExAllocatePoolWithTag(NonPagedPool, sz, 'tGAT');
RtlSecureZeroMemory(fullPathObjectName.Buffer, sz);

fullPathObjectName.Length = 0;
fullPathObjectName.MaximumLength = sz;

RtlAppendUnicodeStringToString(&fullPathObjectName, &prefix);
status = RtlAppendUnicodeStringToString(&fullPathObjectName, &path);
 #32023  by Paul
 Wed Aug 22, 2018 10:24 am
That code does not fail.
Thank you for the hint towards setting Lenght and MaximumLength. I did not set them and that's necessary.

I ended up with this code for the task of getting a full objectname for an absolut path.
Code: Select all
UNICODE_STRING prefix;
RtlInitUnicodeStringEx(&prefix, L"\\DosDevices\\");

UNICODE_STRING fullPathObjectName;
fullPathObjectName.Buffer = ExAllocatePoolWithTag(NonPagedPool, prefix.Length + path.Length + 2, 'nIBC');
fullPathObjectName.Length = 0;
fullPathObjectName.MaximumLength = prefix.Length + path.Length + 2;

if (fullPathObjectName.Buffer == NULL)
{
	DbgPrint("Could not allocate memory for the dlls object name.");
	return STATUS_INSUFFICIENT_RESOURCES;
}

RtlCopyUnicodeString(&fullPathObjectName, &prefix);
status = RtlUnicodeStringCat(&fullPathObjectName, &path);

if (!NT_SUCCESS(status))
{
	DbgPrint("Could not append this unicode strings: \"%wZ\" + \"%wZ\" - Result string is \"%wZ\" - Status 0x%X\n", prefix, path, fullPathObjectName, status);
	return status;
}
So initially I failed about not setting Length + MaximumLength and also the calculation of size using sizeof(WCHAR) is not needed because Length already did that for me.