遍历进程线程

typedef struct _CL_PROCESS_THREADINFO
{
LPVOID pvStartAddr; // 线程的起始地址
DWORD dwTid; // 线程Id
WCHAR wszModuleName[MAX_PATH]; // 所属的模块路径

}CL_PROCESS_THREADINFO;

 BOOL CLThread::QueryThreadInfo_By_Pid(__in DWORD dwPid, __out vector<CL_PROCESS_THREADINFO>& vlst)
{
/************************************************************************/
/* 
extern "C" LONG(__stdcall *ZwQueryInformationThread) (
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
OUT PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL
) = NULL;


extern "C" LONG(__stdcall *RtlNtStatusToDosError) (
IN  ULONG status) = NULL;

HINSTANCE hNTDLL = ::GetModuleHandle(TEXT("ntdll"));

(FARPROC&)ZwQueryInformationThread =
::GetProcAddress(hNTDLL, "ZwQueryInformationThread");

(FARPROC&)RtlNtStatusToDosError =
::GetProcAddress(hNTDLL, "RtlNtStatusToDosError");


可以直接用
status = ZwQueryInformationThread(thread,
ThreadQuerySetWin32StartAddress,
&startaddr,
sizeof (startaddr),
NULL);

*/
/************************************************************************/
typedef enum _THREADINFOCLASS {
ThreadBasicInformation,
ThreadTimes,
ThreadPriority,
ThreadBasePriority,
ThreadAffinityMask,
ThreadImpersonationToken,
ThreadDescriptorTableEntry,
ThreadEnableAlignmentFaultFixup,
ThreadEventPair_Reusable,
ThreadQuerySetWin32StartAddress,
ThreadZeroTlsCell,
ThreadPerformanceCount,
ThreadAmILastThread,
ThreadIdealProcessor,
ThreadPriorityBoost,
ThreadSetTlsArrayAddress,
ThreadIsIoPending,
ThreadHideFromDebugger,
ThreadBreakOnTermination,
MaxThreadInfoClass
} THREADINFOCLASS;

typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID;
typedef CLIENT_ID *PCLIENT_ID;

typedef struct _THREAD_BASIC_INFORMATION { // Information Class 0
LONG     ExitStatus;
PVOID    TebBaseAddress;
CLIENT_ID ClientId;
LONG AffinityMask;
LONG Priority;
LONG BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;

typedef LONG(__stdcall *ZwQueryInformationThread) (
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
OUT PVOID ThreadInformation,
IN ULONG ThreadInformationLength,
OUT PULONG ReturnLength OPTIONAL
);

ZwQueryInformationThread pZwQueryInformationThread = NULL;

auto fnSetThreadInfo_By_Tid = [&pZwQueryInformationThread](__in DWORD dwTid, __out CL_PROCESS_THREADINFO& ThreadInfo)
{
THREAD_BASIC_INFORMATION    tbi = { 0 };
PVOID                       pvStartAddr = NULL;
LONG                        lnStatus = NULL;
HANDLE                      hThread = NULL;
HANDLE hProcess = NULL;

hThread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, dwTid);
if (hThread == NULL)
return FALSE;

lnStatus = pZwQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, &pvStartAddr, sizeof (pvStartAddr), NULL);
if (lnStatus < 0)
{
CloseHandle(hThread);
return FALSE;
}

ZeroMemory(&ThreadInfo, sizeof(ThreadInfo));
ThreadInfo.dwTid = dwTid;
ThreadInfo.pvStartAddr = pvStartAddr;

lnStatus = pZwQueryInformationThread(hThread, ThreadBasicInformation, &tbi, sizeof (tbi), NULL);
if (lnStatus < 0)
{
CloseHandle(hThread);
return FALSE;
};

hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)tbi.ClientId.UniqueProcess);
if (hProcess == NULL)
{
CloseHandle(hThread);
return FALSE;
};

GetMappedFileName(hProcess, pvStartAddr, ThreadInfo.wszModuleName, MAX_PATH);

CloseHandle(hProcess);
CloseHandle(hThread);
return TRUE;
};

try
{
HMODULE hmNtDLL = ::GetModuleHandleW(L"ntdll.dll");
if (hmNtDLL == NULL)
return FALSE;

pZwQueryInformationThread = (ZwQueryInformationThread)::GetProcAddress(hmNtDLL, "ZwQueryInformationThread");
if (pZwQueryInformationThread == NULL)
return FALSE;

static CL_PROCESS_THREADINFO ThreadInfo;
HANDLE hSnapshot = NULL;
THREADENTRY32 te = { 0 };
te.dwSize = sizeof (te);

hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (Thread32First(hSnapshot, &te))
{
do
{
if (te.th32OwnerProcessID == dwPid && fnSetThreadInfo_By_Tid(te.th32ThreadID, ThreadInfo))
vlst.push_back(ThreadInfo);
} while (Thread32Next(hSnapshot, &te));
};
CloseHandle(hSnapshot);
return vlst.size() != NULL ? TRUE : FALSE;
}
catch (...)
{
CPrintLog::PrintLog_W(_SELF, __LINE__, L"QueryThreadInfo_By_Pid出现异常");
}
return FALSE;
}

00000001408875A4 ; __int64 __fastcall DbgkpPostFakeThreadMessages(PEPROCESS targerPorcess, PDEBUG_OBJECT debug_object, PETHREAD Thread, PETHREAD *OutThread, PETHREAD *OutThread2) 00000001408875A4 DbgkpPostFakeThreadMessages proc near ; CODE XREF: DbgkpPostFakeProcessCreateMessages+54↑p 00000001408875A4 ; DbgkpSetProcessDebugObject+E4↓p 00000001408875A4 ; DATA XREF: ... 00000001408875A4 var_1F8 = qword ptr -1F8h 00000001408875A4 var_1E8 = byte ptr -1E8h 00000001408875A4 var_1E7 = byte ptr -1E7h 00000001408875A4 var_1E4 = dword ptr -1E4h 00000001408875A4 PROCESS = qword ptr -1E0h 00000001408875A4 var_1D8 = qword ptr -1D8h 00000001408875A4 var_1D0 = qword ptr -1D0h 00000001408875A4 var_1C8 = qword ptr -1C8h 00000001408875A4 var_1C0 = qword ptr -1C0h 00000001408875A4 var_1B8 = qword ptr -1B8h 00000001408875A4 var_1B0 = qword ptr -1B0h 00000001408875A4 var_1A8 = qword ptr -1A8h 00000001408875A4 var_1A0 = qword ptr -1A0h 00000001408875A4 var_198 = qword ptr -198h 00000001408875A4 var_190 = qword ptr -190h 00000001408875A4 var_message = _DBGKM_APIMSG ptr -188h 00000001408875A4 ApcState = _KAPC_STATE ptr -78h 00000001408875A4 var_48 = qword ptr -48h 00000001408875A4 OutThread2 = qword ptr 28h 00000001408875A4 ; __unwind { // __GSHandlerCheck_SEH 00000001408875A4 mov r11, rsp ; 保存原始栈指针 00000001408875A7 push rbx ; 保存非易失寄存器 00000001408875A8 push rsi 00000001408875A9 push rdi 00000001408875AA push r12 00000001408875AC push r13 00000001408875AE push r14 00000001408875B0 push r15 00000001408875B2 sub rsp, 1E0h ; 分配栈空间 (480字节) 00000001408875B9 mov rax, cs:__security_cookie ; 安全Cookie检查初始化 00000001408875C0 xor rax, rsp ; 计算安全Cookie 00000001408875C3 NtWaitForDebugEvent$filt$0_0: ; 存储安全Cookie 00000001408875C3 mov [rsp+218h+var_48], rax 00000001408875CB mov [rsp+218h+var_1C0], r9 ; 保存第4个参数 (OutThread) 00000001408875D0 mov rbx, r8 ; 保存第3个参数 00000001408875D3 mov [rsp+218h+var_1D0], rdx ; 保存第2个参数 (DebugObject) 00000001408875D8 mov r14, rcx ; 保存第1个参数 (TargetProcess) 00000001408875DB mov [rsp+218h+PROCESS], rcx ; 再次保存TargetProcess 00000001408875E0 mov [rsp+218h+var_1A0], rcx 00000001408875E5 mov [rsp+218h+var_198], rdx 00000001408875ED mov rsi, r8 ; rsi = 第3个参数 00000001408875F0 mov [rsp+218h+var_190], r9 00000001408875F8 mov rax, [rsp+218h+OutThread2] ; 获取第5个参数 (栈传递) 0000000140887600 DbgkQueueUserExceptionReport_0: ; 保存第5个参数 0000000140887600 mov [rsp+218h+var_1B8], rax 0000000140887605 xorps xmm0, xmm0 ; 初始化APC状态结构 0000000140887605 ; 清零XMM0寄存器 0000000140887608 movups xmmword ptr [r11-78h], xmm0 ; 清零ApcState结构 000000014088760D movups xmmword ptr [r11-68h], xmm0 ; Move Unaligned Four Packed Single-FP 0000000140887612 movups xmmword ptr [r11-58h], xmm0 ; Move Unaligned Four Packed Single-FP 0000000140887617 xor edx, edx ; 初始化局部变量内存 0000000140887617 ; 清零作为memset参数 0000000140887619 mov r8d, 110h ; 设置大小 (272字节) 000000014088761F lea rcx, [r11-188h] ; 目标地址 0000000140887626 call memset ; 调用内存清零函数 000000014088762B xor r15d, r15d ; 初始化变量 000000014088762B ; r15d = 0 000000014088762E mov [rsp+218h+var_1D8], r15 ; 清零局部变量 0000000140887633 xor edi, edi ; edi = 0 0000000140887635 mov rax, gs:KPCR.kprcb.CurrentThread ; 获取当前线程 0000000140887635 ; 获取当前ETHREAD 000000014088763E mov [rsp+218h+var_1B0], rax ; 保存当前线程指针 0000000140887643 mov r12d, 0C0000001h ; 预设错误码 STATUS_UNSUCCESSFUL 0000000140887649 test rbx, rbx ; 检查第3个参数是否为NULL 000000014088764C jz short loc_140887669 ; 如果为NULL则跳转 000000014088764E mov r15, rbx ; 处理非NULL的线程参数 000000014088764E ; r15 = 输入线程 0000000140887651 mov [rsp+218h+var_1D8], rbx ; 保存到局部变量 0000000140887656 mov r14d, 'OgbD' ; 设置对象标签 'DBg' 000000014088765C mov edx, r14d ; Tag 标签作为参数 000000014088765F mov rcx, rbx ; Object 对象指针 0000000140887662 call ObfReferenceObjectWithTag ; 增加对象引用计数 0000000140887667 jmp short loc_14088767C ; 跳转到公共代码 0000000140887669 ; --------------------------------------------------------------------------- 0000000140887669 loc_140887669: ; CODE XREF: DbgkpPostFakeThreadMessages+A8↑j 0000000140887669 xor edx, edx ; 处理线程参数为NULL的情况 (遍历进程线程) 0000000140887669 ; 从第一个线程开始遍历 000000014088766B mov rcx, r14 ; TargetProcess 000000014088766E call PsGetNextProcessThread ; 获取进程第一个线程 0000000140887673 mov rbx, rax ; rbx = 当前线程 0000000140887676 mov r14d, 4F676244h ; 设置对象标签 'DBg' 000000014088767C loc_14088767C: ; CODE XREF: DbgkpPostFakeThreadMessages+C3↑j 000000014088767C mov [rsp+218h+var_1C8], rbx ; 公共代码路径 000000014088767C ; 保存当前线程 0000000140887681 test rsi, rsi ; 检查第3个参数 0000000140887684 setz r13b ; 如果为NULL则r13b=1 0000000140887688 mov [rsp+218h+var_1E8], r13b ; 保存标志 000000014088768D loc_14088768D: ; CODE XREF: DbgkpPostFakeThreadMessages+3AC↓j 000000014088768D test rbx, rbx ; 线程遍历主循环 000000014088768D ; 检查当前线程是否有效 0000000140887690 jz loc_1408878D1 ; 如果无效跳转到结束 0000000140887696 test rdi, rdi ; 释放前一线程对象 0000000140887696 ; 检查前一线程指针 0000000140887699 jz short loc_1408876A6 ; 如果为空则跳过 000000014088769B mov edx, r14d ; Tag 标签参数 000000014088769E mov rcx, rdi ; Object 线程对象 00000001408876A1 call ObfDereferenceObjectWithTag ; 减少引用计数 00000001408876A6 loc_1408876A6: ; CODE XREF: DbgkpPostFakeThreadMessages+F5↑j 00000001408876A6 mov rdi, rbx ; 处理当前线程 00000001408876A6 ; 保存当前线程到rdi 00000001408876A9 mov [rsp+218h+var_1A8], rbx ; 保存到局部变量 00000001408876AE mov edx, r14d ; Tag 标签参数 00000001408876B1 mov rcx, rbx ; Object 当前线程 00000001408876B4 call ObfReferenceObjectWithTag ; 增加引用计数 00000001408876B9 test dword ptr [rbx+74h], 400h ; 检查线程状态标志 00000001408876B9 ; 检查ThreadFlags+0x74 00000001408876B9 ; ULONG SystemThread:1; //0x74 00000001408876C0 jnz loc_14088793B ; 如果置位则跳过此线程 表示它是系统线程 00000001408876C6 mov eax, [rbx+_ETHREAD.___u21.CrossThreadFlags] ; 读取Thread->CrossThreadFlags 00000001408876CC test al, 2 ; 表示线程是否已经被插入到进程线程列表中。当线程被创建并成功插入时,此标志被设置 00000001408876CE jnz short loc_1408876EB ; 如果已设置则继续 00000001408876D0 mov rdx, [rsp+218h+var_1B0] ; 同步线程插入操作 00000001408876D0 ; 当前线程 00000001408876D5 mov rcx, rbx ; 目标线程 00000001408876D8 call PsSynchronizeWithThreadInsertion ; 等待线程可用 00000001408876DD mov eax, [rbx+510h] ; 再次读取CrossThreadFlags 00000001408876E3 test al, 2 ; 表示线程是否已经被插入到进程线程列表中。当线程被创建并成功插入时,此标志被设置 00000001408876E5 jz loc_14088793B ; 如果未设置则跳过线程 00000001408876EB loc_1408876EB: ; CODE XREF: DbgkpPostFakeThreadMessages+12A↑j 00000001408876EB lea rcx, [rbx+_ETHREAD.RundownProtect] ; 获取线程运行保护 00000001408876EB ; Thread->RundownProtect 00000001408876F2 call ExAcquireRundownProtection ; 获取运行保护 00000001408876F7 test al, al ; 检查是否成功 00000001408876F9 jz short loc_140887719 ; 失败则跳转 00000001408876FB mov esi, 0Ah ; 挂起线程 00000001408876FB ; 设置状态标志为0xA (挂起成功) 0000000140887700 mov [rsp+218h+var_1E4], esi ; 保存状态标志 0000000140887704 xor edx, edx ; PreviousMode = Kernel 0000000140887706 mov rcx, rbx ; 线程对象 0000000140887709 call PsSuspendThread ; 挂起线程 000000014088770E test eax, eax ; 检查返回值 0000000140887710 js short loc_140887722 ; 失败则跳转 0000000140887712 mov esi, 2Ah ; '*' ; 设置状态标志为0x2A 0000000140887717 jmp short loc_14088771E ; 跳转 0000000140887719 ; --------------------------------------------------------------------------- 0000000140887719 loc_140887719: ; CODE XREF: DbgkpPostFakeThreadMessages+155↑j 0000000140887719 mov esi, 12h ; 运行保护获取失败处理 0000000140887719 ; 设置状态标志为0x12 000000014088771E loc_14088771E: ; CODE XREF: DbgkpPostFakeThreadMessages+173↑j 000000014088771E mov [rsp+218h+var_1E4], esi ; 保存状态标志 0000000140887722 loc_140887722: ; CODE XREF: DbgkpPostFakeThreadMessages+16C↑j 0000000140887722 xor edx, edx ; 初始化消息结构 0000000140887722 ; 清零memset参数 0000000140887724 mov r8d, 110h ; 大小 000000014088772A lea rcx, [rsp+218h+var_message] ; 目标地址 0000000140887732 call memset ; 初始化消息缓冲区 0000000140887737 test r13b, r13b ; 检查是否需要处理系统DLL 0000000140887737 ; 检查标志 000000014088773A jz loc_140887843 ; 如果为0则跳过 0000000140887740 test sil, 10h ; 检查状态标志位4 0000000140887744 jnz loc_140887843 ; 如果置位则跳过 000000014088774A mov r13b, 1 ; 处理系统DLL消息 000000014088774A ; 设置标志 000000014088774D mov [rsp+218h+var_1E7], r13b 0000000140887752 mov dword ptr [rsp+218h+var_message.ApiNumber], 2 ; 设置处理模式 000000014088775D mov r12, [rsp+218h+PROCESS] ; 获取进程的Section句柄 000000014088775D ; TargetProcess 0000000140887762 mov rcx, [r12+_EPROCESS.SectionObject] ; Process->SectionHandle 000000014088776A test rcx, rcx ; 检查是否为NULL 000000014088776D jz short loc_14088777E ; 是则跳转 000000014088776F call DbgkpSectionToFileHandle ; 转换Section对象为句柄 0000000140887774 mov qword ptr [rsp+218h+var_message.u+8], rax ; 保存句柄 000000014088777C jmp short loc_140887787 ; 跳转 000000014088777E ; --------------------------------------------------------------------------- 000000014088777E loc_14088777E: ; CODE XREF: DbgkpPostFakeThreadMessages+1C9↑j 000000014088777E and qword ptr [rsp+218h+var_message.u+8], 0 ; 清空句柄变量 0000000140887787 loc_140887787: ; CODE XREF: DbgkpPostFakeThreadMessages+1D8↑j 0000000140887787 mov rax, [r12+_EPROCESS.SectionBaseAddress] ; 附加到目标进程 0000000140887787 ; Process->Win32Process 000000014088778F mov qword ptr [rsp+218h+var_message.u+10h], rax 0000000140887797 lea rdx, [rsp+218h+ApcState] ; ApcState APC状态指针 000000014088779F mov rcx, r12 ; PROCESS 目标进程 00000001408877A2 call KeStackAttachProcess ; 附加到进程空间 00000001408877A7 nop ; No Operation 00000001408877A8 loc_1408877A8: ; DATA XREF: .rdata:00000001400B5454↑o 00000001408877A8 ; __try { // __except at loc_1408877D9 ; 在目标进程空间中获取NT头 00000001408877A8 mov rcx, [r12+520h] ; Win32Process 00000001408877B0 call RtlImageNtHeader ; 获取PE头 00000001408877B5 test rax, rax ; 检查是否成功 00000001408877B8 jz short loc_1408877D7 ; 失败则跳转 00000001408877BA and qword ptr [rsp+218h+var_message.u+28h], 0 ; 保存PE头信息 00000001408877BA ; 清空变量 00000001408877C3 mov ecx, [rax+0Ch] ; SizeOfHeaders 00000001408877C6 mov dword ptr [rsp+218h+var_message.u+18h], ecx ; 保存 00000001408877CD mov eax, [rax+10h] ; SizeOfImage 00000001408877D0 mov dword ptr [rsp+218h+var_message.u+1Ch], eax ; 保存 00000001408877D7 loc_1408877D7: ; CODE XREF: DbgkpPostFakeThreadMessages+214↑j 00000001408877D7 jmp short DbgkRegisterErrorPort_0 ; 跳转到清理 00000001408877D7 ; } // starts at 1408877A8 00000001408877D9 ; --------------------------------------------------------------------------- 00000001408877D9 loc_1408877D9: ; DATA XREF: .rdata:00000001400B5454↑o 00000001408877D9 ; __except(1) // owned by 1408877A8 ; __except异常处理 00000001408877D9 and qword ptr [rsp+218h+var_message.u+28h], 0 ; 异常时清空变量 00000001408877E2 and dword ptr [rsp+218h+var_message.u+18h], 0 ; Logical AND 00000001408877EA and dword ptr [rsp+218h+var_message.u+1Ch], 0 ; Logical AND 00000001408877F2 mov r14d, 'OgbD' ; 恢复标签 00000001408877F8 mov r15, [rsp+218h+var_1D8] ; 恢复线程指针 00000001408877FD mov esi, [rsp+218h+var_1E4] ; 恢复状态标志 0000000140887801 mov r13b, [rsp+218h+var_1E7] ; 恢复标志 0000000140887806 mov rdi, [rsp+218h+var_1A8] ; 恢复当前线程 000000014088780B mov rbx, [rsp+218h+var_1C8] 0000000140887810 mov rax, [rsp+218h+var_1A0] 0000000140887815 mov [rsp+218h+PROCESS], rax ; 恢复进程指针 000000014088781A mov rax, [rsp+218h+var_198] 0000000140887822 mov [rsp+218h+var_1D0], rax ; 恢复DebugObject 0000000140887827 mov rax, [rsp+218h+var_190] 000000014088782F mov [rsp+218h+var_1C0], rax ; 恢复OutThread 0000000140887834 DbgkRegisterErrorPort_0: ; CODE XREF: DbgkpPostFakeThreadMessages:loc_1408877D7↑j 0000000140887834 lea rcx, [rsp+218h+ApcState] ; ApcState 分离目标进程 0000000140887834 ; APC状态指针 000000014088783C call KeUnstackDetachProcess ; 分离进程 0000000140887841 jmp short loc_140887860 ; 跳转到消息发送 0000000140887843 ; --------------------------------------------------------------------------- 0000000140887843 loc_140887843: ; CODE XREF: DbgkpPostFakeThreadMessages+196↑j 0000000140887843 ; DbgkpPostFakeThreadMessages+1A0↑j 0000000140887843 xor r13b, r13b ; 非系统DLL处理路径 0000000140887843 ; 清除标志 0000000140887846 mov dword ptr [rsp+218h+var_message.ApiNumber], 1 ; 设置处理模式 0000000140887851 mov rax, [rbx+_ETHREAD.Win32StartAddress] 0000000140887858 mov qword ptr [rsp+218h+var_message.u+8], rax ; 保存进程ID 0000000140887860 loc_140887860: ; CODE XREF: DbgkpPostFakeThreadMessages+29D↑j 0000000140887860 mov rax, [rsp+218h+var_1D0] ; 发送调试消息 0000000140887860 ; DebugObject 0000000140887865 mov [rsp+218h+var_1F8], rax ; 参数5: PRKEVENT 000000014088786A mov r9d, esi ; 参数4: 消息类型 000000014088786D lea r8, [rsp+218h+var_message] ; 参数3: 消息缓冲区 0000000140887875 mov rdx, rbx ; 参数2: 线程指针 0000000140887878 mov rcx, [rsp+218h+PROCESS] ; 参数1: 进程指针 000000014088787D call DbgkpQueueMessage ; 发送消息到调试端口 0000000140887882 mov r12d, eax ; 保存返回状态 0000000140887885 test eax, eax ; 检查消息发送结果 0000000140887885 ; 检查状态 0000000140887887 jns short loc_1408878FF ; 成功则跳转 0000000140887889 test sil, 20h ; 错误处理:恢复线程状态 0000000140887889 ; 检查是否挂起了线程 000000014088788D jz short loc_140887899 ; 未挂起则跳过 000000014088788F xor edx, edx ; PreviousMode = Kernel 0000000140887891 mov rcx, rbx ; 线程对象 0000000140887894 call PsResumeThread ; 恢复线程 0000000140887899 loc_140887899: ; CODE XREF: DbgkpPostFakeThreadMessages+2E9↑j 0000000140887899 test sil, 8 ; 检查是否获取了运行保护 000000014088789D jz short loc_1408878AB ; 未获取则跳过 000000014088789F lea rcx, [rbx+4F8h] ; Thread->RundownProtect 00000001408878A6 call ExReleaseRundownProtection_1 ; 释放运行保护 00000001408878AB loc_1408878AB: ; CODE XREF: DbgkpPostFakeThreadMessages+2F9↑j 00000001408878AB cmp dword ptr [rsp+218h+var_message.ApiNumber], 2 ; 清理句柄资源 00000001408878AB ; 检查是否系统DLL模式 00000001408878B3 jnz short loc_1408878C9 ; 不是则跳过 00000001408878B5 mov rcx, qword ptr [rsp+218h+var_message.u+8] ; 获取句柄 00000001408878BD test rcx, rcx ; 检查是否有效 00000001408878C0 jz short loc_1408878C9 ; 无效则跳过 00000001408878C2 xor edx, edx ; PreviousMode = Kernel 00000001408878C4 call ObCloseHandle ; 关闭句柄 00000001408878C9 loc_1408878C9: ; CODE XREF: DbgkpPostFakeThreadMessages+30F↑j 00000001408878C9 ; DbgkpPostFakeThreadMessages+31C↑j 00000001408878C9 mov rcx, rbx ; 获取下一个线程 00000001408878C9 ; 当前线程 00000001408878CC call PsQuitNextProcessThread ; 移动到下一个线程 00000001408878D1 loc_1408878D1: ; CODE XREF: DbgkpPostFakeThreadMessages+EC↑j 00000001408878D1 test r12d, r12d ; 线程遍历结束处理 00000001408878D1 ; 检查最终状态 00000001408878D4 jns short loc_140887955 ; 成功则跳转 00000001408878D6 test r15, r15 ; 错误处理:释放对象引用 00000001408878D6 ; 检查输入线程 00000001408878D9 jz short loc_1408878E6 ; 为空则跳过 00000001408878DB mov edx, r14d ; Tag 00000001408878DE mov rcx, r15 ; Object 00000001408878E1 call ObfDereferenceObjectWithTag ; 释放引用 00000001408878E6 loc_1408878E6: ; CODE XREF: DbgkpPostFakeThreadMessages+335↑j 00000001408878E6 test rdi, rdi ; 检查当前线程 00000001408878E9 jz loc_140887982 ; 为空则跳转到结束 00000001408878EF mov edx, r14d ; Tag 00000001408878F2 mov rcx, rdi ; Object 00000001408878F5 call ObfDereferenceObjectWithTag ; 释放引用 00000001408878FA jmp loc_140887982 ; 跳转到结束 00000001408878FF ; --------------------------------------------------------------------------- 00000001408878FF loc_1408878FF: ; CODE XREF: DbgkpPostFakeThreadMessages+2E3↑j 00000001408878FF test r13b, r13b ; 消息发送成功处理 00000001408878FF ; 检查系统DLL标志 0000000140887902 jz short loc_140887936 ; 未设置则跳过 0000000140887904 xor r13b, r13b ; 发送系统DLL消息 0000000140887907 mov [rsp+218h+var_1E8], r13b ; 清除标志 000000014088790C mov edx, r14d ; Tag 000000014088790F mov rcx, rbx ; 线程对象 0000000140887912 call ObfReferenceObjectWithTag ; 增加引用计数 0000000140887917 mov r15, rbx ; 保存当前线程 000000014088791A mov [rsp+218h+var_1D8], rbx ; 保存当前线程 000000014088791F lea r8, [rsp+218h+var_message] ; 消息缓冲区 0000000140887927 mov rdx, [rsp+218h+var_1D0] ; DebugObject 000000014088792C mov rcx, rbx ; PVOID 000000014088792F call DbgkSendSystemDllMessages_0 ; 发送系统DLL消息 0000000140887934 jmp short loc_14088793B ; 获取下一个线程 0000000140887934 ; 当前线程 0000000140887936 ; --------------------------------------------------------------------------- 0000000140887936 loc_140887936: ; CODE XREF: DbgkpPostFakeThreadMessages+35E↑j 0000000140887936 mov r13b, [rsp+218h+var_1E8] 000000014088793B loc_14088793B: ; CODE XREF: DbgkpPostFakeThreadMessages+11C↑j 000000014088793B ; DbgkpPostFakeThreadMessages+141↑j ... 000000014088793B mov rdx, rbx ; 获取下一个线程 000000014088793B ; 当前线程 000000014088793E mov rcx, [rsp+218h+PROCESS] ; 目标进程 0000000140887943 call PsGetNextProcessThread ; 获取下一个线程 0000000140887948 mov rbx, rax ; 更新当前线程 000000014088794B mov [rsp+218h+var_1C8], rax ; 保存 0000000140887950 jmp loc_14088768D ; 线程遍历主循环 0000000140887950 ; 检查当前线程是否有效 0000000140887955 ; --------------------------------------------------------------------------- 0000000140887955 loc_140887955: ; CODE XREF: DbgkpPostFakeThreadMessages+330↑j 0000000140887955 test r15, r15 ; 成功退出路径 0000000140887955 ; 检查输入线程 0000000140887958 jz short loc_14088796C ; 为空则跳过 000000014088795A mov rax, [rsp+218h+var_1C0] ; 设置输出参数 000000014088795A ; OutThread指针 000000014088795F mov [rax], r15 ; 保存线程指针 0000000140887962 mov rax, [rsp+218h+var_1B8] ; 第5个参数指针 0000000140887967 mov [rax], rdi ; 保存当前线程 000000014088796A jmp short loc_140887982 ; 跳转到结束 000000014088796C ; --------------------------------------------------------------------------- 000000014088796C loc_14088796C: ; CODE XREF: DbgkpPostFakeThreadMessages+3B4↑j 000000014088796C test rdi, rdi ; 无输入线程时的清理 000000014088796F jz short loc_14088797C ; 检查当前线程 000000014088796F ; 为空则跳过 0000000140887971 mov edx, r14d ; Tag 0000000140887974 mov rcx, rdi ; 线程对象 0000000140887977 call ObfDereferenceObjectWithTag ; 释放引用 000000014088797C loc_14088797C: ; CODE XREF: DbgkpPostFakeThreadMessages+3CB↑j 000000014088797C mov r12d, 0C0000001h ; 设置错误码 STATUS_UNSUCCESSFUL 0000000140887982 loc_140887982: ; CODE XREF: DbgkpPostFakeThreadMessages+345↑j 0000000140887982 ; DbgkpPostFakeThreadMessages+356↑j ... 0000000140887982 mov eax, r12d ; 函数退出 0000000140887982 ; 返回值 = 状态码 0000000140887985 mov rcx, [rsp+218h+var_48] ; 恢复安全Cookie 000000014088798D xor rcx, rsp ; StackCookie 0000000140887990 call __security_check_cookie ; 安全检查 0000000140887995 add rsp, 1E0h ; Add 000000014088799C pop r15 000000014088799E pop r14 00000001408879A0 pop r13 00000001408879A2 pop r12 00000001408879A4 pop rdi 00000001408879A5 pop rsi 00000001408879A6 pop rbx 00000001408879A7 retn ; 函数返回 00000001408879A7 ; --------------------------------------------------------------------------- 00000001408879A8 db 0CCh 00000001408879A8 ; } // starts at 1408875A4 00000001408879A8 DbgkpPostFakeThreadMessages endp 生成C代码
最新发布
08-16
<think>根据提供的汇编代码,我们将尝试将其转换为等效的C代码。由于汇编代码涉及Windows内核内部结构,我们将使用适当的Windows内核类型和函数。注意:由于原始汇编代码的复杂性,以下代码是高度简化的伪代码,仅用于展示主要逻辑。 ### 关键结构体和常量 ```c // 假设的结构体定义(实际Windows内核中的定义可能不同) typedef struct _EPROCESS { ... } EPROCESS, *PEPROCESS; typedef struct _ETHREAD { ... } ETHREAD, *PETHREAD; typedef struct _DEBUG_OBJECT { ... } DEBUG_OBJECT, *PDEBUG_OBJECT; typedef struct _DBGKM_APIMSG { ... } DBGKM_APIMSG, *PDBGKM_APIMSG; typedef struct _KAPC_STATE { ... } KAPC_STATE, *PKAPC_STATE; // 常量 #define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) #define TAG_DBG 'OgbD' // 注意:实际标签值可能不同,这里使用汇编中的值 ``` ### 函数:DbgkpPostFakeThreadMessages ```c NTSTATUS DbgkpPostFakeThreadMessages( PEPROCESS TargetProcess, PDEBUG_OBJECT DebugObject, PETHREAD Thread, PETHREAD *OutThread, PETHREAD *OutThread2 ) { // 局部变量声明(根据汇编中的栈变量) KAPC_STATE ApcState; DBGKM_APIMSG Message; PETHREAD CurrentThread = NULL; PETHREAD PreviousThread = NULL; PETHREAD InputThread = Thread; PETHREAD CurrentThreadInLoop = NULL; BOOLEAN IsSystemDllMode = FALSE; NTSTATUS Status = STATUS_UNSUCCESSFUL; ULONG SuspendStatus = 0; BOOLEAN bFlag = (Thread == NULL); // 如果传入线程为NULL,则bFlag为TRUE // 保存当前线程 PETHREAD CurrentSystemThread = KeGetCurrentThread(); // 初始化ApcState和Message RtlZeroMemory(&ApcState, sizeof(ApcState)); RtlZeroMemory(&Message, sizeof(Message)); // 1. 处理输入线程遍历进程线程 if (Thread != NULL) { // 增加输入线程的引用计数 ObfReferenceObjectWithTag(Thread, TAG_DBG); CurrentThreadInLoop = Thread; } else { // 获取目标进程的第一个线程 CurrentThreadInLoop = PsGetNextProcessThread(TargetProcess, NULL); } // 2. 遍历线程主循环 while (CurrentThreadInLoop != NULL) { // 释放前一个线程的引用(如果有) if (PreviousThread != NULL) { ObfDereferenceObjectWithTag(PreviousThread, TAG_DBG); } PreviousThread = CurrentThreadInLoop; // 增加当前线程的引用计数 ObfReferenceObjectWithTag(CurrentThreadInLoop, TAG_DBG); // 跳过系统线程(检查线程标志) if (CurrentThreadInLoop->ThreadFlags & 0x400) { // 假设0x400是系统线程标志 goto NextThread; } // 检查线程是否已插入进程列表(CrossThreadFlags的位1) if (!(CurrentThreadInLoop->CrossThreadFlags & 2)) { // 等待线程插入完成 PsSynchronizeWithThreadInsertion(CurrentThreadInLoop, CurrentSystemThread); if (!(CurrentThreadInLoop->CrossThreadFlags & 2)) { goto NextThread; } } // 获取运行保护 if (!ExAcquireRundownProtection(&CurrentThreadInLoop->RundownProtect)) { SuspendStatus = 0x12; goto SendMessage; } // 挂起线程 Status = PsSuspendThread(CurrentThreadInLoop, NULL); if (NT_SUCCESS(Status)) { SuspendStatus = 0x2A; // 挂起成功 } else { SuspendStatus = 0x0A; // 挂起失败 } SendMessage: // 初始化消息结构 RtlZeroMemory(&Message, sizeof(Message)); // 判断是否为系统DLL模式(当输入线程为NULL且SuspendStatus的位4未设置) if (bFlag && !(SuspendStatus & 0x10)) { IsSystemDllMode = TRUE; Message.ApiNumber = 2; // 表示创建进程消息 // 获取进程的Section句柄并转换为文件句柄 if (TargetProcess->SectionObject != NULL) { Message.u.CreateProcess.FileHandle = DbgkpSectionToFileHandle(TargetProcess->SectionObject); } else { Message.u.CreateProcess.FileHandle = NULL; } // 设置基地址 Message.u.CreateProcess.BaseAddress = TargetProcess->Win32Process; // 附加到目标进程空间 KeStackAttachProcess(TargetProcess, &ApcState); // 在目标进程空间中获取PE头 __try { PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader(TargetProcess->Win32Process); if (NtHeader != NULL) { Message.u.CreateProcess.SizeOfHeaders = NtHeader->OptionalHeader.SizeOfHeaders; Message.u.CreateProcess.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage; } } __except(EXCEPTION_EXECUTE_HANDLER) { // 异常处理:清空相关字段 Message.u.CreateProcess.SizeOfHeaders = 0; Message.u.CreateProcess.SizeOfImage = 0; } // 分离进程 KeUnstackDetachProcess(&ApcState); } else { IsSystemDllMode = FALSE; Message.ApiNumber = 1; // 表示创建线程消息 Message.u.CreateThread.StartAddress = CurrentThreadInLoop->Win32StartAddress; } // 发送消息到调试端口 Status = DbgkpQueueMessage( TargetProcess, CurrentThreadInLoop, &Message, SuspendStatus, DebugObject ); // 错误处理 if (!NT_SUCCESS(Status)) { // 如果挂起了线程,则恢复 if (SuspendStatus & 0x20) { PsResumeThread(CurrentThreadInLoop, NULL); } // 如果获取了运行保护,则释放 if (SuspendStatus & 0x8) { ExReleaseRundownProtection(&CurrentThreadInLoop->RundownProtect); } // 如果是系统DLL模式且文件句柄有效,则关闭句柄 if (IsSystemDllMode && Message.u.CreateProcess.FileHandle != NULL) { ObCloseHandle(Message.u.CreateProcess.FileHandle, KernelMode); } // 继续下一个线程 goto NextThread; } // 如果发送成功且是系统DLL模式,则发送系统DLL消息(这里简化处理) if (IsSystemDllMode) { // 注意:汇编中调用DbgkSendSystemDllMessages_0,这里简化 // 增加引用计数并调用发送函数 ObfReferenceObjectWithTag(CurrentThreadInLoop, TAG_DBG); DbgkSendSystemDllMessages(CurrentThreadInLoop, DebugObject, &Message); // 清除标志,以便后续线程不再进入系统DLL模式 bFlag = FALSE; } NextThread: // 获取下一个线程(如果输入线程非空,则只处理一个线程) if (Thread != NULL) { break; } PETHREAD NextThread = PsGetNextProcessThread(TargetProcess, CurrentThreadInLoop); // 减少当前线程的引用计数(在循环开头会释放前一个线程) CurrentThreadInLoop = NextThread; } // 3. 设置输出参数 if (Thread != NULL) { *OutThread = Thread; *OutThread2 = PreviousThread; Status = STATUS_SUCCESS; } else { // 如果没有指定线程,但遍历线程,则设置输出参数为NULL *OutThread = NULL; *OutThread2 = NULL; // 如果遍历线程但未成功发送消息,则返回错误 if (!NT_SUCCESS(Status)) { Status = STATUS_UNSUCCESSFUL; } } // 4. 清理资源 if (PreviousThread != NULL) { ObfDereferenceObjectWithTag(PreviousThread, TAG_DBG); } if (Thread != NULL) { ObfDereferenceObjectWithTag(Thread, TAG_DBG); } return Status; } ``` ### 代码说明 1. **函数目的**:该函数用于向调试器发送虚假的线程创建消息,模拟线程创建事件,以便调试器能够捕获目标进程的现有线程。 2. **参数处理**: - 如果传入的`Thread`非空,则只处理该线程。 - 如果`Thread`为空,则遍历目标进程的所有线程。 3. **线程遍历**: - 跳过系统线程(通过检查线程标志)。 - 确保线程已插入进程列表(通过`CrossThreadFlags`)。 - 挂起线程以便发送调试事件。 4. **消息构造**: - **系统DLL模式**:当传入线程为空且满足条件时,发送进程创建消息(`ApiNumber=2`),包括进程的映像文件句柄、基地址、PE头信息等。 - **普通线程模式**:发送线程创建消息(`ApiNumber=1`),包括线程的起始地址。 5. **消息发送**:通过`DbgkpQueueMessage`将消息发送到调试端口。 6. **错误处理**:如果发送失败,则恢复线程、释放资源。 7. **输出参数**:如果指定了线程,则输出该线程和最后一个处理的线程;否则输出两个NULL。 ### 注意事项 - 由于Windows内核的复杂性,上述代码是高度简化的伪代码,实际实现需要依赖内部结构体和函数。 - 标签`TAG_DBG`用于对象引用计数,用于跟踪对象的使用。 - 使用`__try/__except`来保护访问用户模式内存的操作(如获取PE头)。 - 运行保护(Rundown Protection)用于确保在操作线程时不会被销毁。 ### §§相关问题§§: 1. Windows内核中如何实现调试事件的传递机制? 2. `PsSuspendThread`和`PsResumeThread`函数的工作原理是什么? 3. 在Windows内核中,如何安全地访问另一个进程的内存空间(如使用`KeStackAttachProcess`)? 4. 调试对象(`DEBUG_OBJECT`)在内核中扮演什么角色?它是如何与用户模式调试器交互的?</think>### 将汇编代码转换为等效的C代码 以下是根据提供的汇编代码实现的等效C代码,使用了Windows内核数据结构和方法: ```c #include <ntifs.h> #include <ntimage.h> NTSTATUS DbgkpPostFakeThreadMessages( _In_ PEPROCESS TargetProcess, _In_ PDEBUG_OBJECT DebugObject, _In_opt_ PETHREAD Thread, _Out_ PETHREAD *OutThread, _Out_ PETHREAD *OutThread2 ) { KAPC_STATE ApcState = {0}; DBGKM_APIMSG Message = {0}; PETHREAD CurrentThread = NULL; PETHREAD PreviousThread = NULL; PETHREAD InputThread = Thread; NTSTATUS Status = STATUS_UNSUCCESSFUL; BOOLEAN IsSystemDllMode = FALSE; ULONG SuspendStatus = 0; const ULONG TAG_DBG = 'DBgO'; // 对象标签 // 1. 处理输入线程遍历进程线程 if (Thread != NULL) { // 增加输入线程的引用计数 ObfReferenceObjectWithTag(Thread, TAG_DBG); CurrentThread = Thread; } else { // 获取目标进程的第一个线程 CurrentThread = PsGetNextProcessThread(TargetProcess, NULL); } // 2. 遍历线程主循环 while (CurrentThread != NULL) { // 释放前一个线程的引用(如果有) if (PreviousThread != NULL) { ObfDereferenceObjectWithTag(PreviousThread, TAG_DBG); } PreviousThread = CurrentThread; // 增加当前线程的引用计数 ObfReferenceObjectWithTag(CurrentThread, TAG_DBG); // 跳过系统线程(检查线程标志) if (CurrentThread->SystemThread) { goto NextThread; } // 检查线程是否已插入进程列表 if (!(CurrentThread->CrossThreadFlags & ThreadInserted)) { // 等待线程插入完成 PsSynchronizeWithThreadInsertion(CurrentThread, KeGetCurrentThread()); if (!(CurrentThread->CrossThreadFlags & ThreadInserted)) { goto NextThread; } } // 获取运行保护 if (!ExAcquireRundownProtection(&CurrentThread->RundownProtect)) { SuspendStatus = 0x12; // 运行保护失败状态码 goto SendMessage; } // 挂起线程 Status = PsSuspendThread(CurrentThread, NULL); SuspendStatus = NT_SUCCESS(Status) ? 0x2A : 0x0A; SendMessage: // 初始化消息结构 RtlZeroMemory(&Message, sizeof(Message)); // 判断是否为系统DLL模式 if (InputThread == NULL && !(SuspendStatus & 0x10)) { IsSystemDllMode = TRUE; Message.ApiNumber = 2; // 创建进程消息 // 获取进程的Section句柄并转换为文件句柄 if (TargetProcess->SectionObject != NULL) { Message.u.CreateProcess.FileHandle = DbgkpSectionToFileHandle(TargetProcess->SectionObject); } // 设置基地址 Message.u.CreateProcess.BaseAddress = TargetProcess->Win32Process; // 附加到目标进程空间 KeStackAttachProcess(TargetProcess, &ApcState); // 在目标进程空间中获取PE头 __try { PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader( (PVOID)TargetProcess->Win32Process); if (NtHeader != NULL) { Message.u.CreateProcess.SizeOfHeaders = NtHeader->OptionalHeader.SizeOfHeaders; Message.u.CreateProcess.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage; } } __except(EXCEPTION_EXECUTE_HANDLER) { // 异常处理:清空相关字段 Message.u.CreateProcess.SizeOfHeaders = 0; Message.u.CreateProcess.SizeOfImage = 0; } // 分离进程 KeUnstackDetachProcess(&ApcState); } else { IsSystemDllMode = FALSE; Message.ApiNumber = 1; // 创建线程消息 Message.u.CreateThread.StartAddress = CurrentThread->Win32StartAddress; } // 发送消息到调试端口 Status = DbgkpQueueMessage( TargetProcess, CurrentThread, &Message, SuspendStatus, DebugObject ); // 错误处理 if (!NT_SUCCESS(Status)) { // 如果挂起了线程,则恢复 if (SuspendStatus & 0x20) { PsResumeThread(CurrentThread, NULL); } // 如果获取了运行保护,则释放 if (SuspendStatus & 0x8) { ExReleaseRundownProtection(&CurrentThread->RundownProtect); } // 如果是系统DLL模式且文件句柄有效,则关闭句柄 if (IsSystemDllMode && Message.u.CreateProcess.FileHandle != NULL) { ZwClose(Message.u.CreateProcess.FileHandle); } } // 如果发送成功且是系统DLL模式,则发送系统DLL消息 else if (IsSystemDllMode) { ObfReferenceObjectWithTag(CurrentThread, TAG_DBG); DbgkSendSystemDllMessages(CurrentThread, DebugObject, &Message); } NextThread: // 获取下一个线程(如果输入线程非空,则只处理一个线程) if (InputThread != NULL) { break; } CurrentThread = PsGetNextProcessThread(TargetProcess, CurrentThread); } // 3. 设置输出参数 if (InputThread != NULL) { *OutThread = InputThread; *OutThread2 = PreviousThread; Status = STATUS_SUCCESS; } // 4. 清理资源 if (PreviousThread != NULL) { ObfDereferenceObjectWithTag(PreviousThread, TAG_DBG); } if (InputThread != NULL) { ObfDereferenceObjectWithTag(InputThread, TAG_DBG); } return Status; } ``` ### 代码关键部分解释 1. **线程遍历逻辑**: - 如果提供了特定线程(`Thread != NULL`),只处理该线程 - 否则遍历目标进程的所有线程(`PsGetNextProcessThread`) - 使用对象标签(`TAG_DBG`)管理线程对象的引用计数 2. **线程挂起与保护**: - 使用`ExAcquireRundownProtection`确保线程不会被销毁 - 通过`PsSuspendThread`挂起线程以便发送调试事件 - 状态码`0x2A`表示挂起成功,`0x0A`表示挂起失败 3. **系统DLL模式处理**: - 当处理进程的第一个线程时进入此模式 - 将进程的Section对象转换为文件句柄 - 附加到目标进程空间获取PE头信息 - 使用`__try/__except`保护内存访问操作 4. **消息发送**: - `ApiNumber = 1`:线程创建消息(包含起始地址) - `ApiNumber = 2`:进程创建消息(包含PE信息) - 通过`DbgkpQueueMessage`发送到调试端口 5. **资源清理**: - 使用`ObfDereferenceObjectWithTag`释放对象引用 - 必要时恢复线程状态(`PsResumeThread`) - 关闭创建的文件句柄(`ZwClose`) ### 关键数据结构说明 ```c // 调试消息结构 (简化版) typedef struct _DBGKM_APIMSG { ULONG ApiNumber; // 消息类型: 1=线程, 2=进程 union { struct { HANDLE FileHandle; // 进程文件句柄 PVOID BaseAddress; // 映像基地址 ULONG SizeOfHeaders; // PE头大小 ULONG SizeOfImage; // 映像大小 } CreateProcess; struct { PVOID StartAddress; // 线程起始地址 } CreateThread; } u; } DBGKM_APIMSG, *PDBGKM_APIMSG; ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值