驱动开发:内核LDE64引擎计算汇编长度

本章开始LyShark将介绍如何在内核中实现InlineHook挂钩这门技术,内核挂钩的第一步需要实现一个动态计算汇编指令长度的功能,该功能可以使用LDE64这个反汇编引擎,该引擎小巧简单可以直接在驱动中使用,LDE引擎是BeaEngine引擎的一部分,后来让BeatriX打包成了一个ShellCode代码,并可以通过typedef动态指针的方式直接调用功能,本章内容作为后期Hook挂钩的铺垫部分,独立出来也是因为代码太多太占空间一篇文章写下来或很长影响阅读。

  • LDE反汇编引擎源代码:https://github.com/BeaEngine/lde64

首先定义一个lyshark_lde64.h头文件,并写入如下ShellCode代码片段,当然这不是最新的,如果你需要最新的可以自己下载源代码编译后提取出来替换即可,不过该引擎很多年没有更新了替换的意义也不大毕竟功能就那么几行而已。

// 署名权
// right to sign one's name on a piece of work
// thanks to Av0id , cyberbob and lena151 for their remarks and advices
// PowerBy: BeaEngine | BeatriX | LyShark
// Email: me@lyshark.com

// 反汇编引擎
unsigned char szShellCode[12800] =
{
// 无法保存:https://www.cnblogs.com/LyShark/p/16832307.html
}

那么该如何调用呢?调用其实很容易,首先调用lde_init()函数将功能载入到内存,然后通过lde_disasm()直接调用功能,在调用时第一个参数传入需要计算的内存地址,第二个参数是位数,如果传入0则表示计算32位汇编汇编,如果传入64则计算64位汇编长度。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com
#include "lyshark_lde64.h"
#include <ntifs.h>

// 计算地址处指令有多少字节
// address = 地址
// bits 32位驱动传入0 64传入64
typedef INT(*LDE_DISASM)(PVOID address, INT bits);

LDE_DISASM lde_disasm;

// 初始化引擎
VOID lde_init()
{
	lde_disasm = ExAllocatePool(NonPagedPool, 12800);
	memcpy(lde_disasm, szShellCode, 12800);
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动已卸载 \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("hello lyshark.com \n");

	// 初始化反汇编引擎
	lde_init();

	UNICODE_STRING unstr;
	PVOID addr;

	RtlInitUnicodeString(&unstr, L"PsLookupProcessByProcessId");
	addr = MmGetSystemRoutineAddress(&unstr);
	DbgPrint("获取内存地址: 0x%p \n", addr);

	// 计算第一条汇编指令长度
	INT asm_len = lde_disasm(addr, 64);
	DbgPrint("第一条指令长度: %d \n", asm_len);

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

运行上方的驱动程序,即可得到PsLookupProcessByProcessId函数第一条指令的实际长度,输出效果如下;

如果我们需要Hook挂钩则最常用的就是填充JMP跨4G跳转,该指令占用14个字节的内存长度,但我们无法保证14个字节就是一个完整的指令长度,有可能指令会被截断从而导致执行异常,此时必须得到完整指令的长度,指令长度就需要大于等于14,所以代码中的计算应该这样来实现。

// 署名权
// right to sign one's name on a piece of work
// PowerBy: LyShark
// Email: me@lyshark.com
#include "lyshark_lde64.h"
#include <ntifs.h>

// 计算地址处指令有多少字节
// address = 地址
// bits 32位驱动传入0 64传入64
typedef INT(*LDE_DISASM)(PVOID address, INT bits);

LDE_DISASM lde_disasm;

// 初始化引擎
VOID lde_init()
{
	lde_disasm = ExAllocatePool(NonPagedPool, 12800);
	memcpy(lde_disasm, szShellCode, 12800);
}

VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("驱动已卸载 \n");
}

// 得到完整指令长度,避免截断
ULONG GetFullPatchSize(PUCHAR Address)
{
	ULONG LenCount = 0, Len = 0;

	// 至少需要14字节
	while (LenCount <= 14)
	{
		Len = lde_disasm(Address, 64);
		Address = Address + Len;
		LenCount = LenCount + Len;
	}
	return LenCount;
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("hello lyshark.com \n");

	// 初始化反汇编引擎
	lde_init();

	UNICODE_STRING unstr;
	PVOID addr;

	RtlInitUnicodeString(&unstr, L"PsLookupProcessByProcessId");
	addr = MmGetSystemRoutineAddress(&unstr);
	DbgPrint("获取内存地址: 0x%p \n", addr);

	ULONG count = GetFullPatchSize(addr);
	DbgPrint("完整指令长度: %d \n", count);

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

运行这个驱动程序,计算得到的结果与上图作比较,此处得到的才是一个完整的指令长度;

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值