zoukankan      html  css  js  c++  java
  • 得到线程入口地址的方式

    要获取入口地址,可以用Native API: NtQueryInformationThread,以ThreadQuerySetWin32StartAddress为参数

    具体代码:

    .h:

    #pragma once
    typedef LONG NTSTATUS;
    typedef NTSTATUS (WINAPI *NTQUERYINFORMATIONTHREAD)(
    	HANDLE ThreadHandle, 
    	ULONG ThreadInformationClass, 
    	PVOID ThreadInformation, 
    	ULONG ThreadInformationLength, 
    	PULONG ReturnLength);
    typedef enum _THREADINFOCLASS {
    	ThreadBasicInformation,
    	ThreadTimes,
    	ThreadPriority,
    	ThreadBasePriority,
    	ThreadAffinityMask,
    	ThreadImpersonationToken,
    	ThreadDescriptorTableEntry,
    	ThreadEnableAlignmentFaultFixup,
    	ThreadEventPair_Reusable,
    	ThreadQuerySetWin32StartAddress,
    	ThreadZeroTlsCell,
    	ThreadPerformanceCount,
    	ThreadAmILastThread,
    	ThreadIdealProcessor,
    	ThreadPriorityBoost,
    	ThreadSetTlsArrayAddress,   // Obsolete
    	ThreadIsIoPending,
    	ThreadHideFromDebugger,
    	ThreadBreakOnTermination,
    	ThreadSwitchLegacyState,
    	ThreadIsTerminated,
    	ThreadLastSystemCall,
    	ThreadIoPriority,
    	ThreadCycleTime,
    	ThreadPagePriority,
    	ThreadActualBasePriority,
    	ThreadTebInformation,
    	ThreadCSwitchMon,          // Obsolete
    	ThreadCSwitchPmu,
    	ThreadWow64Context,
    	ThreadGroupInformation,
    	ThreadUmsInformation,      // UMS
    	ThreadCounterProfiling,
    	ThreadIdealProcessorEx,
    	MaxThreadInfoClass
    } THREADINFOCLASS;
    
    class FindThreadStaAddr
    {
    public:
    	FindThreadStaAddr(void);
    	~FindThreadStaAddr(void);
    
    
    	DWORD GetThreadStartAddr1(DWORD dwThreadId);
    };
    

    .cpp

    #include "StdAfx.h"
    #include "FindThreadStaAddr.h"
    
    FindThreadStaAddr::FindThreadStaAddr(void)
    {
    }
    
    FindThreadStaAddr::~FindThreadStaAddr(void)
    {
    }
    
    
    DWORD FindThreadStaAddr::GetThreadStartAddr1(DWORD dwThreadId)
    {
    	HMODULE hNtdll = LoadLibrary(_T("ntdll.dll"));
    	if (!hNtdll)
    	{
    		return 0;
    	}
    
    	NTQUERYINFORMATIONTHREAD NtQueryInformationThread = NULL;
    	NtQueryInformationThread = (NTQUERYINFORMATIONTHREAD)
    	 GetProcAddress(hNtdll, "NtQueryInformationThread");
    	if (!NtQueryInformationThread)
    	{
    		return 0;
    	}
    
    	HANDLE ThreadHandle = NULL;
    	ThreadHandle = OpenThread(THREAD_QUERY_INFORMATION, FALSE, dwThreadId);
    	if (!ThreadHandle)
    	{
    		return 0;
    	}
    
    	DWORD dwStaAddr = NULL;
    	DWORD dwReturnLength = 0;
    	if(NtQueryInformationThreadtion(ThreadHandle, ThreadQuerySetWin32StartAddress,
    	&dwStaAddr, sizeof(dwStaAddr), &dwReturnLength))
    	{
    		return 0;
    	}
    
    	return dwStaAddr;
    }


    要注意的是

    1.NtQueryInformationThread成功返回的是STATUS_SUCCESS(0)

    另一种判断的方式是直接hook  LdrInitializeThunk

    贴个原型:

    typedef void (__stdcall *LDRINITIALIZETHUNK)(ULONG param0, ULONG param1, ULONG param2, ULONG param3);
    PCONTEXT    pContext;
    pContext = (PCONTEXT)¶m3;
    pContext->Eax即为函数入口地址

    这个是入口地址,而且是在没有进入入口函数地址之前调用的,所以可以在这里判断是否需要KILL此线程.

    自己写了个demo测试第一种方式:

    1。随机生成一个线程,打印它的地址和ID

    2。输入要查询的线程ID,点击查询按钮:

    打印的线程地址和上面的一致,

    源码


     

  • 相关阅读:
    顺序队列C/C++实现
    顺序队列C/C++实现
    顺序队列C/C++实现
    Java文件拷贝
    Java文件拷贝
    三大范式与BCNF
    基础知识
    编辑软件
    Linux基础知识集锦
    Linux基础知识集锦
  • 原文地址:https://www.cnblogs.com/hgy413/p/3693438.html
Copyright © 2011-2022 走看看