最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ZwGetContextThread fails from kernel mode - Stack Overflow

programmeradmin0浏览0评论

The problem is its always fails with status unsuccesfull.

My Goal is to Hijack a thread from a usermode programm using kernel mode. So my idea was to use the Zw Functions so i used windbg on my vmware and search for the functions then creating patterns for them. In my Kernel Driver i wrote a function to find the ntoskrnl.exe baseaddress and size. then i made a findpattern function to search for this bite patterns in the module.Then i tested it if i manage to find the Function addresses.

 const char* moduleName = "ntoskrnl.exe";
 ULONG sizeOfModule = 0;
 uintptr_t moduleBase = get_kernel_module(moduleName,&sizeOfModule);


 if (moduleBase == 0)
 {
     DbgPrint("Failed to locate module: %s\n", moduleName);
     return STATUS_UNSUCCESSFUL;
 }

 DbgPrint("Module %s located at: 0x%p\n", moduleName, (PVOID)moduleBase);
 PUCHAR ModuleStart = (PUCHAR)moduleBase;

 
 PVOID ZwSuspend = (PVOID)FindPattern_Wrapper(ModuleStart, sizeOfModule, "48 8B C4 FA 48 83 EC 10 50 9C 6A 10 48 8D 05 5D 4F 00 00 50");
 DbgPrint("ZwSuspendThread address: 0x%p\n", ZwSuspend);

 PVOID ZwResume = (PVOID)FindPattern_Wrapper(ModuleStart, sizeOfModule, "48 8B C4 FA 48 83 EC 10 50 9C 6A 10 48 8D 05 BD 7C 00 00 50");
 DbgPrint("ZwResumeThread address: 0x%p\n", ZwResume);

 PVOID ZwOpenThread = (PVOID)FindPattern_Wrapper(ModuleStart, sizeOfModule, "48 8B C4 FA 48 83 EC 10 50 9C 6A 10 48 8D 05 1D 61 00 00 50");
 DbgPrint("ZwOpenThread address: 0x%p\n", ZwOpenThread);

 PVOID ZwSetContextThread = (PVOID)FindPattern_Wrapper(ModuleStart, sizeOfModule, "48 8B C4 FA 48 83 EC 10 50 9C 6A 10 48 8D 05 7D 55 00 00 50");
 DbgPrint("ZwtSetContextThread address: 0x%p\n", ZwSetContextThread);

 PVOID ZwGetContextThread = (PVOID)FindPattern_Wrapper(ModuleStart, sizeOfModule, "48 8B C4 FA 48 83 EC 10 50 9C 6A 10 48 8D 05 9D 68 00 00 50");
 DbgPrint("ZwGetContextThread address: 0x%p\n", ZwGetContextThread);

Output:

Module ntoskrnl.exe located at: 0xFFFFF80668A00000
ZwSuspendThread from driver address: 0xFFFFF80668DFB910
Found address from Windbg:           0xFFFFF80668DFB910

ZwResumeThread from driver address: 0xFFFFF80668DF8BB0
Found address from Windbg:      0xFFFFF80668DF8BB0

ZwOpenThread from driver address: 0xFFFFF80668DFA750
Found address from Windbg:    0xFFFFF80668DFA750

ZwtSetContextThread from driver address: 0xFFFFF80668DFB2F0
Found address from Windbg:       0xFFFFF80668DFB2F0

ZwGetContextThread from driver address: 0xFFFFF80668DF9FD0
Found address from Windbg:              0xFFFFF80668DF9FD0

As you can see the Driver finds the right address. Then i worked on the Hijack function.

NTSTATUS HijackThread(DWORD threadID, PVOID remoteBuffer)
{
    NTSTATUS status = STATUS_SUCCESS;
    const char* moduleName = "ntoskrnl.exe";
    ULONG sizeOfModule = 0;
    uintptr_t moduleBase = get_kernel_module(moduleName,&sizeOfModule);

    if (moduleBase == 0)
    {
        DbgPrint("Failed to locate module: %s\n", moduleName);
        return STATUS_UNSUCCESSFUL;
    }
    PUCHAR ModuleStart = (PUCHAR)moduleBase;

    // Get the NtOpenThread function
    static ZwOpenThreadPtr ZwOpenThread = (ZwOpenThreadPtr)FindPattern_Wrapper(ModuleStart, sizeOfModule, "48 8B C4 FA 48 83 EC 10 50 9C 6A 10 48 8D 05 1D 61 00 00 50");

    if (ZwOpenThread == NULL)
    {
        DbgPrint("Failed to get function: ZwOpenThread\n");
        return STATUS_UNSUCCESSFUL;
    }

    // Prepare CLIENT_ID for opening the thread
    CLIENT_ID clientId = { 0 };
    clientId.UniqueThread = (HANDLE)threadID;
    clientId.UniqueProcess = NULL;  // Not required for this case

    OBJECT_ATTRIBUTES objectAttributes;
    InitializeObjectAttributes(&objectAttributes, NULL, 0, NULL, NULL);

    HANDLE threadHandle = NULL;
    status = ZwOpenThread(&threadHandle, THREAD_SUSPEND_RESUME, &objectAttributes, &clientId);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("Failed to open thread, status: 0x%X\n", status);
        return status;
    }

    // Suspend the thread
    static ZwSuspendThreadPtr ZwSuspendThread = (ZwSuspendThreadPtr)FindPattern_Wrapper(ModuleStart, sizeOfModule, "48 8B C4 FA 48 83 EC 10 50 9C 6A 10 48 8D 05 5D 4F 00 00 50");

    if (ZwSuspendThread == NULL)
    {
        DbgPrint("Failed to get function: ZwSuspendThread\n");
        ZwClose(threadHandle);
        return STATUS_UNSUCCESSFUL;
    }

    ULONG suspendCount = 0;
    status = ZwSuspendThread(threadHandle, &suspendCount);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("Failed to suspend thread, status: 0x%X\n", status);
        ZwClose(threadHandle);
        return status;
    }
    ZwClose(threadHandle);

    status = ZwOpenThread(&threadHandle, THREAD_GET_CONTEXT, &objectAttributes, &clientId);
    if (!NT_SUCCESS(status)) {
        DbgPrint("Failed to reopen thread with THREAD_GET_CONTEXT, status: 0x%X\n", status);
        return status;
    }

    // Get the thread context
    static ZwGetContextThreadPtr ZwGetContextThread = (ZwGetContextThreadPtr)FindPattern_Wrapper(ModuleStart, sizeOfModule, "48 8B C4 FA 48 83 EC 10 50 9C 6A 10 48 8D 05 9D 68 00 00 50");

    if (ZwGetContextThread == NULL)
    {
        DbgPrint("Failed to get function: ZwGetContextThread\n");
        ZwClose(threadHandle);
        return STATUS_UNSUCCESSFUL;
    }

    CONTEXT threadContext = { 0 };
    threadContext.ContextFlags = CONTEXT_FULL;
    status = ZwGetContextThread(threadHandle, &threadContext);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("Failed to get thread context, status: 0x%X\n", status);
        ZwClose(threadHandle);
        return status;
    }

    ZwClose(threadHandle);


    // Modify the thread's RIP (instruction pointer)
    static ZwSetContextThreadPtr ZwSetContextThread = (ZwSetContextThreadPtr)FindPattern_Wrapper(ModuleStart, sizeOfModule, "48 8B C4 FA 48 83 EC 10 50 9C 6A 10 48 8D 05 7D 55 00 00 50");

    if (ZwSetContextThread == NULL)
    {
        DbgPrint("Failed to get function: ZwSetContextThread\n");
        ZwClose(threadHandle);
        return STATUS_UNSUCCESSFUL;
    }

    threadContext.Rip = (DWORD_PTR)remoteBuffer;

    status = ZwOpenThread(&threadHandle, THREAD_SET_CONTEXT, &objectAttributes, &clientId);
    if (!NT_SUCCESS(status)) {
        DbgPrint("Failed to reopen thread with THREAD_SET_CONTEXT, status: 0x%X\n", status);
        return status;
    }

    status = ZwSetContextThread(threadHandle, &threadContext);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("Failed to set thread context, status: 0x%X\n", status);
        ZwClose(threadHandle);
        return status;
    }

    ZwClose(threadHandle);

    // Resume the thread
    static ZwResumeThreadPtr ZwResumeThread = (ZwResumeThreadPtr)FindPattern_Wrapper(ModuleStart, sizeOfModule, "48 8B C4 FA 48 83 EC 10 50 9C 6A 10 48 8D 05 BD 7C 00 00 50");

    if (ZwResumeThread == NULL)
    {
        DbgPrint("Failed to get function: ZwResumeThread\n");
        ZwClose(threadHandle);
        return STATUS_UNSUCCESSFUL;
    }

    status = ZwOpenThread(&threadHandle, THREAD_SUSPEND_RESUME, &objectAttributes, &clientId);
    if (!NT_SUCCESS(status)) {
        DbgPrint("Failed to reopen thread for resuming, status: 0x%X\n", status);
        return status;
    }

    ULONG resumeCount = 0;
    status = ZwResumeThread(threadHandle, &resumeCount);
    if (NT_SUCCESS(status))
    {
        DbgPrint("Thread resumed successfully, resume count: %lu\n", resumeCount);
    }
    else
    {
        DbgPrint("Failed to resume thread, status: 0x%X\n", status);
    }

    // Clean up by closing the thread handle
    ZwClose(threadHandle);

    return status;
}

OpenThread and Suspending was working but it always gave error on ZwGetContextThread:

Failed to get thread context, status: 0xC0000001

Means unsuccesfull. But i dont know why. My Usermode programm finds the ThreadID from Notepad so thats not the problem. Thx for any help.

发布评论

评论列表(0)

  1. 暂无评论