SetThreadContext仅修改x64中RIP的最后32位

时间:2017-12-29 09:24:56

标签: c++ windows multithreading winapi 64-bit

由于未知原因, SetThreadContext在x64进程中无法正常工作。我打算在挂起的线程上使用它来修改指令指针并使线程执行一些shellcode。 不幸的是,SetThreadContext似乎只修改了x64指令RIP的最后32位

为了隔离问题,我制作了以下小程序,提示用户输入一个线程ID,如果它成功附加到线程,用户可以输入一个地址来手动修改指令指针。

#include <Windows.h>
#include <iostream>

using namespace std;

int main() {
    DWORD tid = 0;
    cout << "Thread ID: ";
    cin >> dec >> tid;

    HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
    if (hThread == NULL) {
        cout << "Failed." << endl;
        system("pause");
        return EXIT_FAILURE;
    }

    DWORD64 newRip = 0;
    cout << "New RIP: 0x";
    cin >> hex >> newRip;

    CONTEXT tcNew;
    SecureZeroMemory(&tcNew, sizeof(tcNew));
    tcNew.ContextFlags = CONTEXT_FULL;
    tcNew.Rip = newRip;

    SuspendThread(hThread);
    SetThreadContext(hThread, &tcNew);
    ResumeThread(hThread);

    cout << "Done." << endl;
    system("pause");
    return EXIT_SUCCESS;
}

现在,如果我启动另一个x64进程,我附加到调试器并使用Process Hacker或Sysinternals的Process Explorer等工具来获取此进程的运行线程ID,我可以简单地将此程序附加到我想要的线程修改并输入我希望它执行的地址。

我用几个程序(一些是用我的Visual Studio和一些x64进程从我的Windows编译,如记事本或mspaint)和进行测试,如果我将新RIP设置为0x1234567890ABCDEF然后我得到一个Access违规执行位置0x0000000090ABCDEF

现在这很有趣,似乎 RIP地址中最重要的32位由于某种原因在此过程中丢失,我无法解释。 我想到了我的Visual Studio项目配置中的一些问题,所以我再次从头开始,但同样的事情。我还尝试安装另一个IDE和编译器(Code :: Blocks和MinGW64)但由于某种原因问题仍然存在。 更有趣的是, GetThreadContext运行良好,我成功地获得了RIP处于挂起线程中的64位地址。 只有SetThreadContext似乎是问题。

如果你知道为什么会发生这种情况,或者有任何实验建议,我可以尝试让我了解如何解决这个问题的新想法,请毫不犹豫地分享。

非常感谢。

1 个答案:

答案 0 :(得分:0)

谢谢@RbMm在CONTEXT上调用GetThreadContext然后用来编辑RIP解决了问题。我将详细了解这个SegC的作用,以便更详细地了解这个问题的原因。