分类: LINUX
2010-09-07 20:59:51
在木马四中,我给大家介绍了NT系统下利用远程嵌入DLL的方法实现的无进程木马,有很多朋友来信询问,木马四中的代码在Win9x中能不能直接移植,在这里我只能很抱歉的告诉大家,Win9x并不支持我们使用的CreateRemoteThread函数,所以木马四的方法并不适用于Win9X系统。虽然说Win9X下可以通过注册系统服务的方法瞒过进程管理器,但是仍然有诸多的方法可以进行进程浏览、发现系统级的木马。难道Win9X下真的无法实现远程进程的DLL嵌入?其实虽然Win9x下没有类似CreatRemoteThread这样的函数,但是还是可以通过别的方法来解决,今天我们就来研究一下如何在Win9X中实现远程嵌入DLL。
一个最直接的想法是,我们自己写一个CreateRemoteThread函数给Win9X使用(我的一个朋友Kevin_Qing就已经完成了这样的代码),然后用这个函数来实现LoadLibrary功能,这要求你非常熟悉Windows下进程的内存数据格式,同时还可能会涉及到一些机器硬指令和寄存器操作,其实这样是舍近求远了,回头想想我们的最终目的是要嵌入一个DLL给指定进程,所以我们还是多考虑一下动态链接库本身的特性。(当然,自己实现一个Win9X下的CreateRemoteThread()函数也有其特殊的意义,这个我们将在以后的文章中继续探讨)
在Windows中有一种称为钩子的函数,钩子函数具有非常强大的功能,可以用来侦听、截获系统的事件,windows允许用户安装的钩子函数有很多种:消息钩子、鼠标钩子、键盘钩子……钩子函数是通过SetWindowHook函数(或者它的增强版本SetWindowHookEx)来安装的,被安装的钩子函数一般都属于一个DLL;钩子函数有一个特性:如果钩子回调函数由一个DLL提供,而被Hook的进程并没有加载这个DLL,那么系统会自动给这个进程加载这个钩子DLL。看到这里,我想大家已经非常明白,只要使用SetWindowsHook为目标进程安装一个属于某DLL的钩子函数,就可以强迫目标进程加载这个DLL。
SetWindowsHookEx的函数原型为:
HHOOK SetWindowsHookEx( int idHook, // 钩子类型
HOOKPROC lpfn, // 钩子函数
HINSTANCE hMod, // DLL句柄
DWORD dwThreadId // 线程ID );
其中,第一个参数int idHook为钩子类型,有以下的钩子类型可以选择:
WH_CALLWNDPROC
WH_CALLWNDPROCRET
WH_CBT
WH_DEBUG
WH_FOREGROUNDIDLE
WH_GETMESSAGE
WH_JOURNALPLAYBACK
WH_JOURNALRECORD
WH_KEYBOARD
WH_KEYBOARD_LL
WH_MOUSE
WH_MOUSE_LL
WH_MSGFILTER
WH_SHELL
WH_SYSMSGFILTER
一般来说,需要根据目标钩进程的特性选用特定的钩子类型,对于支持鼠标的进程,可以选用鼠标钩子,对于使用键盘输入的钩子,可以使用键盘钩子,在这里我们选用消息钩子,即WH_GETMESSAGE;
第二个参数HOOKPROC lpfn用来指定钩子回调函数,这个函数将在钩子事件发生时被调用,因为这个函数是由我们木马DLL所提供的,所以被钩进程会自动加载木马DLL模块;
第三个参数HINSTANCE hMod是包含钩子函数的DLL的句柄;
第四个参数DWORD dwThreadId 是与钩子函数相关联的线程ID,如果这个参数设为0,那么钩子函数将与本桌面上的所有线程关联。
假设我们的钩子DLL的句柄为g_hinstDll,我们需要钩住的线程ID为dwThread,钩子回调函数为GetMsgProc(),那么通过下面的代码,就可以为目标进程加载一个MESSAGE钩子,也就是说,我们向目标进程嵌入了包含钩子函数的DLL: SetWindowsHookEx( WH_GETMESSAGE, GetMsgProc, g_hinstDll, dwThreadId ); 通过上面的代码,我们可以将包含GetMsgProc函数的DLL嵌入任何目标进程(只要权限允许),但是这其中有一个不好的地方,就是如果我们的钩子安装进程退出,那么系统也会自动卸载所有的钩子DLL(因为显然已经不再需要钩子函数了),这下完蛋了,我们陷入了一个两难命题:如果保留钩子安装进程,这个DLL木马就不能算是没有进程的,如果不保留钩子安装进程,钩子DLL也不能独立存在……难道我们的Win9x版的DLL木马彻底破产了?其实不然,一个简单的解决方法是多使用一个DLL文件,我们在钩子安装进程和木马DLL之间增加一个钩子DLL,钩子安装进程加载钩子DLL,再从钩子DLL中加载木马DLL,钩子安装进程退出时钩子DLL会随之退出,但是木马DLL并不会退出,这样就实现了进程内木马DLL的常驻。假设钩子安装进程为HookInst.exe,钩子DLL为HookDll.dll,木马DLL为Trojan.dll,目标进程为DestProc.exe,那么木马DLL常驻目标进程的过程如下所示: HookInst.exe ---- [ LoadLibrary ]---- HookDll.dll ---[ 进入 ]--> DestProc.exe HookDll.dll ---- [ LoadLibrary ]---- Trojan.dll ---[ 进入 ]--> DestProc.exe HookInst.exe ---- [ ExitProcess ]----- [ 进程退出 ] DestProc.exe ---- [ FreeLibrary ] ---- HookDll.dll ---[ DLL卸载 ] Trojan.dll ---- [ 继续驻留 ] ---- DestProc.exe 其实如果仔细回顾一下DLL加载、卸载的过程,我们还能想出一个更加简单的方法:我们知道,当一个进程调用LoadLibrary加载某个DLL的时候,系统会自动检查进程是否已经加载了这个DLL,如果还没有加载,就对进程执行一次真正的DLL模块加载,如果该DLL已经被本进程的任意一个线程加载过了,那么系统只是简单的将DLL的加载计数器加一;同样,在卸载DLL的时候,系统先将DLL的加载计数器减一,如果这时计数器值变为0,则将DLL模块真正地从内存中卸载,如果计数器值大于0则什么都不做。看到这里,我们就得到一个在不需要第二个DLL的情况下就能够长久驻留进程内部的木马DLL,因为钩子DLL在钩子安装进程退出的时候会被通过调用一次FreeLibrary卸载,所以如果我们使得钩子安装进程退出时木马DLL的加载计数器>1,那么FreeLibrary就会仅仅将木马DLL的加载计数器减一而不是卸载DLL。如何能让木马DLL的加载计数器>1呢?呵呵,简单得很,在钩子DLL的PROCESS_ATTACH中对自己进行一次LoadLibrary,这时木马DLL的加载计数器等于2,在钩子安装进程退出的时候,木马DLL的加载计数器会被减为一,但是DLL并不会被真正卸载,过程如下所示: HookInst.exe ---- [ LoadLibrary ]---- Trojan.dll ---[ 进入 ]--> DestProc.exe Trojan.dll ---- [ LoadLibrary ]---- Trojan.dll --- [ DLL计数器加一 ] HookInst.exe ---- [ ExitProcess ]----- [ 进程退出 ] DestProc.exe ---- [ FreeLibrary ] ---- Trojan.dll ---[ DLL计数器减一 ] Trojan.dll ---- [ 继续驻留 ] ---- DestProc.exe 至此,一个木马DLL被安装进了目标进程,你可以利用这个DLL假冒目标进程的名义做出总总不为人知的操作,实际上我们将在以后的文章中详细讨论如何利用DLL木马来重用端口对抗防火墙的包过滤。