CreateToolhelp32Snapshot

  CreateToolhelp32Snapshot函数为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程[THREAD])建立一个快照[snapshot]。

  HANDLE WINAPI CreateToolhelp32Snapshot(

  DWORD dwFlags,

  DWORD th32ProcessID

  );

  参数:

  dwFlags

  [输入]指定快照中包含的系统内容,这个参数能够使用下列数值(变量)中的一个。

  TH32CS_INHERIT - 声明快照句柄是可继承的。

  TH32CS_SNAPALL - 在快照中包含系统中所有的进程和线程。

  TH32CS_SNAPHEAPLIST - 在快照中包含在th32ProcessID中指定的进程的所有的堆。

  TH32CS_SNAPMODULE - 在快照中包含在th32ProcessID中指定的进程的所有的模块。

  TH32CS_SNAPPROCESS - 在快照中包含系统中所有的进程。

  TH32CS_SNAPTHREAD - 在快照中包含系统中所有的线程。

  Const TH32CS_SNAPHEAPLIST = &H1

  Const TH32CS_SNAPPROCESS = &H2

  Const TH32CS_SNAPTHREAD = &H4

  Const TH32CS_SNAPMODULE = &H8

  Const TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST Or TH32CS_SNAPPROCESS Or TH32CS_SNAPTHREAD Or TH32CS_SNAPMODULE)

  Const TH32CS_INHERIT = &H80000000

  th32ProcessID

  [输入]指定将要快照的进程ID。如果该参数为0表示快照当前进程。该参数只有在设置了TH32CS_SNAPHEAPLIST,TH32CS_SNAPMODULE,TH32CS_SNAPALL后才有效,在其他情况下该参数被忽略,所有的进程都会被快照。

  返回值:

  调用成功,返回快照的句柄,调用失败,返回INVALID_HANDLE_VALUE 。

  备注:

  使用GetLastError函数查找该函数产生的错误状态码。

  要删除快照,使用CloseHandle函数

  delphi使用实例:

  uses TLHelp32;

  procedure TForm1.Button1Click(Sender: TObject);

  var

  ProcessName: string;

  ProcessID: integer;

  ListLoop: Boolean;

  FsnapShotHandle: Thandle;

  FProcessEntry32: TProcessEntry32;

  begin

  Fsnapshothandle := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0);

  FProcessEntry32.dwsize := SizeOF(FProcessEntry32);

  Listloop := Process32First(FSnapshotHandle, FProcessEntry32);

  while Listloop do begin

  ProcessName := FprocessEntry32.szExeFile;

  ProcessID := FProcessEntry32.th32ProcessID;

  // 我写到列表框中了,你可以根据需要自己改

  listbox1.Items.Add('Process NAME:' + ProcessNAme);

  ListLoop := Process32Next(FSnapshotHandle, FprocessEntry32);

  end;

  end;

  VB使用实例:

  Private Type PROCESSENTRY32

  dwSize As Long

  cntUseage As Long

  th32ProcessID As Long

  th32DefaultHeapID As Long

  th32ModuleID As Long

  cntThreads As Long

  th32ParentProcessID As Long

  pcPriClassBase As Long

  swFlags As Long

  szExeFile As String * 1024

  End Type

  Private sub demo()

  Dim MySnapHandle As Long

  Dim ProcessInfo As PROCESSENTRY32

  MySnapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)

  ProcessInfo.dwSize = Len(ProcessInfo)

  If Process32First(MySnapHandle, ProcessInfo) <> 0 Then

  Do

  If Left(LCase(ProcessInfo.szExeFile), InStr(ProcessInfo.szExeFile, ".") + 3) = "notepad.exe" Then

  '遍历进程,查找notepad.exe,找到后执行操作.......

  End If

  Loop While Process32Next(MySnapHandle, ProcessInfo) <> 0

  End If

  CloseHandle MySnapHandle

  end sub

  C++例子

  #include "StdAfx.h"

  #include "windows.h"

  #include "tlhelp32.h"

  #include "stdio.h"

  int main(int argc, char* argv[])

  {

  PROCESSENTRY32 pe32;

  //在使用这个结构前,先设置它的大小

  pe32.dwSize = sizeof(pe32);

  //给系统内所有的进程拍个快照

  HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

  if (hProcessSnap == INVALID_HANDLE_VALUE)

  {

  printf("CreateToolhelp32Snapshot 调用失败./n");

  return -1;

  }

  //遍历进程快照,轮流显示每个进程的信息

  BOOL bMore = ::Process32First(hProcessSnap,&pe32);

  while (bMore)

  {

  printf("进程名称:%s/n",pe32.szExeFile);

  printf("进程ID:%u/n/n",pe32.th32ProcessID);

  bMore = ::Process32Next(hProcessSnap,&pe32);

  }

  //不要忘记清除掉snapshot对象

  ::CloseHandle(hProcessSnap);

  return 0;

  }

 

 

 

PROCESSENTRY32

  PROCESSENTRY32 Structure

  Describes an entry from a list of the processes residing in the system address space when a snapshot was taken.

  用来存放快照进程信息的一个结构体。(存放进程信息和调用成员输出进程信息)

  用来 Process32First指向第一个进程信息,并将进程信息抽取到PROCESSENTRY32中。用 Process32Next指向下一条进程信息。

  

Syntax

C++

  typedef struct tagPROCESSENTRY32

  {

  DWORD dwSize;

  DWORD cntUsage;

  DWORD th32ProcessID;

  ULONG_PTR th32DefaultHeapID;

  DWORD th32ModuleID;

  DWORD cntThreads;

  DWORD th32ParentProcessID;

  LONG pcPriClassBase;

  DWORD dwFlags;

  TCHAR szExeFile[MAX_PATH];

  } PROCESSENTRY32, *PPROCESSENTRY32;

  

Members

dwSize (结构的大小)The size of the structure, in bytes. Before calling the Process32First function, set this member to sizeof(PROCESSENTRY32). If you do not initialize dwSize, Process32First fails.

  (这个结构的长度,以字节为单位,初始化一个实例以后调用Process32First函数,设置成员的大小sizeof(PROCESSENTRY32).如果你没用PROCESSENTRY32中的成员dwSize初始 化,pricess32First将会失败。)

  cntUsage (此进程的引用计数)This member is no longer used and is always set to zero.

  (这个成员已经很久没有使用,总是设置为零。)

  th32ProcessID 进程ID=process identifier=PIDThe process identifier.

  (这个就是任务管理器里面的进程的PID,打开任务管理器--查看---选择列---PID(勾选)就可以显示进程的标示符(PID))

  th32DefaultHeapID 进程默认堆IDThis member is no longer used and is always set to zero.

  (这个成员已经很久没有使用,总是设置为零。)

  th32ModuleID 进程模块IDThis member is no longer used and is always set to zero.

  (这个成员已经很久没有使用,总是设置为零。)

  cntThreads 此进程开启的线程计数The number of execution threads started by the process.

  (这个成员执行线程开始的进程。)

  th32ParentProcessID (父进程的ID)The identifier of the process that created this process (its parent process).

  pcPriClassBase .(线程优先权)The base priority of any threads created by this process

  当前进程创建的任何一个线程的基础优先级,即在当前进程内创建线程的话,其基本优先级的值。

  dwFlags This member is no longer used, and is always set to zero.

  (这个成员已经很久没有使用,总是设置为零。)

  szExeFile (一个数组)进程全名The name of the executable file for the process. To retrieve the full path to the executable file, call the Module32First function and check the szExePath member of the MODULEENTRY32 structure that is returned. However, if the calling process is a 32-bit process, you must call the QueryFullProcessImageName function to retrieve the full path of the executable file for a 64-bit process.

  (进程的可执行文件名称。要获得可执行文件的完整路径,应调用Module32First函 数,再检查其返回的MODULEENTRY32结构的szExePath成员。但是,如果被调用进程是一个32位程序,您必须调用 QueryFullProcessImageName函数去获取64位进程的可执行文件完整路径名。)

GetForegroundWindow

  函数功能:该函数返回前台窗口(用户当前工作的窗口)。系统分配给产生前台窗口的线程一个稍高一点的优先级。

  函数原型:HWND GetForegroundWindow(VOID)

  参数:无。

  返回值:函数返回前台窗回的句柄。

  速查:Windows NT:3.1以上版本;Windows:95以上版本:Windows CE:1.0以上版本:头文件:Winuser.h;库文件:user32.lib。

GetWindowThreadProcessId

目录[隐藏]

一、VC

1.1.函数原型

2.2.参数

3.3.返回值

4.4.函数相关信息

二、VB声明

1.1、说明

2.2、返回值

3.3、参数表

一、VC

1.1.函数原型

2.2.参数

3.3.返回值

4.4.函数相关信息

二、VB声明

1.1、说明

2.2、返回值

3.3、参数表

  GetWindowThreadProcessId

[编辑本段]

一、VC

--------------------------------------------------------------------------------

  The   GetWindowThreadProcessId   function   retrieves   the   identifier   of   the   thread   that   created   the   specified   window   and,   optionally,   the   identifier   of   the   process   that   created   the   window.

  意译:

  找出某个窗口的创建者(线程或进程),返回创建者的标志符

  哪个线程创建了这个窗口,返回的就是这个线程的id号 (进程只有一个线程的话,那么线程标志符与进程标志符就是指同一个标志符)

  可理解为找出某栋房屋的建筑工人的名字。

  

  

1.函数原型

DWORD   GetWindowThreadProcessId(

  HWND   hWnd,

  LPDWORD   lpdwProcessId

  );

  

2.参数

hWnd     [in]   (向函数提供的)被查找窗口的句柄.

  lpdwProcessId     [out]   答案的存放地址(变 量地址) Pointer   to   a   variable   that   receives   the   process   identifier.   If   this   parameter   is   not   NULL,   GetWindowThreadProcessId   copies   the   identifier   of   the   process   to   the   variable;   otherwise,   it   does   not.     (如果参数不为NULL,即提供了存放处--变量,那么本函数把进程标志拷贝到存放处,否则不动作。)

  

  

3.返回值

The   return   value   is   the   identifier   of   the   thread   that   created   the   window.

  返回创建者的标志,注意, lpdwProcessId 存放创建者标志的变量。即,返回值是答案, lpdwProcessId 是答案存放处。

    当然可以把答案再放到其它地方。如

  DWORD PID;

  PID=GetWindowThreadProcessId( hWnd,   lpdwProcessId   );

  

4.函数相关信息

Header   Declared   in   Winuser.h,   include   Windows.h

  Import   library   User32.lib

  Minimum   operating   systems   Windows   95,   Windows   NT   3.1

[编辑本段]

二、VB声明

Declare Function GetWindowThreadProcessId Lib "user32" Alias "GetWindowThreadProcessId" (ByVal hwnd As Long, lpdwProcessId As Long) As Long

  

1、说明

  The GetWindowThreadProcessId function retrieves the identifier of the thread that created the specified window and, optionally, the identifier of the process that created the window

  这个函数获得指定线程的标识符,此线程创建了指定的窗口,并且随机的产生了这个标识符.

  

2、返回值

  Long,拥有窗口的线程的标识符

  

3、参数表

参数 类型及说明

  lpdwProcessId Long,指定一个变量,用于装载拥有那个窗口的一个进程的标识符

  hwnd Long,指定窗口句柄

OpenProcess

目录[隐藏]

一.VC

二.在vb中的使用

三、Delphi

[编辑本段]

一.VC

方法名称: OpenProcess

  位置: Kernel32.dll

  OpenProcess 函数用来打开一个已存在的进程对象,并返回进程的句柄。

  1.函数原型

  HANDLE OpenProcess(

  DWORD dwDesiredAccess, // access flag

  BOOL bInheritHandle, // handle inheritance option

  DWORD dwProcessId // process identifier

  );

  2.返回值:

  如成功,返回值为指定进程的句柄。

  如失败,返回值为空,可调用GetLastError获得错误代码。

  -------------------------------------------------------------

  3.举例

  HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pID );

  ----------------------

  4.附:

  BOOL ReadProcessMemory( HANDLE hProcess, PVOID pvAddressRemote, PVOID pvBufferLocal, DWORD dwSize, PDWORD pdwNumBytesRead);

  参数

  hProcess //为远程进程的句柄

  pvAddressRemote //用于指明远程进程中的地址

  pvBufferLocal //是本地进程中的内存地址

  dwSize //是需要传送的字节数

  pdwNumBytesRead和pdwNumBytesWritten //用于指明实际传送的字节数.当函数返回时,可以查看这两个参数的值.

[编辑本段]

二.在vb中的使用

1.VB声明

  Declare Function OpenProcess Lib "kernel32" Alias "OpenProcess" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long

  说明

  打开一个现有进程的句柄

  2.返回值

  Long,如执行成功,返回进程句柄;零表示失败。会设置GetLastError

  3.参数表

  参数 类型 及 说明

  dwDesiredAccess Long,指定这个句柄要求的访问方法。指定API32.TXT文件中以PROCESS_???开头的一个或多个常数

  bInheritHandle Long,如句柄能够由子进程继承,则为TRUE

  dwProcessId Long,要打开那个进程的进程标识符

  4.注解

  这个函数经常用来打开一个要进行同步的进程(同步:即步调协同,你说完,我再说,按说好的先后次序来)

  5.举例

  hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, pid) 打开进程

  If hProcess Then

      ReadProcessMemory hProcess, ByVal &H12F82C, base, 4, 0& 读写进程内存

  CloseHandle hProcess 结束进程

  End If

[编辑本段]

三、Delphi

var

  ProcessHandle, PID: longword;

  begin

  GetWindowThreadProcessId(FindWindow('Shell_TrayWnd', nil), @PID);//获取c的PID

  ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, PID);//打开进程

  Inject(ProcessHandle, @Main);//插入代码

  CloseHandle(ProcessHandle);//关闭线程句柄

  end.

dword

  1个二进制位称为1个bit(位),8个二进制位称为1个Byte(字节),也就是1个字节(8位),2个字节    就是1个Word(1个字,16位),则DWORD(DOUBLE WORD)就是双字的意思,两个字(32位)</CA>

  windef.h中

  typedef unsigned long DWORD;

  关于DWORD使用中重要的一点。DWORD 现在表示 32bit 无符号整数,即使以后 Windows

  升级到64位,DWORD 仍然是 32bit 无符号整数(也许以后的 long 不

  是32bit了,只需要重新定义一下 DWORD 就可以了)。对于那些直接

  和位数有关的整数,最好不用 int, long, short 之内的内型,因为

  这些类型的位数可能不确定(比如,在16位程序里,int 是16位的,在

  32位程序里,int 是32位的,谁知道在以后的64位程序里,int 是多少

  位,long 又是多少位)。用重新定义的内型就没有这方面的问题了,

最多到时候修改一下定义就可以了,而不需要在程序里一行一行的查找

Hook

Hook解释

   Hook是Windows中提供的一种用以替换DOS下“中断”的系统机制,中文译为“挂钩”或“钩子”。在对特定的系统事件进行hook后,一旦发生已hook事件,对该事件进行hook的程序就会受到系统的通知,这时程序就能在第一时间对该事件做出响应。

  另一解释:

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

   钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

  Hook原理

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

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

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

  系统钩子与线程钩子

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

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

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

  几点说明:

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

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

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

  Hook的应用模式

  观察模式

  最为常用,像Windows提供的SetWindowHook就是典型地为这类应用准备的。而且这也是最普遍的用法。

  这个模式的特点是,在事情发生的时候,发出一个通知信息。观察者只可以查看过程中的信息,根据自己关心的内容处理自己的业务,但是不可以更改原来的流程。

  如全局钩子中,经常使用的鼠标消息、键盘消息的监视等应用。金山词霸屏幕取词的功能是一个典型的应用(具体技术可以参考此类文章)。

  注入模式

  这个模式和观察模式最大的不一样的地方在于,注入的代码是为了扩展原始代码的功能业务。插件模式是此类模式的典型案例。

  不管瘦核心的插件系统(如Eclipse)还是胖核心的插件系统(如Delphi、Visual Studio等IDE环境),其对外提供的插件接口都是为了扩展本身系统的功能的。

  这种扩展的应用方式的典型特点,就是新的扩展代码和原来的代码会协调处理同类业务。

  替换模式

  如果针对应用目的不同,可以叫修复模式或破解模式。前者是为了修改系统中的BUG,后者是为了破解原有系统的限制。

  很多黑客使用此种模式,将访问加密锁的DLL中的导出表,替换成自己的函数,这样跳过对软件的控制代码。这类应用的难点是,找出函数的参数。

  这类模式的特点是,原有的代码会被新的代码所替换。

  前面三个是基本模式,还有很多和实际应用相关的模式。

  集权模式

  此类模式的出现,大都是为了在全部系统中,统一处理某类事情。它的特点不在于注入的方式,而在于处理的模式。

  这个模式,大都应用到某类服务上,比如键盘服务,鼠标服务,打印机服务等等特定服务上。通过统一接管此类服务的访问,限制或者协调对服务的访问。

  比如键盘锁功能的实现,就是暂时关闭键盘的所有应用。

  这类模式的特点主要会和特点服务有关联。

  修复模式

  替换模式的一种,这里强调的是其应用的目的是为了修复或扩展原有系统的功能。

  破解模式

  替换模式的一种,这里强调的是其应用的目的是为了跳过原有系统的一部分代码。如加密检测代码,网络检测代码等等。

  插件模式

  注入模式的一种,在系统的内部直接依靠HOOK机制进行扩展业务功能。

  共享模式

  这类应用中,经常是为了获取对方的数据。必然我希望获取对方系统中,所有字符串的值。可以通过替换对方的内存管理器,导出所有字符串。

  这个应用比较特殊。不过其特点在于,目的是达到系统之间的数据共享。

  其实现,可能是观察模式,也可能是替换模式。

  VB中的Hook技术应用

  一、Hook简介

  Hook这个东西有时令人又爱又怕,Hook是用来拦截系统某些讯息之用,例如说,我们想

  让系统不管在什么地方只要按个Ctl-B便执行NotePad,或许您会使用Form的KeyPreview

  ,设定为True,但在其他Process中按Ctl-B呢?那就没有用,这是就得设一个Keyboard

  Hook来拦截所有Key in的键;再如:MouseMove的Event只在该Form或Control上有效,如果希望在Form的外面也能得知Mouse Move的讯息,那只好使用Mouse Hook来栏截Mouse

  的讯息。再如:您想记录方才使用者的所有键盘动作或Mosue动作,以便录巨集,那就

  使用JournalRecordHook,如果想停止所有Mosue键盘的动作,而放(执行)巨集,那就

  使用JournalPlayBack Hook;Hook呢,可以是整个系统为范围(Remote Hook),即其他

  Process的动作您也可以拦截,也可以是LocalHook,它的拦截范围只有Process本身。

  Remote Hook的Hook Function要在.Dll之中,Local Hook则在.Bas中。

  在VB如何设定Hook呢?使用SetWindowsHookEx()

  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

  idHook代表是何种Hook,有以下几种

  Public Const WH_CALLWNDPROC = 4

  Public Const WH_CALLWNDPROCRET = 12

  Public Const WH_CBT = 5

  Public Const WH_DEBUG = 9

  Public Const WH_FOREGROUNDIDLE = 11

  Public Const WH_GETMESSAGE = 3

  Public Const WH_HARDWARE = 8

  Public Const WH_JOURNALPLAYBACK = 1

  Public Const WH_JOURNALRECORD = 0

  Public Const WH_KEYBOARD = 2

  Public Const WH_MOUSE = 7

  Public Const WH_MSGFILTER = (-1)

  Public Const WH_SHELL = 10

  Public Const WH_SYSMSGFILTER = 6

  WH_CALLWNDPROC 当调用SendMessage时

  WH_CALLWNDPROCRET 当SendMessage的调用返回时

  WH_GETMESSAGE 当调用GetMessage 或 PeekMessage时

  WH_KEYBOARD 当调用GetMessage 或 PeekMessage 来从消息队列中查询WM_KEYUP 或 WM_KEYDOWN 消息时

  WH_MOUSE 当调用GetMessage 或 PeekMessage 来从消息队列中查询鼠标事件消息时

  WH_HARDWARE 当调用GetMessage 或 PeekMessage 来从消息队列种查询非鼠标、键盘消息时

  WH_MSGFILTER 当对话框、菜单或滚动条要处理一个消息时。该钩子是局部的。它时为那些有自己的消息处理过程的控件对象设计的。

  WH_SYSMSGFILTER 和WH_MSGFILTER一样,只不过是系统范围的

  WH_JOURNALRECORD 当WINDOWS从硬件队列中获得消息时

  WH_JOURNALPLAYBACK 当一个事件从系统的硬件输入队列中被请求时

  WH_SHELL 当关于WINDOWS外壳事件发生时,譬如任务条需要重画它的按钮.

  WH_CBT 当基于计算机的训练(CBT)事件发生时

  WH_FOREGROUNDIDLE 由WINDOWS自己使用,一般的应用程序很少使用

  WH_DEBUG 用来给钩子函数除错

  lpfn代表Hook Function所在的Address,这是一个CallBack Fucnction,当挂上某个

  Hook时,我们便得定义一个Function来当作某个讯息产生时,来处理它的Function

  ,这个Hook Function有一定的叁数格式

  Private Function HookFunc(ByVal ncode As Long, _

  ByVal wParam As Long, _

  ByVal lParam As Long) As Long

  nCode 代表是什么请况之下所产生的Hook,随Hook的不同而有不同组的可能值

  wParam lParam 传回值则随Hook的种类和nCode的值之不同而不同。

  因这个叁数是一个 Function的Address所以我们固定将Hook Function放在.Bas中,

  并以AddressOf HookFunc传入。至于Hook Function的名称我们可以任意给定,不一

  定叫 HookFunc

  hmod 代表.DLL的hInstance,如果是Local Hook,该值可以是Null(VB中可传0进去),

  而如果是Remote Hook,则可以使用GetModuleHandle('.dll名称')来传入。

  dwThreadId 代表执行这个Hook的ThreadId,如果不设定是那个Thread来做,则传0(所以

  一般来说,Remote Hook传0进去),而VB的Local Hook一般可传App.ThreadId进去

  值回值如果SetWindowsHookEx()成功,它会传回一个值,代表目前的Hook的Handle,

  这个值要记录下来。

  因为A程式可以有一个System Hook(Remote Hook),如KeyBoard Hook,而B程式也来设一

  个Remote的KeyBoard Hook,那么到底KeyBoard的讯息谁所拦截?答案是,最后的那一个

  所拦截,也就是说A先做keyboard Hook,而后B才做,那讯息被B拦截,那A呢?就看B的

  Hook Function如何做。如果B想让A的Hook Function也得这个讯息,那B就得呼叫

  CallNextHookEx()将这讯息Pass给A,于是产生Hook的一个连线。如果B中不想Pass这讯息

  给A,那就不要呼叫CallNextHookEx()。

  Declare Function CallNextHookEx Lib 'user32' _

  (ByVal hHook As Long, _

  ByVal ncode As Long, _

  ByVal wParam As Long, _

  lParam As Any) As Long

  hHook值是SetWindowsHookEx()的传回值,nCode, wParam, lParam则是Hook Procedure

  中的三个叁数。

  最后是将这Hook去除掉,请呼叫UnHookWindowHookEx()

  Declare Function UnhookWindowsHookEx Lib 'user32' (ByVal hHook As Long) As Long

  hHook便是SetWindowsHookEx()的传回值。此时,以上例来说,B程式结束Hook,则换A可

  以直接拦截讯息。

  KeyBoard Hook的范例

  Hook Function的三个叁数

  nCode wParam lParam 传回值

  HC_ACTION 表按键Virtual Key 与WM_KEYDOWN同 若讯息要被处理传0

  或 反之传1

  HC_NOREMOVE

  Public hHook As Long

  Public Sub UnHookKBD()

  If hnexthookproc &lt;&gt; 0 Then

  UnhookWindowsHookEx hHook

  hHook = 0

  End If

  End Sub

  Public Function EnableKBDHook()

  If hHook &lt;&gt; 0 Then

  Exit Function

  End If

  hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf MyKBHFunc, App.hInstance, App.ThreadID)

  End Function

  Public Function MyKBHFunc(ByVal iCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

  MyKBHFunc = 0 '表示要处理这个讯息

  If wParam = vbKeySnapshot Then '侦测 有没有按到PrintScreen键

  MyKBHFunc = 1 '在这个Hook便吃掉这个讯息

  End If

  Call CallNextHookEx(hHook, iCode, wParam, lParam) '传给下一个Hook

  End Function

只要将上面代码放在VB的模块中,用标准VB程序就可以了,当运行该程序后,就能拦截所有键盘操作。

ReadProcessMemory

目录[隐藏]

EN:

1.1、原型

2.2.Parameters

3.3.Return Values

4.4.Requirements

5.5.See Also

二、CH:

1.1.ReadProcessMemory

2.2、参数

三、例子

EN:

1.1、原型

2.2.Parameters

3.3.Return Values

4.4.Requirements

5.5.See Also

二、CH:

1.1.ReadProcessMemory

2.2、参数

三、例子

[编辑本段]

EN:

  

1、原型

This function reads memory in a specified process. The entire area to be read must be accessible or the operation fails.

  BOOL ReadProcessMemory(

  HANDLE hProcess,

  LPCVOID lpBaseAddress,

  LPVOID lpBuffer,

  DWORD nSize,

  LPDWORD lpNumberOfBytesRead

  );

  

2.Parameters

  1)hProcess

  [in] Handle to the process whose memory is being read.

  In Windows CE, any call to OpenProcess returns a process handle with the proper access rights.

  2)lpBaseAddress

  [in] Pointer to the base address in the specified process to be read.

  Before data transfer occurs, the system verifies that all data in the base address and memory of the specified size is accessible for read access. If so, the function proceeds; otherwise, the function fails.

  3)lpBuffer

  [out] Pointer to a buffer that receives the contents from the address space of the specified process.

  4)nSize

  [in] Specifies the requested number of bytes to read from the specified process.

  5)lpNumberOfBytesRead

  [out] Pointer to the number of bytes transferred into the specified buffer.

  If lpNumberOfBytesRead is NULL, the parameter is ignored.

  

3.Return Values

Nonzero   indicates success.

  

  Zero   indicates failure.

  To get extended error information, call GetLastError.

  The function fails if the requested read operation crosses into an area of the process that is inaccessible.

  Remarks

  ReadProcessMemory copies data in the specified address range from the address space of the specified process into the specified buffer of the current process. The process whose address space is read is typically, but not necessarily, being debugged.

  The entire area to be read must be accessible. If it is not, the function fails.

  

4.Requirements

OS Versions: Windows CE 2.0 and later.

  Header: Winbase.h.

  Link Library: Coredll.lib, Nk.lib.

  

5.See Also

OpenProcess | WriteProcessMemory

  ---------------------------------------------------------------------------------------

[编辑本段]

二、CH:

1.ReadProcessMemory

BOOL ReadProcessMemory(

  HANDLE hProcess,

  PVOID pvAddressRemote,

  PVOID pvBufferLocal,

  DWORD dwSize,

  PDWORD pdwNumBytesRead

  );

  

2、参数

hProcess                 [in]远程进程句柄。 被读取者

  pvAddressRemote   [in]远程进程中内存地址。 从具体何处读取

  pvBufferLocal          [out]本地进程中内存地址.  函数将读取的内容写入此处

  dwSize                     [in]要传送字节数。要写入多少

  pdwNumBytesRead [out]实际传送字节数.   函数返回时报告实际写入多少

[编辑本段]

三、例子

  ReadProcessMemory读出数据,权限要大一些。下面这个打开进程的方式具备了 查询 读和写的权限

  hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, ProcessId)

  Delphi下的OpenProcess

  var

  hProcess:HWND;

  wltId:DWord;

  hProcess:=OpenProcess(PROCESS_CREATE_THREAD + PROCESS_VM_OPERATION+ PROCESS_VM_WRITE, FALSE, wltId);

  然后就要结合上面的程序来搜索了。只有当内存是处于被占用状态时才去读取其中的内容,而忽略空 闲状态的内存。程序我就不在这儿写了,和上面那段差不多。只是把dwTotalCommit = dwTotalCommit + mi.RegionSize换成了读取内存以及搜索这一块内存的函数而已。

  1.通过FindWindow读取窗体的句柄

  2.通过GetWindowThreadProcessId读取查找窗体句柄进程的PID值

  var

  nProcId:DWord;

  nProcId:=GetWindowThreadProcessId(hFound, @nProcId);

  3.用OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, ProcessId)打开查到PID值的进程. 此打开具备读取,写入,查询的权限

  4.ReadProcessMemory读出指定的内存地址数据

  BOOL ReadProcessMemory(

  HANDLE hProcess, // 被读取进程的句柄;

  LPCVOID lpBaseAddress, // 读的起始地址;

  LPVOID lpBuffer, // 存放读取数据缓冲区;

  DWORD nSize, // 一次读取的字节数;

  LPDWORD lpNumberOfBytesRead // 实际读取的字节数;

  );

  例题:

  ReadProcessMemoryX(dwProcessId, (LPVOID)数据地址, szPassBuff, sizeof(szPassBuff), 0);

WriteProcessMemory

  EN:

  This function writes memory in a specified process. The entire area to be written to must be accessible, or the operation fails.

  BOOL WriteProcessMemory(

  HANDLE hProcess,

  LPVOID lpBaseAddress,

  LPVOID lpBuffer,

  DWORD nSize,

  LPDWORD lpNumberOfBytesWritten

  );

  Parameters

  hProcess

  [in] Handle returned from the OpenProcess function that provided full access to the process.

  lpBaseAddress

  [in] Pointer to the base address in the specified process.

  Before data transfer occurs, the system verifies that all data in the base address and memory of the specified size is accessible for write access. If so, the function proceeds; otherwise, the function fails.

  lpBuffer

  [in] Pointer to the buffer that supplies data to be written into the address space of the specified process.

  nSize

  [in] Specifies the requested number of bytes to write into the specified process.

  lpNumberOfBytesWritten

  [out] Pointer to the number of bytes transferred into the specified process.

  This parameter is optional.

  If lpNumberOfBytesWritten is NULL, the parameter is ignored.

  Return Values

  Nonzero indicates success.

  Zero indicates failure.

  To get extended error information, call GetLastError.

  The function fails if the requested write operation crosses into an area of the process that is inaccessible.

  Remarks

  WriteProcessMemory copies data from the specified buffer in the current process to the address range of the specified process. The process whose address space is being written to is typically, but not necessarily, being debugged.

  The entire area to be written to must be accessible. If it is not, the function fails.

  Requirements

  OS Versions: Windows CE 2.0 and later.

  Header: Winbase.h.

  Link Library: Nk.lib.

  See Also

  OpenProcess | ReadProcessMemory

  ---------------------------------------------------------------------------------------------

  ch:

  WriteProcessMemory

  VB函数原型:

  Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long

  作用:写内存

  说明:

  hProcess , 进程的句柄

  lpBaseAddress, 写入进程的位置(地址)

  lpBuffer, 数据当前存放地址

  nSize, 数据的长度

  lpNumberOfBytesWritten,实际数据的长度

  nSize以字节为单位,一个字节Byte等于8位

  基本数据类型的长度

  ShortInt 8位 = 1Byte

  SmallInt 16位 = 2Byte

  Integer 16位 = 2Byte

  LongInt 32位 = 4Byte

  Word 16位 = 2Byte

  LongWord 32位 = 4Byte

  Boolean 8位 = 1Byte

  WordBool 16位 = 2Byte

  LongBool 32位 = 4Byte

  比如要写入Integer类型的数据,那么Integer长度2Byte

  所以nSize = 2

VirtualQueryEx

  VirtualQueryEx

  函数功能描述:查询地址空间中内存地址的信息。

  函数原型:

  DWORD VirtualQueryEx( HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, DWORD dwLength );

  参数:

  hProcess    进程句柄。

  LpAddress   查询内存的地址。

  LpBuffer    指向MEMORY_BASIC_INFORMATION结构的指针,用于接收内存信息。

  DwLength    MEMORY_BASIC_INFORMATION结构的大小。

  返回值:

  函数写入lpBuffer的字节数,如果不等于sizeof(MEMORY_BASIC_INFORMATION)表示失败。

  备注:

  MEMORY_BASIC_INFORMATION在WinNT.h中定义如下:

  typedef struct _MEMORY_BASIC_INFORMATION {

  PVOID BaseAddress;       // 区域基地址。

  PVOID AllocationBase;    // 分配基地址。

  DWORD AllocationProtect; // 区域被初次保留时赋予的保护属性。

  SIZE_T RegionSize;       // 区域大小(以字节为计量单位)。

  DWORD State;             // 状态(MEM_FREE、MEM_RESERVE或 MEM_COMMIT)。

  DWORD Protect;           // 保护属性。

  DWORD Type;              // 类型。

  } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

  成员解释:

  BaseAddress                    与LpAddress参数的值相同,但是四舍五入为页面的边界值。

  AllocationBase                 指明用VirtualAlloc函数分配内存区域的基地址。LpAddress

  在该区域之内。

  AllocationProtect              指明该地址空间区域被初次保留时赋予该区域的保护属性。

  PAGE_READONLY              只读属性,如果试图进行写操作,将引发访问违规。如果系统

  区分只读、执行两种属性,那么试图在该区域执行代码也将引

  发访问违规。

  PAGE_READWRITE             允许读写。

  PAGE_EXECUTE               只允许执行代码,对该区域试图进行读写操作将引发访问违规。

  PAGE_EXECUTE_READ          允许执行和读取。

  PAGE_EXECUTE_READWRITE     允许读写和执行代码。

  PAGE_EXECUTE_WRITECOPY     对于该地址空间的区域,不管执行什么操作,都不会引发访问违

  规。如果试图在该页面上的内存中进行写入操作,就会将它自己

  的私有页面(受页文件的支持)拷贝赋予该进程。

  PAGE_GUARD                 在页面上写入一个字节时使应用程序收到一个通知(通过一个异

  常条件)。该标志有一些非常巧妙的用法。Windows 2000在创建

  线程堆栈时使用该标志。

  PAGE_NOACCESS              禁止一切访问。

  PAGE_NOCACHE               停用已提交页面的高速缓存。一般情况下最好不要使用该标志,

  因为它主要是供需要处理内存缓冲区的硬件设备驱动程序的开发

  人员使用的。

  RegionSize                     用于指明内存块从基地址即BaseAddress开始的所有页面的大

  小(以字节为计量单位)这些页面与含有用LpAddress参数设

  定的地址的页面拥有相同的保护属性、状态和类型。

  State                          用于指明所有相邻页面的状态。

  MEM_COMMIT                 指明已分配物理内存或者系统页文件。

  MEM_FREE                   空闲状态。该区域的虚拟地址不受任何内存的支持。该地址空间没

  有被保留。改状态下AllocationBase、AllocationProtect、Protect

  和Type等成员均未定义。

  MEM_RESERVE                指明页面被保留,但是没有分配任何物理内存。该状态下Protect成

  员未定。

  Protect                        用于指明所有相邻页面(内存块)的保护属性。这些页面与含有

  拥有相同的保属性、状态和类型。意义同AllocationProtect。

  Type                           用于指明支持所有相邻页面的物理存储器的类型(MEM_IMAGE,

  MEM_MAPPED或MEM_PRIVATE)。这些相邻页面拥有相同的保护属

  性、状态和类型。如果是Windows 98,那么这个成员将总是

  MEM_PRIVATE 。

  MEM_IMAGE                 指明该区域的虚拟地址原先受内存映射的映像文件(如.exe或DLL

  文件)的支持,但也许不再受映像文件的支持。例如,当写入模块

  映像中的全局变量时,“写入时拷贝”的机制将由页文件来支持特

  定的页面,而不是受原始映像文件的支持。

  MEM_MAPPED                该区域的虚拟地址原先是受内存映射的数据文件的支持,但也许不

  再受数据文件的支持。例如,数据文件可以使用“写入时拷贝”的

  保护属性来映射。对文件的任何写入操作都将导致页文件而不是原

  始数据支持特定的页面。

  MEM_PRIVATE               指明该内存区域是私有的。不被其他进程共享。

  示例代码:

  #include "stdafx.h"

  #include <windows.h>

  #include <TCHAR.H>

  BOOL ShowProcMemInfo(DWORD dwPID);

  int _tmain(int argc, char* argv[])

  {

  ShowProcMemInfo( GetCurrentProcessId() );

  return 0;

  }

  // 显示一个进程的内存状态 dwPID为进程ID

  BOOL ShowProcMemInfo(DWORD dwPID)

  {

  HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,

  FALSE,

  dwPID);

  if(hProcess == NULL)

  return FALSE;

  MEMORY_BASIC_INFORMATION mbi;

  PBYTE pAddress = NULL;

  TCHAR szInfo[200] = _T("BaseAddr     Size        Type        State         Protect /n");

  _tprintf(szInfo);

  while(TRUE)

  {

  if(VirtualQueryEx(hProcess, pAddress, &mbi, sizeof(mbi)) != sizeof(mbi))

  {

  break;

  }

  if((mbi.AllocationBase != mbi.BaseAddress) && (mbi.State != MEM_FREE))

  {

  _stprintf(szInfo, _T("  %08X  %8dK  "),

  mbi.BaseAddress,

  mbi.RegionSize>>10);

  }

  else

  {

  _stprintf(szInfo, _T("%08X    %8dK  "),

  mbi.BaseAddress,

  mbi.RegionSize>>10);

  }

  PCTSTR pStr = _T("");

  switch(mbi.Type)

  {

  case MEM_IMAGE:      pStr = _T("MEM_IMAGE  "); break;

  case MEM_MAPPED:   pStr = _T("MEM_MAPPED "); break;

  case MEM_PRIVATE:   pStr = _T("MEM_PRIVATE"); break;

  default:         pStr = _T("-----------"); break;

  }

  _tcscat(szInfo, pStr);

  _tcscat(szInfo, _T("  "));

  switch(mbi.State)

  {

  case MEM_COMMIT:   pStr = _T("MEM_COMMIT "); break;

  case MEM_RESERVE:   pStr = _T("MEM_RESERVE"); break;

  case MEM_FREE:      pStr = _T("MEM_FREE   "); break;

  default:         pStr = _T("-----------"); break;

  }

  _tcscat(szInfo, pStr);

  _tcscat(szInfo, _T("  "));

  switch(mbi.AllocationProtect)

  {

  case PAGE_READONLY:            pStr = _T("PAGE_READONLY         "); break;

  case PAGE_READWRITE:         pStr = _T("PAGE_READWRITE        "); break;

  case PAGE_WRITECOPY:         pStr = _T("PAGE_WRITECOPY        "); break;

  case PAGE_EXECUTE:            pStr = _T("PAGE_EXECUTE          "); break;

  case PAGE_EXECUTE_READ:         pStr = _T("PAGE_EXECUTE_READ     "); break;

  case PAGE_EXECUTE_READWRITE:   pStr = _T("PAGE_EXECUTE_READWRITE"); break;

  case PAGE_EXECUTE_WRITECOPY:   pStr = _T("PAGE_EXECUTE_WRITECOPY"); break;

  case PAGE_GUARD:            pStr = _T("PAGE_GUARD            "); break;

  case PAGE_NOACCESS:            pStr = _T("PAGE_NOACCESS         "); break;

  case PAGE_NOCACHE:            pStr = _T("PAGE_NOCACHE          "); break;

  default:                  pStr = _T("----------------------"); break;

  }

  _tcscat(szInfo, pStr);

  _tcscat(szInfo, _T("/n"));

  _tprintf(szInfo);

  pAddress = ((PBYTE)mbi.BaseAddress + mbi.RegionSize);

  }

  CloseHandle(hProcess);

  return TRUE;

  }

SetWindowsHookEx

目录[隐藏]

基本概念

运行机制

钩子回调函数必须按照以下的语法

几点说明

钩子类型

使用原型

[编辑本段]

基本概念

  钩子(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_JOURNALPLAYBACK Hook使应用程序可以插入消息到系统消息队列。可以使用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连续的鼠标和键盘事件。只要WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘事件就是无效的。

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

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

  WH_JOURNALPLAYBACK是system-wide local hooks,它们不会被注射到任何行程位址空间。

  7、WH_JOURNALRECORD Hook

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

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

  WH_JOURNALRECORD是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注册它自己。

最近研究的windows API相关推荐

  1. c语言windows api编程,windows API编程学习

    我并不是计算机专业的学生,从事的工作也和编程没啥关系,并且是工作了五六年后开始在业余时间学习windows编程的,这种背景下开始学编程确实比较痛苦. 买了Charles Petzold 的<wi ...

  2. windows API 菜鸟学习之路(一)

    从今天开始学习  windows api编程,记录菜鸟学习的点点滴滴 首先从线程开始 直接上函数 msdn上面的函数原型 HANDLE CreateThread(   LPSECURITY_ATTRI ...

  3. Windows API 函数SendMessage与PostMessage使用方法和常见的坑

    Windows API 函数中 SendMessage 与 PostMessage 用处很大,经常被程序员们使用.对老手们来说,了如知掌,但对新手来说,可能会遇到这样那样的问题.我作为一名老手中的新手 ...

  4. C++使用windows API实现https站点的访问

    以前,研究了一段时间的openssl,于是使用openssl实现了https站点的访问.后来发现,其实使用windows API也可以实现https站点的访问.关键就是设置一些标识符.关键代码如下: ...

  5. Rust/WinRT更名,全面支持Windows API

    击"开发者技术前线",选择"星标" 让一部分开发者看到未来 文 | 白开水 来自 | OSC开源社区 微软已宣布推出 Rust for Windows v0.9 ...

  6. 纯Windows API打造西门子移动网程控交换机人机终端(曾经最有成就感的作品)

    今天,翻了一下曾经写过的代码,曾经,因为工作需要,潜心研究了西门子移动网交换机人机互动编程,出了很多个OMTV操作终端版本,有delphi版的,有C++Builder版的,最有成就感的还是用VC++6 ...

  7. C#中调用Windows API时的数据类型对应关系

    C#中调用Windows API时的数据类型对应关系 原文 C#中调用Windows API时的数据类型对应关系 BOOL=System.Int32 BOOLEAN=System.Int32 BYTE ...

  8. C#调用windows api的要点

    在.Net Framework SDK文档中,关于调用Windows API的指示比较零散,并且其中稍全面一点的是针对Visual Basic .net讲述的.本文将C#中调用API的要点汇集如下,希 ...

  9. C#中调用Windows API的要点

    在.Net Framework SDK文档中,关于调用Windows API的指示比较零散,并且其中稍全面一点的是针对Visual Basic .net讲述的.本文将C#中调用API的要点汇集如下,希 ...

最新文章

  1. 第2关:计算二叉树的深度和节点个数
  2. Python集合之set()使用方法详解
  3. 强大Jquery插件,table排序之二
  4. 苹果9是5g手机吗_苹果手机扩容对手机有影响吗
  5. [vue] 如何引入scss?引入后如何使用?
  6. 「今天沾一口野味,明天地府相会!」AI如何抗击「野味肺炎」
  7. Linux 磁盘管理--RAID1创建
  8. Struts2 + Spring + Hibernate 通用 Service 和 DAO
  9. 那些非常好用的电脑软件
  10. 建立个人腾讯云服务器
  11. 图形面积计算Java,Java计算几何图形面积的实例代码
  12. 第十二周 项目一--图基本算法库
  13. QCC514x-QCC304x(headset)系列(实战篇)之5.1 tone详解
  14. 计算机模拟CS,CS跳跃模拟器电脑版_CS跳跃模拟器手游电脑版_游戏堡
  15. 使用FFMPEG 模仿微信拍视频
  16. Vue UI组件库(Element UI库)
  17. 相约,一朵春天的微笑
  18. 决策树(信息熵、增益率、基尼指数)
  19. java查找第k大的数字_查找数组中第k大的数
  20. oppo r9plus 无限制重启前的日志。

热门文章

  1. 葵花宝典第二招:突破单峰密集
  2. 魅族m15简单开启Usb调试模式的步骤
  3. Nature:13个维度,手把手教“研究er”如何做学术报告
  4. kubectl logs和docker logs输出日志不同的问题
  5. 雷军:小米今年预计销售200亿 站在风口猪都会飞
  6. 发生错误,无法导入项目(不能取回此项的内容)
  7. 什么是散列表(Hash Table)
  8. 如何在html页面中左尖括号,想要在HTML中显示一个尖括号“
  9. Qt 开发使用VSCode
  10. python 词云 教程