I am having difficulty comparing a string passed from usermode type LPWSTR to a LDR table entry type UNICODE_STRING
Kernel C:
struct {
int pid;
int user_pid;
int size;
int protection_mode;
int allocation_type;
void* address;
void* write_buffer;
LPWSTR module_name;
}
userland_operation;
This struct is passed to the kernel via deviceiocontrol. The counterpart userland struct is as follows:
public struct MemOperation
{
public int Pid;
public int UserPid;
public int Size;
public int protection_mode;
public int allocation_type;
public IntPtr Addr;
public IntPtr WriteBuffer;
[MarshalAs(UnmanagedType.LPWStr)] public String ModuleName;
}
Where the String ModuleName
is Marshaled as LPWStr.
ModuleName
is the desired search term for the loaded module in a process. Now, here's where things get tricky. The string I have access to via the _LDR_DATA_TABLE_ENTRY
is a UNICODE_STRING
. I want to compare this UNICODE_STRING with my LPWSTR.
I have tried the following and it did not work:
{
UNICODE_STRING str;
RtlInitUnicodeString(&str, module_name) // module name is the userland passed string LPWSTR
if (RtlCompareUnicodeString(&str, &module_ldr->BaseDllName, TRUE) {
}
}
I've also tried wcscmp, and a few other things. I'm not sure how I can compare these two properly. I've added some minor pseudocode to the function to provide additional context on what I'm looking to do.
NTSTATUS GetModuleList(HANDLE PID, PVOID UserBuffer, LPWSTR module_name) {
KAPC_STATE APC;
__try {
PEPROCESS TargetProcess;
PsLookupProcessByProcessId(PID, &TargetProcess);
PPEB Peb = PsGetProcessPeb(TargetProcess);
if (!Peb)
return STATUS_INVALID_PARAMETER;
KeStackAttachProcess(TargetProcess, &APC);
UINT64 Ldr = (UINT64)Peb + PEBLDR_OFFSET;
ProbeForRead((CONST PVOID)Ldr, 8, 8);
PLIST_ENTRY ModListHead = (PLIST_ENTRY)(*(PULONG64)Ldr + PEBLDR_MEMORYLOADED_OFFSET);
ProbeForRead((CONST PVOID)ModListHead, 8, 8);
PLIST_ENTRY Module = ModListHead->Flink;
while (ModListHead != Module) {
LDR_DATA_TABLE_ENTRY* Module_Ldr = (LDR_DATA_TABLE_ENTRY*)(Module);
//psuedo if (module_name is in Module_Ldr->BaseDllName) // the comparison, where BaseDllName is type UNICODE_STRING
Module = Module->Flink;
}
KeUnstackDetachProcess(&APC);
ObDereferenceObject(TargetProcess);
return STATUS_SUCCESS;
Passing by by reference refers to a method of passing the address of an argument in the calling function to a corresponding parameter in the called function. In C, the corresponding parameter in the called function must be declared as a pointer type.
Values of variables are passed by the Simple technique. Pointer variables are necessary to define to store the address values of variables. Note: In C, we use pointers to achieve call by reference. In C++, we can either use pointers or references for pass by reference.
To pass a value by reference, argument pointers are passed to the functions just like any other value. So accordingly you need to declare the function parameters as pointer types as in the following function swap(), which exchanges the values of the two integer variables pointed to, by their arguments.
In this call below:
if (RtlCompareUnicodeString(&str, &module_ldr->BaseDllName) {
This function takes an additional argument which you are not passing. Please refer to https://docs.microsoft.com/en-us/windows/win32/devnotes/rtlcompareunicodestring
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With