在C#中获取外部进程的线程起始地址

时间:2017-09-10 20:31:14

标签: c# windows memory-address

我已经设置了一个简单的C#程序。 我是从kernel32.dll OpenProcessReadProcessMemoryWriteProcessMemory导入的。

我已经在Process课程中获得了一个外部流程。

如何为特定StartAddress获取主题#0 ProcessThread

Process process = Process.GetProcessesByName("Calculator")[0];
if (process == null) {
    Console.WriteLine("Process not found");
    return;
}

foreach (ProcessThread thread in process.Threads) {
    Console.WriteLine(thread.StartAddress);
}

上面代码的结果是:

-157479632
-157479632
-157479632
-157479632
0
-157479632
-157479632
-157479632
-157479632
-157479632
-157479632
-157479632

为什么有一些0,其余都是相同的,都是否定的?

1 个答案:

答案 0 :(得分:0)

线程对象(struct _ETHREAD)中的

存在2个不同的起始地址 - StartAddress - 这是通过LdrInitializeThunk遍历DLL后线程开始执行的地址。也存在第二个地址 - Win32StartAddress。感觉这个地址 - 当我们通过win32函数Create[Remothe]Thread(或它的shell)创建线程时 - win32 level将公共线程StartAddress设置为ntdll.RtlThreadThreadStart(此函数的名称取决于windows版本,在xp上说 - 另一个名字),实际的 lpStartAddress 作为参数传递给Create[Remothe]ThreadRtlThreadThreadStart已经调用了实际的 lpStartAddress lpStartAddress 并存储在Win32StartAddress中。

因为大多数线程是通过win32 Create[Remothe]Thread创建的 - 所有线程都具有相同的StartAddress(对于另一个StartAddress我们需要直接调用低级别api,如RtlCreateUserThread。在系统进程中 - StartAddress是内核中的实际线程起始地址)

使用代码时

foreach (ProcessThread thread in process.Threads) {
    Console.WriteLine(thread.StartAddress);
}

你得到StartAddress - 绝对正常,你在大多数情况下给出相同的地址。在某些情况下,你可以得到0或另一个不正确的值 - 因为在某些版本的窗口StartAddress与另一个成员联合保存并且可以被覆盖。

获取Win32StartAddress您必须使用THREAD_QUERY_LIMITED_INFORMATIONTHREAD_QUERY_INFORMATION打开广告句柄并使用ZwQueryInformationThread致电ThreadQuerySetWin32StartAddress

    PVOID pv;
    ZwQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, &pv, sizeof(pv), 0);

和约all negative?

因为你错误地打印了线程地址 - 指针。你打印它作为有符号整数。但是你必须用十六进制打印它作为%p格式的指针