⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mergebin.cpp

📁 sqlite 3.3.8 支持加密的版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/********************************************************
 * mergebin
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 * Released to the public domain, use at your own risk!
 ********************************************************/

#include "stdafx.h"
#include "MetaData.h"
#include "MetaDataTables.h"
#include "TableData.h"

void DumpCLRInfo(LPCTSTR pszFile);
void MergeModules(LPCTSTR pszAssembly, LPCTSTR pszNative, LPCTSTR pszSection);
void DumpCLRPragma(LPCTSTR pszAssembly, LPCTSTR pszSection);

typedef struct EXTRA_STUFF
{
  DWORD dwNativeEntryPoint;
} EXTRA_STUFF, *LPEXTRA_STUFF;

int _tmain(int argc, _TCHAR* argv[])
{
  if (argc == 1)
  {
    _tprintf(_T(
"MERGEBIN - Merges a pure .NET assembly with a native DLL\n \
Syntax: MERGEBIN [/I:assembly] [/S:sectionname assembly nativedll]\n \
/I:assembly            Returns the number of bytes required\n \
                       to consume the assembly\n \
/S:sectionname         The name of the section in the nativedll\n \
                       to insert the CLR data\n \
/P:assembly            Outputs the C++ pragma code that can be used\n \
                       as additional input to a C++ app to reserve\n \
                       a section block large enough for the managed code.\n \
\n \
The native DLL must have an unused section in it, into which the\n \
.NET assembly will be inserted.  You can do this with the following code:\n \
  #pragma data_seg(\".clr\")\n \
  #pragma comment(linker, \"/SECTION:.clr,ER\")\n \
   char __ph[92316] = {0}; // 92316 is the number of bytes to reserve\n \
  #pragma data_seg()\n \
You would then specify /SECTION:.CLR in the command-line for the location to\n \
insert the .NET assembly.  The number of bytes reserved in the section needs\n \
to be equal to or more than the number of bytes returned by the /I parameter.\n \
\n \
The native DLL must also export a function that calls _CorDllMain in \n \
MSCOREE.DLL.  This function must have the same parameters and calling\n \
conventions as DllMain, and its name must have the word \"CORDLLMAIN\"\n \
in it.\n \
"));
    return 0;
  }

  LPTSTR pszAssembly = NULL;
  LPTSTR pszNative = NULL;
  LPTSTR pszSection = NULL;
  BOOL bDoPragma = FALSE;

  for (int n = 1; n < argc; n++)
  {
    if (argv[n][0] != '-' && argv[n][0] != '/')
    {
      if (pszAssembly == NULL)
        pszAssembly = argv[n];
      else if (pszNative == NULL)
        pszNative = argv[n];
      else
      {
        _tprintf(_T("Too many files specified\n"));
        return 0;
      }
      continue;
    }

    switch(argv[n][1])
    {
    case 'I':
    case 'i':
      pszAssembly = &argv[n][3];
      if (argv[n][2] != ':' || lstrlen(pszAssembly) == 0)
      {
        _tprintf(_T("/I requires an assembly name\n"));
        return 0;
      }
      DumpCLRInfo(pszAssembly);
      return 0;
      break;
    case 'P':
    case 'p':
      pszAssembly = &argv[n][3];
      if (argv[n][2] != ':' || lstrlen(pszAssembly) == 0)
      {
        _tprintf(_T("/P requires an assembly name\n"));
        return 0;
      }
      bDoPragma = TRUE;
      break;
    case 'S':
    case 's':
      pszSection = &argv[n][3];
      if (argv[n][2] != ':' || lstrlen(pszSection) == 0)
      {
        _tprintf(_T("/S requires a section name\n"));
        return 0;
      }
      break;
    }
  }

  if (pszAssembly && pszNative && pszSection && !bDoPragma)
    MergeModules(pszAssembly, pszNative, pszSection);

  if (pszAssembly && bDoPragma)
    DumpCLRPragma(pszAssembly, pszSection);

  return 0;
}

BOOL GetMinMaxCOR20RVA(CPEFile& file, DWORD& dwMin, DWORD& dwMax)
{
  PIMAGE_COR20_HEADER pCor = file;
  dwMin = MAXDWORD;
  dwMax = 0;

  if (!pCor) return FALSE;

  if (pCor->MetaData.Size) dwMin = min(dwMin, pCor->MetaData.VirtualAddress);
  if (pCor->Resources.Size) dwMin = min(dwMin, pCor->Resources.VirtualAddress);
  if (pCor->StrongNameSignature.Size) dwMin = min(dwMin, pCor->StrongNameSignature.VirtualAddress);
  if (pCor->CodeManagerTable.Size) dwMin = min(dwMin, pCor->CodeManagerTable.VirtualAddress);
  if (pCor->VTableFixups.Size) dwMin = min(dwMin, pCor->VTableFixups.VirtualAddress);
  if (pCor->ExportAddressTableJumps.Size) dwMin = min(dwMin, pCor->ExportAddressTableJumps.VirtualAddress);
  if (pCor->ManagedNativeHeader.Size) dwMin = min(dwMin, pCor->ManagedNativeHeader.VirtualAddress);

  dwMax = max(dwMax, (pCor->MetaData.VirtualAddress + pCor->MetaData.Size));
  dwMax = max(dwMax, (pCor->Resources.VirtualAddress + pCor->Resources.Size));
  dwMax = max(dwMax, (pCor->StrongNameSignature.VirtualAddress + pCor->StrongNameSignature.Size));
  dwMax = max(dwMax, (pCor->CodeManagerTable.VirtualAddress + pCor->CodeManagerTable.Size));
  dwMax = max(dwMax, (pCor->VTableFixups.VirtualAddress + pCor->VTableFixups.Size));
  dwMax = max(dwMax, (pCor->ExportAddressTableJumps.VirtualAddress + pCor->ExportAddressTableJumps.Size));
  dwMax = max(dwMax, (pCor->ManagedNativeHeader.VirtualAddress + pCor->ManagedNativeHeader.Size));

  CMetadata meta(file);
  CMetadataTables tables(meta);
  CTableData *p;
  DWORD *pdwRVA;
  DWORD dwRows;

  for (int n = 0; n < 2; n++)
  {
    p = tables.GetTable((n == 0) ? ttMethodDef : ttFieldRVA);
    if (p)
    {
      dwRows = p->GetRowCount();
      for (UINT uRow = 0; uRow < dwRows; uRow ++)
      {
        pdwRVA = (DWORD *)p->Column(uRow, (UINT)0);
        if (*pdwRVA)
          dwMin = min(dwMin, (*pdwRVA));
      }
    }
  }
  return TRUE;
}

void DumpCLRInfo(LPCTSTR pszFile)
{
  CPEFile peFile;
  HRESULT hr;
  hr = peFile.Open(pszFile);
  if (FAILED(hr)) return;

  DWORD dwMinRVA;
  DWORD dwMaxRVA;

  if (!GetMinMaxCOR20RVA(peFile, dwMinRVA, dwMaxRVA))
  {
    _tprintf(_T("Unable to retrieve .NET assembly information for file %s\n"), pszFile);
    return;
  }

  _tprintf(_T("%d Bytes required to merge %s\n"), (dwMaxRVA - dwMinRVA) + ((PIMAGE_COR20_HEADER)peFile)->cb + sizeof(EXTRA_STUFF), pszFile);
}

void DumpCLRPragma(LPCTSTR pszAssembly, LPCTSTR pszSection)
{
  CPEFile peFile;
  HRESULT hr;
  DWORD dwMinRVA;
  DWORD dwMaxRVA;

  hr = peFile.Open(pszAssembly);
  if (FAILED(hr)) return;
  
  if (pszSection == NULL) pszSection = _T(".clr");

  if (!GetMinMaxCOR20RVA(peFile, dwMinRVA, dwMaxRVA))
  {
    _tprintf(_T("// Unable to retrieve .NET assembly information for file %s\n"), pszAssembly);
    return;
  }

  _tprintf(_T("// This code was automatically generated from assembly\n\
// %s\n\n\
#include <windef.h>\n\n\
#pragma data_seg(\"%s\")\n\
#pragma comment(linker, \"/SECTION:%s,ER\")\n\
  char __ph[%d] = {0}; // The number of bytes to reserve\n\
#pragma data_seg()\n\n\
typedef BOOL (WINAPI *DLLMAIN)(HANDLE, DWORD, LPVOID);\n\
typedef struct EXTRA_STUFF\n\
{\n\
  DWORD dwNativeEntryPoint;\n\
} EXTRA_STUFF, *LPEXTRA_STUFF;\n\n\
__declspec(dllexport) BOOL WINAPI _CorDllMainStub(HANDLE hModule, DWORD dwReason, LPVOID pvReserved)\n\
{\n\
  HANDLE hMod;\n\
  DLLMAIN proc;\n\
  LPEXTRA_STUFF pExtra;\n\n\
  hMod = GetModuleHandle(_T(\"mscoree\"));\n\
  if (hMod)\n\
    proc = (DLLMAIN)GetProcAddress(hMod, _T(\"_CorDllMain\"));\n\
  else\n\
  {\n\
    MEMORY_BASIC_INFORMATION mbi;\n\n\
    VirtualQuery(_CorDllMainStub, &mbi, sizeof(mbi));\n\
    pExtra = (LPEXTRA_STUFF)__ph;\n\
    proc = (DLLMAIN)(pExtra->dwNativeEntryPoint + (DWORD)mbi.AllocationBase);\n\
  }\n\
  return proc(hModule, dwReason, pvReserved);\n\
}\n\
"), pszAssembly, pszSection, pszSection, (dwMaxRVA - dwMinRVA) + ((PIMAGE_COR20_HEADER)peFile)->cb + sizeof(EXTRA_STUFF));
}

/*   When merged, the native DLL's entrypoint must go to _CorDllMain in MSCOREE.DLL.
  ** In order to do this, we need to change the DLL's entrypoint to "something" that will
  ** call CorDllMain.  Since its too much hassle to add imports to the DLL and make drastic
  ** changes to it, we rely on the native DLL to export a function that we can call which will
  ** forward to CorDllMain.  Exported functions are easy to identify and get an RVA for.
  ** The exported function must have the same calling conventions and parameters as DllMain,
  ** and must contain the letters "CORDLLMAIN" in the name.  The search is case-insensitive. */
DWORD GetExportedCorDllMainRVA(CPEFile& file)
{
  PIMAGE_EXPORT_DIRECTORY pExportDir;
  PIMAGE_SECTION_HEADER header;
  INT delta; 
  DWORD i;
  DWORD *pdwFunctions;
  PWORD pwOrdinals;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -