逆--Win7x64 UserTimer结构获取,NtUserSetTimer,_SetTimer,InternalSetTimer 枚举进程定时器
Posted zhuhuibeishadiao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆--Win7x64 UserTimer结构获取,NtUserSetTimer,_SetTimer,InternalSetTimer 枚举进程定时器相关的知识,希望对你有一定的参考价值。
用户层调用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 ; Elapse .text:FFFFF97FFF084CCD mov rdx, rbp ; TimerID .text:FFFFF97FFF084CD0 mov rcx, rbx ; tagWND* .text:FFFFF97FFF084CD3 call InternalSetTimer ; InternalSetTimer .text:FFFFF97FFF084CD3 ; ( .text:FFFFF97FFF084CD3 ; tagWND* pWND .text:FFFFF97FFF084CD3 ; __int64 TimerID .text:FFFFF97FFF084CD3 ; __int64 elapse .text:FFFFF97FFF084CD3 ; __int64 lpTimerFunc .text:FFFFF97FFF084CD3 ; __int64 flags //这个应该就是为0 .text:FFFFF97FFF084CD3 ; ) .text:FFFFF97FFF084CD8 .text:FFFFF97FFF084CD8 loc_FFFFF97FFF084CD8: ; CODE XREF: _SetTimer+44j .text:FFFFF97FFF084CD8 mov rbx, [rsp+38h+pTagWnd] .text:FFFFF97FFF084CDD mov rbp, [rsp+38h+nTimerID] .text:FFFFF97FFF084CE2 mov rsi, [rsp+38h+elapse] .text:FFFFF97FFF084CE7 add rsp, 30h .text:FFFFF97FFF084CEB pop rdi .text:FFFFF97FFF084CEC retn .text:FFFFF97FFF084CEC ; --------------------------------------------------------------------------- .text:FFFFF97FFF084CED align 20h .text:FFFFF97FFF084CED _SetTimer endp
这个函数判断当前来设置timer是不是自己
防止应用程序从一个到另一个应用程序窗口中设置一个定时器
call InternalSetTimer
在这下面就能获得很多我们需要的结构信息了
text:FFFFF97FFF0B8A38 ; =============== S U B R O U T I N E ======================================= .text:FFFFF97FFF0B8A38 .text:FFFFF97FFF0B8A38 ; InternalSetTimer .text:FFFFF97FFF0B8A38 ; ( .text:FFFFF97FFF0B8A38 ; tagWND* pWND .text:FFFFF97FFF0B8A38 ; __int64 TimerID .text:FFFFF97FFF0B8A38 ; __int64 elapse .text:FFFFF97FFF0B8A38 ; __int64 lpTimerFunc .text:FFFFF97FFF0B8A38 ; __int64 flags //这个应该就是为0 .text:FFFFF97FFF0B8A38 ; ) .text:FFFFF97FFF0B8A38 .text:FFFFF97FFF0B8A38 ; __int64 __fastcall InternalSetTimer(__int64 pWND, __int64 TimerID, __int64 Elasp, __int64 lpTimerFuc, __int64 flags) .text:FFFFF97FFF0B8A38 InternalSetTimer proc near ; CODE XREF: AccessTimeOutReset+48p .text:FFFFF97FFF0B8A38 ; _SetTimer+57p ... .text:FFFFF97FFF0B8A38 .text:FFFFF97FFF0B8A38 pRetTagWnd = qword ptr -48h .text:FFFFF97FFF0B8A38 pFindedTimerObject= qword ptr -38h .text:FFFFF97FFF0B8A38 var_28 = byte ptr -28h .text:FFFFF97FFF0B8A38 lpTimerFuc = qword ptr 20h .text:FFFFF97FFF0B8A38 flags = qword ptr 28h .text:FFFFF97FFF0B8A38 .text:FFFFF97FFF0B8A38 mov rax, rsp .text:FFFFF97FFF0B8A3B mov [rax+8], rbx .text:FFFFF97FFF0B8A3F mov [rax+10h], rbp .text:FFFFF97FFF0B8A43 mov [rax+18h], rsi .text:FFFFF97FFF0B8A47 mov [rax+20h], r9 .text:FFFFF97FFF0B8A4B push rdi .text:FFFFF97FFF0B8A4C push r12 .text:FFFFF97FFF0B8A4E push r13 .text:FFFFF97FFF0B8A50 push r14 .text:FFFFF97FFF0B8A52 push r15 .text:FFFFF97FFF0B8A54 sub rsp, 40h .text:FFFFF97FFF0B8A58 cmp cs:gbCleanupInitiated, 0 .text:FFFFF97FFF0B8A5F mov esi, r8d ; elapse .text:FFFFF97FFF0B8A62 mov r14, rdx ; TimerID .text:FFFFF97FFF0B8A65 mov r12, rcx ; tagWND* .text:FFFFF97FFF0B8A68 jz short loc_FFFFF97FFF0B8A71 ; 如果elapse小于10 那么esi = 10 .text:FFFFF97FFF0B8A6A .text:FFFFF97FFF0B8A6A loc_FFFFF97FFF0B8A6A: ; CODE XREF: InternalSetTimer+C0j .text:FFFFF97FFF0B8A6A ; InternalSetTimer+102j .text:FFFFF97FFF0B8A6A xor eax, eax .text:FFFFF97FFF0B8A6C jmp loc_FFFFF97FFF0B8CCD .text:FFFFF97FFF0B8A71 ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B8A71 .text:FFFFF97FFF0B8A71 loc_FFFFF97FFF0B8A71: ; CODE XREF: InternalSetTimer+30j .text:FFFFF97FFF0B8A71 mov eax, 0Ah ; 如果elapse小于10 那么esi = 10 .text:FFFFF97FFF0B8A76 cmp r8d, eax .text:FFFFF97FFF0B8A79 cmovb esi, eax .text:FFFFF97FFF0B8A7C mov eax, 7FFFFFFFh ; 如果elapse大于7ffffff,那么elapse=7ffffff .text:FFFFF97FFF0B8A81 cmp esi, eax .text:FFFFF97FFF0B8A83 cmova esi, eax .text:FFFFF97FFF0B8A86 call cs:__imp_PsGetCurrentThreadWin32Thread .text:FFFFF97FFF0B8A8C mov edi, dword ptr [rsp+68h+flags] .text:FFFFF97FFF0B8A93 mov r15, rax ; 当前线程 .text:FFFFF97FFF0B8A96 mov r13, rax .text:FFFFF97FFF0B8A99 test rax, rax ; 如果当前线程为0跳转 .text:FFFFF97FFF0B8A9C jz short loc_FFFFF97FFF0B8AB0 ; 这个应该是全局tagTHREADINFO .text:FFFFF97FFF0B8A9E test dil, 4 ; flags & 4 > 0不跳 .text:FFFFF97FFF0B8AA2 jnz short loc_FFFFF97FFF0B8AB0 ; 这个应该是全局tagTHREADINFO .text:FFFFF97FFF0B8AA4 test r12, r12 ; 如果tagWND为NULL 跳转 .text:FFFFF97FFF0B8AA7 jz short loc_FFFFF97FFF0B8AB7 .text:FFFFF97FFF0B8AA9 mov r13, [r12+10h] ; 如果tagWND不为NULL 将tagTHREADINFO给r13 .text:FFFFF97FFF0B8AAE jmp short loc_FFFFF97FFF0B8AB7 .text:FFFFF97FFF0B8AB0 ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B8AB0 .text:FFFFF97FFF0B8AB0 loc_FFFFF97FFF0B8AB0: ; CODE XREF: InternalSetTimer+64j .text:FFFFF97FFF0B8AB0 ; InternalSetTimer+6Aj .text:FFFFF97FFF0B8AB0 mov r13, cs:gptiRit ; 这个应该是全局tagTHREADINFO .text:FFFFF97FFF0B8AB7 .text:FFFFF97FFF0B8AB7 loc_FFFFF97FFF0B8AB7: ; CODE XREF: InternalSetTimer+6Fj .text:FFFFF97FFF0B8AB7 ; InternalSetTimer+76j .text:FFFFF97FFF0B8AB7 lea rax, [rsp+68h+pFindedTimerObject] .text:FFFFF97FFF0B8ABC xor r9d, r9d ; lpTimerFunc .text:FFFFF97FFF0B8ABF mov r8d, edi ; flags .text:FFFFF97FFF0B8AC2 mov rdx, r14 ; TimerID .text:FFFFF97FFF0B8AC5 mov rcx, r12 ; tagWND* .text:FFFFF97FFF0B8AC8 mov [rsp+68h+pRetTagWnd], rax ; pRetWnd .text:FFFFF97FFF0B8ACD call FindTimer ; FindTimer .text:FFFFF97FFF0B8ACD ; ( .text:FFFFF97FFF0B8ACD ; tagWND* tagWND .text:FFFFF97FFF0B8ACD ; __int64 TimerID .text:FFFFF97FFF0B8ACD ; __int64 flags .text:FFFFF97FFF0B8ACD ; __int64 lpTimerFunc .text:FFFFF97FFF0B8ACD ; tagWND** tagRetWnd .text:FFFFF97FFF0B8ACD ; ) .text:FFFFF97FFF0B8AD2 test eax, eax .text:FFFFF97FFF0B8AD4 jnz loc_FFFFF97FFF0B8BA8 ; 如果FindTimer返回false不跳 .text:FFFFF97FFF0B8ADA mov r9d, 80h ; 申请一个0x80的空间 从这里可以知道TIME_OBJECT结构有0x80大 .text:FFFFF97FFF0B8AE0 mov r8b, 10h .text:FFFFF97FFF0B8AE3 xor edx, edx .text:FFFFF97FFF0B8AE5 mov rcx, r13 ; tagTHADINFO .text:FFFFF97FFF0B8AE8 call HMAllocObject ; 这里返回的就是PTIMER空间 PTIME是泄露代码中的结构 也就是这里的TIMER_OBJECT 保存定时器信息的结构 .text:FFFFF97FFF0B8AED mov rbx, rax .text:FFFFF97FFF0B8AF0 mov [rsp+68h+pFindedTimerObject], rax ; 将申请到的空间给pRetTagWnd .text:FFFFF97FFF0B8AF5 test rax, rax ; 为NULL 就返回0了 .text:FFFFF97FFF0B8AF8 jz loc_FFFFF97FFF0B8A6A .text:FFFFF97FFF0B8AFE and qword ptr [rax+28h], 0 ; rax + 0x28 是ptagWnd .text:FFFFF97FFF0B8B03 mov ebp, 1 .text:FFFFF97FFF0B8B08 test r12, r12 ; tagWND为NULL跳转 .text:FFFFF97FFF0B8B0B jnz short loc_FFFFF97FFF0B8B4D ; 如果tagWND有效 那么timer_object + 0x38保存TIMERID .text:FFFFF97FFF0B8B0D mov eax, cs:g_cTimerId ; 取全局TimerID .text:FFFFF97FFF0B8B13 mov ecx, eax .text:FFFFF97FFF0B8B15 .text:FFFFF97FFF0B8B15 loc_FFFFF97FFF0B8B15: ; CODE XREF: InternalSetTimer+F8j .text:FFFFF97FFF0B8B15 sub eax, ebp ; --eax .text:FFFFF97FFF0B8B17 mov edx, 7EFFh .text:FFFFF97FFF0B8B1C cmovs eax, edx ; if(eax<edx)(edx=7EFF) .text:FFFFF97FFF0B8B1F bts cs:gTimerId, eax .text:FFFFF97FFF0B8B26 mov cs:g_cTimerId, eax .text:FFFFF97FFF0B8B2C jnb short loc_FFFFF97FFF0B8B3F ; 如果tagWND为NULL .text:FFFFF97FFF0B8B2E cmp eax, ecx ; 如果tagWND是NULL && bts gTimerID == g_cTimerID 就释放?? .text:FFFFF97FFF0B8B30 jnz short loc_FFFFF97FFF0B8B15 ; 这里应该是对全局timerID进行赋值,前提是tagWND为NULL ,应该是系统的 .text:FFFFF97FFF0B8B32 mov rcx, rbx ; P .text:FFFFF97FFF0B8B35 call HMFreeObject .text:FFFFF97FFF0B8B3A jmp loc_FFFFF97FFF0B8A6A .text:FFFFF97FFF0B8B3F ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B8B3F .text:FFFFF97FFF0B8B3F loc_FFFFF97FFF0B8B3F: ; CODE XREF: InternalSetTimer+F4j .text:FFFFF97FFF0B8B3F add eax, 100h ; 如果tagWND为NULL .text:FFFFF97FFF0B8B44 movsxd rcx, eax .text:FFFFF97FFF0B8B47 mov [rbx+38h], rcx ; 如果tagWND为NULL timer_object + 0x38h = eax & 0x100 .text:FFFFF97FFF0B8B4B jmp short loc_FFFFF97FFF0B8B51 ; 取全局tmrLishHead .text:FFFFF97FFF0B8B4D ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B8B4D .text:FFFFF97FFF0B8B4D loc_FFFFF97FFF0B8B4D: ; CODE XREF: InternalSetTimer+D3j .text:FFFFF97FFF0B8B4D mov [rax+38h], r14 ; 如果tagWND有效 那么timer_object + 0x38保存TIMERID .text:FFFFF97FFF0B8B51 .text:FFFFF97FFF0B8B51 loc_FFFFF97FFF0B8B51: ; CODE XREF: InternalSetTimer+113j .text:FFFFF97FFF0B8B51 mov rax, cs:gtmrListHead ; 取全局tmrLishHead .text:FFFFF97FFF0B8B58 lea rcx, [rbx+18h] ; 取timer_object + 0x18处 .text:FFFFF97FFF0B8B5C lea rdx, gtmrListHead ; 取全局tmrLishHead地址 .text:FFFFF97FFF0B8B63 mov [rcx], rax ; timer_object + 0x18处保存全局tmlLishHead .text:FFFFF97FFF0B8B66 mov [rcx+8], rdx ; timer_object下的gtmrLishHead +8 保存grmrLishHead .text:FFFFF97FFF0B8B6A mov [rax+8], rcx ; gtmrLishead + 8处把保存timer_object+0x18处的全局tmlLishHead .text:FFFFF97FFF0B8B6E mov cs:gtmrListHead, rcx ; 将timer_object下的全局tmrLishHead给全局tmrLishHead 这里就是插入操作 .text:FFFFF97FFF0B8B75 lea rdx, [rbx+70h] ; 取timer_object + 0x70处 这里应该是保存hashtable的 .text:FFFFF97FFF0B8B79 lea rax, gTimerHashTable ; 取gTimerHashTable .text:FFFFF97FFF0B8B80 mov rcx, r12 ; mov rvx,tagWND* .text:FFFFF97FFF0B8B83 shr rcx, 8 ; tagWND >> 8 .text:FFFFF97FFF0B8B87 add ecx, [rbx+38h] ; tagWND >> 8 + timerID .text:FFFFF97FFF0B8B8A and ecx, 3Fh ; tagWND >> 8 + timerID & 0x3f .text:FFFFF97FFF0B8B8D shl rcx, 4 ; tagWND >> 8 + timerID & 0x3f << 4 .text:FFFFF97FFF0B8B91 add rcx, rax ; tagWND >> 8 + timerID & 0x3f << 4 + gTimerHashTable .text:FFFFF97FFF0B8B94 mov rax, [rcx+8] ; mov rax,[tagWND >> 8 + timerID & 0x3f << 4 + gTimerHashTable +8] .text:FFFFF97FFF0B8B98 mov [rdx], rcx ; 将计算好的hash数据给timer_object + 0x70处的数据 .text:FFFFF97FFF0B8B9B mov [rdx+8], rax ; 将timer_object + 0x70下的hashtable中的+8处保存为计算好的数据 .text:FFFFF97FFF0B8B9F mov [rax], rdx ; 将timer_object + 0x70的数据给计算好的hash数据 .text:FFFFF97FFF0B8BA2 mov [rcx+8], rdx ; 将计算好的hash数据+8处赋值为timer_object + 0x70处的数据 典型的hash插入操作 .text:FFFFF97FFF0B8BA6 jmp short loc_FFFFF97FFF0B8BE4 ; 这里的rbx是申请到的Timer_object +0x28是什么暂时不知道 .text:FFFFF97FFF0B8BA8 ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B8BA8 .text:FFFFF97FFF0B8BA8 loc_FFFFF97FFF0B8BA8: ; CODE XREF: InternalSetTimer+9Cj .text:FFFFF97FFF0B8BA8 mov rbx, [rsp+68h+pFindedTimerObject] ; 取到找到的返回到的Timer_Object空间头 .text:FFFFF97FFF0B8BAD mov ebp, 1 .text:FFFFF97FFF0B8BB2 test [rbx+48h], bpl ; if([rbx+0x48]^1) .text:FFFFF97FFF0B8BB6 jz short loc_FFFFF97FFF0B8BE4 ; if(![rbx+0x48]^1) .text:FFFFF97FFF0B8BB8 mov rax, [rbx+68h] ; UnKnow .text:FFFFF97FFF0B8BBC mov rcx, [rbx+60h] ; UnKnow .text:FFFFF97FFF0B8BC0 mov rdx, [rbx+30h] ; tagTHREADINFO .text:FFFFF97FFF0B8BC4 mov [rax], rcx ; timer_object+0x68处数据的值为timer_object+0x60处的值 .text:FFFFF97FFF0B8BC7 mov [rcx+8], rax ; timer_object+0x60处的值的+8的值等于timer_object+0x68的值 .text:FFFFF97FFF0B8BCB add dword ptr [rdx+1E4h], 0FFFFFFFFh ; +0x30是tagTHREADINFO 这个结构下的1E4处是cTimersReady 执行-1操作 .text:FFFFF97FFF0B8BD2 jnz short loc_FFFFF97FFF0B8BE4 ; 如果cTimersReady为0跳转 .text:FFFFF97FFF0B8BD4 mov rax, [rdx+170h] ; /*0x170*/ struct _tagCLIENTTHREADINFO* pcti; .text:FFFFF97FFF0B8BDB mov ecx, 0FFEFh .text:FFFFF97FFF0B8BE0 and [rax+6], cx ; /*0x006*/ UINT16 fsWakeBits; fsWakeBits &= 0xFFEF .text:FFFFF97FFF0B8BE4 .text:FFFFF97FFF0B8BE4 loc_FFFFF97FFF0B8BE4: ; CODE XREF: InternalSetTimer+16Ej .text:FFFFF97FFF0B8BE4 ; InternalSetTimer+17Ej ... .text:FFFFF97FFF0B8BE4 lea rcx, [rbx+28h] ; 这里的rbx是申请到的Timer_object +0x28是什么暂时不知道 .text:FFFFF97FFF0B8BE8 mov rdx, r12 ; tagWND* .text:FFFFF97FFF0B8BEB call HMAssignmentLock .text:FFFFF97FFF0B8BF0 mov rax, [rsp+68h+lpTimerFuc] ; 得到lptimerFunc参数 .text:FFFFF97FFF0B8BF8 mov [rbx+44h], esi ; timer_object + 0x44处是Elapse .text:FFFFF97FFF0B8BFB xor r12d, r12d .text:FFFFF97FFF0B8BFE mov [rbx+40h], esi ; timer_object + 0x44处也是Elapse .text:FFFFF97FFF0B8C01 mov [rbx+50h], rax ; timer_object + 0x50处保存lptimerFunc .text:FFFFF97FFF0B8C05 mov [rbx+58h], r12 ; 0???? .text:FFFFF97FFF0B8C09 test dil, dil .text:FFFFF97FFF0B8C0C jns short loc_FFFFF97FFF0B8C14 ; if(flags>=0) .text:FFFFF97FFF0B8C0E btr edi, 7 ; 将flags第7位送给CF标志 .text:FFFFF97FFF0B8C12 jmp short loc_FFFFF97FFF0B8C1E ; flags ^ 8 .text:FFFFF97FFF0B8C14 ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B8C14 .text:FFFFF97FFF0B8C14 loc_FFFFF97FFF0B8C14: ; CODE XREF: InternalSetTimer+1D4j .text:FFFFF97FFF0B8C14 bt edi, 8 ; 将flags第8为送给CF标志 .text:FFFFF97FFF0B8C18 jnb short loc_FFFFF97FFF0B8C1E ; if(cf==0) .text:FFFFF97FFF0B8C1A mov [rbx+58h], r15 ; timer_object + 0x58保存当前线程 .text:FFFFF97FFF0B8C1E .text:FFFFF97FFF0B8C1E loc_FFFFF97FFF0B8C1E: ; CODE XREF: InternalSetTimer+1DAj .text:FFFFF97FFF0B8C1E ; InternalSetTimer+1E0j .text:FFFFF97FFF0B8C1E or edi, 8 ; flags ^ 8 .text:FFFFF97FFF0B8C21 mov [rbx+48h], edi ; timer_object + 0x48保存flags相关 这个应该是跟是否过期有关 .text:FFFFF97FFF0B8C24 mov [rbx+30h], r13 ; timer_object + 0x30 处保存tagTHADINFO .text:FFFFF97FFF0B8C28 cmp cs:gbRITAlerted, r12b ; 至此 结构的大部分需要的信息已经得到 .text:FFFFF97FFF0B8C2F jnz loc_FFFFF97FFF0B8CC2 .text:FFFFF97FFF0B8C35 cmp cs:gbTimersProcActive, r12b .text:FFFFF97FFF0B8C3C jnz short loc_FFFFF97FFF0B8CBB .text:FFFFF97FFF0B8C3E mov rcx, ds:7FFE0320h .text:FFFFF97FFF0B8C46 mov eax, ds:7FFE0004h .text:FFFFF97FFF0B8C4D mov edx, cs:gdmsNextTimer .text:FFFFF97FFF0B8C53 imul rcx, rax .text:FFFFF97FFF0B8C57 shr rcx, 18h .text:FFFFF97FFF0B8C5B sub ecx, cs:gcmsLastTimer .text:FFFFF97FFF0B8C61 cmp ecx, edx .text:FFFFF97FFF0B8C63 ja short loc_FFFFF97FFF0B8C9E .text:FFFFF97FFF0B8C65 lea eax, [rsi+rcx] .text:FFFFF97FFF0B8C68 cmp eax, esi .text:FFFFF97FFF0B8C6A jb short loc_FFFFF97FFF0B8C9E .text:FFFFF97FFF0B8C6C and dword ptr [rbx+48h], 0FFFFFFF7h .text:FFFFF97FFF0B8C70 add [rbx+40h], ecx .text:FFFFF97FFF0B8C73 sub edx, ecx .text:FFFFF97FFF0B8C75 cmp edx, esi .text:FFFFF97FFF0B8C77 jbe short loc_FFFFF97FFF0B8CB4 .text:FFFFF97FFF0B8C79 mov eax, [rbx+40h] .text:FFFFF97FFF0B8C7C mov rcx, cs:gptmrMaster ; Timer .text:FFFFF97FFF0B8C83 movsxd rdx, esi .text:FFFFF97FFF0B8C86 imul rdx, 0FFFFFFFFFFFFD8F0h ; DueTime .text:FFFFF97FFF0B8C8D xor r8d, r8d ; Dpc .text:FFFFF97FFF0B8C90 mov cs:gdmsNextTimer, eax .text:FFFFF97FFF0B8C96 call cs:__imp_KeSetTimer .text:FFFFF97FFF0B8C9C jmp short loc_FFFFF97FFF0B8CB4 .text:FFFFF97FFF0B8C9E ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B8C9E .text:FFFFF97FFF0B8C9E loc_FFFFF97FFF0B8C9E: ; CODE XREF: InternalSetTimer+22Bj .text:FFFFF97FFF0B8C9E ; InternalSetTimer+232j .text:FFFFF97FFF0B8C9E mov rcx, cs:gpkthreadRIT .text:FFFFF97FFF0B8CA5 xor edx, edx .text:FFFFF97FFF0B8CA7 mov cs:gbRITAlerted, bpl .text:FFFFF97FFF0B8CAE call cs:__imp_KeAlertThread .text:FFFFF97FFF0B8CB4 .text:FFFFF97FFF0B8CB4 loc_FFFFF97FFF0B8CB4: ; CODE XREF: InternalSetTimer+23Fj .text:FFFFF97FFF0B8CB4 ; InternalSetTimer+264j .text:FFFFF97FFF0B8CB4 mov rbx, [rsp+68h+pFindedTimerObject] .text:FFFFF97FFF0B8CB9 jmp short loc_FFFFF97FFF0B8CC2 .text:FFFFF97FFF0B8CBB ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B8CBB .text:FFFFF97FFF0B8CBB loc_FFFFF97FFF0B8CBB: ; CODE XREF: InternalSetTimer+204j .text:FFFFF97FFF0B8CBB mov cs:gbRITRescan, bpl .text:FFFFF97FFF0B8CC2 .text:FFFFF97FFF0B8CC2 loc_FFFFF97FFF0B8CC2: ; CODE XREF: InternalSetTimer+1F7j .text:FFFFF97FFF0B8CC2 ; InternalSetTimer+281j .text:FFFFF97FFF0B8CC2 mov rax, [rbx+38h] .text:FFFFF97FFF0B8CC6 cmp rax, r12 .text:FFFFF97FFF0B8CC9 cmovz rax, rbp .text:FFFFF97FFF0B8CCD .text:FFFFF97FFF0B8CCD loc_FFFFF97FFF0B8CCD: ; CODE XREF: InternalSetTimer+34j .text:FFFFF97FFF0B8CCD lea r11, [rsp+68h+var_28] .text:FFFFF97FFF0B8CD2 mov rbx, [r11+30h] .text:FFFFF97FFF0B8CD6 mov rbp, [r11+38h] .text:FFFFF97FFF0B8CDA mov rsi, [r11+40h] .text:FFFFF97FFF0B8CDE mov rsp, r11 .text:FFFFF97FFF0B8CE1 pop r15 .text:FFFFF97FFF0B8CE3 pop r14 .text:FFFFF97FFF0B8CE5 pop r13 .text:FFFFF97FFF0B8CE7 pop r12 .text:FFFFF97FFF0B8CE9 pop rdi .text:FFFFF97FFF0B8CEA retn .text:FFFFF97FFF0B8CEA ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B8CEB db 9 dup(90h) .text:FFFFF97FFF0B8CEB InternalSetTimer endp
基本大致需要的信息在这个函数都能发现了,
这里有两个函数函数可以看看
一个FindTimer,另一个HMAllocObject
FindTimer ( tagWND* tagWND __int64 TimerID __int64 elapse __int64 lpTimerFunc tagWND** tagRetWnd ) .text:FFFFF97FFF0B8938 ; __int64 __fastcall FindTimer(__int64 pTagWnd, __int64 TimerID, __int64 flags, __int64 lpTimerFuc, __int64 pRetTagWnd) .text:FFFFF97FFF0B8938 FindTimer proc near ; CODE XREF: AccessTimeOutReset+20p .text:FFFFF97FFF0B8938 ; SetMouseTrails+3B2p ... .text:FFFFF97FFF0B8938 .text:FFFFF97FFF0B8938 pTagWnd = qword ptr 8 .text:FFFFF97FFF0B8938 TimerID = qword ptr 10h .text:FFFFF97FFF0B8938 Elapse = qword ptr 18h .text:FFFFF97FFF0B8938 lpTimerFunc = qword ptr 20h .text:FFFFF97FFF0B8938 pRetTagWnd = qword ptr 28h .text:FFFFF97FFF0B8938 .text:FFFFF97FFF0B8938 mov rax, rsp .text:FFFFF97FFF0B893B mov [rax+8], rbx .text:FFFFF97FFF0B893F mov [rax+18h], rbp .text:FFFFF97FFF0B8943 mov [rax+20h], rsi .text:FFFFF97FFF0B8947 mov [rax+10h], rdx .text:FFFFF97FFF0B894B push rdi .text:FFFFF97FFF0B894C push r12 .text:FFFFF97FFF0B894E push r13 .text:FFFFF97FFF0B8950 push r14 .text:FFFFF97FFF0B8952 push r15 .text:FFFFF97FFF0B8954 sub rsp, 20h .text:FFFFF97FFF0B8958 mov r12, rcx ; pTagWnd .text:FFFFF97FFF0B895B xor edi, edi .text:FFFFF97FFF0B895D mov r13, rcx ; pTagWnd .text:FFFFF97FFF0B8960 shr r12, 8 ; pTagWnd >> 8 .text:FFFFF97FFF0B8964 lea rcx, gTimerHashTable ; 取全局TimerHashTable .text:FFFFF97FFF0B896B mov r15d, r9d ; lpTimerFunc .text:FFFFF97FFF0B896E add r12, rdx ; pTagWnd >> 8 + TimerID .text:FFFFF97FFF0B8971 mov r14d, r8d ; Elapse .text:FFFFF97FFF0B8974 mov rax, rdx ; TimerID .text:FFFFF97FFF0B8977 and r12d, 3Fh ; pTagWnd >> 8 + TimerID & 3F .text:FFFFF97FFF0B897B mov esi, edi .text:FFFFF97FFF0B897D shl r12, 4 ; pTagWnd >> 8 + TimerID & 3F << 4 .text:FFFFF97FFF0B8981 add r12, rcx ; pTagWnd >> 8 + TimerID & 3F << 4 + 全局timerHashTable .text:FFFFF97FFF0B8984 mov rbp, [r12] ; hash表中的值给rbp .text:FFFFF97FFF0B8988 cmp rbp, r12 ; 是否存在 .text:FFFFF97FFF0B898B jz short loc_FFFFF97FFF0B89F9 ; 不存在就跳 返回false .text:FFFFF97FFF0B898D .text:FFFFF97FFF0B898D loc_FFFFF97FFF0B898D: ; CODE XREF: FindTimer+A8j .text:FFFFF97FFF0B898D lea rbx, [rbp-70h] ; hash数据中-0x70 应该是TIMER_OBJECT 这个就是我们需要逆的结构 .text:FFFFF97FFF0B8991 cmp [rbx+28h], r13 ; timer_object + 0x28处应该是存放pTagWnd .text:FFFFF97FFF0B8995 jnz short loc_FFFFF97FFF0B89D7 ; if([rbx+0x28] != r13) 跳转 不相等就跳 .text:FFFFF97FFF0B8997 cmp [rbx+38h], rax ; timer_object + 0x38处应该是TimerID .text:FFFFF97FFF0B899B jnz short loc_FFFFF97FFF0B89D7 ; if([rbx+0x38] != rax) 跳转 不相等就跳 .text:FFFFF97FFF0B899D mov eax, [rbx+48h] ; 暂时不知道timer_object + 0x48干什么的 .text:FFFFF97FFF0B89A0 xor eax, r14d ; eax ^ elapse .text:FFFFF97FFF0B89A3 test al, 6 ; eax ^ elapse & 6 .text:FFFFF97FFF0B89A5 jnz short loc_FFFFF97FFF0B89D2 ; if(eax ^ elapse & 6) .text:FFFFF97FFF0B89A7 test byte ptr [rbx+48h], 40h ; if([rbx+0x48]^0x40) .text:FFFFF97FFF0B89AB jnz short loc_FFFFF97FFF0B89E2 ; goto End .text:FFFFF97FFF0B89AD call cs:__imp_PsGetCurrentProcessWin32Process .text:FFFFF97FFF0B89B3 mov r11, rax ; 返回tagPROCESSINFO .text:FFFFF97FFF0B89B6 mov rax, [rbx+30h] ; 这个可以知道timer_object + 0x30 是存在tagTHREADINFO .text:FFFFF97FFF0B89BA cmp r11, [rax+158h] ; 比较当前的和结构下的tagPROCESSINF是否相同 .text:FFFFF97FFF0B89C1 jz short loc_FFFFF97FFF0B89E2 ; 相等就跳 .text:FFFFF97FFF0B89C3 cmp r13, rdi ; r13 = pTagWnd rdi应该是0 .text:FFFFF97FFF0B89C6 jnz short loc_FFFFF97FFF0B89D2 ; 相等不跳 .text:FFFFF97FFF0B89C8 mov eax, [rbx+48h] .text:FFFFF97FFF0B89CB xor eax, r14d .text:FFFFF97FFF0B89CE test al, 4 ; [rbx+0x48]^elapse & 4 .text:FFFFF97FFF0B89D0 jz short loc_FFFFF97FFF0B89E2 ; if(([rbx+0x48]^elapse & 4)) .text:FFFFF97FFF0B89D2 .text:FFFFF97FFF0B89D2 loc_FFFFF97FFF0B89D2: ; CODE XREF: FindTimer+6Dj .text:FFFFF97FFF0B89D2 ; FindTimer+8Ej .text:FFFFF97FFF0B89D2 mov rax, [rsp+48h+TimerID] .text:FFFFF97FFF0B89D7 .text:FFFFF97FFF0B89D7 loc_FFFFF97FFF0B89D7: ; CODE XREF: FindTimer+5Dj .text:FFFFF97FFF0B89D7 ; FindTimer+63j .text:FFFFF97FFF0B89D7 mov rbp, [rbp+0] .text:FFFFF97FFF0B89DB cmp rbp, r12 ; 如果在hashtable张发现等于自己 就跳转 其实就是遍历hashtable .text:FFFFF97FFF0B89DE jz short loc_FFFFF97FFF0B89FE ; 遍历完了 还是没有找到 .text:FFFFF97FFF0B89E0 jmp short loc_FFFFF97FFF0B898D ; hash数据中-0x70 应该是TIMER_OBJECT 这个就是我们需要逆的结构 .text:FFFFF97FFF0B89E2 ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B89E2 .text:FFFFF97FFF0B89E2 loc_FFFFF97FFF0B89E2: ; CODE XREF: FindTimer+73j .text:FFFFF97FFF0B89E2 ; FindTimer+89j ... .text:FFFFF97FFF0B89E2 cmp r15d, edi ; 如果timefunc存在就释放当InternalSetTimer来调用的话 这个参数是NULL .text:FFFFF97FFF0B89E5 jz short loc_FFFFF97FFF0B89F2 ; 如果lptimeFunc为NULL就跳 .text:FFFFF97FFF0B89E7 mov rcx, rbx ; P .text:FFFFF97FFF0B89EA call FreeTimer .text:FFFFF97FFF0B89EF mov rbx, rdi .text:FFFFF97FFF0B89F2 .text:FFFFF97FFF0B89F2 loc_FFFFF97FFF0B89F2: ; CODE XREF: FindTimer+ADj .text:FFFFF97FFF0B89F2 mov esi, 1 ; esi应该找的的一个标志 .text:FFFFF97FFF0B89F7 jmp short loc_FFFFF97FFF0B89FE .text:FFFFF97FFF0B89F9 ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B89F9 .text:FFFFF97FFF0B89F9 loc_FFFFF97FFF0B89F9: ; CODE XREF: FindTimer+53j .text:FFFFF97FFF0B89F9 mov rbx, [rsp+48h+TimerID] .text:FFFFF97FFF0B89FE .text:FFFFF97FFF0B89FE loc_FFFFF97FFF0B89FE: ; CODE XREF: FindTimer+A6j .text:FFFFF97FFF0B89FE ; FindTimer+BFj .text:FFFFF97FFF0B89FE mov rcx, [rsp+48h+pRetTagWnd] .text:FFFFF97FFF0B8A03 cmp rcx, rdi ; 如果pRetTagWnd为就跳 .text:FFFFF97FFF0B8A06 jz short loc_FFFFF97FFF0B8A12 .text:FFFFF97FFF0B8A08 cmp esi, 1 ; 如果esi = 1 .text:FFFFF97FFF0B8A0B cmovz rdi, rbx ; 做返回值的处理 .text:FFFFF97FFF0B8A0F mov [rcx], rdi .text:FFFFF97FFF0B8A12 .text:FFFFF97FFF0B8A12 loc_FFFFF97FFF0B8A12: ; CODE XREF: FindTimer+CEj .text:FFFFF97FFF0B8A12 mov rbx, [rsp+48h+pTagWnd] .text:FFFFF97FFF0B8A17 mov rbp, [rsp+48h+Elapse] .text:FFFFF97FFF0B8A1C mov eax, esi .text:FFFFF97FFF0B8A1E mov rsi, [rsp+48h+lpTimerFunc] .text:FFFFF97FFF0B8A23 add rsp, 20h .text:FFFFF97FFF0B8A27 pop r15 .text:FFFFF97FFF0B8A29 pop r14 .text:FFFFF97FFF0B8A2B pop r13 .text:FFFFF97FFF0B8A2D pop r12 .text:FFFFF97FFF0B8A2F pop rdi .text:FFFFF97FFF0B8A30 retn .text:FFFFF97FFF0B8A30 ; --------------------------------------------------------------------------- .text:FFFFF97FFF0B8A31 align 8 .text:FFFFF97FFF0B8A31 FindTimer endp
HMAllocObject:
HMAllocObject(PTHREADINFO pti, PDESKTOP pdesk, BYTE btype, DWORD size);
w2k中的代码private\ntos\w32\ntuser\kernel\timer.c
ptmr = (PTIMER)HMAllocObject(NULL, NULL, TYPE_TIMER, sizeof(TIMER));
根据泄露的NT代码来看,这个函数返回的就是保存USER定时器TIMER_OBJECT空间
根据上层函数的传参,可以知道TIMER_OBJECT结构有0x80大小
从汇编代码来看
我们需要的TIMER结构应该是这样的
typedef struct _User_Timer{ ULONG64 UnKnow1;//8 ULONG64 UnKnow2;//10 LIST_ENTRY gtmrLish;//18 ULONG64 UnKnow3;//20 ULONG64 hWnd_Object;//28 ULONG64 pTagTHADINFO;//30 ULONG64 TimerId;//38 ULONG uElapse;//40 ULONG uElapse;//44 ULONG64 flag;//48 ULONG64 lpTimerFunc;//50 ULONG64 UnKnow4;//58 ULONG64 UnKnow5;//60 ULONG64 UnKnow6//68 LIST_ENTRY List_UnKnow1;//70 timerhash相关 ULONG64 UnKnow7;//78 ULONG64 UnKnow8;//80 }User_Timer,*pUser_Timer;
不过移除定时器 还需要0x70 0x60两个偏移的信息,待有时间再来看看
以上是关于逆--Win7x64 UserTimer结构获取,NtUserSetTimer,_SetTimer,InternalSetTimer 枚举进程定时器的主要内容,如果未能解决你的问题,请参考以下文章
chromium源代码下载(Win7x64+VS2013sp2, 39.0.2132.2)