A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #8872  by Tigzy
 Fri Sep 30, 2011 10:58 pm
Hello

I need to find a mean to unregister callbacks set with cmregistercallback (or others , as PsSetNotifyxxx).
To do so, I guess we could find an object in memory where all of theses are stored, and nullify them.

Anyone ever tried to unregister callbacks?
 #8874  by EP_X0FF
 Sat Oct 01, 2011 12:00 am
Implementation of PsXXX callbacks are different on XP/2003 and Vista+
Implementation of CM callbacks are different on XP/2003 and Vista+

Meanwhile there are exists other callback types (Io, Se, Ke) all can be used by malware.

Yes it possible to remove them all. First of all you need length disasm engine.
 #8881  by Tigzy
 Sat Oct 01, 2011 7:07 am
I'm afraid misunderstood what you meant by "First of all you need length disasm engine."
The CmUnRegisterCallback needs a cookie, is it possible to bruteforce it? I guess a LARGE_INTEGER is a pain in the ass to bruteforce cause it's 64 bits long...
NTSTATUS CmUnRegisterCallback(
__in LARGE_INTEGER Cookie
);
 #8882  by EP_X0FF
 Sat Oct 01, 2011 7:10 am
How do you will decide what callback to remove with your brute-force (which itself is completely abnormal idea)? Kill them all with long long cycle?
Tigzy wrote:I'm afraid misunderstood what you meant by "First of all you need length disasm engine."
http://www.kernelmode.info/forum/viewto ... ?f=15&t=38
 #8884  by EP_X0FF
 Sat Oct 01, 2011 7:23 am
Ouah, a whole engine only for that? Why is this necessary?
Not whole, it's just a example. As in fact you need only LDE (Length Disassembler Engine). This is required for searching callbacks data (arrays, linked lists etc).
 #8886  by EP_X0FF
 Sat Oct 01, 2011 8:00 am
Lets take PsSetCreateProcessNotifyRoutine and old NT5 as example because it's simpler.

Internally it looks like
Code: Select all
for (i=0; i < PSP_MAX_CREATE_PROCESS_NOTIFY; i++) {
        if (Remove) {
            if (PspCreateProcessNotifyRoutine[i] == NotifyRoutine) {
                PspCreateProcessNotifyRoutine[i] = NULL;
                PspCreateProcessNotifyRoutineCount -= 1;
                return STATUS_SUCCESS;
            }

        } else {
            if (PspCreateProcessNotifyRoutine[i] == NULL) {
                PspCreateProcessNotifyRoutine[i] = NotifyRoutine;
                PspCreateProcessNotifyRoutineCount += 1;
                return STATUS_SUCCESS;
            }
        }
    }
where PSP_MAX_CREATE_PROCESS_NOTIFY = 8, this value valid up to current time.

So to operate with callbacks of this type (for example to list them) you need to read PspCreateProcessNotifyRoutine array,
Code: Select all
PCREATE_PROCESS_NOTIFY_ROUTINE PspCreateProcessNotifyRoutine[ PSP_MAX_CREATE_PROCESS_NOTIFY ];
(which is not exported of course) from kernel memory. How to do this? Obviously by finding a valid pointer to this data. And this can be done by disassembling owner PsSetCreateProcessNotifyRoutine function body and looking for a specific pattern describing that array. There you need LDE (of course if you not plan to do any kind of hardcode - BSOD generator).

LoadImage, ThreadCreate also uses similar arrays (valid for NT5 kernels). CmRegistryCallback introduced in Windows XP and it's internals also varies from NT5 to NT6 versions. There is no generic way to get what you want. You need a separate callback handling code for two different kernels and data signatures also can depends from service pack version.
 #8888  by Brock
 Sat Oct 01, 2011 9:05 am
PsX notify routines will be the easiest to locate, version checking is still imperative as EP mentions. Modern ARKs have had this feature for some time as has some malware.