参考:某驱动云下发器
通过注册关机回调,使得驱动能够接收系统的关机时间,在这个时候检测自己的服务及文件是否正常。如下图:
*注册关机回调
*系统关机消息处理函数
注意:
当然还可以寻找更晚的时机来确保驱动能在下次开机能够启动。 不过,这种还是会在比如,安全模式下被发现的。
*kernel shellcode
//apc demo
//user-mode
//
//ethread is the target execution environment,
//addr is the user-mode shellcode address
//
VOID UsermodeApc(PETHREAD ethread, PVOID address)
{
PRKAPC apc = NULL;
//check the apcs condition
if (KeAreAllApcsDisabled() == FALSE&&
address)
{
//we can use apcs
apc = (PRKAPC)ExAllocatePool(NonPagedPool, sizeof(KAPC));
if (apc)
{
//initialize apc structure
//
// for user mode apc
// set RundownRoutine to NULL
// ProcessorMode to UserMode
// NormalRoutine to user-mdoe routine address
//
KeInitializeApc(
apc, //apc
ethread, //thread set the target thread obejct ,PsLookupThreadByThradId
OriginalApcEnvironment, //Enviroment
KernelRoutine, //KernelRoutine
NULL,//RundownRoutine, //RundownRoutine
(PKNORMAL_ROUTINE)address, //NormalRoutine
UserMode, //ProcessMode,specify under which mode the NormalRoutine will run
NULL); //NormalContext
//insert apc into apc list
DbgPrint("[%s]inserting user-mode apc!\n", __FUNCTION__);
KeInsertQueueApc(
apc, //apc
NULL, //SystemArguemnt1,which can be used in KernelRoutine and NormalRoutine
NULL, //SystemArgument2,which can be used in KernelRoutine and NormalRoutine
IO_NO_INCREMENT //Increment
);
}
}
}
//kernel mode
//using KernelMode apc
void NTAPI KernelRoutine(PKAPC apc,
PKNORMAL_ROUTINE* NormalRoutine,
PVOID* NormalContext,
PVOID* SystemArgument1,
PVOID* SystemArgument2)
{
UNREFERENCED_PARAMETER(NormalRoutine);
UNREFERENCED_PARAMETER(NormalContext);
UNREFERENCED_PARAMETER(SystemArgument1);
UNREFERENCED_PARAMETER(SystemArgument2);
ExFreePool(apc);
}
void NTAPI RundownRoutine(PRKAPC apc)
{
ExFreePool(apc);
}
void NTAPI NormalRoutine(PVOID NormalContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
UNREFERENCED_PARAMETER(NormalContext);
UNREFERENCED_PARAMETER(SystemArgument1);
UNREFERENCED_PARAMETER(SystemArgument2);
//to do something
DbgPrint("%s", (char*)SystemArgument1);
}
VOID TestKernelApc()
{
PRKAPC apc =NULL;
CHAR RawData[0x100] = "in apc NormalRoutine";
//check the apcs condition
if (KeAreAllApcsDisabled()==FALSE)
{
//we can use apcs
apc = (PRKAPC)ExAllocatePool(NonPagedPool, sizeof(KAPC));
if (apc)
{
//initialize apc structure
//
// for user mode apc
// set RundownRoutine to NULL
// ProcessorMode to UserMode
// NormalRoutine to user-mdoe routine address
//
KeInitializeApc(apc, //apc
PsGetCurrentThread(), //thread set the target thread obejct ,PsLookupThreadByThradId
OriginalApcEnvironment, //Enviroment
KernelRoutine, //KernelRoutine
RundownRoutine, //RundownRoutine
NormalRoutine, //NormalRoutine
KernelMode, //ProcessMode,specify under which mode the NormalRoutine will run
NULL); //NormalContext
//insert apc into apc list
DbgPrint("[%s]inserting apc!\n",__FUNCTION__);
KeInsertQueueApc(apc, //apc
RawData, //SystemArguemnt1,which can be used in KernelRoutine and NormalRoutine
NULL, //SystemArgument2,which can be used in KernelRoutine and NormalRoutine
IO_NO_INCREMENT //Increment
);
}
}
}