通告例程 VC使用逦告例程嚣嚣躺隧硎口LL一瞄

■soc…ket一;………一,至于SSDTShadowHOOK~]ISSDTShadow测量与恢复.还请你们继续关注本文的后续文章。(编辑提醒:本文涉及的代码,已收录入本期光碟刊物相关栏目;也可以到黑防官方网站下载)后置知识:VC使用逦告类库嚣嚣∞■瓣_-囊嘲赣——l–_—-幽-_—,——__·——簟i一篮蓊嚣躺隧硎口LL一随着隐藏进程监测技术的进步,木马也转来表明容许或是拒绝正在执行的操作,而通告而向无进程方向发展。一般,它们会将代码编函数只是告知驱动一个操作正在发生。一般而译成一个DLL(在本文中,DLL特指用户模式下言,通告函数没有返回值,因而驱动未能阻绝的动态链接库)或则一个驱动而随其他进程加执行正在执行的操作{VistaServicePack1新载f驱动被加载到System进程).所以怎样监控引入的PsSetCreateProcessNotifyRoutineEx是一个特驱动以及DLL加载成为了防马的重要一环。本文例,通过该函数所注册的通告函数将介绍一种通过使用WindowsNT系统所提供的createPr0CessN0t.fYEX,可以通过更改参数注册通告类库来监控驱动以及DLL加载的方式。

Createlnfo的成员CreationStatus来控制进程创建.在驱动中存在两种相像的可以被注册的例这有可能是为了在函数名上往前兼容而造成程反弹(Callback)以及通告(NOt…Cation)。的)。并且甚至于在wDK的说明文档中.这两其中.反弹函数拥有返回值,可以通过返回值个术语也常常被混用。广义上而言.通告也是—圄l’一。PR叩RAMM。)栏罢目编辑)sOcke¨—■圈瞄■●目一El曩瞄■_1_.一种反弹,但这些反弹不会对函数执行形成影可以通过CON丁AfNG~RECORD(fmagefnfo,IMAGEINFOEX响,因而,本文将会把注册的加载模块通告函~—,Imagelnfo)得至lIMAGE—INFO—EX数称之为反弹。结构的数据,其中多出了FiIeObject,我们可以直接通过FiIeObject便捷的获取信息。以下只讨注册回滑论ViSta之前系统的情况。注册模块加载反弹通过PSSetLOadJmage对于DLL(包括EXE)的加载,可以分为三NotifyRoutine(LoadImageNotifyRoutine)即可完种情况。

成.然后每当系统中有新的驱动或则DLL被加①对于EXE文件自身载,LoadlmageNotifyRoutine都会被调用,其参数因为EXE以及ntdlI.dlI是由系统在进程开始执Fu…mageN8me指明了正在加载的模块文件名行之前就映射入进程空间的,因而这两个文件f然而信息不一定完全,具体后文会提到)的加载反弹被系统特殊处理f普通的DLL加载是Processld:J~明了加载该模块的进程PID,Imagelnfo通过ZwMapViewOfSection(如未特殊指明,本的成员SystemModelnf时旨明了是否为内核模块文中的zWMaPView0fSecti0n均特指ntdll!(通常为驱动)。ZwMapViewOfSection)加载的.而EXE是在创建进程空间然后通过MmtiaIizeProcessAddress梗块文件名Space映射入进程空间的ntdl】.dlI是在进程创建1)内核模块的文件名了进程空间以后由PsMapSystemDII映射入进程空对于内核模块而言,LoadlmageNotifyRoutine间的(均在PspcreatePr。

cess(以及该函数所调用的参数FufIImageName即指明了该内核模块的文的函数)中完成))。件名,但并不是我们常见的DOS风格的文件名通过在LoadlmageNotifyRoutine上下断.可以(DOS风格的文件名是指C:\XXXXXX”这样的见到如下调用堆栈文件名),通过一些转换即可获取该模块的DOS风格文件各对于\7\X:\Xxx\Xxx,除去前缀“\7\”即可(前面的\77”实际上是DOSDevices”这个符号链接的目标):对于\SYStemROOt\XXX,将“\SYstemROOt\替一层一层向下回溯:换为Windows目录(SystemRoot实质上是一个符nt!PsCalllmageNotifyRoutines+0x2b:号链接,目标是windOWS目录)对于pus}1dwordptrfebp410410h】pushdwordptrfebp+OCh]“\wINDOWS\system32\xXX”,在字符串后端pushdwordptre【bp+8】加上windOWS所在分区的c盘即可。

//反弹爵敦钩参敦Fuu|mage№H,也是Psc口Lu玎ngB这是一项其实冗长但并不困难的工作,本NifyI的豢一个参数文不多讨论。对于1、2两种情况.均可使用后calleax//调用曰调函数文所提及的转换NT风格路径的方式来转换为再向下回溯一层DOS风格路径。2)DLL的文件名虽然本文主要讨论的是模块加载,但因为创建进程时,EXE自身也会被系统作为模块的加载来处理,换句话说,也会引起反弹,为此,EXE的加载将在此处一起被讨论。从Vista起,IMAGE—INFO结构中多了成员ExtendedlnfoPresent当ExtendedlnfoPresent=1时,√l|毫_li老矗]I瞳__匕l_鲞曩I孟l_善磊:、::”;………一为了便捷编码,我没有对EXE以及ntdII做特殊处理,而是将EXE、ntdIl以及其他模块使用相同的方式获取文件名(详见后文)。③对于普通DLL无论是程序启动时加载的DLL(ntdlI.dll除外,其余的启动时加载的dIl均是由ntdlI.dIl力口载的)还是后来加载以及注入的DLL.均是通过ZwMaPViewOfSection来加载的。

同样,我们先是MmGetFiIeNameF0rSecti0n传出的查看调用堆栈:FileNamelnfo,其内容是EXE的完整路径(NT风格路径,类似于\DeviceHarddiSkVOlume1\XXX,NT风格路径通过转换可以得到DOS风格路径(转换方式将在后文提及))。②对于ntd1【.dll对于ntdII而言,反弹同样是从DbgkcreateThread发起的,查看调用堆栈LoadlmageNotifyDdver!LoadhnageNotifyRoutinentrPsCalltmageNotifyRoutilleS+0x36nt!DbgkCreateI’hread+0xl25因为MiMapViewOflmageSection的反汇编太nt!PspUserThreadStartupt0x9d长因而不再贴出其内部通过COntrOlAreant!KiThreadStartup10xl6(由MmMapViewOfSection形成)->FiIePointer得回溯至1DbgkcreateThread到被映射的文件的FiIeObject,之后将nt!DbgkCreateThreadt0xre:pushoffsetnt!DbgkIXSc~tionToFilcHandle40x70FiIeObject一>FileName作为Fu…mageName传给(80638f96)PScalllmageN0tifYR0ut_ne,因而得到的//妥始他讷UNICODE牟猜串Fu…mageName没有c盘,只有路径以及文件名leaeax,lebp—OE4h】pushoax(类似于”\wINDOWS\SYStem32\kerneI32.callnt!Rtl[nitUnicodeString(8052afaf22c)dIl),其实这样的信息不够找到一个文件,因而我们须要通过其他方式来获取文件名。

图片[1]-通告例程 VC使用逦告例程嚣嚣躺隧硎口LL一瞄-唐朝资源网

nt!DbgkCreateThread40xl0f:我们晓得,ZwOueryVirtuaIMemory可以按照leaeax,[ebp2Ch]VA(VirtuaIAddress,虚拟地址)来获取映射pusheaxpushdwordptr[esiI8484h】到该地址的文件的文件名(其内部会遍历VADleaeax,[ebp0E4h]树找到该VA对应的树枝,然后得到//上面使用RtJ【nitUn’codestring韧始化的字符串COntr0JArea因而得到FiIe0bject),因而,从pusheax理论上讲,我们可以通过ZwQueryVirtuaIMemoryacllnt!PsCalllmageNotffyRoutines(805c5640)//调用反弹(ZWCurrentPr0Cess(),MemorYMaPPedkd>dunt!DbgklxSectionToFileHandle+0x70FilenamelnformationlmageFiIeName,BufferSize,’\,SystemRoot\System32\ntdl1.dli”&BufferSize)来获得文件名。

然而实际操作后会//速就是被韧始化的卒待串发觉,我们得不到任何输出,加载模块的线程可以看出,对于ntdlldl1.Fu…mageName被也不会继续执行。查看该线程的调用堆栈硬编码为”\SystemRoot\System32\ntdl1.dlI根据前文处理内核模块文件名的方式,可以转换为DOS风格路径。困訾曩“、\三!!●●_。)栏目编辑)sOcket>强嚣豳瞄目—E■●显然,在MmMaPViewOfSection中,AddressCreationLock早已被获取了,而快速互斥体不能被递归的获取(请注意快速互斥体与互斥体的区别)因而会造成死锁,所以,在调用ZwQueryVirtualMemory之前通告例程,我们须要通过某种方式来防止再度试图获取这个互斥体。拦截睡块加载无论是内核模块还是DLL,它们的人口点就会返回一个值来表明初始化成功或是失败,因Object在等待某个对象变为讯号态,而KeWait此我们可以更改人口点的代码使其直接返回F0rsingleObject的调用是由NtQueryVirtualMemory失败通告例程,系统便会撤消之前所做的操作.使这次想要获取某个快速互斥体而导致的。

我们回溯加载模块失败。~JlNtQueryVirtualMemory.其它问题因为ZwQueryVirtuaIMemory不一定被导入(对于那些未文档化的函数,不同系统导入情况不同,例如对于我所使用的windowsServer2008R2ZwQueryVirtua1Memory就被导入了,而且对于WindowsXP而言,该函数就没有被导入),所以我们须要自己定位或则自己实现这个函数。因为每次查询模块文件名都须要分配缓冲区,而一个进程启动免不了大量的加载模块,查看EPROCESS结构假如每次都分配/释放,难免引起显存碎片,增加系统性能。具体实瑰1)ZwQueryVirtuaIMemory实现这个函数很短,我们可以自行实现这个函可以看出.NtQueryVirtuaIMemory想要获取AddressCreationLock。同时,从调用堆栈可知我们的反弹是由MmMapViewOfSection–层一层引起的,反汇编MmMapViewOfSection可得如下结果:从IA32开发指南可以获知,相同特权级发生中断时,CPU所执行的操作为(这个中断不涉及错误码):依次将EflagS、CS、EjP入栈,之后转跳到中断处理类库。

入栈ElP,之后转跳即是一个Ca【l因而,以上代码模拟了一个中断现—200912饕窑精富线■■曝矗_)栏目编辑)s0cket)场,之后通过KiSystemService转而调用NtQuery同时.为了得~ljZwQueryVirtuaIMemory的Serviceld我们须要加载ntdl1.dII,并从中找到VirtualMemory。我们也可以模拟一个,ntd_jIzwQuerYVirtuaIMemorY。因为ntd…ZwQueryVirtuaIMemory的第一条指令是moveaxServiceldZwQueryVirtuaIMemory”.—,因而我们从*rene【rpret—cast

© 版权声明
THE END
喜欢就支持一下吧
点赞247赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容