Code: 487E6B push 'bcMC' ; Pool Tag: "CMcb" 487E70 xor ebx, ebx 487E72 push 38h ; NumberOfBytes: 0x38 487E74 inc ebx 487E75 push ebx ; PoolType: PAGEDPOOL 487E76 call ExAllocatePoolWithTag ; ExAllocatePoolWithTag(x,x,x): allocates pool memory 487E7B mov esi, eax ; eax is the pointer to the allocated pool memory, PCM_CALLBACK_CONTEXT_BLOCK 487E7D xor edi, edi 487E7F cmp esi, edi ; Is PCM_CALLBACK_CONTEXT_BLOCK a NULL pointer? 487E81 jz cmRegisterCallback_fails ; yes: function fails... 487E87 push esi 487E88 push [ebp+Function] ; PEX_CALLBACK_FUNCTION, pointer to callback function 487E8B call _ExAllocateCallBack ; allocates and fill EX_CALLBACK_ROUTINE_BLOCK structure (more on this later...) 487E90 cmp eax, edi ; ExAllocateCallback success or not? 487E92 mov [ebp+PEX_CALLBACK_ROUTINE_BLOCK], eax ; store the pointer to the allocated pool memory 487E95 jnz short _ExAllocateCallBack_success ... ; fill CM_CALLBACK_CONTEXT_BLOCK fields 487EDC mov ebx, offset CmpCallBackVector 487EE1 mov [ebp+i], edi ; i = 0 487EE4 try_next_slot: 487EE4 push edi ; OldBlock: NULL 487EE5 push [ebp+PEX_CALLBACK_ROUTINE_BLOCK] ; NewBlock with information to add 487EE8 push ebx ; CmpCallbackVector[i] 487EE9 call _ExCompareExchangeCallBack ; try to *insert* the new callback inside CmpCallBack vector 487EEE test al, al ;check the result... 487EF0 jnz short free_slot_has_been_found ; jump if the vector has an empty space for the new entry 487EF2 add [ebp+i], 4 ; i++, increase the counter 487EF6 add ebx, 4 ; shift to the next item of the vector to check 487EF9 cmp [ebp+i], 190h ; is the end of the vector? 487F00 jb short try_next_slot ; no: try another one. yes: no free slot! ... 487F11 cmRegisterCallback_fails: 487F11 mov eax, STATUS_INSUFFICIENT_RESOURCES 487F16 end_CmRegisterCallback: ... 487F1A retn 0Ch ... 487F1D free_slot_has_been_found: 487F1D mov eax, 1 487F22 mov ecx, offset _CmpCallBackCount ; CmpCallBackCount: number of not NULL item inside the vector 487F27 xadd [ecx], eax ; there's a new callback, it increases the number of item inside the vector 487F2A xor eax, eax 487F2C jmp short end_CmRegisterCallback

Code: 52AB35 push 'brbC' ; Pool Tag: Cbrb 52AB3A push 0Ch ; NumberOfBytes: 0x0C 52AB3C push 1 ; PoolType: PAGED_POOL 52AB3E call ExAllocatePoolWithTag ; alloc a EX_CALLBACK_ROUTINE_BLOCK structure 52AB43 test eax, eax ; ExAllocatePoolWithTag success or not? 52AB45 jz short _ExAllocateCallBack_fails 52AB47 mov ecx, [ebp+_pex_callback_function] ; pointer to callback function (PEX_CALLBACK_FUNCTION) 52AB4A and dword ptr [eax], 0 ; 1° field: 0 52AB4D mov [eax+4], ecx ; 2° field: _pex_callback_function 52AB50 mov ecx, [ebp+_pool_allocated_memory] ; PCM_CALLBACK_CONTEXT_BLOCK 52AB53 mov [eax+8], ecx ; 3° field: _pcm_callback_context_block 52AB56 _ExAllocateCallBack_fails: ...

Code: typedef struct _EX_CALLBACK_ROUTINE_BLOCK { EX_RUNDOWN_REF RundownProtect; PEX_CALLBACK_FUNCTION Function; PCM_CALLBACK_CONTEXT_BLOCK Context; } EX_CALLBACK_ROUTINE_BLOCK, *PEX_CALLBACK_ROUTINE_BLOCK;

Code: 52AB81 mov eax, [ebp+CmpCallbackVector] ; vector at the current position 52AB84 mov ebx, [eax] ; ebx is a PEX_CALLBACK_ROUTINE_BLOCK, the item could be NULL or not 52AB86 mov eax, ebx 52AB88 xor eax, [ebp+OldBlock] ; OldBlock is NULL for a registration process 52AB8B mov [ebp+current_pex_callback_routine_block], ebx 52AB8E cmp eax, 7 ; check used to see if the current item is NULL or not 52AB91 ja short loc_52ABB5 ; jump if not NULL 52AB93 test esi, esi ; is NewBlock NULL? 52AB95 jz short loc_52ABA1 ; jump if it's NULL 52AB97 mov eax, esi ; esi, NewBlock pointer (changed...) 52AB99 or eax, 7 ; PAY ATTENTION HERE: or 7 !?! 52AB9C mov [ebp+NewBlock], eax ; change NewBlock pointer: NewBlock = NewBlock OR 7 52AB9F jmp short loc_52ABA5 ... 52ABA5 mov eax, [ebp+var_4] ; here if CmpCallbackVector's item is null 52ABA8 mov ecx, [ebp+CmpCallbackVector] ; current empty slot 52ABAB mov edx, [ebp+NewBlock] ; new pointer to insert 52ABAE cmpxchg [ecx], edx ; insert the new pointer inside the empty slot! 52ABB1 cmp eax, ebx 52ABB3 jnz short loc_52AB81 52ABB5 and ebx, not 7 ; PAY ATTENTION HERE! 52ABB8 cmp ebx, [ebp+OldBlock] ; here if CmpCallbackVector's item is not null 52ABBB jnz short loc_52AC19 52ABBD test ebx, ebx 52ABBF jz short loc_52AC15

Code: 52AC15 mov al, 1 ; 1 means success, new item has been added to CmpCallbackVector 52AC17 jmp short loc_52AC29 52AC19 test esi, esi ; esi -> NewBlock 52AC1B jz short loc_52AC27 52AC1D push 8 52AC1F pop edx 52AC20 mov ecx, esi 52AC22 call ExReleaseRundownProtectionEx ; if esi is not null something went wrong... 52AC27 xor al, al ; 0 means insuccess, new item has not been added to CmpCallbackVector

Code: cells = 0x64; // cells inside CmpCallbackVector nMod = *(DWORD*)_sysmodBuffer; // _sysmodBuffer filled by "ZwQuerySystemInformation(SystemModuleInformation..." for(i=0;i<cells;i++) { // take current item from CmpCallbackVector (look at the "& ~7" operation) pCBRB = (PEX_CALLBACK_ROUTINE_BLOCK)((*(DWORD*)(_CmpCallbackVectorAddress + 4*i )) & ~7); if (pCBRB != 0) { sysmodTmp = (PSYSTEM_MODULE_INFORMATION)((DWORD)_sysmodBuffer + 4); j = 0; while (jFunction) Base + (DWORD)sysmodTmp->Size) && ((DWORD)pCBRB->Function) > ((DWORD)sysmodTmp->Base)) { // Callback has been found DbgPrint("Result: %LX: %s\r

", pCBRB->Function, sysmodTmp->ImageName); break; } // get the next module sysmodTmp = (PSYSTEM_MODULE_INFORMATION)((DWORD)sysmodTmp + sizeof(SYSTEM_MODULE_INFORMATION)); j = j + 1; } }

Code: PAGE:005392D0 BB 20 05 48 00 mov ebx, offset _CmpCallBackVector .data:00480520 _CmpCallBackVector db 0

Code: callbackAddress = CmUnregisterCallback address in memory pagePointer = pointer_to_PAGE_section while (pagePointer < pointer_to_PAGE_section + size_of_PAGE_section) { value = get dword pointed by pagePointer if (value is inside DATA section) if ((pagePointer > callbackAddress) && (pagePointer < callbackAddress + range)) { CmpCallbackVector = value exit! } pagePointer++ }

Code: if ((pagePointer > callbackAddress) && (pagePointer < callbackAddress + range))

Code: PAGE:005392C3 8B FF mov edi, edi PAGE:005392C5 55 push ebp PAGE:005392C6 8B EC mov ebp, esp PAGE:005392C8 51 push ecx PAGE:005392C9 83 65 FC 00 and [ebp+var_4], 0 PAGE:005392CD 53 push ebx PAGE:005392CE 56 push esi PAGE:005392CF 57 push edi PAGE:005392D0 BB 20 05 48 00 mov ebx, offset _CmpCallBackVector

Code: PAGE:0065712A mov edi, edi PAGE:0065712C push ebp PAGE:0065712D mov ebp, esp PAGE:0065712F push [ebp+Cookie] PAGE:00657132 mov eax, offset stru_4FFDF0 PAGE:00657137 push 1 PAGE:00657139 push [ebp+Context] PAGE:0065713C push [ebp+Function] PAGE:0065713F call sub_657153 ; It's everything inside this call!!! PAGE:00657144 pop ebp PAGE:00657145 retn 0Ch