软件安全之Hook 技术 Inline Hook技术应用 TraceMe.exe


百度网盘地址(提取码1111)中计算序列号的代码,获取正确的序列号,加深对 Hook 技术的理解。

实验 4 练习3DLL 中的步骤,创建 DLL 项目,实现劫持 lpk.dll 的功能,并在 DllMain 创建的线程函数中,将弹出对话框的功能替换为安装 Inline Hook

在这里插入图片描述

线程函数

实验 2 中的分析可知,下图所示 TraceMe.exe 中调用 wsprintfA 之前,计算得到的序列号存放在 edx 寄存器中,并被压入栈,调用 wsprintfA 之后,序列号仍在栈中,因此可通过 Hook 图中红色框中的指令获取序列号。

在这里插入图片描述

TraceMe 格式化序列号的指令

据此实现的 Detour 函数如图所示,图中 XX 的值为8 ,AAAA、BBBB、CCCC 三条指令依次为:add esp,0xcpush edipush dword ptr[ebp+8]

  • 在这里插入图片描述
Detour 函数
- `push [esp + 8]`是为了将计算得出的edx序列号压入栈。 - esp是栈指针,push、pop指令会自动调整esp的值;esp为x86CPU使用的堆栈指针,每进行一次入栈操作,esp要减4,堆栈一个单元是4Byte,进过了两次push才将序列号送进去,使用基址-偏移量寻址,即[esp+8]。
  • 三条指令是为了保持原有功能,防止程序运行出错。

__declspec(naked)是告知编译器代码中的汇编语言不需要编译器画蛇添足添加其它汇编代码。对于jmp类型的hook,若没有说明__declspec(naked),系统为了控制堆栈平衡,会自动添加一些额外的代码,破坏hook函数的堆栈。如果没有使用JMP到原函数,就必须要用 RET 或 RET n 指令返回。

_declspec(naked) void DetourFunction() 
{
	_asm
	{
		push [esp + 8]
		call DoSomething

		add esp,0xc
		push edi
		push dword ptr[ebp+8]
		jmp g_backPos
	}
}

实验 4 练习3DLL劫持 步骤4的操作,新建文件夹,并将 TraceMe.exe、lpk.dll 和 lpkOrg.dll 放在该文件夹中。运行 TraceMe.exe,输入用户名和序列号,观察计算得到的序列号。

在这里插入图片描述

随后我们输入发现确实成功了

在这里插入图片描述

参照实验2用 OllyDbg 打开修改后的 TraceMe,观察 Hook 之处的代码。

  • 快捷键Ctrl+G打开"跟随表达式"窗口,找到 GetWindowTextA 函数的入口地址,按下 F2 快捷键在入口处下断点;

在这里插入图片描述

在这里插入图片描述

  • 按下 F9 快捷键运行程序,在程序窗口中输入用户名,然后单击 "Check"按钮;

  • 程序在 GetWindowTextA 函数的入口地址处暂停,按下 F2 快捷键,取消该处的断点,之后按下"Alt+F9"快捷键,从系统代码空间返回用户代码空间。

  • 找到紧跟在两次调用 GetDlgItemTextA 函数之后的调用用户自定义函数处,按下 F4 快捷键运行到该处;或者以 F8 单步跟踪的方式,运行到该处,如图所示的00BD11EF |. E8 92FEFFFF call 00BD1086的指令。

在这里插入图片描述

  • F7 进入该函数内部, 然后运行至调用 lstrcmpA 函数处,发现指令确实已经被修改,多了一个jmp指令不知跳向何方

    在这里插入图片描述

  • 但程序知道,F4运行至jmp处变跳转到了目标地址,来到了它的起源地,如下图所示,正是我们创造出的Hook,正是我们第二步所编写的Detour函数。

    在这里插入图片描述

6思考与总结

1尝试用其他非 JMP 方式,以及不同的位置实现 Inline Hook。

  • 在构造Detour 函数时我们变知晓,如果没有使用JMP到原函数,就必须要用 RET 或 RET n 指令返回。故也可以使用这种方式实现Hook。

2总结 C/ASM 混合编程的方法。

  • C指C,ASM是C++中的一个关键字,用于在C++源码中内嵌汇编语言。__asm关键字启动内联汇编并且能写在任何C++合法语句之处。汇编代码装入asm代码块中。