APC
1. apc的分发必须不被禁用,2. 目标进程必须有处于alertable的线程.特别是后者这个条件,很多时候不一定有.比如explorer进程有很多线程,通常能找到.但是像记事本这种单线程程序,就找不到.
UserModeCallback.必须在目标进程空间调用,不能是attach.的.必须加载过User32的.,这样才有Kernelcallbacktable
在某些特定的时机,我们是有机会执行的.比如在进程刚刚创建的时候,我们可以修改OEP,修改IAT等加载我们的dll在第一个线程创建之后,我们可以插入apc.这些条件都很好满足.
虽然我们可以构造出场景,比如,如果你是一个过滤驱动或者hook型的,那么总是有机会会切换到目标进程上空的,这个时候就有机会可以UserModeCallback.
第一步:创建线程初始的栈,分配和保留栈空间.设置栈保护页.实现栈的自动增长.
第二步:设置线程上下文,各个段寄存器和基本寄存器,设置eip指向Kernel32!BaseThreadTrunk
第三步:对于vista以后,还得分配TEB的ActiveContextStackPointer.要不然执行某些用户态的API的时候,那些API没有检查TEB的ActiveContextStackPointer是否为NULL就从中取值,造成崩溃. windows的CreateThread也做了这些事.
第四步:获取当前进程的BaseObject目录,可以是默认的
第五步:ZwCreateThread创建线程对象了.挂起的
第六步:通知csrss进程,有新线程创建了.
第七步:恢复线程的执行.
对于windows的CreateThread还有一些其他的操作,比如判断是否是csrss进程自己在创建线程.vista以后对于远程的线程,还有session的检查等.
代码在:xp/2003 32win7/8/8.1 32/64xSpy@binvul.comxSpy@vxjump.net这些环境下测试过没问题!
步骤虽然繁琐,但是能解决问题就是答案,希望能帮到大家!