无法将 C# 字符串从用户空间传递到内核模式 C 并使用它来查找特定的 LDR_DATA_TABLE_ENTRY

Ben*_*Ben 10 c c# deviceiocontrol windows-kernel

我在比较从用户模式类型 LPWSTR 传递到 LDR 表条目类型 UNICODE_STRING 的字符串时遇到困难

内核 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;
Run Code Online (Sandbox Code Playgroud)

这个结构体通过 deviceiocontrol 传递给内核。对应的用户空间结构如下:

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;
}
Run Code Online (Sandbox Code Playgroud)

字符串在哪里 ModuleName被编组为 LPWStr。

ModuleName是进程中加载​​模块的所需搜索词。现在,事情变得棘手了。我可以通过访问的字符串_LDR_DATA_TABLE_ENTRYUNICODE_STRING. 我想将此 UNICODE_STRING 与我的 LPWSTR 进行比较。

我尝试了以下方法,但没有奏效:

{
    UNICODE_STRING str;
    RtlInitUnicodeString(&str, module_name) // module name is the userland passed string LPWSTR
    if (RtlCompareUnicodeString(&str, &module_ldr->BaseDllName, TRUE) {


    }
}
Run Code Online (Sandbox Code Playgroud)

我也试过 wcscmp 和其他一些东西。我不确定如何正确比较这两者。我在函数中添加了一些次要的伪代码,以提供有关我要执行的操作的附加上下文。

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;
Run Code Online (Sandbox Code Playgroud)

Ben*_*Ben 1

我想我会回答这个问题,因为我几年前问过这个问题,现在不再有这个问题了。

我在调用之前从用户区创建的字符串KeStackAttachProcess一旦被调用就无效。我不太确定这是否就是堆栈附加到进程的工作原理,但无论如何修复都是非常微不足道的,例如(这是伪的):

RtlInitUnicodeString(&str, module_name)
UNICODE_STRING example;

KeStachAttachProcess()

example = &module_ldr->BaseDllName;

KeStackDetachProcess()

RtlCompareUnicodeString(&example, &module_name)
Run Code Online (Sandbox Code Playgroud)

比较是在附加之外进行的。