@会网络的老鼠

涂飞平的博客空间

由Ring0回调Ring3代码的方法

12 年前 0

从内核中执行用户态的代码.一共有3种方式达到这种效果.
第一种:
是最"正统"的方式,那就是APC(异步过程调用),下面是此方法的示例代码:

Apc=(KAPC *)ExAllocatePool(NonPagedPool,sizeof(KAPC));
KeInitializeApc(Apc,KeGetCurrentThread(),0,(PKKERNEL_ROUTINE)&KMApcCallback,NULL,(PKNORMAL_ROUTINE)pBaseAddr,UserMode,(PVOID)socket);
KeInsertQueueApc(Apc,(PVOID)&Event,NULL,0);
KeInitializeEvent(&Event,SynchronizationEvent,FALSE);
KeWaitForSingleObject(&Event,Executive,UserMode,TRUE,&Timeout);
其中pBaseAddr就是要在用户态执行的代码地址.KeInsertQueueApc插如系统APC队列,KeInitializeEvent和KeWaitForSingleObject一起触发了当前线程的APC,分别在内核和用户态调用KMApcCallback和pBaseAddr.KMApcCallback主要是释放一些资源.代码如下:
void KMApcCallback(PKAPC Apc,PKNORMAL_ROUTINE NormalRoutine,PVOID NormalContext,PVOID SystemArgument1,PVOID SystemArgument2)
{
UNREFERENCED_PARAMETER(NormalRoutine);
UNREFERENCED_PARAMETER(NormalContext);
ObDereferenceObject(SystemArgument1);
ExFreePool(Apc); return;
}
第二种:
是使用KeUserModeCallback函数,他是立即性质的,而不是象APC那样是"延迟"的.
第三种:
是直接中断返回的方式,具体实现可以参照linux的任务0从内核态转如用户态的实现,move_to_user_mode宏.实际上KeUserModeCallback也是用的这种方式.
注意:第一种方式可以用于任意线程,而后两种只能用于当前线程。

编写评论