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

为何硬编码路径下nss3.dll加载仍返回126错误?

调用nss3.dll解密时出现ERROR_MOD_NOT_FOUND(126)错误排查

问题描述

尝试用C语言调用nss3.dll进行解密操作,实现代码如下:

#include <stdio.h>
#include <windows.h>


typedef int SECStatus;
typedef struct {
    unsigned char *data;
    unsigned int len;
} SECItem;

typedef struct {
} PK11SlotInfo;
typedef SECStatus (*PK11SDR_Decrypt_p)(SECItem*, SECItem*, void*);
typedef PK11SlotInfo* (*PK11_GetInternalKeySlot_p)(void);
typedef void (*PK11_FreeSlot_p)(PK11SlotInfo*);
typedef SECStatus (*NSS_Init_p)(const char*);
typedef void (*NSS_Shutdown_p)(void);
typedef void (*PL_ArenaFinish_p)(void);
typedef SECStatus (*PR_Cleanup_p)(void);

PK11_GetInternalKeySlot_p fpPK11_GetInternalKeySlot = NULL;
PK11_FreeSlot_p fpPK11_FreeSlot = NULL;
PK11SDR_Decrypt_p fpPK11SDR_Decrypt = NULL;
NSS_Init_p fpNSS_Init = NULL;
NSS_Shutdown_p fpNSS_Shutdown = NULL;
PL_ArenaFinish_p fpPL_ArenaFinish = NULL;
PR_Cleanup_p fpPR_Cleanup = NULL;

int Base64Decode(const char* input, char** output, DWORD* outputSize) {
    DWORD cryptFlags = CRYPT_STRING_BASE64;
    HMODULE hCrypt32 = LoadLibrary("crypt32.dll");
    if (!hCrypt32) {
        return -2;
    }
    typedef BOOL(WINAPI* CryptStringToBinaryFunc)(LPCSTR, DWORD, DWORD, BYTE*, DWORD*, DWORD*, DWORD*);
    CryptStringToBinaryFunc cryptStringToBinary = (CryptStringToBinaryFunc)GetProcAddress(hCrypt32, "CryptStringToBinaryA");
    if (!cryptStringToBinary) {
        FreeLibrary(hCrypt32);
        return -3;
    }
    if (!cryptStringToBinary(input, 0, cryptFlags, NULL, outputSize, NULL, NULL)) {
        FreeLibrary(hCrypt32);
        return -4;
    }
    *output = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *outputSize);
    if (!*output) {
        FreeLibrary(hCrypt32);
        return -5;
    }
    if (!cryptStringToBinary(input, 0, cryptFlags, (BYTE*)*output, outputSize, NULL, NULL)) {
        HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, *output);
        FreeLibrary(hCrypt32);
        return -6;
    }
    FreeLibrary(hCrypt32);
    return 0;
}

BOOL initNSS() {
    HMODULE moduleNSS = LoadLibrary("C:\\Program Files\\Mozilla Firefox\\nss3.dll");
    if (moduleNSS == NULL) {
        printf("Error loading nss3.dll: %d\n", GetLastError());
        return FALSE;
    }
    fpNSS_Init = (NSS_Init_p)GetProcAddress(moduleNSS, "NSS_Init");
    fpNSS_Shutdown = (NSS_Shutdown_p)GetProcAddress(moduleNSS, "NSS_Shutdown");
    fpPL_ArenaFinish = (PL_ArenaFinish_p)GetProcAddress(moduleNSS, "PL_ArenaFinish");
    fpPR_Cleanup = (PR_Cleanup_p)GetProcAddress(moduleNSS, "PR_Cleanup");
    fpPK11_GetInternalKeySlot = (PK11_GetInternalKeySlot_p)GetProcAddress(moduleNSS, "PK11_GetInternalKeySlot");
    fpPK11_FreeSlot = (PK11_FreeSlot_p)GetProcAddress(moduleNSS, "PK11_FreeSlot");
    fpPK11SDR_Decrypt = (PK11SDR_Decrypt_p)GetProcAddress(moduleNSS, "PK11SDR_Decrypt");

    if (!fpNSS_Init || !fpNSS_Shutdown || !fpPL_ArenaFinish || !fpPR_Cleanup || !fpPK11_GetInternalKeySlot || !fpPK11_FreeSlot || !fpPK11SDR_Decrypt) {
        printf("Error getting function pointers from nss3.dll\n");
        FreeLibrary(moduleNSS);
        return FALSE;
    }
    return 0;
}

char* DecryptString(char* strCryptData) {
    if (strCryptData[0] == 0x0) {
        return NULL;
    }

    DWORD dwOut;
    char* strClearData = NULL;
    char* lpBuffer;
    DWORD outputSize;

    int result = Base64Decode(strCryptData, &lpBuffer, &outputSize);
    if (result != 0) {
        printf("Error decoding Base64: %d\n", result);
        return NULL;
    }

    if (!initNSS() == 0) {
        printf("Error initializing NSS.\n");
        return NULL;
    }

    PK11SlotInfo* pK11Slot = fpPK11_GetInternalKeySlot();
    if (pK11Slot) {
        SECItem pInSecItem, pOutSecItem;

        pInSecItem.data = (unsigned char*)lpBuffer;
        pInSecItem.len = outputSize;

        pOutSecItem.data = NULL;
        pOutSecItem.len = 0;

        if (fpPK11SDR_Decrypt(&pInSecItem, &pOutSecItem, NULL) == 0) {
            strClearData = (char*)malloc(pOutSecItem.len + 1);
            if (strClearData != NULL) {
                memcpy(strClearData, pOutSecItem.data, pOutSecItem.len);
                strClearData[pOutSecItem.len] = '\0';
            }
        }

        fpPK11_FreeSlot(pK11Slot);
    }

    fpNSS_Shutdown();
    fpPL_ArenaFinish();
    fpPR_Cleanup();
    HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpBuffer);

    return strClearData;
}

int main() {
    char* encryptedData = "MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECGBlfa+Zvyb2BBBCU5Y9bU8rUwoDfW2dn7yO";
    char* decryptedData = DecryptString(encryptedData);
    if (decryptedData != NULL) {
        printf("Decrypted string: %s\n", decryptedData);
        free(decryptedData);
    } else {
        printf("Decryption failed.\n");
    }

    return 0;
}

运行代码时始终报错:

Error loading nss3.dll: 126

根据微软官方文档,错误码126对应ERROR_MOD_NOT_FOUND(0x7E),即指定模块未找到,但已确认nss3.dll存在于硬编码路径C:\Program Files\Mozilla Firefox\nss3.dll中,怀疑错误出在initNSS函数中,需协助排查问题原因。

已参考以下文档:

  • 《Firefox凭据的秘密》
  • 《网络安全服务(NSS) - Firefox源码文档》

问题分析与解决方法

核心原因:依赖库缺失或位数不兼容

错误码126并非一定是目标dll不存在,更多时候是目标dll的依赖库无法被加载。nss3.dll并非独立运行的库,它依赖Firefox目录下的其他核心库(如nspr4.dll、plc4.dll、plds4.dll等),系统加载nss3.dll时会自动查找这些依赖,若找不到就会返回126错误。

具体解决步骤

  1. 检查程序与dll的位数兼容性

    • 确认编译的程序位数(32位/64位)与Firefox安装目录的dll位数一致:
      • 若程序是32位,需使用32位Firefox目录下的nss3.dll;
      • 若程序是64位,需使用64位Firefox目录下的nss3.dll。
    • 位数不匹配会直接导致加载失败,返回126错误。
  2. 确保依赖库可被系统找到
    有两种方式解决依赖库查找问题:

    • 方式一:将Firefox安装目录(C:\Program Files\Mozilla Firefox\)添加到系统PATH环境变量中,重启程序后再运行;
    • 方式二:使用LoadLibraryEx替代LoadLibrary,指定LOAD_WITH_ALTERED_SEARCH_PATH参数,让系统优先从nss3.dll所在目录查找依赖。修改initNSS函数中的加载代码:
      HMODULE moduleNSS = LoadLibraryEx("C:\\Program Files\\Mozilla Firefox\\nss3.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
      
  3. 修正initNSS函数的返回值错误
    当前initNSS函数声明返回BOOL,但最后返回0(对应FALSE),这会导致后续判断!initNSS() == 0逻辑错误。需将最后一行返回值改为TRUE:

    return TRUE;
    

内容的提问来源于stack exchange,提问作者M A I N

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:17:01