You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Windows ImportRedirection实现DLL导入函数Hook

Windows API导入重定向实现失效排查

问题背景

Windows 10及以上版本提供API Redirection(API导入重定向)特性,支持将进程加载DLL时的导入函数调用重定向到自定义实现,本次实现目标为:

  • 编写A.dll,导出原生Sum()函数
  • 编写Redirection.dll,实现自定义mySum()函数
  • 启动目标进程target.exe时,将其对A.dll!Sum()的调用重定向到Redirection.dll!mySum()
    初步规划实现步骤仅包含编写重定向DLL、关联重定向DLL创建进程两步,但实际运行时重定向DLL未被加载,重定向完全不生效。

现有实现代码

Redirection.dll 代码

#include "pch.h"
#include <stdlib.h>

int mySum(int a, int b) {
     printf("rewrite! \n");
    return 222222222;
} 

const REDIRECTION_FUNCTION_DESCRIPTOR RedirectionFunction[] = {
   { "Dll1.lib", "Sum", &mySum }
};

extern "C" __declspec(dllexport) const REDIRECTION_DESCRIPTOR __RedirectionInformation__ = {
  CURRENT_IMPORT_REDIRECTION_VERSION,
  _countof(RedirectionFunction),
  RedirectionFunction
};

A.dll 代码

#include "pch.h"
extern "C" _declspec(dllexport) int Sum(int a, int b) {
    printf("orginal dll1. \n");
    return a + b; 
}

target.exe 代码

#include <Windows.h>
#include <iostream>
#pragma comment(lib,"A.lib") 
#define DLLIMPORT extern "C" _declspec(dllimport)


DLLIMPORT int Sum(int a, int b);

int main() {
    std::cout << "this is injectFuction main process: Hello World!\n";
    std::cout << Sum(1, 2) << std::endl;
    Sleep(10000000);
    return 0; 
}

进程创建代码

#include <Windows.h>
#include "ntdll.h"

int main()
{
    UNICODE_STRING NtImagePath;
    UNICODE_STRING NtDLLPath;

    RtlInitUnicodeString(&NtImagePath, (PWSTR)L"\\??\\D:\\newJunFiles\\RedirectionExample\\x64\\Debug\\target.exe");
    RtlInitUnicodeString(&NtDLLPath, (PWSTR)L"\\??\\D:\\newJunFiles\\RedirectionExample\\x64\\Debug\\Redirection.dll");

    PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
     RtlCreateProcessParametersEx(&ProcessParameters,
        &NtImagePath, &NtDLLPath, NULL, NULL, NULL, NULL, NULL, NULL, NULL, RTL_USER_PROCESS_PARAMETERS_NORMALIZED);

    PS_CREATE_INFO CreateInfo = { 0 };
    CreateInfo.Size = sizeof(CreateInfo);
    CreateInfo.State = PsCreateInitialState;

    PPS_ATTRIBUTE_LIST AttributeList = (PPS_ATTRIBUTE_LIST)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PS_ATTRIBUTE));
    AttributeList->TotalLength = sizeof(PS_ATTRIBUTE_LIST) - sizeof(PS_ATTRIBUTE);
    AttributeList->Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
    AttributeList->Attributes[0].Size = NtImagePath.Length;
    AttributeList->Attributes[0].Value = (ULONG_PTR)NtImagePath.Buffer;

    HANDLE hProcess, hThread = NULL;
    NtCreateUserProcess(&hProcess,
        &hThread, 
        PROCESS_ALL_ACCESS,
        THREAD_ALL_ACCESS,
        NULL, NULL, NULL, NULL,
        ProcessParameters,
        &CreateInfo,
        AttributeList);

    RtlFreeHeap(RtlProcessHeap(), 0, AttributeList);
    RtlDestroyProcessParameters(ProcessParameters);
}

失效原因与修正方案

现有实现存在3个核心错误,按顺序修正即可生效:

  1. 重定向描述符DLL名称配置错误
    REDIRECTION_FUNCTION_DESCRIPTOR结构体第一个字段需要填写被重定向DLL的PE导出名称,不是导入库的.lib后缀名。你要重定向的是A.dll的导出,这里应填"A.dll",而非"Dll1.lib"。
    修正后的重定向函数表写法:
const REDIRECTION_FUNCTION_DESCRIPTOR RedirectionFunction[] = {
   { "A.dll", "Sum", &mySum }
};
  1. 错误使用RtlCreateProcessParametersEx参数
    该函数第三个参数是进程初始化时的默认DLL搜索路径,不是用来指定要加载的重定向DLL路径,直接将该参数传NULL即可。重定向DLL只需要放在目标EXE同目录,或者加入系统已知DLL列表,就能被加载器自动识别。
  2. PS_ATTRIBUTE列表缺少重定向启用配置
    当前属性列表仅配置了镜像名称,没有添加PS_ATTRIBUTE_REDIRECTION_STATE属性来显式启用导入重定向,加载器不会主动扫描重定向DLL的导出符号。需要在属性列表中新增该配置项,设置值为启用状态。

额外注意事项:

  • __RedirectionInformation__导出符号必须用extern "C"修饰避免名称改编,当前写法正确无需修改
  • 重定向函数的签名、参数个数、调用约定必须和原函数完全一致,否则会触发栈损坏
  • 重定向DLL的架构必须和目标进程完全匹配,x64进程只能加载x64重定向DLL,x86同理
    补充:该API重定向特性仅在Windows 10 1903及以上版本系统中生效,低版本系统不支持该机制

内容的提问来源于stack exchange,提问作者GuangJun Liu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 13:51:09