C++ 系统范围ApI挂钩

C++ 系统范围ApI挂钩,c++,dll,hook,C++,Dll,Hook,我必须开发一个程序,它可以钩住kernel32.dll,Advapi32.dll中的一些函数 例如,我必须更改某些函数的功能,例如 RegOpenKey()。由于这个事实,我不能向目标进程注入任何代码, 因为,当目标程序启动时,它首先调用该函数 我还被迫不向目标进程注入任何代码。 此外,我必须为每个当前正在运行的进程和应用程序(32位、控制台应用程序、Win应用程序)更改此功能,这些将在将来运行。 我读过很多关于DLL注入、DLL挂钩的文章,但我不知道如何克服这些。 因此,请帮助我并与我分享您的

我必须开发一个程序,它可以钩住kernel32.dll,Advapi32.dll中的一些函数 例如,我必须更改某些函数的功能,例如 RegOpenKey()。由于这个事实,我不能向目标进程注入任何代码, 因为,当目标程序启动时,它首先调用该函数 我还被迫不向目标进程注入任何代码。 此外,我必须为每个当前正在运行的进程和应用程序(32位、控制台应用程序、Win应用程序)更改此功能,这些将在将来运行。 我读过很多关于DLL注入、DLL挂钩的文章,但我不知道如何克服这些。
因此,请帮助我并与我分享您的知识。

也许您可以看看。

根据您的需要,您应该编写一个内核驱动程序,可以钩住所需的调用,您希望更改(或提供)额外的功能。例如:如果你钩住
write
调用,在你的机器上运行的每个程序(除了一些可能的例外,我认为你不应该担心),当你调用
write
操作时,你的钩住函数将被调用,其中包含关于调用过程的适当信息和一些其他信息(通常称为回调数据)。然后,您可以在钩住的函数中执行/添加任何您想做的事情


如果您使用的是windows xp SP3及更高版本,您可以选择一个筛选器驱动程序,因为与传统的windows驱动程序相比,它易于学习和实现。虽然筛选器驱动程序有一些限制,但根据您的要求,它们将非常适合您。

为此,您最好的选择是热补丁,这是MS自己使用它们来应用系统范围内的de当函数通过其更新系统进行修补时,将进行巡查。

在不注入代码的情况下拦截的唯一选项是内核模式驱动程序。注册表驱动程序很容易从Vista+实现,但您需要进行一些SSDT注册表挂接。在XP和Vista/W7中,SSDT不适用于相同的代码,在x64中根本不起作用环境(不允许使用挂钩技术)。
因此,您必须为XP制作一个内核模式过滤器驱动程序,为Vista和W7()制作一个挂接注册表SSDT和CmRegisterCallback的驱动程序.

正如我从您的描述中了解到的,您希望更改某个API的行为。但是,您没有指定是要更改传递给此类API的数据还是忽略请求。在任何情况下,对于此类需求,最简单的解决方案是编写一个迷你过滤器内核驱动程序。在这种方法中,您将l使用
CmRegisterCallbackEx
而不是
CmRegisterCallback
(因为这一个已经过时)注册回调以筛选注册表事件。然后,您可以编写自己的回调函数来处理您要更改的每个注册表事件。下面是一个关于如何编写此类迷你筛选器内核驱动程序的简单片段。请记住,您仍然需要编写逻辑,通过简单地拒绝请求或改变它的内容

#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>

LARGE_INTEGER g_Cookie = { 0 };

NTSTATUS DriverRegistryCallback(
    _In_ PVOID CallbackContext, 
    _In_ PVOID Argument1, 
    _In_ PVOID Argument2
    ) {
    UNREFERENCED_PARAMETER(CallbackContext);

    PREG_POST_OPERATION_INFORMATION PreInfo;
    PREG_OPEN_KEY_INFORMATION_V1 OpenKey;
    PREG_CREATE_KEY_INFORMATION_V1 CreateKey;

    REG_NOTIFY_CLASS RegOp = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1;
    switch (RegOp) {
        case RegNtPreCreateKeyEx:
            PreInfo = (PREG_POST_OPERATION_INFORMATION)Argument2;
            CreateKey = (PREG_CREATE_KEY_INFORMATION_V1)PreInfo->PreInformation;
            if (PreInfo->Status == STATUS_SUCCESS) {
                // do something here
            }
            break;

        case RegNtPreOpenKeyEx:
            PreInfo = (PREG_POST_OPERATION_INFORMATION)Argument2;
            OpenKey = (PREG_OPEN_KEY_INFORMATION_V1)PreInfo->PreInformation;
            if (PreInfo->Status == STATUS_SUCCESS) {
                // do something here
            }
            break;

        default:
            break;
    }

    return STATUS_SUCCESS;
}

VOID 
DriverUnload(
    _In_ PDRIVER_OBJECT pDriverObject
    ) {
    UNREFERENCED_PARAMETER(pDriverObject);

    PAGED_CODE();

    NTSTATUS status = CmUnRegisterCallback(g_Cookie);
    if (!NT_SUCCESS(status)) {
        DbgPrint("[RegistryFilter] Failed to unregister callback\n");
    }

    DbgPrint("[RegistryFilter] Driver unloaded successfully\n");
}

NTSTATUS 
DriverEntry(
    _In_ PDRIVER_OBJECT pDriverObject, 
    _In_ PUNICODE_STRING pRegistryPath
    ) {
    UNREFERENCED_PARAMETER(pRegistryPath);

    pDriverObject->DriverUnload = DriverUnload;

    UNICODE_STRING AltitudeString = RTL_CONSTANT_STRING(L"360000");
    NTSTATUS status = CmRegisterCallbackEx(DriverRegistryCallback, &AltitudeString, pDriverObject, NULL, &g_Cookie, NULL);
    if (!NT_SUCCESS(status)) {
        DbgPrint("[RegistryFilter] Failed to register callback\n");

        return status;
    }

    DbgPrint("[RegistryFilter] Driver loaded successfully\n");

    return status;
}
#包括
#包括
#包括
大整数g_Cookie={0};
NTSTATUS驱动器注册回调(
_在uupvoid回调上下文中,
_在uupvoid Argument1中,
_In_uupvoidargument2
) {
未引用的_参数(CallbackContext);
预、后、操作信息预信息;
PREG_OPEN_KEY_INFORMATION_V1 OpenKey;
PREG_CREATE_KEY_INFORMATION_V1 CreateKey;
REG_NOTIFY_CLASS RegOp=(REG_NOTIFY_CLASS)(ULONG_PTR)参数1;
开关(RegOp){
案例RegNtPreCreateKeyEx:
PreInfo=(PREG\u POST\u OPERATION\u INFORMATION)Argument2;
CreateKey=(PREG\u CREATE\u KEY\u INFORMATION\u V1)PreInfo->PreInformation;
如果(预信息->状态==状态\成功){
//在这里做点什么
}
打破
案例RegNtPreOpenKeyEx:
PreInfo=(PREG\u POST\u OPERATION\u INFORMATION)Argument2;
OpenKey=(PREG\u OPEN\u KEY\u INFORMATION\u V1)PreInfo->PreInformation;
如果(预信息->状态==状态\成功){
//在这里做点什么
}
打破
违约:
打破
}
返回状态\成功;
}
无效的
驱动负载(
_In_PDRIVER_PDRIVER对象PDRIVER对象
) {
未引用的_参数(pDriverObject);
PAGED_代码();
NTSTATUS status=CmUnRegisterCallback(g_Cookie);
如果(!NT_成功(状态)){
DbgPrint(“[RegistryFilter]未能注销回调\n”);
}
DbgPrint(“[RegistryFilter]驱动程序已成功卸载\n”);
}
NTSTATUS
出租汽车(
_在PDRIVER对象pDriverObject中,
_在\uPUNICODE\u字符串预存路径中
) {
未引用的_参数(pRegistryPath);
pDriverObject->drivernload=drivernload;
UNICODE_STRING AltitudeString=RTL_常量_字符串(L“360000”);
NTSTATUS status=CmRegisterCallbackEx(DriverRegistryCallback和AltitudeString、pDriverObject、NULL和g_Cookie、NULL);
如果(!NT_成功(状态)){
DbgPrint(“[RegistryFilter]注册回调失败\n”);
返回状态;
}
DbgPrint(“[RegistryFilter]驱动程序已成功加载\n”);
返回状态;
}
请记住,这不是您的最终解决方案。您需要编写您自己的逻辑,正如我前面提到的,通过将返回的数据与您自己的静态数据进行比较,然后返回
状态\u访问\u拒绝
来拒绝访问某个调用,或者更改保留值的数据结构,然后将其传回。您必须知道如果您希望更改任何
Open*
事件,您需要首先处理
Create*
事件。因为任何
Open*
事件都必须先处理
Create*
事件

另一方面,由于索引从Windows版本到另一版本以及从一个Service Pack到另一个Service Pack的变化,SSDT不是一个更好的解决方案。一般来说,它是不可靠的,至少对于这个简单的任务,不建议使用它。更不用说在x64 a上使用它会有问题