3I5105 发表于 2024-11-18 14:20

version.dll劫持注入模版(支持x64)

version.dll劫持是经常用到的技术,但是我用c写劫持dll时总是得把所有导出函数都写一遍
version.dll劫持注入模版_version.dll 劫持源代码-CSDN博客
网上能搜到的只能支持32位
其实这事说简单也简单,没啥技术含量;说难也难,有十几个函数得按着签名写一遍...非常浪费时间,故把通用模板放到论坛上以备我自己和大家取用
#include <Windows.h>

// 处理MSVC下wcscat警告
#ifdef _MSC_VER
#pragma warning(disable:4996)
#endif

// 全局原始version.dll句柄
static HMODULE hVersion;

// 辅助取函数地址
PVOID GetVersionFuncAddress(LPCSTR FuncName)
{
    if(!hVersion)
    {
      wchar_t systemDirectory;
      if (!::GetSystemDirectory(systemDirectory, MAX_PATH))
            return nullptr;
      wcscat(systemDirectory, L"\\System32\\version.dll");
      hVersion = ::LoadLibraryW(systemDirectory);
      if (!hVersion)
            return nullptr;
    }
    return GetProcAddress(hVersion, FuncName);
}

// 导出
#pragma comment(linker, "/EXPORT:GetFileVersionInfoA=P_GetFileVersionInfoA,@1")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoByHandle=P_GetFileVersionInfoByHandle,@2")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoExA=P_GetFileVersionInfoExA,@3")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoExW=P_GetFileVersionInfoExW,@4")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeA=P_GetFileVersionInfoSizeA,@5")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExA=P_GetFileVersionInfoSizeExA,@6")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExW=P_GetFileVersionInfoSizeExW,@7")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeW=P_GetFileVersionInfoSizeW,@8")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoW=P_GetFileVersionInfoW,@9")
#pragma comment(linker, "/EXPORT:VerFindFileA=P_VerFindFileA,@10")
#pragma comment(linker, "/EXPORT:VerFindFileW=P_VerFindFileW,@11")
#pragma comment(linker, "/EXPORT:VerInstallFileA=P_VerInstallFileA,@12")
#pragma comment(linker, "/EXPORT:VerInstallFileW=P_VerInstallFileW,@13")
#pragma comment(linker, "/EXPORT:VerLanguageNameA=P_VerLanguageNameA,@14")
#pragma comment(linker, "/EXPORT:VerLanguageNameW=P_VerLanguageNameW,@15")
#pragma comment(linker, "/EXPORT:VerQueryValueA=P_VerQueryValueA,@16")
#pragma comment(linker, "/EXPORT:VerQueryValueW=P_VerQueryValueW,@17")


// 原始函数
extern "C" BOOL P_GetFileVersionInfoA(
    LPCSTR lptstrFilename,
    DWORD dwHandle,
    DWORD dwLen,
    LPVOID lpData
) {
    BOOL(*pGetFileVersionInfoA)(LPCSTR, DWORD, DWORD, LPVOID) = (BOOL(*)(LPCSTR, DWORD, DWORD, LPVOID)) (GetVersionFuncAddress("GetFileVersionInfoA"));
    return pGetFileVersionInfoA(lptstrFilename, dwHandle, dwLen, lpData);
}

extern "C" BOOL P_GetFileVersionInfoByHandle(
    DWORD dwFlags,
    HANDLE hFile,
    PDWORD pdwLen
) {
    BOOL(*pGetFileVersionInfoByHandle)(DWORD, HANDLE, PDWORD) = (BOOL(*)(DWORD, HANDLE, PDWORD)) (GetVersionFuncAddress("GetFileVersionInfoByHandle"));
    return pGetFileVersionInfoByHandle(dwFlags, hFile, pdwLen);
}

extern "C" BOOL P_GetFileVersionInfoExA(
    DWORD dwFlags,
    LPCSTR lpwstrFilename,
    DWORD dwHandle,
    DWORD dwLen,
    LPVOID lpData
) {
    BOOL(*pGetFileVersionInfoExA)(DWORD, LPCSTR, DWORD, DWORD, LPVOID) = (BOOL(*)(DWORD, LPCSTR, DWORD, DWORD, LPVOID)) (GetVersionFuncAddress("GetFileVersionInfoExA"));
    return pGetFileVersionInfoExA(dwFlags, lpwstrFilename, dwHandle, dwLen, lpData);
}

extern "C" BOOL P_GetFileVersionInfoExW(
    DWORD dwFlags,
    LPCWSTR lpwstrFilename,
    DWORD dwHandle,
    DWORD dwLen,
    LPVOID lpData
) {
    BOOL(*pGetFileVersionInfoExW)(DWORD, LPCWSTR, DWORD, DWORD, LPVOID) = (BOOL(*)(DWORD, LPCWSTR, DWORD, DWORD, LPVOID)) (GetVersionFuncAddress("GetFileVersionInfoExW"));
    return pGetFileVersionInfoExW(dwFlags, lpwstrFilename, dwHandle, dwLen, lpData);
}

extern "C" DWORD P_GetFileVersionInfoSizeA(
    LPCSTR lptstrFilename,
    LPDWORD lpdwHandle
) {
    DWORD(*pGetFileVersionInfoSizeA)(LPCSTR, LPDWORD) = (DWORD(*)(LPCSTR, LPDWORD)) (GetVersionFuncAddress("GetFileVersionInfoSizeA"));
    return pGetFileVersionInfoSizeA(lptstrFilename, lpdwHandle);
}

extern "C" DWORD P_GetFileVersionInfoSizeExA(
    DWORD dwFlags,
    LPCSTR lpwstrFilename,
    LPDWORD lpdwHandle
) {
    DWORD(*pGetFileVersionInfoSizeExA)(DWORD, LPCSTR, LPDWORD) = (DWORD(*)(DWORD, LPCSTR, LPDWORD)) (GetVersionFuncAddress("GetFileVersionInfoSizeExA"));
    return pGetFileVersionInfoSizeExA(dwFlags, lpwstrFilename, lpdwHandle);
}

extern "C" DWORD P_GetFileVersionInfoSizeExW(
    DWORD dwFlags,
    LPCWSTR lpwstrFilename,
    LPDWORD lpdwHandle
) {
    DWORD(*pGetFileVersionInfoSizeExW)(DWORD, LPCWSTR, LPDWORD) = (DWORD(*)(DWORD, LPCWSTR, LPDWORD)) (GetVersionFuncAddress("GetFileVersionInfoSizeExW"));
    return pGetFileVersionInfoSizeExW(dwFlags, lpwstrFilename, lpdwHandle);
}

extern "C" DWORD P_GetFileVersionInfoSizeW(
    LPCWSTR lptstrFilename,
    LPDWORD lpdwHandle
) {
    DWORD(*pGetFileVersionInfoSizeW)(LPCWSTR, LPDWORD) = (DWORD(*)(LPCWSTR, LPDWORD)) (GetVersionFuncAddress("GetFileVersionInfoSizeW"));
    return pGetFileVersionInfoSizeW(lptstrFilename, lpdwHandle);
}

extern "C" BOOL P_GetFileVersionInfoW(
    LPCWSTR lptstrFilename,
    DWORD dwHandle,
    DWORD dwLen,
    LPVOID lpData
) {
    BOOL(*pGetFileVersionInfoW)(LPCWSTR, DWORD, DWORD, LPVOID) = (BOOL(*)(LPCWSTR, DWORD, DWORD, LPVOID)) (GetVersionFuncAddress("GetFileVersionInfoW"));
    return pGetFileVersionInfoW(lptstrFilename, dwHandle, dwLen, lpData);
}

extern "C" DWORD P_VerFindFileA(
    DWORD uFlags,
    LPCSTR szFileName,
    LPCSTR szWinDir,
    LPCSTR szAppDir,
    LPSTR szCurDir,
    PUINT puCurDirLen,
    LPSTR szDestDir,
    PUINT puDestDirLen
) {
    DWORD(*pVerFindFileA)(DWORD, LPCSTR, LPCSTR, LPCSTR, LPSTR, PUINT, LPSTR, PUINT) = (DWORD(*)(DWORD, LPCSTR, LPCSTR, LPCSTR, LPSTR, PUINT, LPSTR, PUINT)) (GetVersionFuncAddress("VerFindFileA"));
    return pVerFindFileA(uFlags, szFileName, szWinDir, szAppDir, szCurDir, puCurDirLen, szDestDir, puDestDirLen);
}

extern "C" DWORD P_VerFindFileW(
    DWORD uFlags,
    LPCWSTR szFileName,
    LPCWSTR szWinDir,
    LPCWSTR szAppDir,
    LPWSTR szCurDir,
    PUINT puCurDirLen,
    LPWSTR szDestDir,
    PUINT puDestDirLen
) {
    DWORD(*pVerFindFileW)(DWORD, LPCWSTR, LPCWSTR, LPCWSTR, LPWSTR, PUINT, LPWSTR, PUINT) = (DWORD(*)(DWORD, LPCWSTR, LPCWSTR, LPCWSTR, LPWSTR, PUINT, LPWSTR, PUINT)) (GetVersionFuncAddress("VerFindFileW"));
    return pVerFindFileW(uFlags, szFileName, szWinDir, szAppDir, szCurDir, puCurDirLen, szDestDir, puDestDirLen);
}

extern "C" DWORD P_VerInstallFileA(
    DWORD uFlags,
    LPCSTR szSrcFileName,
    LPCSTR szDestFileName,
    LPCSTR szSrcDir,
    LPCSTR szDestDir,
    LPCSTR szCurDir,
    LPSTR szTmpFile,
    PUINT puTmpFileLen
) {
    DWORD(*pVerInstallFileA)(DWORD, LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPSTR, PUINT) = (DWORD(*)(DWORD, LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPSTR, PUINT)) (GetVersionFuncAddress("VerInstallFileA"));
    return pVerInstallFileA(uFlags, szSrcFileName, szDestFileName, szSrcDir, szDestDir, szCurDir, szTmpFile, puTmpFileLen);
}

extern "C" DWORD P_VerInstallFileW(
    DWORD uFlags,
    LPCWSTR szSrcFileName,
    LPCWSTR szDestFileName,
    LPCWSTR szSrcDir,
    LPCWSTR szDestDir,
    LPCWSTR szCurDir,
    LPWSTR szTmpFile,
    PUINT puTmpFileLen
) {
    DWORD(*pVerInstallFileW)(DWORD, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, LPWSTR, PUINT) = (DWORD(*)(DWORD, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, LPWSTR, PUINT)) (GetVersionFuncAddress("VerInstallFileW"));
    return pVerInstallFileW(uFlags, szSrcFileName, szDestFileName, szSrcDir, szDestDir, szCurDir, szTmpFile, puTmpFileLen);
}

extern "C" DWORD P_VerLanguageNameA(
    DWORD wLang,
    LPSTR szLang,
    DWORD cchLang
) {
    DWORD(*pVerLanguageNameA)(DWORD, LPSTR, DWORD) = (DWORD(*)(DWORD, LPSTR, DWORD)) (GetVersionFuncAddress("VerLanguageNameA"));
    return pVerLanguageNameA(wLang, szLang, cchLang);
}

extern "C" DWORD P_VerLanguageNameW(
    DWORD wLang,
    LPWSTR szLang,
    DWORD cchLang
) {
    DWORD(*pVerLanguageNameW)(DWORD, LPWSTR, DWORD) = (DWORD(*)(DWORD, LPWSTR, DWORD)) (GetVersionFuncAddress("VerLanguageNameW"));
    return pVerLanguageNameW(wLang, szLang, cchLang);
}

extern "C" BOOL P_VerQueryValueA(
    LPCVOID pBlock,
    LPCSTR lpSubBlock,
    LPVOID lplpBuffer,
    PUINT puLen
) {
    BOOL(*pVerQueryValueA)(LPCVOID, LPCSTR, LPVOID, PUINT) = (BOOL(*)(LPCVOID, LPCSTR, LPVOID, PUINT)) (GetVersionFuncAddress("VerQueryValueA"));
    return pVerQueryValueA(pBlock, lpSubBlock, lplpBuffer, puLen);
}

extern "C" BOOL P_VerQueryValueW(
    LPCVOID pBlock,
    LPCWSTR lpSubBlock,
    LPVOID lplpBuffer,
    PUINT puLen
) {
    BOOL(*pVerQueryValueW)(LPCVOID, LPCWSTR, LPVOID, PUINT) = (BOOL(*)(LPCVOID, LPCWSTR, LPVOID, PUINT)) (GetVersionFuncAddress("VerQueryValueW"));
    return pVerQueryValueW(pBlock, lpSubBlock, lplpBuffer, puLen);
}



另外,这里是一个读取文件中函数原型生成形如上的劫持代码的小工具,上面的代码是用这个小工具根据提取的函数原型生成的
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <regex>
// 将函数签名字符串分解为函数返回类型、函数名、参数类型等
struct FuncSignature
{
    std::string returnType;
    std::string funcName;
    std::vector<std::string> paramTypes;
    std::vector<std::string> paramNames;
};
// 使用正则表达式解析函数签名
FuncSignature parseFunctionSignature(const std::string& signature)
{
    std::regex re(R"((\w+)\s+(\w+)\((.*?)\))");
    std::smatch match;
    if (std::regex_search(signature, match, re))
    {
      FuncSignature funcSig;
      funcSig.returnType = match;
      funcSig.funcName = match;
// 解析参数列表
      std::string params = match;
      std::regex paramRe(R"((\w+)\s+(\w+))");
      auto paramBegin = std::sregex_iterator(params.begin(), params.end(), paramRe);
      auto paramEnd = std::sregex_iterator();
      for (auto it = paramBegin; it != paramEnd; ++it)
      {
            funcSig.paramTypes.push_back(it->str(1));// 参数类型
            funcSig.paramNames.push_back(it->str(2));// 参数名
      }
      return funcSig;
    }
    throw std::invalid_argument("Invalid function signature.");
}
// 生成导出函数代码
std::string generateExportFunctionCode(const FuncSignature& sig)
{
    std::ostringstream code;
// 构造新的函数名
    std::string newFuncName = "P_" + sig.funcName;
// 函数签名的代码
// code << "#pragma comment(linker, \"/EXPORT:" << sig.funcName << "=" << newFuncName << ",@1\")\n\n";
    code << "extern \"C\" " << sig.returnType << " " << newFuncName << "(\n";
// 参数代码
    for (size_t i = 0; i < sig.paramTypes.size(); ++i)
    {
      code << "" << sig.paramTypes << " " << sig.paramNames;
      if (i < sig.paramTypes.size() - 1)
            code << ",\n";
      else
            code << "\n";
    }
    code << ") {\n";
    code << "" << sig.returnType << " (*p" << sig.funcName << ")(";
// 参数类型列表
    for (size_t i = 0; i < sig.paramTypes.size(); ++i)
    {
      code << sig.paramTypes;
      if (i < sig.paramTypes.size() - 1)
            code << ", ";
    }
    code << ") = (" << sig.returnType << "(*)(";
// 再次列出参数类型
    for (size_t i = 0; i < sig.paramTypes.size(); ++i)
    {
      code << sig.paramTypes;
      if (i < sig.paramTypes.size() - 1)
            code << ", ";
    }
    code << ")) (GetVersionFuncAddress(\"" << sig.funcName << "\"));\n";
// 调用原函数
    code << "return p" << sig.funcName << "(";
    for (size_t i = 0; i < sig.paramNames.size(); ++i)
    {
      code << sig.paramNames;
      if (i < sig.paramNames.size() - 1)
            code << ", ";
    }
    code << ");\n";
    code << "}\n";
    return code.str();
}
int main()
{
// 输入函数签名
    std::string funcSig;
    std::ifstream inf;
    inf.open("cilp_r.txt");
    while (std::getline(inf, funcSig))
    {
      try
      {
            // 解析函数签名
            FuncSignature sig = parseFunctionSignature(funcSig);
            // 生成导出函数代码
            std::string exportCode = generateExportFunctionCode(sig);
            // 输出生成的代码
            std::cout << exportCode << std::endl;
      }
      catch (const std::exception& e)
            std::cerr << "Error: " << e.what() << std::endl;
    }
    return 0;
}


读取文件cilp_r.txt示例:
BOOL GetFileVersionInfoA(LPCSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData);
BOOL GetFileVersionInfoByHandle(DWORD dwFlags, HANDLE hFile, LPVOID * lplpData, PDWORD pdwLen );
BOOL GetFileVersionInfoExA(DWORD dwFlags, LPCSTR lpwstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData);
BOOL GetFileVersionInfoExW(DWORD dwFlags, LPCWSTR lpwstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData);
DWORD GetFileVersionInfoSizeA(LPCSTR lptstrFilename, LPDWORD lpdwHandle);
DWORD GetFileVersionInfoSizeExA(DWORD dwFlags, LPCSTR lpwstrFilename, LPDWORD lpdwHandle);
DWORD GetFileVersionInfoSizeExW(DWORD dwFlags, LPCWSTR lpwstrFilename, LPDWORD lpdwHandle);
DWORD GetFileVersionInfoSizeW(LPCWSTR lptstrFilename, LPDWORD lpdwHandle);
BOOL GetFileVersionInfoW(LPCWSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData);
DWORD VerFindFileA(DWORD uFlags, LPCSTR szFileName, LPCSTR szWinDir, LPCSTR szAppDir, LPSTR szCurDir, PUINT puCurDirLen, LPSTR szDestDir, PUINT puDestDirLen);
DWORD VerFindFileW(DWORD uFlags, LPCWSTR szFileName, LPCWSTR szWinDir, LPCWSTR szAppDir, LPWSTR szCurDir, PUINT puCurDirLen, LPWSTR szDestDir, PUINT puDestDirLen);
DWORD VerInstallFileA(DWORD uFlags, LPCSTR szSrcFileName, LPCSTR szDestFileName, LPCSTR szSrcDir, LPCSTR szDestDir, LPCSTR szCurDir, LPSTR szTmpFile, PUINT puTmpFileLen);
DWORD VerInstallFileW(DWORD uFlags, LPCWSTR szSrcFileName, LPCWSTR szDestFileName, LPCWSTR szSrcDir, LPCWSTR szDestDir, LPCWSTR szCurDir, LPWSTR szTmpFile, PUINT puTmpFileLen);
DWORD VerLanguageNameA(DWORD wLang, LPSTR szLang, DWORD cchLang);
DWORD VerLanguageNameW(DWORD wLang, LPWSTR szLang, DWORD cchLang);
BOOL VerQueryValueA(LPCVOID pBlock, LPCSTR lpSubBlock, LPVOID lplpBuffer, PUINT puLen);
BOOL VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID lplpBuffer, PUINT puLen);

fjqisba 发表于 2024-11-18 16:22

aheadlib了解一下

3I5105 发表于 2024-11-18 16:37

https://wwgz.lanzouw.com/b00mowf4la
密码:1dzb
很好奇大家要完整的工程文件干啥...只是一个用来重定向某个软件写入配置文件的dll
主贴中第一段代码是模板文件,第二、三段代码是用来生成模板文件的程序
如果要使用模板文件,只需要将包含第一段代码的文件包括到工程中即可
如果要创建其他dll劫持的模板文件才需要用到第二、三段代码
@wszjf @朱朱你堕落了 @redapple2015

beatone 发表于 2024-11-18 14:50

感谢分享技术贴。。。

redapple2015 发表于 2024-11-18 15:25

这个文件能不能打包一下?谢谢!

yangaiwen 发表于 2024-11-18 19:02

感谢分享技术贴。。。

lml0126 发表于 2024-11-18 19:04

严重性        代码        说明        项目        文件        行        禁止显示状态        详细信息
错误        C1010        在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "pch.h"”?        PS_SFM_HOOK       

不会C,这是差什么文件么?

pizazzboy 发表于 2024-11-18 20:08

感谢分享。虽然不会C++

wtujoxk 发表于 2024-11-18 20:28

aheadlib和baymax patch tools 了解一下

flybird2007 发表于 2024-11-18 20:37

lml0126 发表于 2024-11-18 19:04
严重性        代码        说明        项目        文件        行        禁止显示状态        详细信息
错误        C1010        在查找预编译头时遇到意外的文件结尾。 ...

是少了头文件pch.h 吧
页: [1] 2 3
查看完整版本: version.dll劫持注入模版(支持x64)