https://github.com/fancycode/MemoryModule

MemoryModule is a library that can be used to load a DLL completely from memory - without storing on the disk first.

The default windows API functions to load external libraries into a program (LoadLibrary,LoadLibraryEx)

only work with files on the filesystem. It's therefore impossible to load a DLL from memory.

But sometimes, you need exactly this functionality (e.g. you don't want to distribute a lot of files or want to make disassembling harder). Common workarounds for this problems are to write the DLL into a temporary file first and import it from there. When the program terminates, the temporary file gets deleted.

MemoryModule is a library that can be used to load a DLL completely from memory - without storing on the disk first.

See doc/readme.txt for more informations about the format of a DLL file and a tutorial how they can be loaded directly.

:author:    Joachim Bauch
:contact: mail@joachim-bauch.de
:copyright: `Creative Commons License (by-sa)`__ __ http://creativecommons.org/licenses/by-sa/2.5/ .. contents:: Overview
========= The default windows API functions to load external libraries into a program
(LoadLibrary, LoadLibraryEx) only work with files on the filesystem. It's
therefore impossible to load a DLL from memory.
But sometimes, you need exactly this functionality (e.g. you don't want to
distribute a lot of files or want to make disassembling harder). Common
workarounds for this problems are to write the DLL into a temporary file
first and import it from there. When the program terminates, the temporary
file gets deleted. In this tutorial, I will describe first, how DLL files are structured and
will present some code that can be used to load a DLL completely from memory -
without storing on the disk first. Windows executables - the PE format
==================================== Most windows binaries that can contain executable code (.exe, .dll, .sys)
share a common file format that consists of the following parts: +----------------+
| DOS header |
| |
| DOS stub |
+----------------+
| PE header |
+----------------+
| Section header |
+----------------+
| Section |
+----------------+
| Section |
+----------------+
| . . . |
+----------------+
| Section n |
+----------------+ All structures given below can be found in the header file `winnt.h`. DOS header / stub
------------------ The DOS header is only used for backwards compatibility. It precedes the DOS
stub that normally just displays an error message about the program not being
able to be run from DOS mode. Microsoft defines the DOS header as follows:: typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; PE header
---------- The PE header contains informations about the different sections inside the
executable that are used to store code and data or to define imports from other
libraries or exports this libraries provides. It's defined as follows:: typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; The `FileHeader` describes the *physical* format of the file, i.e. contents, informations
about symbols, etc:: typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; .. _OptionalHeader: The `OptionalHeader` contains informations about the *logical* format of the library,
including required OS version, memory requirements and entry points:: typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
// WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData; //
// NT additional fields.
// DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; .. _DataDirectory: The `DataDirectory` contains (`IMAGE_NUMBEROF_DIRECTORY_ENTRIES`) entries
defining the logical components of the library: ===== ==========================
Index Description
===== ==========================
Exported functions
----- --------------------------
Imported functions
----- --------------------------
Resources
----- --------------------------
Exception informations
----- --------------------------
Security informations
----- --------------------------
Base relocation table
----- --------------------------
Debug informations
----- --------------------------
Architecture specific data
----- --------------------------
Global pointer
----- --------------------------
Thread local storage
----- --------------------------
Load configuration
----- --------------------------
Bound imports
----- --------------------------
Import address table
----- --------------------------
Delay load imports
----- --------------------------
COM runtime descriptor
===== ========================== For importing the DLL we only need the entries describing the imports and the
base relocation table. In order to provide access to the exported functions,
the exports entry is required. Section header
--------------- The section header is stored after the OptionalHeader_ structure in the PE
header. Microsoft provides the macro `IMAGE_FIRST_SECTION` to get the start
address based on the PE header. Actually, the section header is a list of informations about each section in
the file:: typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; A section can contain code, data, relocation informations, resources, export or
import definitions, etc. Loading the library
==================== To emulate the PE loader, we must first understand, which steps are neccessary
to load the file to memory and prepare the structures so they can be called from
other programs. When issuing the API call `LoadLibrary`, Windows basically performs these tasks: . Open the given file and check the DOS and PE headers. . Try to allocate a memory block of `PEHeader.OptionalHeader.SizeOfImage` bytes
at position `PEHeader.OptionalHeader.ImageBase`. . Parse section headers and copy sections to their addresses. The destination
address for each section, relative to the base of the allocated memory block,
is stored in the `VirtualAddress` attribute of the `IMAGE_SECTION_HEADER`
structure. . If the allocated memory block differs from `ImageBase`, various references in
the code and/or data sections must be adjusted. This is called *Base
relocation*. . The required imports for the library must be resolved by loading the
corresponding libraries. . The memory regions of the different sections must be protected depending on
the section's characteristics. Some sections are marked as *discardable*
and therefore can be safely freed at this point. These sections normally
contain temporary data that is only needed during the import, like the
informations for the base relocation. . Now the library is loaded completely. It must be notified about this by
calling the entry point using the flag `DLL_PROCESS_ATTACH`. In the following paragraphs, each step is described. Allocate memory
---------------- All memory required for the library must be reserved / allocated using
`VirtualAlloc`, as Windows provides functions to protect these memory blocks.
This is required to restrict access to the memory, like blocking write access
to the code or constant data. The OptionalHeader_ structure defines the size of the required memory block
for the library. It must be reserved at the address specified by `ImageBase`
if possible:: memory = VirtualAlloc((LPVOID)(PEHeader->OptionalHeader.ImageBase),
PEHeader->OptionalHeader.SizeOfImage,
MEM_RESERVE,
PAGE_READWRITE); If the reserved memory differs from the address given in `ImageBase`, base
relocation as described below must be done. Copy sections
-------------- Once the memory has been reserved, the file contents can be copied to the
system. The section header must get evaluated in order to determine the
position in the file and the target area in memory. Before copying the data, the memory block must get committed:: dest = VirtualAlloc(baseAddress + section->VirtualAddress,
section->SizeOfRawData,
MEM_COMMIT,
PAGE_READWRITE); Sections without data in the file (like data sections for the used variables)
have a `SizeOfRawData` of ``, so you can use the `SizeOfInitializedData`
or `SizeOfUninitializedData` of the OptionalHeader_. Which one must get
choosen depending on the bit flags `IMAGE_SCN_CNT_INITIALIZED_DATA` and
`IMAGE_SCN_CNT_UNINITIALIZED_DATA` that may be set in the section`s
characteristics. Base relocation
---------------- All memory addresses in the code / data sections of a library are stored relative
to the address defined by `ImageBase` in the OptionalHeader_. If the library
can't be imported to this memory address, the references must get adjusted
=> *relocated*. The file format helps for this by storing informations about
all these references in the base relocation table, which can be found in the
directory entry of the DataDirectory_ in the OptionalHeader_. This table consists of a series of this structure :: typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;
DWORD SizeOfBlock;
} IMAGE_BASE_RELOCATION; It contains `(SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / ` entries of bits
each. The upper bits define the type of relocation, the lower bits define
the offset relative to the `VirtualAddress`. The only types that seem to be used in DLLs are IMAGE_REL_BASED_ABSOLUTE
No operation relocation. Used for padding.
IMAGE_REL_BASED_HIGHLOW
Add the delta between the `ImageBase` and the allocated memory block to the
bits found at the offset. Resolve imports
---------------- The directory entry of the DataDirectory_ in the OptionalHeader_ specifies
a list of libraries to import symbols from. Each entry in this list is defined
as follows:: typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; // 0 for terminating null import descriptor
DWORD OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
};
DWORD TimeDateStamp; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND) DWORD ForwarderChain; // -1 if no forwarders
DWORD Name;
DWORD FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
} IMAGE_IMPORT_DESCRIPTOR; The `Name` entry describes the offset to the NULL-terminated string of the library
name (e.g. `KERNEL32.DLL`). The `OriginalFirstThunk` entry points to a list
of references to the function names to import from the external library.
`FirstThunk` points to a list of addresses that gets filled with pointers to
the imported symbols. When we resolve the imports, we walk both lists in parallel, import the function
defined by the name in the first list and store the pointer to the symbol in the
second list:: nameRef = (DWORD *)(baseAddress + importDesc->OriginalFirstThunk);
symbolRef = (DWORD *)(baseAddress + importDesc->FirstThunk);
for (; *nameRef; nameRef++, symbolRef++)
{
PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase + *nameRef);
*symbolRef = (DWORD)GetProcAddress(handle, (LPCSTR)&thunkData->Name);
if (*funcRef == )
{
handleImportError();
return;
}
} Protect memory
--------------- Every section specifies permission flags in it's `Characteristics` entry.
These flags can be one or a combination of IMAGE_SCN_MEM_EXECUTE
The section contains data that can be executed. IMAGE_SCN_MEM_READ
The section contains data that is readable. IMAGE_SCN_MEM_WRITE
The section contains data that is writeable. These flags must get mapped to the protection flags - PAGE_NOACCESS
- PAGE_WRITECOPY
- PAGE_READONLY
- PAGE_READWRITE
- PAGE_EXECUTE
- PAGE_EXECUTE_WRITECOPY
- PAGE_EXECUTE_READ
- PAGE_EXECUTE_READWRITE Now, the function `VirtualProtect` can be used to limit access to the memory.
If the program tries to access it in a unauthorized way, an exception gets
raised by Windows. In addition the section flags above, the following can be added: IMAGE_SCN_MEM_DISCARDABLE
The data in this section can be freed after the import. Usually this is
specified for relocation data. IMAGE_SCN_MEM_NOT_CACHED
The data in this section must not get cached by Windows. Add the bit
flag `PAGE_NOCACHE` to the protection flags above. Notify library
--------------- The last thing to do is to call the DLL entry point (defined by
`AddressOfEntryPoint`) and so notifying the library about being attached
to a process. The function at the entry point is defined as :: typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved); So the last code we need to execute is :: DllEntryProc entry = (DllEntryProc)(baseAddress + PEHeader->OptionalHeader.AddressOfEntryPoint);
(*entry)((HINSTANCE)baseAddress, DLL_PROCESS_ATTACH, ); Afterwards we can use the exported functions as with any normal library. Exported functions
=================== If you want to access the functions that are exported by the library, you need to find the entry
point to a symbol, i.e. the name of the function to call. The directory entry of the DataDirectory_ in the OptionalHeader_ contains informations about
the exported functions. It's defined as follows:: typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
DWORD AddressOfFunctions; // RVA from base of image
DWORD AddressOfNames; // RVA from base of image
DWORD AddressOfNameOrdinals; // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; First thing to do, is to map the name of the function to the ordinal number of the exported
symbol. Therefore, just walk the arrays defined by `AddressOfNames` and `AddressOfNameOrdinals`
parallel until you found the required name. Now you can use the ordinal number to read the address by evaluating the n-th element of the
`AddressOfFunctions` array. Freeing the library
==================== To free the custom loaded library, perform the steps - Call entry point to notify library about being detached:: DllEntryProc entry = (DllEntryProc)(baseAddress + PEHeader->OptionalHeader.AddressOfEntryPoint);
(*entry)((HINSTANCE)baseAddress, DLL_PROCESS_ATTACH, ); - Free external libraries used to resolve imports.
- Free allocated memory. MemoryModule
============= MemoryModule is a C-library that can be used to load a DLL from memory. The interface is very similar to the standard methods for loading of libraries:: typedef void *HMEMORYMODULE; HMEMORYMODULE MemoryLoadLibrary(const void *);
FARPROC MemoryGetProcAddress(HMEMORYMODULE, const char *);
void MemoryFreeLibrary(HMEMORYMODULE); Downloads
---------- The latest development release can always be grabbed from Github at
http://github.com/fancycode/MemoryModule/ Known issues
------------- - All memory that is not protected by section flags is gets committed using `PAGE_READWRITE`.
I don't know if this is correct. License
-------- Since version 0.0., the MemoryModule library is released under the Mozilla Public License (MPL).
Version 0.0. has been released unter the Lesser General Public License (LGPL). It is provided as-is without ANY warranty. You may use it at your own risk. Copyright
========== The MemoryModule library and this tutorial are
Copyright (c) - by Joachim Bauch.

MemoryModule -- load a DLL completely from memory的更多相关文章

  1. System.load(PWConnector.dll)加载异常 Can't find dependent libraries

    System.load(PWConnector.dll)加载异常 Can't find dependent libraries 错误信息:D:\PWAdapter\PWConnector.dll: C ...

  2. win2008server R2 x64 部署.net core到IIS上出现【Failed to load the dll from [C:\Program Files\dotnet\host\fxr\1.0.1\hostfxr.dll], HRESULT: 0x80070057】错误

    win2008server R2 x64 部署.net core到IIS上出现[Failed to load the dll from [C:\Program Files\dotnet\host\fx ...

  3. Apache2.4为什么启动报错Cannot load php5apache2_4.dll into server

    最近学习php,按照书上的描述,下载好apache和php后,按照其中配置进行,结果遇到了上述问题.花费了近一个半小时的时间解决了上述问题.现把解决问题过程中看到的方法总结如下.  最先肯定是一定要注 ...

  4. Navicat 连接 Oracle数据库 提示 cannot load OCI DLL 的解决

    一.32位系统下 cannot load OCI DLL,126 解决方法:工具->选项->OCI 选择oracle安装目录下bin里面的oci.dll 二 .在64位系统下安装了Orac ...

  5. sikuli运行出现问题:Win32Util.dll: Can't load 32-bit .dll on a AMD 64 bit platform

    Win32Util.dll: Can't load 32-bit .dll on a AMD 64 bit platform 解决办法:将该工程设置成JDK为32位的 ,我设成1.6的32位不能用,因 ...

  6. “Cannot load php5apache2_4.dll into server”问题的解决方法

    摘要 PHP5.5.0+Apache Httpd 2.4.3,完成配置文件的修改后,启动Apache服务器,报Cannot load php5apache2_4.dll into server错误,记 ...

  7. 8.3 sikuli 集成进eclipse 报错:eclipse中运行提示 Win32Util.dll: Can't load 32-bit .dll on a AMD 64 bit platform

    sikuli运行出现问题:Win32Util.dll: Can't load 32-bit .dll on a AMD 64 bit platform 在64位平台上无法加载32位的dll文件 解决办 ...

  8. Navicat连接报错:cannot load OCI DLL,126

    32位系统下报错:cannot load OCI DLL,126 解决方法:navicat 菜单中 -工具->选项->OCI 选择oracle安装目录下bin里面的oci.dll 在win ...

  9. Intel MKL FATAL ERROR: Cannot load mkl_intel_thread.dll

    Intel MKL FATAL ERROR: Cannot load mkl_intel_thread.dll 在使用Anaconda创建一个虚拟环境出来,然后安装了scikit-learn.nump ...

随机推荐

  1. uWSGI+Nginx+Flask在Linux下的部署

    搞了一天多,终于搞通了uWSGI的部署原理,下面总结一下遇到的一些坑,希望给读者能够少走弯路.        简单来说,uWSGI是一个web服务器,Nginx进行反向代理的其实跟这些服务器可以说没有 ...

  2. 安装mysql驱动之 mysqlclient 出现的报错处理(ubuntu16.04)

    首先 更新软件! sudo apt-get update 然后尝试安装mysqlclient,报错 后执行下面的步骤 安装mysql驱动之 mysqlclient 出现的报错信息处理 报错1: OSE ...

  3. php+mysql缓存技术的实现

    本教程适合于那些对缓存SQL查询以减少数据库连接与执行的负载.提高脚本性能感兴趣的PHP程序员.概述 许多站点使用数据库作为站点数据存储的容器.数据库包含了产器信息.目录结构.文章或者留言本,有些数据 ...

  4. GPS位置模拟-安卓

    测试定位功能时都需要位置模拟,一般有如下3种方式: a)手机上安装第三方模拟软件:需要Root: b)PC模拟其中运行app并模拟位置:不能在真机上运行,手机兼容性不能测试到: b)在app中让开发增 ...

  5. 转:google测试分享-SET和TE

    原文:  http://blog.sina.com.cn/s/blog_6cf812be0102vbnb.html 前端时间看了google测试之道,收获了一些,在此总结下并打算写一个系列blog,顺 ...

  6. EL(表达式)语言的几种运算符

    1.EL的基本语法 (1)EL表达式语法:以${开头,以}结束,中间为合法的表达式,具体语法格式如下: ${expression} (2)参数说明:Expression:指定要输出的内容,可以是字符串 ...

  7. SP 页面缓存以及清除缓存

    JSP 页面缓存以及清除缓存 一.概述 缓存的思想可以应用在软件分层的各个层面.它是一种内部机制,对外界而言,是不可感知的. 数据库本身有缓存,持久层也可以缓存.(比如:hibernate,还分1级和 ...

  8. Dagger:快速的依赖注入for 安卓&Java

    Dagger:快速的依赖注入for 安卓&Java 2014年5月8日 星期四 15:29 官网: http://square.github.io/dagger/ GitHub: https: ...

  9. Codeforces 351D Jeff and Removing Periods(莫队+区间等差数列更新)

    题目链接:http://codeforces.com/problemset/problem/351/D 题目大意:有n个数,每次可以删除掉数值相同并且所在位置成等差数列的数(只删2个数或者只删1个数应 ...

  10. 在eclipse中使用Maven3(笔记二)

    笔记本二   在Eclipse 中使用Maven 第一节:m2eclipse 插件安装 打开Eclipse,点击菜单Help - > Install New Software 点击Add 按钮N ...