RtlEncodePointer
该函数的作用是把传进来的值和进程的指定信息进行异或 然后返回该值
.text:7C9333DF __stdcall RtlEncodePointer(x)
.text:7C9333DF public _RtlEncodePointer@4
.text:7C9333DF _RtlEncodePointer@4 proc near ; CODE XREF: RtlDecodePointer(x)+6↓j
.text:7C9333DF ; RtlAddVectoredExceptionHandler(x,x)+25↓p
.text:7C9333DF ; DATA XREF: ...
.text:7C9333DF
.text:7C9333DF loc_ProcessInformation= dword ptr -4
.text:7C9333DF arg_0 = dword ptr 8
.text:7C9333DF
.text:7C9333DF mov edi, edi ;
.text:7C9333E1 push ebp
.text:7C9333E2 mov ebp, esp
.text:7C9333E4 push ecx
.text:7C9333E5 push 0 ; ReturnLength
.text:7C9333E7 push 4 ; 大小是4个字节
.text:7C9333E9 lea eax, [ebp+loc_ProcessInformation]
.text:7C9333EC push eax ; 接受返回值的buffer 大小由ProcessInformationClass决定
.text:7C9333ED push 24h ; '$' ; 要检索的进程信息 ProcessBreakOnTermination | ProcessDebugPort
.text:7C9333EF push 0FFFFFFFFh ; ProcessHandle
.text:7C9333F1 call _ZwQueryInformationProcess@20 ; ZwQueryInformationProcess(x,x,x,x,x)
.text:7C9333F6 mov eax, [ebp+loc_ProcessInformation]
.text:7C9333F9 xor eax, [ebp+arg_0] ;返回异或后的值
.text:7C9333FC leave
.text:7C9333FD retn 4
.text:7C9333FD _RtlEncodePointer@4 endp
RtlDecodePointer
int __stdcall RtlDecodePointer(PLIST_ENTRY pExceptionRecord) 对指定内容进行解密 与加密函数对应,也是取进程的指定信息进行异或操作。
AddVectoredExceptionHandler
函数作用:添加一个新的VEH全局异常处理程序
参数说明:
PVOID AddVectoredExceptionHandler(
ULONG First, //如果这个值非0,那么这个异常处理程序是第一个被调用的。
如果再一次调用该函数,并且该参数非0,那么新的异常处理程序会被第一个调用。
PVECTORED_EXCEPTION_HANDLER Handler 异常处理程序地址
);
.text:7C956BFA ; int __stdcall RtlAddVectoredExceptionHandler(ULONG First, PVOID ExpceptionHandler)
.text:7C956BFA public _RtlAddVectoredExceptionHandler@8
.text:7C956BFA _RtlAddVectoredExceptionHandler@8 proc near
.text:7C956BFA ; DATA XREF: .text:off_7C923428↑o
.text:7C956BFA
.text:7C956BFA First = dword ptr 8
.text:7C956BFA ExpceptionHandler= dword ptr 0Ch
.text:7C956BFA
.text:7C956BFA ; FUNCTION CHUNK AT .text:7C96264D SIZE 0000001B BYTES
.text:7C956BFA
.text:7C956BFA mov edi, edi
.text:7C956BFC push ebp
.text:7C956BFD mov ebp, esp
.text:7C956BFF push esi
.text:7C956C00 mov eax, large fs:_TEB.NtTib.Self
.text:7C956C06 mov eax, [eax+_TEB.ProcessEnvironmentBlock]
.text:7C956C09 push 0Ch
.text:7C956C0B push 0
.text:7C956C0D push [eax+_PEB.ProcessHeap]
.text:7C956C10 call _RtlAllocateHeap@12 ; 分配0xC大小的内存
.text:7C956C15 mov esi, eax
.text:7C956C17 test esi, esi ; esi=分配的内存
.text:7C956C19 jz short loc_7C956C5A ; 内存申请失败,直接返回
.text:7C956C1B push edi
.text:7C956C1C push [ebp+ExpceptionHandler]
.text:7C956C1F call _RtlEncodePointer@4 ; 把VEH异常处理程序的值进行异或加密
.text:7C956C24 mov edi, offset _RtlpCalloutEntryLock
.text:7C956C29 push edi
.text:7C956C2A mov [esi+8], eax ; 分配的内存+8 =加密后的异常处理函数地址
.text:7C956C2D call _RtlEnterCriticalSection@4 ; RtlEnterCriticalSection(x)
.text:7C956C32 cmp [ebp+First], 0
.text:7C956C36 jz loc_7C96264D ; 如果参数为First参数为0 则挂到链表尾 跳转就挂到链表尾巴
.text:7C956C3C mov eax, _RtlpCalloutEntryList
.text:7C956C41 mov [esi], eax ; 申请的内存的+0 +4 都写入链表头的值
.text:7C956C43 mov dword ptr [esi+4], offset _RtlpCalloutEntryList
.text:7C956C4A mov [eax+4], esi
.text:7C956C4D mov _RtlpCalloutEntryList, esi ; 申请的内存成为链表头
.text:7C956C53
.text:7C956C53 loc_7C956C53: ; CODE XREF: RtlAddVectoredExceptionHandler(x,x)+BA69↓j
.text:7C956C53 push edi
.text:7C956C54 call _RtlLeaveCriticalSection@4 ; RtlLeaveCriticalSection(x)
.text:7C956C59 pop edi
.text:7C956C5A
.text:7C956C5A loc_7C956C5A: ; CODE XREF: RtlAddVectoredExceptionHandler(x,x)+1F↑j
.text:7C956C5A mov eax, esi
.text:7C956C5C pop esi
.text:7C956C5D pop ebp
.text:7C956C5E retn 8
.text:7C956C5E _RtlAddVectoredExceptionHandler@8 endp
总结: 在VEH异常处理链表中+8的位置是经过异或加密的异常处理函数。也可以看出WINDOWS链表头插入的方式是:新申请内存的+0 和+4存入的是原来的链表头的值,原来的链表头+0 +4分别存入新申请的内存地址。
RtlCallVectoredExceptionHandlers 调用异常处理函数
.text:7C94A914 ; int __stdcall RtlCallVectoredExceptionHandlers(PVOID pExceptionRecord, PCONTEXT pContext)
.text:7C94A914 _RtlCallVectoredExceptionHandlers@8 proc near
.text:7C94A914 ; CODE XREF: RtlDispatchException(x,x)+14↓p
.text:7C94A914
.text:7C94A914 loc_pExceptionRecord= dword ptr -8
.text:7C94A914 loc_pContext = dword ptr -4
.text:7C94A914 pExceptionRecord= dword ptr 8
.text:7C94A914 pContext = dword ptr 0Ch
.text:7C94A914 RtlpCalloutEntryList= dword ptr 7C99B3C0h
.text:7C94A914 arg_7C99D5D8 = byte ptr 7C99D5E0h
.text:7C94A914
.text:7C94A914 ; FUNCTION CHUNK AT .text:7C9625F9 SIZE 00000054 BYTES
.text:7C94A914
.text:7C94A914 mov edi, edi
.text:7C94A916 push ebp
.text:7C94A917 mov ebp, esp
.text:7C94A919 push ecx
.text:7C94A91A push ecx
.text:7C94A91B push edi
.text:7C94A91C mov edi, RtlpCalloutEntryList
.text:7C94A921 cmp _RtlpCalloutEntryList, edi ; 判断链表是否为空
.text:7C94A927 jnz loc_7C9625F9
.text:7C94A92D xor al, al ; VEH没有处理成功 返回0
.text:7C94A92F
.text:7C94A92F loc_7C94A92F: ; CODE XREF: RtlCallVectoredExceptionHandlers(x,x)+17D2E↓j
.text:7C94A92F pop edi
.text:7C94A930 leave
.text:7C94A931 retn 8
.text:7C94A931 _RtlCallVectoredExceptionHandlers@8 endp
//链表不为空的操作
.text:7C9625F9 loc_7C9625F9: ; CODE XREF: RtlCallVectoredExceptionHandlers(x,x)+13↑j
.text:7C9625F9 mov eax, [ebp+pExceptionRecord]
.text:7C9625FC push ebx
.text:7C9625FD push esi
.text:7C9625FE mov [ebp+loc_pExceptionRecord], eax ; 保存异常记录指针
.text:7C962601 mov eax, [ebp+pContext]
.text:7C962604 mov ebx, 7C99D5E0h
.text:7C962609 push ebx
.text:7C96260A mov [ebp+loc_pContext], eax ; 保存Context指针
.text:7C96260D call _RtlEnterCriticalSection@4 ; RtlEnterCriticalSection(x)
.text:7C962612 mov esi, _RtlpCalloutEntryList
.text:7C962618 jmp short loc_7C96262F ; 最开始 esi=_RtlpCalloutEntryList edi=7C99B3C0h 如果这两个值相等则链表为空,不相等说明由VEH异常处理程序
.text:7C96261A ; ---------------------------------------------------------------------------
.text:7C96261A
.text:7C96261A loc_7C96261A: ; CODE XREF: RtlCallVectoredExceptionHandlers(x,x)+17D1D↓j
.text:7C96261A push dword ptr [esi+8] ; 异常处理链表+8 存的是加密后的异常处理程序
.text:7C96261D call _RtlDecodePointer@4 ; RtlDecodePointer(x)
.text:7C962622 lea ecx, [ebp+loc_pExceptionRecord]
.text:7C962625 push ecx
.text:7C962626 call eax ; 异常处理函数是经过异或操作加密过的,需要解密后使用。
.text:7C962628 cmp eax, 0FFFFFFFFh
.text:7C96262B jz short loc_7C962647 ; 如果异常处理程序返回值是-1 则不再继续再链表里面找异常处理程序
.text:7C96262D mov esi, [esi]
.text:7C96262F
.text:7C96262F loc_7C96262F: ; CODE XREF: RtlCallVectoredExceptionHandlers(x,x)+17D04↑j
.text:7C96262F cmp esi, edi ; 最开始 esi=_RtlpCalloutEntryList edi=7C99B3C0h 如果这两个值相等则链表为空,不相等说明由VEH异常处理程序
.text:7C962631 jnz short loc_7C96261A ; 异常处理链表+8 存的是加密后的异常处理程序
.text:7C962633 mov byte ptr [ebp+pExceptionRecord+3], 0
.text:7C962637
.text:7C962637 loc_7C962637: ; CODE XREF: RtlCallVectoredExceptionHandlers(x,x)+17D37↓j
.text:7C962637 push ebx
.text:7C962638 call _RtlLeaveCriticalSection@4 ; RtlLeaveCriticalSection(x)
.text:7C96263D mov al, byte ptr [ebp+pExceptionRecord+3]
.text:7C962640 pop esi
.text:7C962641 pop ebx
.text:7C962642 jmp loc_7C94A92F
.text:7C962647 ; ---------------------------------------------------------------------------
.text:7C962647
.text:7C962647 loc_7C962647: ; CODE XREF: RtlCallVectoredExceptionHandlers(x,x)+17D17↑j
.text:7C962647 mov byte ptr [ebp+pExceptionRecord+3], 1
.text:7C96264B jmp short loc_7C962637
函数总结:RtlCallVectoredExceptionHandlers函数在链表_RtlpCalloutEntryList为空的情况下直接返回0,表明异常并没有处理处理成功,接下来交给SEH异常处理。
在链表中有值的情况下,取出链表+8位置的加密的异常处理函数。经过异或解密再调用,调用的异常处理函数返回-1,返回 1,其他情况返回 0