用户层调用SetTimer-->内核NtUserSetTimer处理
NtUserSetTimer -->_SetTimer --> InternalSetTimer-->FindTimer / HMAllocObject
去看看NtUserSetTimer
函数原型
UINT_PTR
APIENTRY
NtUserSetTimer
(
HWND hWnd,
UINT_PTR nIDEvent,
UINT uElapse,
TIMERPROC lpTimerFunc
)
.text:FFFFF97FFF084BD0 ; __int64 __fastcall NtUserSetTimer(HWND hWnd, __int64 nIDTimer, __int64 uElapse, __int64 lpTimerFunc)
.text:FFFFF97FFF084BD0 NtUserSetTimer proc near ; DATA XREF: .text:FFFFF97FFF0D30C0o
.text:FFFFF97FFF084BD0 ; .pdata:FFFFF97FFF2E9AF0o ...
.text:FFFFF97FFF084BD0
.text:FFFFF97FFF084BD0 hWnd = qword ptr 8
.text:FFFFF97FFF084BD0 nIDTime = qword ptr 10h
.text:FFFFF97FFF084BD0 uElapse = qword ptr 18h
.text:FFFFF97FFF084BD0 lpTimerFuc = qword ptr 20h
.text:FFFFF97FFF084BD0
.text:FFFFF97FFF084BD0 mov rax, rsp
.text:FFFFF97FFF084BD3 mov [rax+8], rbx
.text:FFFFF97FFF084BD7 mov [rax+10h], rbp
.text:FFFFF97FFF084BDB mov [rax+18h], rsi
.text:FFFFF97FFF084BDF mov [rax+20h], rdi
.text:FFFFF97FFF084BE3 push r12
.text:FFFFF97FFF084BE5 sub rsp, 20h
.text:FFFFF97FFF084BE9 mov rdi, rcx ; hWnd
.text:FFFFF97FFF084BEC mov rcx, cs:gpresUser
.text:FFFFF97FFF084BF3 mov rbp, r9
.text:FFFFF97FFF084BF6 mov esi, r8d
.text:FFFFF97FFF084BF9 mov r12, rdx
.text:FFFFF97FFF084BFC call cs:__imp_ExEnterPriorityRegionAndAcquireResourceExclusive
.text:FFFFF97FFF084C02 xor ebx, ebx
.text:FFFFF97FFF084C04 mov cs:gbValidateHandleForIL, 1
.text:FFFFF97FFF084C0B mov cs:gptiCurrent, rax
.text:FFFFF97FFF084C12 cmp rdi, rbx
.text:FFFFF97FFF084C15 jz short loc_FFFFF97FFF084C26 ; tagWND*
.text:FFFFF97FFF084C17 mov rcx, rdi
.text:FFFFF97FFF084C1A call ValidateHwnd ; 据我所知这个返回tagWND*
.text:FFFFF97FFF084C1F cmp rax, rbx
.text:FFFFF97FFF084C22 jnz short loc_FFFFF97FFF084C29
.text:FFFFF97FFF084C24 jmp short loc_FFFFF97FFF084C51
.text:FFFFF97FFF084C26 ; ---------------------------------------------------------------------------
.text:FFFFF97FFF084C26
.text:FFFFF97FFF084C26 loc_FFFFF97FFF084C26: ; CODE XREF: NtUserSetTimer+45j
.text:FFFFF97FFF084C26 mov rax, rbx ; tagWND*
.text:FFFFF97FFF084C29
.text:FFFFF97FFF084C29 loc_FFFFF97FFF084C29: ; CODE XREF: NtUserSetTimer+52j
.text:FFFFF97FFF084C29 mov ecx, 0Ah
.text:FFFFF97FFF084C2E mov r9, rbp ; lpTimerFunc
.text:FFFFF97FFF084C31 mov rdx, r12 ; nTimerID
.text:FFFFF97FFF084C34 cmp esi, ecx
.text:FFFFF97FFF084C36 cmovb esi, ecx
.text:FFFFF97FFF084C39 mov ecx, 7FFFFFFFh
.text:FFFFF97FFF084C3E cmp esi, ecx
.text:FFFFF97FFF084C40 cmova esi, ecx
.text:FFFFF97FFF084C43 mov rcx, rax ; tagWND*
.text:FFFFF97FFF084C46 mov r8d, esi ; uElapse
.text:FFFFF97FFF084C49 call _SetTimer ; _SetTimer
.text:FFFFF97FFF084C49 ; (
.text:FFFFF97FFF084C49 ; tagWND* hWnd_Object
.text:FFFFF97FFF084C49 ; __int64 nTimerID
.text:FFFFF97FFF084C49 ; __int64 elapse
.text:FFFFF97FFF084C49 ; __int64 lpTimerFunc
.text:FFFFF97FFF084C49 ; )
.text:FFFFF97FFF084C4E mov rbx, rax
.text:FFFFF97FFF084C51
.text:FFFFF97FFF084C51 loc_FFFFF97FFF084C51: ; CODE XREF: NtUserSetTimer+54j
.text:FFFFF97FFF084C51 call UserSessionSwitchLeaveCrit
.text:FFFFF97FFF084C56 mov rbp, [rsp+28h+nIDTime]
.text:FFFFF97FFF084C5B mov rsi, [rsp+28h+uElapse]
.text:FFFFF97FFF084C60 mov rdi, [rsp+28h+lpTimerFuc]
.text:FFFFF97FFF084C65 mov rax, rbx
.text:FFFFF97FFF084C68 mov rbx, [rsp+28h+hWnd]
.text:FFFFF97FFF084C6D add rsp, 20h
.text:FFFFF97FFF084C71 pop r12
.text:FFFFF97FFF084C73 retn
.text:FFFFF97FFF084C73 ; ---------------------------------------------------------------------------
.text:FFFFF97FFF084C74 db 8 dup(90h)
.text:FFFFF97FFF084C74 NtUserSetTimer endp
据我所知
call ValidateHwnd
会得到一个窗口对象 tagWND*
内部某个地方应该call了UserGetWindowObject
这个函数检验了hwnd的有效性,然后就call _SetTimer
看下_SetTimer
SetTimer
(
tagWND* hWnd_Object
__int64 nTimerID
__int64 elapse
__int64 lpTimerFunc
)
.text:FFFFF97FFF084C7C ; __int64 __fastcall SetTimer(__int64 pTagWND, __int64 nTimerID, __int64 elapse, __int64 lpTimerFunc)
.text:FFFFF97FFF084C7C _SetTimer proc near ; CODE XREF: NtUserSetTimer+79p
.text:FFFFF97FFF084C7C ; xxxMNDoScroll+86p ...
.text:FFFFF97FFF084C7C
.text:FFFFF97FFF084C7C var_local_flag = dword ptr -18h
.text:FFFFF97FFF084C7C pTagWnd = qword ptr 8
.text:FFFFF97FFF084C7C nTimerID = qword ptr 10h
.text:FFFFF97FFF084C7C elapse = qword ptr 18h
.text:FFFFF97FFF084C7C
.text:FFFFF97FFF084C7C mov [rsp+pTagWnd], rbx
.text:FFFFF97FFF084C81 mov [rsp+nTimerID], rbp
.text:FFFFF97FFF084C86 mov [rsp+elapse], rsi
.text:FFFFF97FFF084C8B push rdi
.text:FFFFF97FFF084C8C sub rsp, 30h
.text:FFFFF97FFF084C90 mov rdi, r9 ; lpTimerFunc
.text:FFFFF97FFF084C93 mov esi, r8d ; elapse
.text:FFFFF97FFF084C96 mov rbp, rdx ; nTimerID
.text:FFFFF97FFF084C99 mov rbx, rcx ; pTagWND
.text:FFFFF97FFF084C9C test rcx, rcx ; 如果pTagWND为NULL 跳转
.text:FFFFF97FFF084C9F jz short loc_FFFFF97FFF084CC2 ; flag
.text:FFFFF97FFF084CA1 call cs:__imp_PsGetCurrentProcessWin32Process
.text:FFFFF97FFF084CA7 mov r10, [rbx+10h] ; tagWND+0x10是_THRDESKHEAD结构下的tagTHREADINFO
.text:FFFFF97FFF084CAB cmp rax, [r10+158h] ; tagTHREADINFO +0x158是tagPROCESSINFO结构 第一个成员是EPROCESS
.text:FFFFF97FFF084CB2 jz short loc_FFFFF97FFF084CC2 ; 相同跳转 如果当前EPROCESS和结构下的EPROCESS相同 判断是不是自己应该
.text:FFFFF97FFF084CB4 mov ecx, 5
.text:FFFFF97FFF084CB9 call UserSetLastError
.text:FFFFF97FFF084CBE xor eax, eax
.text:FFFFF97FFF084CC0 jmp short loc_FFFFF97FFF084CD8
.text:FFFFF97FFF084CC2 ; ---------------------------------------------------------------------------
.text:FFFFF97FFF084CC2
.text:FFFFF97FFF084CC2 loc_FFFFF97FFF084CC2: ; CODE XREF: _SetTimer+23j
.text:FFFFF97FFF084CC2 ; _SetTimer+36j
.text:FFFFF97FFF084CC2 and [rsp+38h+var_local_flag], 0 ; flag
.text:FFFFF97FFF084CC7 mov r9, rdi ; lpTimerFunc
.text:FFFFF97FFF084CCA mov r8d, esi