C++动态库获取调用者

前言:

如果你自己写了一个C++动态库,不希望别人的程序能调用,那么本篇文章能为你提供一个思路,通过获取调用了动态库的进程的信息进行判断。

核心代码:

#include <Windows.h>
#include <TlHelp32.h>
#include <Psapi.h>
#include <tchar.h>

#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "version.lib")

// 获取文件的详细信息
int get_file_detail_info(LPCWSTR procPath, LPCTSTR pName, LPTSTR ptBuf, UINT lenBuf) {
	try
	{
		DWORD dwDummyHandle = 0;
		DWORD dwLen = 0;
		LPBYTE pVersionInfo = NULL;
		BOOL bRetVal;

		VS_FIXEDFILEINFO FileVersion;

		struct TRANSLATION
		{
			WORD langID;
			WORD charset;
		} Translation;
		Translation.langID = 0x0409;
		Translation.charset = 1252;

		dwLen = GetFileVersionInfoSize(procPath, &dwDummyHandle);
		if (dwLen == 0) {
			//write_log("test", "GetFileVersionInfoSize Error!!");
			return -1;
		}
		pVersionInfo = new BYTE[dwLen];
		bRetVal = GetFileVersionInfo(procPath, NULL, dwLen, pVersionInfo);
		if (bRetVal == FALSE) {
			//write_log("test", "GetFileVersionInfo Error!!");
			return -1;
		}
		LPVOID pVI;
		UINT uLen;

		bRetVal = VerQueryValue(pVersionInfo, L"\\", &pVI, &uLen);
		if (bRetVal == FALSE) {
			//write_log("test", "VerQueryValue Error!!");
			return -1;
		}

		memcpy(&FileVersion, pVI, sizeof(VS_FIXEDFILEINFO));

		bRetVal = VerQueryValue(pVersionInfo, L"\\VarFileInfo\\Translation", &pVI, &uLen);
		if (bRetVal && uLen >= 4) {
			memcpy(&Translation, pVI, sizeof(TRANSLATION));
		}
		else {
			//write_log("test", "Translation Error[1]!!");
			return -1;
		}

		if (FileVersion.dwSignature != VS_FFI_SIGNATURE) {
			//write_log("test", "Translation Error[2]!!");
			return -1;
		}

		LPVOID pVal;
		UINT iLenVal;

		if (pName != NULL) {
			TCHAR szQuery[1024];
			_stprintf_s(szQuery, 1024, L"\\StringFileInfo\\%04X%04X\\%s", Translation.langID, Translation.charset, pName);
			bRetVal = VerQueryValue(pVersionInfo, szQuery, &pVal, &iLenVal);
			if (bRetVal) {
				_stprintf_s(ptBuf, lenBuf, L"%s", (TCHAR*)pVal);
			}
			else {
				_stprintf_s(ptBuf, lenBuf, L"%s", L"");
			}
		}

		delete[] pVersionInfo;
		return 0;
	}
	catch (const std::exception&)
	{
		return -99;
	}
}

// 鉴权
int auth_func(wstring dll_company_name) {
	try
	{
		int res = 0;
		PROCESSENTRY32 pe32; //进程结构
		pe32.dwSize = sizeof(PROCESSENTRY32);
		// 给系统内所有的进程拍个快照
		HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		// 某个进程所有的DLL快照句柄
		HANDLE hModuleSnap = NULL;
		if (hProcessSnap == INVALID_HANDLE_VALUE) {
			return -1;
		}
		BOOL bMore = ::Process32First(hProcessSnap, &pe32);
		HANDLE hProcess = NULL;
		WCHAR procPath[_MAX_PATH] = { 0 };
		MODULEENTRY32 lpme;
		lpme.dwSize = sizeof(MODULEENTRY32);
		BOOL bRet = FALSE;
		// 遍历进程快照,显示每个进程的信息
		while (bMore) {
			// 打开一个已存在的进程对象,并返回进程句柄
			hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
			// 得到该进程的全路径
			GetModuleFileNameEx(hProcess, NULL, procPath, _MAX_PATH);
			wstring exeName(pe32.szExeFile);
			// write_log("debug", L"PorcessName: " + exeName); // 进程名称 xx.exe
			// write_log("debug", "PID: " + to_string(pe32.th32ProcessID)); // 进程PID
			// 给一个已存在的进程内所有的DLL拍个快照
			hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe32.th32ProcessID);
			bRet = ::Module32First(hModuleSnap, &lpme);
			// 遍历DLL快照,显示该进程所加载的DLL信息
			while (bRet) {
				wstring dllPath(lpme.szExePath);
				// write_log("debug", L"--- " + dllPath); // 进程完整路径 及 引用DLL文件完整路径

				if (dllPath.find(string2wstring(currentName)) != string::npos && exeName != L"[System Process]") {
					// 找到本程序集的调用者【父进程】
					// write_log("test", L"Parent Process: " + wstring(procPath));
					// 获取父进程信息
					TCHAR* companyNameStr = new TCHAR[1024];
					get_file_detail_info(procPath, L"CompanyName", companyNameStr, 1024); // 公司
					TCHAR* copyrightStr = new TCHAR[1024];
					get_file_detail_info(procPath, L"LegalCopyright", copyrightStr, 1024); // 版权
					// 判断父进程是否获得授权
					if (wstring(companyNameStr).find(dll_company_name) != string::npos && wstring(copyrightStr).find(dll_company_name) != string::npos) {
						res = 1;
					}
				}

				bRet = ::Module32Next(hModuleSnap, &lpme);
			}
			// 关闭快照对象
			::CloseHandle(hModuleSnap);
			bMore = ::Process32Next(hProcessSnap, &pe32);
			// write_log("debug", "---------");
		}
		// 关闭快照对象
		::CloseHandle(hProcessSnap);
		return res;
	}
	catch (const std::exception&)
	{
		return -99;
	}
}

调用方式:

// 动态库入口函数
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH: {
            // 鉴权,为全局变量赋值
            isAuth = auth_func(L"xxxx有限公司") == 1;
            break;
        }
        case DLL_THREAD_ATTACH: {
            break;
        }
        case DLL_THREAD_DETACH: {
            break;
        }
        case DLL_PROCESS_DETACH: {
        }
    }
    return TRUE;
}

调用者(*.exe)需要做的对应更改:

以.NET为例,项目属性中的Copyright标签与Company标签都需要打上版权标识

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWindowsForms>true</UseWindowsForms>
    <ImplicitUsings>enable</ImplicitUsings>
    <PlatformTarget>x86</PlatformTarget>
    <Copyright>xxxx有限公司© 2025</Copyright>
	<Company>xxxx有限公司</Company>
  </PropertyGroup>

</Project>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值