C#_HOOK

C#_HOOK
C#_HOOK

C#中实现Hook

目前的程序中想要添加Hook,截获键盘按键消息,所以上网找了一下关于C#下Hook的东西。发现很多人都在说在C#中添加Hook不成功和不稳定,而建议使用C++封一个Dll给C#使用。

,可喜的是最后我还是成功的在程序中使用C#添加了Hook,经过测试还是没有什么问题的。

进行Hook需要使用三个API函数

SetWindowsHookEx 进行Hook的注册

UnhookWindowsHookEx 取消已经注册的Hook

CallNext HookEx 将消息传递给下一个Hook函数

看一下定义

1 [DllImport("user32.dll")]

2private static extern IntPtr SetWindowsHookEx(

3 HookType code, HookProc func, IntPtr instance, int threadID);

4

5 [DllImport("user32.dll")]

6private static extern int UnhookWindowsHookEx(IntPtr hook);

7

8 [DllImport("user32.dll")]

9private static extern int CallNext HookEx(

10 IntPtr hook, int code, IntPtr wParam, ref KBDLLHOOKST RUCT lPara m);

我们需要定义一个delegate来接收消息

1private delegate int HookProc(int code, IntPtr wParam, ref KBDLLHOOKS TRUCT lParam);

定义两个event提供给外界使用

1public delegate void HookEventHandler(object sender, HookEventArgs e); 2public event HookEventHandler KeyDown;

3public event HookEventHandler KeyUp;

4

因为要接收的是键盘的消息所以要定义一些消息,和我们要接收的结构。

1public class HookEventArgs : EventArgs

2 {

3// using Windows.Forms.Keys instead of Input.Key since the Form s.Key

s m aps

4 // to the Win32 KBDLLHOOKSTRUCT virtual key member, where Input.K ey does not

5public Keys Key;

6public bool Alt;

7public bool Control;

8public bool Shift;

9

10public HookEventArgs(UInt32 keyCode)

11 {

12// detect what m odifier keys are pressed, using

13 // Windows.Forms.Control.ModifierKeys instead of Keyboard.Modifier s

14 // since Keyboard.Modifiers does not correctly get the state of the

15 // m odifier keys when the application does not have focus

16this.Key = (Keys)keyCode;

17this.Alt = (System.Windows.Forms.Control.ModifierKeys & Keys.Alt) !

= 0;

18this.Control = (System.Windows.Forms.Control.ModifierKeys & Keys. Control) != 0;

19this.Shift = (System.Windows.Forms.Control.ModifierKeys & Keys.Shi ft) != 0;

20 }

21 }

1private enum HookType : int

2 {

3 WH_JOURNALRECORD = 0,

4 WH_JOURNALPLAYBACK = 1,

5 WH_KEYBOARD = 2,

6 WH_GETMESSAGE = 3,

7 WH_CALLWNDPROC = 4,

8 WH_CBT = 5,

9 WH_SYSMSGFILTER = 6,

10 WH_MOUSE = 7,

11 WH_HARDWARE = 8,

12 WH_DEBUG = 9,

13 WH_SHELL = 10,

14 WH_FOREGROUNDIDLE = 11,

15 WH_CALLWNDPROCRET = 12,

16 WH_KEYBOARD_LL = 13,

17 WH_MOUSE_LL = 14

18 }

19

20public struct KBDLLHOOKSTRUCT

21 {

22public UInt32 vkCode;

23public UInt32 scanCode;

24public UInt32 flags;

25public UInt32 time;

26public IntPtr extraInfo;

27 }

关键的在这里注册Hook

1private void Install()

2 {

3if (_hookHandle != IntPtr.Zero)

4return;

5

6 Module[] list = System.Reflection.Assembly.GetExecutingAssembly(). GetModules();

7 System.Diagnostics.Debug.Assert(list !=null && list.Length > 0);

8

9 _hookHandle = SetWindowsHookEx(_hookType,

10 _hookFunction, Marshal.GetHINSTANCE(list[0]), 0);

11

12 }

哦,还有HookType _hookType =HookType.WH_KEY BOARD_LL; 因为要截获键盘消息

还有_hookFunction =new HookProc(HookCallback);

其实最关键的是Marshal.GetHINSTANCE(list[0])得到当前程序的instance,这样这个Hoo k就是全局的Hook,这个位置也可以是null,这样就不是全局Hook。

有个很奇怪的现象就是这个函数,在调试状态执行不能成功,而做成Release以后运行成功,

所以你在做程序时,不要因为调试失败而对这个函数有怀疑,编一个Release版本的程序,独立运行再试一下。我使用的环境是VS2005 +Vista。

接收消息的函数

1private int HookCallback(int code, IntPtr wParam, ref KBDLLHOOKST RUC T lParam)

2 {

3if (code < 0)

4return CallNextHookEx(_hookHandle, code, wParam, ref lParam); 5

6if ((lParam.flags & 0x80) != 0 && this.KeyUp != null)

7this.KeyUp(this, new HookEventArgs(lParam.vkCode));

8

9if ((lParam.flags & 0x80) == 0 && this.KeyDown != null)

10 {

11this.KeyDown(this, new HookEventArgs(lParam.vkCode));

12if (lParam.vkCode == 44)

13 {

14return 1;

15 }

16 }

17

18return CallNextHookEx(_hookHandle, code, wParam, ref lParam);

19 }

这里会区分KeyUp和KeyDown,注意一定要调用CallNextHookEx,这样会将这个消息在系统中继续传递,这很重要。除非你想阻止这个消息,也不希望其他程序再处理这个消息。

下面最后的操作,释放注册。

1private void Uninstall()

2 {

3if (_hookHandle != IntPtr.Zero)

4 {

5 UnhookWindowsHookEx(_hookHandle);

6 _hookHandle = IntPtr.Zero;

7 }

8 }

Ok,完成了。

类似的问题好多............前几天就有人文这个问题。你也不说明什么问题就发代码...

新建一个form4窗体.增加2个button,增加事件。。然后复制代码

其实不一样的地方就是红色的地方

using System;

using System.Collections.Generic;

using https://www.360docs.net/doc/6317021236.html,ponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;

using System.Reflection;

using System.Diagnostics;

namespace WindowsApplication1

{

///

/// Description of MainForm.

///

public partial class Form4 : Form

{

//委托

public delegate int HookProc(int nCode, int wParam, IntPtr lParam);

static int hHook = 0;

public const int WH_KEYBOARD_LL = 13;

//LowLevel键盘截获,如果是WH_KEYBOARD=2,并不能对系统键盘截取,Acrobat

Reader会在你截取之前获得键盘。

HookProc KeyBoardHookProcedure;

//键盘Hook结构函数

[StructLayout(LayoutKind.Sequential)]

public class KeyBoardHookStruct

{

public int vkCode;

public int scanCode;

public int flags;

public int time;

public int dwExtraInfo;

}

#region DllImport

//设置钩子

[DllImport("user32.dll")]

public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

//抽掉钩子

public static extern bool UnhookWindowsHookEx(int idHook);

[DllImport("user32.dll")]

//调用下一个钩子

public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);

[DllImport("kernel32.dll")]

public static extern int GetCurrentThreadId();

[DllImport("kernel32.dll")]

public static extern IntPtr GetModuleHandle(string name);

#endregion

#region 自定义事件

public void Hook_Start()

{

// 安装键盘钩子

if (hHook == 0)

{

KeyBoardHookProcedure = new HookProc(KeyBoardHookProc);

//hHook = SetWindowsHookEx(2,

// KeyBoardHookProcedure,

// GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), GetCurrentThreadId());

hHook = SetWindowsHookEx(WH_KEYBOARD_LL,

KeyBoardHookProcedure,

GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);

//如果设置钩子失败.

if (hHook == 0)

{

Hook_Clear();

//throw new Exception("设置Hook失败!");

}

}

}

//取消钩子事件

public void Hook_Clear()

{

bool retKeyboard = true;

if (hHook != 0)

{

retKeyboard = UnhookWindowsHookEx(hHook);

hHook = 0;

}

//如果去掉钩子失败.

if (!retKeyboard) throw new Exception("UnhookWindowsHookEx failed.");

}

//这里可以添加自己想要的信息处理

public static int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam)

{

if (nCode >= 0)

{

KeyBoardHookStruct kbh = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct));

if (kbh.vkCode == (int)Keys.S && (int)Control.ModifierKeys == (int)Keys.Control) // 截获F8 {

MessageBox.Show("快捷键已拦截!不能保存!");

return 1;

}

if (kbh.vkCode == (int)Keys.Y

&& (int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt) //截获Ctrl+Alt+Y

{

//MessageBox.Show("不能全部保存!");

return 1;

}

if (kbh.vkCode == (int)Keys.X)

{

MessageBox.Show("不能全部保存!");

return 1;

}

}

return CallNextHookEx(hHook, nCode, wParam, lParam); }

#endregion

public Form4()

{

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e) {

Hook_Start();

}

private void button2_Click(object sender, EventArgs e) {

Hook_Clear();

}

}

}

HOOK专题

目录

?基本概念

?运行机制

?钩子类型

?作者

基本概念

钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。

钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控

制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

运行机制

1、钩子链表和钩子子程:

每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。这个列表的指针指向指定的,应用程序定义的,被Hook子程调用的回调函数,也就是该钩子的各个处理子程。当与指定的Hook 类型关联的消息发生时,系统就把这个消息传递到Hook子程。一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。

Windows 并不要求钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Hook链表。如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。

钩子子程是一个应用程序定义的回调函数(CALLBACK Function),不能定义成某个类的成员函数,只能定义为普通的C函数。用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。

钩子子程必须按照以下的语法:

LRESULT CALLBACK HookProc

(

int nCode,

WPARAM wParam,

LPARAM lParam

);

HookProc是应用程序定义的名字。

nCode参数是Hook代码,Hook子程使用这个参数来确定任务。这个参数的值依赖于Hook类型,每一种Hook都有自己的Hook代码特征字符集。

wParam和lParam参数的值依赖于Hook代码,但是它们的典型值是包含了关于发送或者接收消息的信息。

2、钩子的安装与释放:

使用API函数SetWindowsHookEx()把一个应用程序定义的钩子子程安装到钩子链表中。SetWindowsHookEx函数总是在Hook链的开头安装Hook子程。当指定类型的Hook监视的事件发生时,系统就调用与这个Hook关联的Hook链的开头的Hook子程。每一个Hook链中的Hook子程都决定是否把这个事件传递到下一个Hook子程。Hook子程传递事件到下一个Hook子程需要调用CallNextHookEx函数。

HHOOK SetWindowsHookEx(

int idHook, // 钩子的类型,即它处理的消息类型

HOOKPROC lpfn, // 钩子子程的地址指针。如果dwThreadId参数为0

// 或是一个由别的进程创建的线程的标识,

// lpfn必须指向DLL中的钩子子程。

// 除此以外,lpfn可以指向当前进程的一段钩子子程代码。

// 钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。

HINSTANCE hMod, // 应用程序实例的句柄。标识包含lpfn所指的子程的

DLL。

// 如果dwThreadId 标识当前进程创建的一个线程,

// 而且子程代码位于当前进程,hMod必须为NULL。

// 可以很简单的设定其为本应用程序的实例句柄。

DWORD dwThreadId // 与安装的钩子子程相关联的线程的标识符。

// 如果为0,钩子子程与所有的线程关联,即为全局钩子。

);

函数成功则返回钩子子程的句柄,失败返回NULL。

以上所说的钩子子程与线程相关联是指在一钩子链表中发给该线程的消息同时发送给钩子子程,且被钩子子程先处理。

在钩子子程中调用得到控制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须调用另外一个SDK中的API函数CallNextHookEx来传递它,以执行钩子链表所指的下一个钩子子程。这个函数成功时返回钩子链中下一个钩子过程的返回值,返回值的类型依赖于钩子的类型。这个函数的原型如下:

LRESULT CallNextHookEx

(

HHOOK hhk;

int nCode;

WPARAM wParam;

LPARAM lParam;

);

hhk为当前钩子的句柄,由SetWindowsHookEx()函数返回。

NCode为传给钩子过程的事件代码。

wParam和lParam 分别是传给钩子子程的wParam值,其具体含义与钩子类型有关。

钩子函数也可以通过直接返回TRUE来丢弃该消息,并阻止该消息的传递。否则的话,其他安装了钩子的应用程序将不会接收到钩子的通知而且还有可能产生不正确的结果。

钩子在使用完之后需要用UnHookWindowsHookEx()卸载,否则会造成麻烦。释放钩子比较简单,UnHookWindowsHookEx()只有一个参数。函数原型如下:

UnHookWindowsHookEx

(

HHOOK hhk;

);

函数成功返回TRUE,否则返回FALSE。

3、一些运行机制:

在Win16环境中,DLL的全局数据对每个载入它的进程来说都是相同的;而在Win32环境中,情况却发生了变化,DLL函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。当进程在载入DLL时,操作系统自动把DLL地址映射到该进程的私有空间,也就是进程的虚拟地址空间,而且也复制该DLL的全局数据的一份拷贝到该进程空间。也就是说每个进程所拥有的相同的DLL的全局数据,它们的名称相同,但其值却并不一定是相同的,而且是互不干涉的。

因此,在Win32环境下要想在多个进程中共享数据,就必须进行必要的设置。在访问同一个Dll的各进程之间共享存储器是通过存储器映射文件技术实现的。也可以把这些需要共享的数据分离出来,放置在一个独立的数据段里,并把该段的属性设置为共享。必须给这些变量赋初值,否则编译器会把没有赋初始值的变量放在一个叫未被初始化的数据段中。

#pragma data_seg预处理指令用于设置共享数据段。例如:

#pragma data_seg("SharedDataName")

HHOOK hHook=NULL;

#pragma data_seg()

在#pragma data_seg("SharedDataName")和#pragma data_seg()之间的所有变量将被访问该Dll 的所有进程看到和共享。再加上一条指令#pragma

comment(linker,"/section:.SharedDataName,rws"),那么这个数据节中的数据可以在所有DLL的实例之间共享。所有对这些数据的操作都针对同一个实例的,而不是在每个进程的地址空间中都有一份。

当进程隐式或显式调用一个动态库里的函数时,系统都要把这个动态库映射到这个进程的虚拟地址空间里(以下简称"地址空间")。这使得DLL成为进程的一部分,以这个进程的身份执行,使用这个进程的堆栈。

4、系统钩子与线程钩子:

SetWindowsHookEx()函数的最后一个参数决定了此钩子是系统钩子还是线程钩子。

线程勾子用于监视指定线程的事件消息。线程勾子一般在当前线程或者当前线程派生的线程内。

系统勾子监视系统中的所有线程的事件消息。因为系统勾子会影响系统中所有的应用程序,所以勾子函数必须放在独立的动态链接库(DLL) 中。系统自动将包含"钩子回调函数"的DLL映射到受钩子函数影响的所有进程的地址空间中,即将这个DLL注入了那些进程。

几点说明:

(1)如果对于同一事件(如鼠标消息)既安装了线程勾子又安装了系统勾子,那么系统会自动先调用线程勾子,然后调用系统勾子。

(2)对同一事件消息可安装多个勾子处理过程,这些勾子处理过程形成了勾子链。当前勾子处理结束后应把勾子信息传递给下一个勾子函数。

(3)勾子特别是系统勾子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装勾子,在使用完毕后要及时卸载。

钩子类型

每一种类型的Hook可以使应用程序能够监视不同类型的系统消息处理机制。下面描述所有可以利用的Hook类型。

1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks

WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你可以监视发送到窗口过程的消息。系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC Hook子程,并且在窗口过程处理完消息之后调用WH_CALLWNDPROCRET Hook子程。

WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCT结构,再传递到Hook子程。CWPRETSTRUCT结构包含了来自处理消息的窗口过程的返回值,同样也包括了与这个消息关联的消息参数。

2、WH_CBT Hook

在以下事件之前,系统都会调用WH_CBT Hook子程,这些事件包括:

1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件;

2. 完成系统指令;

3. 来自系统消息队列中的移动鼠标,键盘事件;

4. 设置输入焦点事件;

5. 同步系统消息队列事件。

Hook子程的返回值确定系统是否允许或者防止这些操作中的一个。

3、WH_DEBUG Hook

在系统调用系统中与其他Hook关联的Hook子程之前,系统会调用WH_DEBUG Hook子程。你可以使用这个Hook来决定是否允许系统调用与其他Hook关联的Hook子程。

4、WH_FOREGROUNDIDLE Hook

当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE Hook执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就会调用WH_FOREGROUNDIDLE Hook子程。5、WH_GETMESSAGE Hook

应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及其他发送到消息队列中的消息。6、WH_JOURNALPLAYBACK Hook

WH_J OURNALPLAYBACK Hook使应用程序可以插入消息到系统消息队列。可以使用这个Hook回放通过使用WH_J OURNALRECORD Hook记录下来的连续的鼠标和键盘事件。只要

WH_J OURNALPLAYBACK Hook已经安装,正常的鼠标和键盘事件就是无效的。

WH_J OURNALPLAYBACK Hook是全局Hook,它不能象线程特定Hook一样使用。

WH_J OURNALPLAYBACK Hook返回超时值,这个值告诉系统在处理来自回放Hook当前消息之前需要等待多长时间(毫秒)。这就使Hook可以控制实时事件的回放。

WH_J OURNALPLAYBACK是system-wide local hooks,它們不會被注射到任何行程位址空間。

7、WH_JOURNALRECORD Hook

WH_J OURNALRECORD Hook用来监视和记录输入事件。典型的,可以使用这个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook来回放。

WH_J OURNALRECORD Hook是全局Hook,它不能象线程特定Hook一样使用。

WH_J OURNALRECORD是system-wide local hooks,它們不會被注射到任何行程位址空間。

8、WH_KEYBOARD Hook

在应用程序中,WH_KEYBOARD Hook用来监视WM_KEYDOWN and WM_KEYUP消息,这些消息通过GetMessage or PeekMessage function返回。可以使用这个Hook来监视输入到消息队列中的键盘消息。

9、WH_KEYBOARD_LL Hook

WH_KEYBOARD_LL Hook监视输入到线程消息队列中的键盘消息。

10、WH_MOUSE Hook

WH_MOUSE Hook监视从GetMessage 或者PeekMessage 函数返回的鼠标消息。使用这个Hook 监视输入到消息队列中的鼠标消息。

11、WH_MOUSE_LL Hook

WH_MOUSE_LL Hook监视输入到线程消息队列中的鼠标消息。

12、WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks

WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通过安装了Hook子程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook监视所有应用程序消息。

WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间过滤消息,这等价于在主消息循环中过滤消息。

通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循环里一样。

13、WH_SHELL Hook

外壳应用程序可以使用WH_SHELL Hook去接收重要的通知。当外壳应用程序是激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELL Hook子程。

WH_SHELL 共有5钟情況:

1. 只要有个top-level、unowned 窗口被产生、起作用、或是被摧毁;

2. 当Taskbar需要重画某个按钮;

3. 当系统需要显示关于Taskbar的一个程序的最小化形式;

4. 当目前的键盘布局状态改变;

5. 当使用者按Ctrl+Esc去执行Task Manager(或相同级别的程序)。

按照惯例,外壳应用程序都不接收WH_SHELL消息。所以,在应用程序能够接收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function注册它自己。

我想用C#实现对指定进程进行HOOK,然后控制程序里面的滚动条。比如浏览器、WORD甚至QQ,让里面的滚动条上滚或下滚。请问该设置鼠标钩子然后发送按下左键并轮转中键的信号吗??请问大虾怎么实现,有其他思路也行!!

static LRESULT CALLBACK ShellHookCallback(int code, WPARAM wparam, LPARAM lparam)

{

if (code >= 0)

{

UINT msg = 0;

if (code == HSHELL_ACTIV A TESHELLWINDOW)

msg=RegisterWindowMessage("CUSTM_HOOK_HSHELL_ACTIV A TESHELLWINDOW");

else if (code == HSHELL_GETMINRECT)

msg = RegisterWindowMessage("CUSTM_HOOK_HSHELL_GETMINRECT");

else if (code == HSHELL_LANGUAGE)

msg = RegisterWindowMessage("CUSTM_HOOK_HSHELL_LANGUAGE");

else if (code == HSHELL_REDRAW)

msg = RegisterWindowMessage("CUSTM_HOOK_HSHELL_REDRA W");

else if (code == HSHELL_TASKMAN)

msg = RegisterWindowMessage("CUSTM_HOOK_HSHELL_TASKMAN");

else if (code == HSHELL_WINDOWACTIV A TED)

msg=RegisterWindowMessage("CUSTM_HOOK_HSHELL_WINDOWACTIV A TED");

else if (code == HSHELL_WINDOWCREA TED)

msg=RegisterWindowMessage("CUSTM_HOOK_HSHELL_WINDOWCREA TED");

else if (code == HSHELL_WINDOWDESTROYED)

msg=RegisterWindowMessage("CUSTM_HOOK_HSHELL_WINDOWDESTROYED");

HWND dstWnd = (HWND)GetProp(GetDesktopWindow(), "CUSTM_HOOK_HWND_SHELL");

if (msg != 0)

{

SendNotifyMessage(dstWnd, msg, wparam, lparam);

}

}

return CallNextHookEx(hookShell, code, wparam, lparam);

}

只有键盘和鼠标可以在托管代码中实现全局钩子,否则要通过C++写DLL,原因貌似.net的垃圾回收机制?思路可以这样

在DLL里面

1)用SetProp函数将C#写的一个窗口设置成特别的属性,比如:

SetProp(GetDesktopWindow(), "FLAG_WND", target);

2)挂上钩子,捕捉到相应的Hook code后,用RegisterWindowMessage函数注册信息,然后用SendNotifyMessage函数将该信息发送给特定属性的托管窗口

hook的使用实例

在网上找了好久都没有找到消息hook的实例,下面是我的例子给大家分享一下 下面是dll中的代码: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //我的经验,编译的时候会提示DllMain,已在DllMain.cpp中定义,把DllMain.cpp从源文件里删掉就好了 #include "stdafx.h" #include HHOOK hkey=NULL; HINSTANCE h_dll; #pragma data_seg(".MySec") //定义字段,段名.MySec HWND h_wnd=NULL; #pragma data_seg() #pragma comment(linker,"/section:.MySec,RWS") BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) { h_dll=hinstDLL; // MessageBox(0,"运行dllman","",MB_OK); return TRUE; } LRESULT CALLBACK my_test(int nCode,WPARAM wParam,LPARAM iParam)// { /* if(nCode==HC_ACTION) { MessageBox(0,"成功!!","标题",MB_OK); } else { MessageBox(0,"失败!!","标题",MB_OK); } */ MessageBox(0,"被截取","",MB_OK); UnhookWindowsHookEx(hkey); return 1; } void SetHook(HWND hwnd) { h_wnd = hwnd; // MessageBox(0,"运行sethook","",MB_OK); hkey=SetWindowsHookEx(WH_KEYBOARD,my_test,h_dll,0); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 下面是EXE的代码:有很多头文件是没用上的,我个人习惯都带着- -,虽然这不是好习惯

通过DLL劫持技术HookAPI

DLL劫持技术 当一个可执行文件运行时,Windows加载器将可执行模块映射到进程的地址空间中,加载器分析可执行模块的输入表,并设法找出任何需要的DLL,并将它们映射到进程的地址空间中。 由于输入表中只包含DLL名而没有它的路径名,因此加载程序必须在磁盘上搜索DLL文件。首先会尝试从当前程序所在的目录加载DLL,如果没找到,则在Windows系统目录中查找,最后是在环境变量中列出的各个目录下查找。利用这个特点,先伪造一个系统同名的DLL,提供同样的输出表,每个输出函数转向真正的系统DLL。程序调用系统DLL时会先调用当前目录下伪造的DLL,完成相关功能后,再跳到系统DLL同名函数里执行,如图18.3所示。这个过程用个形象的词来描述就是系统DLL被劫持(hijack)了。 图18.3 DLL劫持技术演示 利用这种方法取得控制权后,可以对主程序进行补丁。此种方法只对除kernel32.dll、ntdll.dll等核心系统库以外的DLL有效,如网络应用程序的ws2_32.dll、游戏程序中的d3d8.dll,还有大部分应用程序都调用的lpk.dll,这些DLL都可被劫持。 利用第5章5.6.2节提供的CrackMeNet.exe来演示一下如何利用劫持技术制作补丁,目标文件用Themida v1.9.2.0加壳保护。 1.补丁地址 去除这个CrackMe网络验证方法参考第5章5.6.2节,将相关补丁代码存放到函数PatchProcess()里。例如将401496h改成:00401496 EB 29 jmp short 004014C1

补丁编程实现就是: unsigned char p401496[2] = {0xEB, 0x29}; WriteProcessMemory(hProcess,(LPVOID)0x401496, p401496, 2, NULL); p401496这个数组的数据格式,可以用OllyDbg插件获得,或十六进制工具转换。例如Hex Workshop打开文件,执行菜单“Edit/Copy As/Source”即可得到相应的代码格式。 2.构建输出函数 查看实例CrackMeNet.exe输入表,会发现名称为“ws2_32.dll”的DLL,因此构造一个同名的DLL来完成补丁任务。伪造的ws2_32.dll 有着真实ws2_32.dll一样的输出函数,完整源码见光盘映像文件。实现时,可以利用DLL模块中的函数转发器来实现这个目标,其会将对一个函数的调用转至另一个DLL中的另一个函数。可以这样使用一个pragma指令: #pragma comment(linker, "/EXPORT:SomeFunc=DllWork.someOtherFunc") 这个pragma告诉链接程序,被编译的DLL应该输出一个名叫SomeFunc的函数。但是SomeFunc函数的实现实际上位于另一个名叫SomeOtherFunc的函数中,该函数包含在称为DllWork. dll的模块中。 如果要达到劫持DLL的目的,生成的DLL输出函数必须与目标DLL输出函数名一样。本例可以这样构造pragma指令: #pragma comment(linker, "/EXPORT:WSAStartup=_MemCode_WSAStartup,@115") 编译后的DLL,会有与ws2_32.dll同名的一个输出函数WSAStartup,实际操作时,必须为想要转发的每个函数创建一个单独的pragma 代码行,读者可以用工具AheadLib或用其他办法,将ws2_32.dll输出函数转换成相应的pragma指令。 当应用程序调用伪装ws2_32.dll的输出函数时,必须将其转到系统ws2_32.dll中,这部分的代码自己实现。例如,WSAStartup输出函数构造如下:

VB外挂之HOOK技术的最详细教程

vb外挂之HOOK技术终极详细解说 By:史上最大小强 很多学习vb的人都想学习外挂及hook,我在网上也找到了一段程序,后台键盘记录外挂,其实网上大多数流传的HOOK代码都跟这段代码几乎一个出处。网上有关于这些代码的解释,但是关键部分根本就没解释,等于没说。 下面的程序解释得很详细。有的地方全属个人看法,不过还是值得一看。不对的地方欢迎大家指出。当然,高手勿笑。 好吧,正式我们的hook学习。 Hook并不神秘,它说到底就是通过调用API函数在消息队列中安装钩子,实现截获消息,处理消息的功能。在这里,我浅浅的讲讲windows的消息机制。比如,我们按键盘的某个键时,系统就会生成一个消息到系统的消息队列,系统再发送到应用程序消息队列中,windows有不同的消息队列。对于键盘钩子,是安装在系统的消息队列中。 看程序:(以下程序在模块中,呵呵,工程-----添加模块) Option Explicit ‘强制性变量声明,不允许出现未声明的变量。呵呵,都懂!! Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer ‘Getkeystate是api函数,顾名思义,获取某个键的状态,参数nvirtkey就是某个键的虚拟键键码,不同的系统虚拟键码不同。比如vbkeycontrol或者vbkeyshift就可以作为参数。 返回值是16位的,如开关键打开,则位0设为1(开关键包括CapsLock,NumLock,ScrollLock);如某个键当时正处于按下状态,则位15为1;如已经抬起,则为0。数据在储存器中,最高位为1时是负数,为0时是正数。 Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long ‘Setwindowshookex,就是建立钩子的函数,最主要的的函数。 参数: Idhoook:要建立什么类型的hook。 有以下类型: WH_MSGFILTER = -1; 线程级; 截获用户与控件交互的消息 WH_JOURNALRECORD = 0; 系统级; 记录所有消息队列从消息队列送出的输入消息, 在消息从队列中清除时发生; 可用于宏记录 WH_JOURNALPLAYBACK = 1; 系统级; 回放由WH_JOURNALRECORD 记录的消息, 也就是将这些消息重新送入消息队列 WH_KEYBOARD = 2; 系统级或线程级; 截获键盘消息 WH_GETMESSAGE = 3; 系统级或线程级; 截获从消息队列送出的消息 WH_CALLWNDPROC = 4; 系统级或线程级; 截获发送到目标窗口的消息, 在SendMessage 调用时发生 WH_CBT = 5; 系统级或线程级; 截获系统基本消息, 譬如: 窗口的创建、激活、关闭、最大最小化、移动等等 WH_SYSMSGFILTER = 6; 系统级; 截获系统范围内用户与控件交互的消息

常用钩子的类型

常用钩子的类型 1、WH_CALLWNDPROC 1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你可以监视发送到窗口过程的消息。系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC Hook子程,并且在窗口过程处理完消息之后调用WH_CALLWNDPROCRET Hook 子程。 WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCT结构,再传递到Hook子程。CWPRETSTRUCT结构包含了来自处理消息的窗口过程的返回值,同样也包括了与这个消息关联的消息参数。 2、WH_CBT Hook 在以下事件之前,系统都会调用WH_CBT Hook子程,这些事件包括: 1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件; 2. 完成系统指令; 3. 来自系统消息队列中的移动鼠标,键盘事件; 4. 设置输入焦点事件; 5. 同步系统消息队列事件。 Hook子程的返回值确定系统是否允许或者防止这些操作中的一个。 3、WH_DEBUG Hook 在系统调用系统中与其他Hook关联的Hook子程之前,系统会调用 WH_DEBUG Hook子程。你可以使用这个Hook来决定是否允许系统调用与其他Hook关联的Hook子程。 4、WH_FOREGROUNDIDLE Hook 当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE Hook执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就会调用WH_FOREGROUNDIDLE Hook子程。 5、WH_GETMESSAGE Hook 应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及其他发送到消息队列中的消息。

恶意插件务必清除,介绍几种手工清除方法

20种恶意插件手工清除方法 如今,恶意软件及插件已经成为一种新的网络问题,恶意插件及软件的整体表现为清除困难,强制安装,甚至干拢安全软件的运行。下面的文章中就给大家讲一部份恶意插件的手工清除方法,恶意插件实在太多,无法做到一一讲解,希望下面的这些方法能为中了恶意插件的网友提供一定的帮助。 1、恶意插件Safobj 相关介绍: 捆绑安装,系统速度变慢,没有卸载项/无法卸载,强制安装,干扰其它软件正常运行, 清除方法: 重新注册IE项,修复IE注册。从开始->运行 输入命令 regsvr32 actxprxy.dll 确定 输入命令 regsvr32 shdocvw.dll 确定 重新启动,下载反间谍专家查有没有ADWARE,spyware,木马等并用其IE修复功能修复IE和注册表,用流氓软件杀手或微软恶意软件清除工具清除一些难卸载的网站插件。 到https://www.360docs.net/doc/6317021236.html,下载KillBox.exe。在C:\Program Files\Internet Explorer\目录下,把LIB 目录或Supdate.log删除。 跳窗网页可能保留在HOSTS,一经上网就先触发该网址为默认,就会自动打开,检查HOSTS: 用记事本在C:\WINDOWS\system32\drivers\etc\目录下打开HOSTS 在里面检查有没有网址,有则删除。 或在前面加 127.0.0.1 保存后屏蔽掉。 如果是弹出的信使: 从开始->运行,输入命令: net stop msg net stop alert 即终止信使服务。 2、恶意插件MMSAssist 相关介绍: 这其实是一款非常简便易用的彩信发送工具,但它却属于流氓软件!并采用了类似于木马的Hook(钩子)技术,常规的方法也很难删除它,而且很占用系统的资源。 清除方法: 方法一:它安装目录里第一个文件夹有个.ini文件,它自动从 https://www.360docs.net/doc/6317021236.html,/updmms/mmsass.cab下载插件包,包里有albus.dll文件,UPX 0.80 - 1.24的壳,脱掉用16位进制软件打开发现这个垃圾插件利用HOOK技术插入到explorer和iexplore中,开机就在后台自动运行。 安全模式下,右键点击我的电脑-管理-服务-禁用jmediaservice服务,删除C:\windows\system32下的Albus.DAT,删除C:\WINDOWS\SYSTEM32\DRIVERS下的Albus.SYS,删除彩信通的安装文件夹,开始-运行-regedit-查找所有MMSAssist并删除,如果怕注册表还有彩信通的垃圾存在,下载个超级兔子扫描下注册表再一一删除,你也可以试试超级兔子的超级卸载功能。 要阻止它再次安装,也很简单。彻底删除它之后,你在它原来的位置新建一个与它同名的文件夹,

Rootkit的类型、功能及主要技术

Rootkit的类型、功能及主要技术Rootkit 的类型小结 1.固化Rootkits和BIOS Rootkits 固化程序是存于ROM中,通常很小,使用系统硬件和BIOS 创建顽固的软件镜像。将制定的代码植入到BIOS 中,刷新BIOS,在BIOS 初始化的末尾获得运行机会。重启无用、格式化无用,在硬盘上无法探测,现有的安全软件将大部分的扫描时间用在了对硬盘的扫描上。 本文整理:(第三方信息安全网)https://www.360docs.net/doc/6317021236.html,/ 2 内核级Rootkits 内核级Rootkits(Kernelland Rootkits)是通过修改内核、增加额外的代码、直接修改系统 调用表、系统调用跳转(Syscall Jump),并能够替换一个操作系统的部分功能,包括内核和相关的设备驱动程序。现在的操作系统大多没有强化内核和驱动程序的不同特性。许多内核模式的Rootkit 是作为设备驱动程序而开发,或者作为可加载模块,如Linux 中的可加载模块或Windows 中的设备驱动程序,这类Rootkit 极其危险,它可获得不受限制的安全访问权。如果代码中有任何一点错误,那么内核级别的任何代码操作都将对整个系统的稳定性产生深远的影响。 特点:无进程;无端口。与用户级Rootkit 相比,与操作系统处于同一级别,可以修改或破坏由其它软件所发出的任何请求。 3 用户态Rootkits 用户态Rootkits(Userland Rootkits)是运行在Ring3 级的Rootkit,由于Ring3 级就是 用户应用级的程序,而且信任级别低,每一个程序运行,操作系统给这一层的最小权限。用

源程序程序破解之 API HOOK技术

【源程序】程序破解之API HOOK技术 API HOOK,就是截获API调用的技术,在程序对一个API调用之前先执行你的函数,然后根据你的需要可以执行缺省的API调用或者进行其他处理,假设如果想截获一个进程对网络的访问,一般是几个socket API : recv,recvfrom, send, sendto等等,当然你可以用网络抓包工具,这里只介绍通过API HOOK的方式来实现, 主要原理是在程序运行中动态修改目标函数地址的内存数据,使用jmp语句跳转到你的函数地址,执行完后再恢复内存数据, 汇编代码是: mov eax, pNewAddr[/size][size=3] jmp eax 读写进程内存方法: 1.读进程内存: 2.VirtualProtect(lpAddress, nSize, PAGE_READONLY, &dwOldProtect); 3.ReadProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwRead); 4.VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect); 2.写进程内存: VirtualProtect(lpAddress, nSize, PAGE_READWRITE, &dwOldProtect); WriteProcessMemory(hProcess, lpAddress, lpBuffer, nSize, &dwWrite); VirtualProtect(lpAddress, nSize, dwOldProtect, &dwOldProtect); 在很多年前这种技术非常的流行,有各种各样的工具和SDK,我自己也实现了一个C++ class,名为CAdHookApi, 主要几个函数是: class CAdHookApi { public: // 指定DLL的某个函数进行HOOK HANDLE Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData = 0); // 给定一个函数地址进行HOOK HANDLE Add(void *pOldAddr, void *pNewAddr, const BYTE *verifyData = NULL, DWORD verifySize = 0, DWORD dwData = 0); BOOL Remove(HANDLE hHook); BOOL Begin(HANDLE hHook); BOOL End(HANDLE hHook); BOOL Begin2(void *pNewAddr); BOOL End2(void *pNewAddr); int BeginAll(); int EndAll(); };

常见表扣的分类

《外贸手表那些事儿》 外贸钟表交流微信号:YXCsince1989 第一课 第一讲——表扣 根据结构功能使用方法的不同,手表表扣有如下7种基本类型: 手表针扣、手表皮带按扣、手表钩扣、手表蝴蝶扣、手表暗扣、手表折叠扣和手表折叠安全扣。 1. 手表针扣(Buckle)不锈钢材质为多,也有塑料材质的,有单针和双针,是人们平常见得最多的手表表扣之一,它一般被用于皮带手表,硅胶手表,可自行调节手表表带周长,使用方便.可镭射LOGO.

2.手表皮带按扣(leather deployment buckle),蝴蝶扣的一种,使用得高档皮带手表,基本上都是不锈钢材质。因为只固定于皮带一边,因此使用较复杂,但是牢固。可镭射LOGO。

3.手表钩扣(Hook Buckle) ,一般为不锈钢,多用于钢网带和不锈钢带手表.可镭射LOGO。

4 蝴蝶双按扣(Push-Button Hidden Clasp),基本上都是不锈钢,由于连接钢带两边,操作比皮带蝴蝶扣更加方便,佩带舒适,多用于高档不锈钢手表,陶瓷手表。一般不可镭射LOGO(因为藏在表带下面,LOGO看不到),LOGO可做在表带上面。

5.手表暗扣(hidden clasp )基本上都是不锈钢,一般用于钢带手表,折叠起来后与表带浑然一体,非常美观因此也很受人们欢迎。一般不可镭射LOGO(因为藏在表带下面,LOGO看不到),LOGO可以做在表带上面. 6. 手表珠宝扣(Bracelet Clasp) ,有不锈钢材质也有合金材质,一般用于中低档手链手表。操作方便,可镭射LOGO。

7. 手表折叠安全扣(folding clasp with safety),龟背扣的一种,有单按双按,一般为不锈钢材质,单按扣很便宜,是中低档钢带手表中使用率最高的表扣类型,生活中非常常见,不过如果质量不过关的话比较容易松脱。双按保险扣(右图)质量比较好,可以镭射LOGO.

API Hook基本原理和实现

API Hook基本原理和实现[图文] 关键字:API Hook,消息,拦截API,钩子,wskjuf 作者:wskjuf 更新:2007-12-23 08:18:25 浏览:18142 注:本文主要为解决论坛上 https://www.360docs.net/doc/6317021236.html,/forum/forum_posts.asp?TID=7281的提问而写的。我搜索了一下互联网,将网络上几篇有代表性的api hook文章的精华进行了浓缩和适当简化,写成这篇介绍性文章。另外也希望初学者能够认真思考本文采用的循序渐进的分析思路,如何解决了一个未知的问题。文中借鉴的文献资料列于文末附录一节。 hook是什么? windows系统下的编程,消息message的传递是贯穿其始终的。这个消息我们可以简单理解为一个有特定意义的整数,正如我们看过的老故事片中的“长江长江,我是黄河”一个含义。windows中定义的消息给初学者的印象似乎是“不计其数”的,常见的一部分消息在winuser.h头文件中定义。hook与消息有着非常密切的联系,它的中文含义是“钩子”,这样理解起来我们不难得出“hook 是消息处理中的一个环节,用于监控消息在系统中的传递,并在这些消息到达最终的消息处理过程前,处理某些特定的消息”。这也是hook分为不同种类的原因。 hook的这个本领,使它能够将自身的代码“融入”被hook住的程序的进程中,成为目标进程的一个部分。我们也知道,在windows2000以后的系统中,普通用户程序的进程空间都是独立的,程序的运行彼此间都不受干扰。这就使我们希望通过一个程序改变其他程序的某些行为的想法不能直接实现,但是hook的出现给我们开拓了解决此类问题的道路。 api hook是什么? 在windows系统下编程,应该会接触到api函数的使用,常用的api函数大概有2000个左右。今天随着控件,stl等高效编程技术的出现,api的使用概率在普通的用户程序上就变得越来越小了。当诸如控件这些现成的手段不能实现的功能时,我们还需要借助api。最初有些人对某些api函数的功能不太满意,就产生了如何修改这些api,使之更好的服务于程序的想法,这样api hook就自然而然的出现了。我们可以通过api hook,改变一个系统api的原有功能。基本的方法就是通过hook“接触”到需要修改的api函数入口点,改变它的地址指向新的自定义的函数。api hook并不属于msdn上介绍的13类hook中的任何一种。所以说,api hook并不是什么特别不同的hook,它也需要通过基本的hook提高自己的权限,跨越不同进程间访问的限制,达到修改api函数地址的目的。对于自身进程空间下使用到的api函数地址的修改,是不需要用到api hook技术就

易语言HookAPI 技巧

易语言HookAPI 技巧 易语言Hook的代码有很多,Hook的跳转代码也很简单,不多说,主要注意的有: 1.可以保存原API函数的API头到自己申请的地址,Hook跳转的地址仍然是自己的子程序, 但如果保存了API头,就可以call addr 实现不恢复Hook调用原函数。 .版本2 .如果真(FuncAddress =0 或HookFuncAddr =0) 返回(0) .如果真结束 hHook =VirtualAlloc (0, 14, 位或(#MEM_COMMIT, #MEM_RESERVE), #PAGE_EXECUTE_READWRITE) .如果真(hHook =0) 返回(0) .如果真结束 RtlMoveMemory_1 (hHook, 到字节集(FuncAddress), 4) JmpCode =hHook +4 RtlMoveMemory (JmpCode, FuncAddress, 5) RtlMoveMemory_1 (JmpCode +5, { 233 } +到字节集(到整数(FuncAddress + 5 -JmpCode -10)), 5) VirtualProtect (FuncAddress, 5, #PAGE_EXECUTE_READWRITE, OldProtect) RtlMoveMemory_1 (FuncAddress, { 233 } +到字节集(到整数(HookFuncAddr -FuncAddress -5)), 5) VirtualProtect (FuncAddress, 5, OldProtect, 0) 返回(JmpCode) 2.Hook recv函数等的技巧,这类函数的特点是,某个参数是具有缓冲区性质的,并在函数 调用完成后参数会直接传递数据,所以结合上面的代码,就可以这样了: ret=Call(jmpcode,para1,para2.etc) 这时候,再对参数para1等进行处理,才可以获得数据 3.Anti-Hook的躲避技巧,部分程序会有检测API头5字节,所以我们只需要在Hookaddr 上面加上一段偏移(大于5)即可躲避。更深入地,如果检测的是整个API头,我们就需要深入API的调用过程,Hook核心函数或其他流程来躲避。由于校验所有API头hash 值需要大量的CPU占用及时间,所以一般也只会对重点函数进行检测。

内核级hook的几种实现与应用

内核级HOOK的几种实现与应用 创建时间:2003-03-26 文章来源:https://www.360docs.net/doc/6317021236.html, 文章提交:sinister (jiasys_at_https://www.360docs.net/doc/6317021236.html,) 内核级HOOK的几种实现与应用 Author : sinister Email : sinister@https://www.360docs.net/doc/6317021236.html, HomePage: https://www.360docs.net/doc/6317021236.html, 实现内核级 HOOK 对于拦截、分析、跟踪系统内核起着致关重要的作用。实现的方法不同意味着应用侧重点的不同。如想要拦截 NATIVE API 那么可能常用的就是 HOOK SERVICE TABLE 的方法。如果要分析一些系统调用,那么可能想到用 HOOK INT 2E 中断来实现。如果想要拦截或跟踪其他内核 DRIVER 的调用,那么就要用到HOOK PE 的方法来实现。这里我们更注重的是实现,原理方面已有不少高手在网上发表过文章。大家可以结合起来读。下面以我写的几个实例程序来讲解一下各种方法的实现。错误之处还望各位指正。 1、HOOK SERVICE TABLE 方法: 这种方法对于拦截 NATIVE API 来说用的比较多。原理就是通过替换系统导 出的一个 SERVICE TABLE 中相应的 NATIVE API 的地址来达到拦截的目的。 因为此方法较为简单,网上也有不少资料来介绍。所以这里就不给出实例程序了。SERVICE TABLE 的结构如下: typedef struct ServiceDescriptorEntry { unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; unsigned int NumberOfServices; unsigned char *ParamTableBase; } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t; 2、HOOK INT 2E 方法: 这种方法对于跟踪、分析系统调用来说用的比较多。原理是通过替换 IDT

HOOK API 函数跳转详解

什么是HOOK API: Windows下暴露的对开发人员的接口叫做应用程序编程接口,就是我们常说的API。我们在写应用层应用程序软件的时候都是通过调用各种API来实现的。有些时候,我们需要监控其他程序调用的API,也就是,当其他应用程序调用我们感兴趣的API的时候,我们在他调用前有一个机会做自己的处理,这就是HOOK API的涵义。 思路: 我们知道Windows系统API函数都是被封装到DLL中,在某个应用程序要调用一个API函数的时候,如果这个函数所在的DLL没有被加载到本进程中则加载它,然后保存当前环境(各个寄存器和函数调用完后的返回地址等)。接着程序会跳转到这个API函数的入口地址去执行此处的指令。由此看来,我们想在调用真正的API之前先调用我们的函数,那么可以修改这个API函数的入口处的代码,使他先跳转到我们的函数地址,然后在我们的函数最后再调用原来的API函数。下面以拦截WS2_32.dll中的recv函数为例说明拦截的主要过程。首先把自己编写的DLL挂接到系统当前运行的所有进程中(要排除一些Windows 系统自身的进程,否则会出现问题,影响系统正常工作),挂接的意思是,要我们的DLL运行在目标进程的地址空间中。可以使用列举系统进程然后用远程线程注入的方法,但是这种方法只适用于Win2000以上的操作系统。 当我们的DLL被所有目标进程加载后,我们就可以进行真正的工作了。首先使用Tool Help库的相关函数列举目标进程加载的所有模块,看看是否有ws2_32.dll,如果没有,说明这个进程没有使用Winsock提供的函数,那么我们就不用再给这个进程添乱了。如果找到ws2_32.dll模块,那么OK,我们可以开工了。先是用GetProcAddress函数获得进程中ws2_32.dll模块的recv函数的入口地址,也就是函数的起始地址。刚才说过,我们想把recv 函数起始位置加入一条跳转指令,让它先跳转到我们的函数中运行。跳转指令可以用0xE9来表示(0xE9是汇编语言中CALL指令的机器码),后面还有4个字节的我们函数的相对地址。也就是我们要修改recv函数前5个字节。这5个字节由1个字节的跳转指令和4个字节的地址组成。这样当程序运行到这里的时候,将会跳转到这4个字节表示的地址处去运行代码。还要注意的是这4个字节的地址是偏移地址,而偏移地址= 我们函数的地址- 原API函数的地址- 5(我们这条指令的长度)。好了,别忘了我们要先读取稍后要被覆盖的recv 函数入口处的5个字节的内容,把它保存起来留着以后恢复时使用。因为在我们的函数中要想调用真正的recv的时候,必须把它前5个字节恢复了,他才能正常工作呢。 通过上面的说明,我们可以整理出这样的一个流程: 1.保存recv的前5个字节的内容 2.把recv的前5个字节的内容改变成CALL xxxx(xxxx是我们的函数的偏移地址)3.在我们的函数中恢复recv的前5个字节的内容,并作处理。 4.我们的函数返回后,再把recv的前5个字节的内容改变成CALL xxxx 慢着,你一定发现问题了吧?当我们为了调用原来的recv函数而刚刚把recv入口处的5个字节恢复,这时系统中的其他线程调用了recv函数,而这个调用将会成为漏网之鱼而不会进入到我们的函数中来。简单的解决办法是使用临界对象CriticalSection来保证同时只能有一个线程对recv函数入口处5个字节进行读写操作。 最后记得在你想要停止拦截的时候恢复所有你修改过的进程和这些进程中被修改的API的

UCOS—III 常用资料整理

UC/OS—III的常用资料整理 作者:~风中的叶~ QQ:654705188 任务堆栈:存储任务中的调用的函数、局部变量、中断服务程序和CPU寄存器的值。 全局变量的保护: 1.如果只在一个任务中写(或只有一个数据),而在其他任务中只是读取,则可以不用互斥型信号量,最多会造成读取的数据未被完全写完。 2.如果全局变量在多个任务中写,则需要用互斥型信号量保护,这样当有任务申请到互斥型信号量(保护不可重入的程序段)写数据时,其他任务的同一个互斥型信号量必须等待上一个任务的释放才可进行写。 3.如果全局变量在中断中写,则在其他任务中的全局变量的写操作要用临界段(禁止中断和禁止调度:保护不可被分割的程序段)保护。(因为如果不关中断相当于中断的优先级最高,而且不能被像其他任务那样挂起。) OS_CFG_ISR_POST_DEFERRED_EN为1临界段使用锁调度器方式; 为0临界段使用禁中断方式 (CPU_SR_ALLOC();存放中断的变量 OS_CRITICAL_ENTER();OS_CRITICAL_EXIT(); OS_CRITICAL_EXIT_NO_SCHED(); OSSchedLockNestingCtr记录调度器被锁的次数)。 检测任务堆栈的使用情况: OS_CFG_STAT_TASK_STK_CHK_EN使能 OS_ERRerr; CPU_STK_SIZE stk_free; CPU_STK_SIZE stk_used; OSTaskStkChk(&TaskBStkTCB,&stk_free,&stk_used,&err); 中断中使用OSIntEnter(); 和OSIntExit();是为了退出中断后执行中断调度操作,如果中断中并未用到OSSemPost();等系统函数,则退出中断服务程序后不需要进行任务调度,就可以不在中断服务程序中使用OSIntEnter(); 和OSIntExit();。 (有时候用:CPU_CRITICAL_ENTER();OSIntNestingCtr++; CPU_CRITICAL_EXIT();替代OSIntEnter();) 一、变量类型 在cpu.h中是有关cpu变量的重新定义,还包括CPU_STK(CPU堆栈类型), 和CPU_STK_SIZE(CPU堆栈类型的大小)的定义,CPU_SR(CPU状态寄存 器的定义)。 在os.h中是有关os类型的定义如OS_TCB(任务控制块)、OS_SEM(信号量)、OS_MUTEX (互斥型信号量)、OS_MSG(消息)、OS_Q(消息队列)、OS_ERR(系统错误)等。 在cpu_core.h中是有关cpu的定义,如CPU_ERR、CPU_TS、CPU_TS_TMR等。 CPU_STK:typedef unsigned int堆栈的类型定义

HOOK监控任务管理器

HOOK监控任务管理器 思路:其实比较简单,还是利用DLL,首写跟据API函数OpenProcess与TerminateProcess的结构自已编写两个与这两个API一样的函数,再利用GetProcAddress获取系统的那两个API函数入口地址,最后用WriteProcessMemory将你写的函数的地址替换掉原来系统的函数地址。这样所有调用这两系统API都将先执行你的函数。 如果只Hook其中一个函数比如只hook OpenProcess的话那么任务管理器将不能获取到你的进程信息那么会出错。如果只hook TerminateProcess那样也不行,因为一个进程的句柄在本进程与别的进程中是不一样的,所以如果你不知道自已进程在别人进程中的句柄那么是没办法hook TerminateProcess的。 本例中首先利用OpenProcess获取自已在别的进程中的句柄,然后hook TerminateProcess进程监控,如果发现有程序调用TerminateProcess并且所结束的对象正是自已,那么就给出提示窗口。 貌似讲了一大堆废话。。。还是看代码直接 ------------------------------------------------调用部分 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; procedure StartHook(pid: DWORD); stdcall; external 'hookdll.dll'; procedure EndHook; stdcall; external 'hookdll.dll'; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin

使用自旋锁的各种HOOK

#include #define MEM_TAG 'TMEM' typedef struct _THREAD_BASIC_INFORMA TION { NTSTATUS ExitStatus; PVOID TebBaseAddress; CLIENT_ID ClientId; KAFFINITY AffinityMask; KPRIORITY Priority; KPRIORITY BasePriority; }THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMA TION; typedef BOOL (*NTUSERPOSTTHREADMESSAGE) ( DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam ); typedef NTSTATUS (*NTOPENPROCESS) ( OUT PHANDLE ProcessHandle, IN ACCESS_MASK AccessMask, IN POBJECT_A TTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId ); typedef NTSTATUS (*NTOPENTHREAD) ( OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_A TTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId ); typedef NTSTATUS (*NTDUPLICATEOBJECT) ( IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG Attributes, IN ULONG Options );

外挂技术(钩子)

外挂技术(钩子) WIndows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的。而钩子是WIndows系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子可以监视系统或进程中的各种事件消息,截获发往目标窗口的消息并进行处理。这样,我们就可以在系统中安装自定义的钩子,监视系统中特定事件的发生,完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词,日志监视等等。可见,利用钩子可以实现许多特殊而有用的功能。因此,对于高级编程人员来说,掌握钩子的编程方法是很有必要的。 钩子的类型 一.按事件分类,有如下的几种常用类型 (1)键盘钩子和低级键盘钩子可以监视各种键盘消息。 (2)鼠标钩子和低级鼠标钩子可以监视各种鼠标消息。 (3)外壳钩子可以监视各种Shell事件消息。比如启动和关闭应用程序。 (4)日志钩子可以记录从系统消息队列中取出的各种事件消息。 (5)窗口过程钩子监视所有从系统消息队列发往目标窗口的消息。 此外,还有一些特定事件的钩子提供给我们使用,不一一列举。 下面描述常用的Hook类型: 1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你可以监视发送到窗口过程的消息。系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC Hook 子程,并且在窗口过程处理完消息之后调用WH_CALLWNDPRO CRET Hook子程。WH_CalLWNDPROCRET Hook传递指针到CWPRETSTRUCT结构,再传递到Hook子程。CWPRETSTRUCT结构包含了来自处理消息的窗口过程的返回值,同样也包括了与这个消息关联的消息参数。 2、WH_CBT Hook 在以下事件之前,系统都会调用WH_CBT Hook子程,这些事件包括: 1. 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件; 2. 完成系统指令; 3. 来自系统消息队列中的移动鼠标,键盘事件; 4. 设置输入焦点事件; 5. 同步系统消息队列事件。 Hook子程的返回值确定系统是否允许或者防止这些操作中的一个。 3、WH_DEBUG Hook 在系统调用系统中与其他Hook关联的Hook子程之前,系统会调用WH_DEBUG Hook 子程。你可以使用这个Hook来决定是否允许系统调用与其他HooK关联的Hook子程。 4、WH_FOREGROUNDIDLE Hook 当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE Hook 执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就会调用WH_FOREGROUNDIDLE Hook子程。 5、WH_GETMESSAGE Hook 应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及其他

相关文档
最新文档