bb107 / memorymodulepp Goto Github PK
View Code? Open in Web Editor NEWMemoryModule which compatible with Win32 API and support exception handling
License: MIT License
MemoryModule which compatible with Win32 API and support exception handling
License: MIT License
你添加的 comment 命令
#ifdef _WIN64 #pragma comment(linker,"/export:LdrUnloadDllMemoryAndExitThread") #pragma comment(linker,"/export:FreeLibraryMemoryAndExitThread=LdrUnloadDllMemoryAndExitThread") #else #pragma comment(linker,"/export:LdrUnloadDllMemoryAndExitThread=_NtUnloadDllMemoryAndExitThread@8") #pragma comment(linker,"/export:FreeLibraryMemoryAndExitThread=_NtUnloadDllMemoryAndExitThread@8") #endif
编译的时候老这里报错
问题复现如下:
从 http://jacquelin.potier.free.fr/HeliumHexEditor 下载64位版,解压将其中的 HexControl64.dll 改为 HexControl64_orig.dll.
然后编译自己的 HexControl64.dll从内存加载HexControl64_orig.dll,主要程序如下:
#include <windows.h>
#define RETTYPE __int64
#define CREATEHEXCONTROLOBJECT "CreateHexControlObject"
#define DESTROYHEXCONTROLOBJECT "DestroyHexControlObject"
typedef RETTYPE (*CreateHexControlObject_t)();
typedef RETTYPE (*DestroyHexControlObject_t)();
CreateHexControlObject_t OrigCreateHexControlObject = NULL;
DestroyHexControlObject_t OrigDestroyHexControlObject = NULL;
void LoadOrigDll()
{
size_t DllSize;
PVOID lpDll = ReadDllFile("HexControl64_orig.dll", &DllSize);
do {
CHAR currPath[MAX_PATH+1];
GetCurrentDirectory(MAX_PATH, currPath);
HMODULE m = LoadLibraryMemoryExA(lpDll, 0, NULL, currPath, 0);
OrigCreateHexControlObject = (CreateHexControlObject_t)GetProcAddress(m, CREATEHEXCONTROLOBJECT);
OrigDestroyHexControlObject = (DestroyHexControlObject_t)GetProcAddress(m, DESTROYHEXCONTROLOBJECT);
} while (0);
}
extern "C" __declspec(dllexport) RETTYPE CreateHexControlObject()
{
RETTYPE r = 0;
if (OrigCreateHexControlObject == NULL) {
LoadOrigDll();
}
if (OrigCreateHexControlObject)
r = OrigCreateHexControlObject();
return r;
}
extern "C" __declspec(dllexport) RETTYPE DestroyHexControlObject()
{
RETTYPE r = 0;
if (OrigDestroyHexControlObject == NULL) {
LoadOrigDll();
}
if (OrigDestroyHexControlObject)
r = OrigDestroyHexControlObject();
return r;
}
BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpReserved )
{
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
运行程序 HeliumHexEditor64.exe 后HexControl64_orig.dll加载成功,但弹窗报错,关闭报错窗口可继续使用。
使用 MemoryModule 或 RDI 方法加载不会报错,但程序不稳定,启动10次会出现几次crash。
麻烦帮忙看看是哪里的问题造成的。
另外:LoadLibraryMemoryExA 的参数 Flag 没有传递给 LoadLibraryMemoryExW
Hi, I've successfully loaded ntdll.dll, kernel32.dll, advapi32.dll. However I've failed to load both user32.dll and ole32.dll (all x64).
I'd like to ask whether or not is known limitation.
My environment:
Windows x64 19042
test.exe a normal exe with not use mmpp
i comment this line:// const NTSTATUS Initializer = Initialize();
a.dll build with mmpp static libirary,export loaddll func
void loaddll()
{
Initialize();
mmload("b.dll");
}
b.dll is a normal dll
test.exe
void main()
{
hmodule hmod=loadlibrary(a.dll)
call hmod.loaddll();
call freelibrary(hmod);
//now everything is ok!
while(true)
{
sleep(1000);
}
}
a few moment ,the test.exe will crash!!!
两层内存加载情况下,Win7下多线程程序不能运行,创建线程就会崩溃,单线程程序正常;多线程程序在Win10下正常
加载顺序:MemoryModule(https://github.com/fancycode/MemoryModule) -> MemoryModulePP binary -> APP binary
跟踪代码发现MmpTLS.cpp->MmpUserThreadStart中的auto size = CONTAINING_RECORED(record->TlspLdrBlock, TLS_VERCTOR, ModuleTlsData)->Length;获取到的size不正常,值为大数,但Win10中其是正常的
MemoryModulePP的API使用的LoadLibraryMemory
同时我注释掉了以下代码,以下代码会直接崩溃
auto tls = CONTAINING_RECORD(NtCurrentTeb()->ThreadLocalStoragePointer, TLS_VECTOR, TLS_VECTOR::ModuleTlsData);
if (tls && tls->Length > MMP_START_TLS_INDEX) {
RtlRaiseStatus(STATUS_NOT_SUPPORTED);
return FALSE;
}
if (MmpGlobalDataPtr->MmpTls->MmpTlsList.Flink != &MmpGlobalDataPtr->MmpTls->MmpTlsList) { assert(NtCurrentTeb()->ThreadLocalStoragePointer == nullptr); }
file: MmpTls , line:378
不知道啥原因
现象描述:
我先用loadlibrary加载一个dll,然后再用LdrLoadDllMemoryExW加载同样的dll,LdrLoadDllMemoryExW没有办法识别已经加载过的loadlibrary,无法对dll引用进行自增,而是重复执行dll加载代码。
无法识别的代码段:
函数位置LdrLoadDllMemoryExW->MapMemoryModuleHandle
具体代码:pModule->Signature != MEMORY_MODULE_SIGNATURE和pModule->codeBase != (LPBYTE)hModule都为true,导致返回结果为nullptr
发现导入表的dll同样是采用LoadLibrary加载的,是否可以指定部分依赖的dll也采用内存加载?
崩溃堆栈如下,看着像是延迟加载dll导致的。
刚开机得时候没有问题,过一段时间后只要调用就崩溃。
奇怪得是把枚举摄像头得代码单独拎出来测试又没有问题。在把MmpGlobalDataPtr改成(PMMP_GLOBAL_DATA)RtlAllocateHeap(RtlProcessHeap(), HEAP_ZERO_MEMORY, 0x2000);的方式后会较高概率出现崩溃。
出现崩溃时会发现有两次dll_thread_attach如下
DLL_PROCESS_ATTACH
DLL_THREAD_ATTACH
DLL_THREAD_ATTACH
001
crash
正常情况是
DLL_PROCESS_ATTACH
DLL_THREAD_ATTACH
001
002
....
DLL_THREAD_ATTACH
DLL_THREAD_DETACH
DLL_PROCESS_DETACH
采用系统LoadLibrary或通过特征码获取LdrpHandleTlsData得方式都没有问题。
枚举摄像头的代码如下
#include <atlbase.h>
#include <dshow.h>
#pragma comment(lib, "strmiids.lib")
#define SAFE_RELEASECOM( x )
if ( NULL != (x) )
{
(x)->Release();
(x) = NULL;
}
BOOL RunThread()
{
ICreateDevEnum* pCreateDevEnum = nullptr;
ICaptureGraphBuilder2* pBuilder = nullptr;
IBaseFilter* pVCap = nullptr;
IAMStreamConfig* pVSC = nullptr;
if (CoInitialize(nullptr) != S_OK)
{
return FALSE;
}
HRESULT hr = CoCreateInstance((REFCLSID)CLSID_CaptureGraphBuilder2,
nullptr, CLSCTX_INPROC, (REFIID)IID_ICaptureGraphBuilder2,
reinterpret_cast<void**>(&pBuilder));
hr = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&pCreateDevEnum));
if (hr != NOERROR)
{
return FALSE;
}
IEnumMoniker* pEm = nullptr;
hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);
if (hr != NOERROR)
{
return FALSE;
}
pEm->Reset();
ULONG cFetched = 0;
IMoniker* pMoniker = nullptr;
int index = -1;
while (hr = pEm->Next(1, &pMoniker, &cFetched), hr == S_OK)
{
index++;
IPropertyBag* pBag;
hr = pMoniker->BindToStorage(nullptr, nullptr, IID_IPropertyBag, reinterpret_cast<void**>(&pBag));
if (hr != S_OK)
{
continue;
}
VARIANT var;
VariantInit(&var);
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, nullptr);
if (hr == NOERROR)
{
VariantClear(&var);
}
SAFE_RELEASECOM(pBag);
printf("001\n");
hr = pMoniker->BindToObject(nullptr, nullptr, IID_IBaseFilter, reinterpret_cast<void**>(&pVCap));
if (hr != S_OK)
{
continue;
}
printf("002\n");
hr = pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
pVCap, IID_IAMStreamConfig, reinterpret_cast<void**>(&pVSC));
if (hr != S_OK)
{
hr = pBuilder->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
pVCap, IID_IAMStreamConfig, reinterpret_cast<void**>(&pVSC));
}
if (hr != S_OK)
{
continue;
}
printf("003\n");
int iCount = 0, iSize = 0;
hr = pVSC->GetNumberOfCapabilities(&iCount, &iSize);
if (hr == S_OK && iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
{
for (int iFormat = 0; iFormat < iCount; iFormat++)
{
VIDEO_STREAM_CONFIG_CAPS scc;
AM_MEDIA_TYPE* pmtConfig = nullptr;
hr = pVSC->GetStreamCaps(iFormat, &pmtConfig, reinterpret_cast<BYTE*>(&scc));
if (hr != S_OK)
{
continue;
}
if (HEADER(pmtConfig->pbFormat)->biWidth != 0 && HEADER(pmtConfig->pbFormat)->biHeight != 0)
{
printf("OK\n");
}
}
}
}
return TRUE;
}
extern "C" __declspec(dllexport)
BOOL test2()
{
std::thread* pThread = new std::thread(RunThread);
pThread->join();
delete pThread;
return FALSE;
}
Service process crash with system permissions.
X86 process running on win11 [10.0.22621.2361]
100% probability of crashing during startup
RtlInitUnicodeString(&us, buffer);
InitializeObjectAttributes(&oa, &us, 0, nullptr, nullptr);
li.QuadPart = 0x1000;
ServiceMessageBox("MmpAllocateGlobalData", "MmpAllocateGlobalData 2222222222222222222", MB_ICONERROR, TRUE);
status = NtCreateSection( //fail
&hSection,
SECTION_ALL_ACCESS,
&oa,
&li,
PAGE_READWRITE,
SEC_COMMIT,
nullptr
);
Causing the following code to crash.....
// Allocate memory for image headers
if (MmpGlobalDataPtr== 0) //null pointer
ServiceMessageBox("MemoryLoadLibrary", "MemoryLoadLibrary fffffffffffffffffffffffffffff MmpGlobalDataPtr == 0)", MB_ICONERROR, TRUE);
size_t alignedHeadersSize = (DWORD)AlignValueUp(old_header->OptionalHeader.SizeOfHeaders + sizeof(MEMORYMODULE), MmpGlobalDataPtr->SystemInfo.dwPageSize); //Crash
if (alignedHeadersSize == 0)
Win11 32位程序下:
注释掉
const NTSTATUS Initializer = Initialize();
后能正常调用Win32的LoadLibrary
代码结构如下:
while(true)
{
...
LdrLoadDllMemoryExW(...);
func = (FUNCW)GetProcAddress(...);
func();
LdrUnloadDllMemory(...);
}
调试跟踪,首次运行均正常,循环后再次运行func()有很大几率报错“帧不在模块中”,但有较低几率执行正常
void Test()
{
MessageBox(NULL, TEXT("memory module load successfuly."), TEXT("info"), MB_ICONINFORMATION);
PCHAR p = NULL;
__try{
*p = '0';
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
MessageBox(NULL, TEXT("exception 1"), TEXT("info"), MB_ICONINFORMATION);
}
}
这个Test()异常能正常处理
void Test2()
{
std::string str("foo");
try {
str.at(10); // access element, may throw std::out_of_range
}
catch (const std::out_of_range& e) {
// what() is inherited from std::exception and contains an explanatory message
MessageBox(NULL, TEXT("exception 2"), TEXT("info"), MB_ICONINFORMATION);
}
}
Win7 SP1 64 位下 内存加载64位DLL 处理C++ 异常Test2()会导致奔溃 跟踪是在 RtlpWaitOnCriticalSection 这个函数
如题,加载user32.dll DLL_PROCESS_ATTACH失败,能找到函数,但会报访问无效地址的错误
最新的版本依赖很多HOOK来达到处理tls相关函数的效果。
我使用HOOK会有问题,想用之前没有MmpTls的版本来在win10 21H1平台下的dll。
是不是我只需要补充LdrpHandleTlsData的特征码就能达到我想要的效果了。谢谢。
Hi,
I integrated this great library into our application and we got an error when this application creates a C++11 thread.
The callstack starts from last line of MmpUserThreadStart() and ends a thread_local variable reference. The variable is a simple pointer to a structure what is newed before the first usage of the pointer. The program did not use the MMPP api at this early stage just want to create some background threads. Without linking MMPP, no issue w the thread creation.
Does the lib MMPP support C++11 thread_local?
问一下,https://github.com/c-smile/sciter-js-sdk 项目的 sciter.dll 能否从内存中加载?
我试了一下,加载后运行失败了。
主要把sciter-x-api.h中的以下部分代码改成从内存加载
`#elif defined(WINDOWS)
inline ISciterAPI* _SAPI( ISciterAPI* ext ) {
static ISciterAPI* _api = NULL;
if( ext ) _api = ext;
if( !_api )
{
HMODULE hm = LoadLibrary( TEXT("sciter.dll") );
if(hm) {
SciterAPI_ptr sciterAPI = (SciterAPI_ptr) GetProcAddress(hm, "SciterAPI");
if( sciterAPI ) {
_api = sciterAPI();
//#if defined(__cplusplus) && !defined(PLAIN_API_ONLY)
// tiscript::ni( _api->TIScriptAPI() );
//#endif
} else {
FreeLibrary(hm);
}
}
}
assert(_api);
if( !_api ) {
//::MessageBox(NULL, TEXT("Sciter engine not found, quiting"),TEXT("Error"),MB_OK);
exit(-1);
}
return _api;
}
#elif defined(OSX)
`
最新版 sciter.dll(v5.0.3.13) 用 mmpp 加载崩溃 STATUS_ACCESS_VIOLATION 错,v5.0.3.13版之前的均可正常加载。
不知这一版开始有了什么变化。
dll下载连接 https://gitlab.com/sciter-engine/sciter-js-sdk/-/blob/main/bin/windows/x32/sciter.dll?ref_type=heads
用最新提交的 mmpp 加载也不行。
__LdrLoadDllMemoryExW 崩溃 STATUS_ACCESS_VIOLATION
int main() {
size_t len = 0;
PVOID buffer = ReadDllFile2("MemoryModule.dll", &len);
printf("1: %p, %u\n", buffer, len);
HMODULE hm = (HMODULE)LoadLibraryWithReflectiveLoader( buffer, len );
printf("2: hm: %p\n", hm);
//MmpGlobalDataPtr = *(PMMP_GLOBAL_DATA*)GetProcAddress(hm, "MmpGlobalDataPtr");
//printf("3: %p\n", MmpGlobalDataPtr);
__LdrLoadDllMemoryExW = (LdrLoadDllMemoryExW_t)GetProcAddress(hm, "LdrLoadDllMemoryExW");
__LdrUnloadDllMemory = (LdrUnloadDllMemory_t)GetProcAddress(hm, "LdrUnloadDllMemory");
printf("4: %p, %p\n", __LdrLoadDllMemoryExW, __LdrUnloadDllMemory);
VirtualFree(buffer, len, MEM_RELEASE);
buffer = ReadDllFile2("sciter50313.dll", &len);
printf("5: %p, %u\n", buffer, len);
HMODULE hm1 = NULL;
NTSTATUS res = __LdrLoadDllMemoryExW(&hm1, NULL, LOAD_FLAGS_NOT_FAIL_IF_HANDLE_TLS, buffer, 0, NULL, NULL);
printf("6: res: %x, hm1: %p\n", res, hm1);
//DisplayStatus();
return 0;
}
上面 ReadDllFile2 中内存是用 VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE) 分配的。
错误日志
故障存储段 2115915853192506159,类型 1
事件名称: APPCRASH
响应: 不可用
Cab ID: 0
问题签名:
P1: loader_mmpp_from_mem.exe
P2: 0.0.0.0
P3: 00000000
P4: 3752B4E99BA4A6F1.DLL
P5: 0.0.0.0
P6: 66843965
P7: c0000005
P8: 000059e4
P9:
P10:
上面测试程序可以正常加载 5.0.3.13版之前的 sciter.dll
麻烦大侠看看能否解决一下,多谢了。
Utils 的RtlFindMemoryBlockFromModuleSection函数--SearchContext->RemainingLength;这个代码应该放到if外边 否则第二次查找的时候就可能内存越界崩溃了。LdrHashEntry计算函数和RtlFindLdrTableEntryByBaseName查找函数的计算方式是个经验值 在一些系统是不适用的
I'm testing loading a dll proteted with Themida using your MemoryModule project.
I protected the a.dll
that comes with the project, when i try to load it the code fail at this line: status = STATUS_NO_MEMORY;
//
// Allocate and copy sections
//
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(new_header);
for (DWORD i = 0; i < new_header->FileHeader.NumberOfSections; ++i, ++section) {
DWORD size = AlignValueUp(
section->Misc.VirtualSize,
new_header->OptionalHeader.SectionAlignment
);
if (size < section->SizeOfRawData) {
status = STATUS_INVALID_IMAGE_FORMAT;
break;
}
LPVOID dest = VirtualAlloc(
(LPSTR)new_header->OptionalHeader.ImageBase + section->VirtualAddress,
size,
MEM_COMMIT,
PAGE_READWRITE
);
if (!dest) {
status = STATUS_NO_MEMORY; // <---- failed here
break;
}
if (section->SizeOfRawData) {
RtlCopyMemory(
dest,
LPBYTE(data) + section->PointerToRawData,
section->SizeOfRawData
);
}
}
It does fail in the latest section, could you please, help debug this?
被调用的程序如果使用了SetUnhandledExceptionFilter来处理异常。用MemoryModulePP来加载后,相应的回调是无法触发的。
目前mmptls的实现默认会初始化并hook
如果是dll的话需要在卸载的时候unload所有dll并且清理掉hook
如果可以自己主动调用初始化和反初始化就好了
1.the test.exe memload a.dll
2.a.dll compile with memorymodulepp.lib
3.in a.dll dllmain DLL_PROCESS_ATTACH memload b.dll
if use test.exe memlod b.dll it's ok!
but use test.exe memload a.dll,in a.dll memload b.dll will crash in test.exe call a.dllmain
I comment //static const BOOL MmpStaticInitializer = MmpInitialize();
then call MmpInitialize before LdrLoadDllMemoryExW
the a.dll load successful, but a.dll call MmpInitialize crash
auto tls = CONTAINING_RECORD(NtCurrentTeb()->ThreadLocalStoragePointer, TLS_VECTOR, TLS_VECTOR::ModuleTlsData);
if (tls && tls->Length > MMP_START_TLS_INDEX) {
RtlRaiseStatus(STATUS_NOT_SUPPORTED);-->crash here
return FALSE;
}
Currently, I see that MemoryModulePP has no releases.
Also, it is only built as a static library (.lib
).
There are use cases where a .dll
of MemoryModulePP
might be preferred, such as bootstrapping MemoryModulePP from a less powerful .dll
loader.
ReflectiveLoader.c 中以下语句影响的
#if !(defined(_M_ARM) || defined(_M_ARM64) || defined(_USRDLL))
https://github.com/Tsinworks/MemoryModulePP/tree/ic
测试数据 https://github.com/Tsinworks/MemoryModulePP/tree/ic/test/data
This library is the best pe loader I've found thanks for your contribution, I was just thinking it would be great if you add .net support, I have not so much information but I know before loading .net dlls with export clr.dll gets initialized, It should be possible to add it to the MMPP, It will be great if you can implement it.
Thanks
一个用ue打包成的c++ dll(a.dll) 直接加载在执行到LdrpCallInitializers时会报”帧不在模块中“。经测试不是tls处理的问题----注释掉处理tls的代码采用直接获取LdrpHandleTlsData指针调用报同样错误。
另一个问题如下
a.dll是依赖b.dll的 (b.dll是可以内存加载成功)
首先修改MemoryModoule文件240行 VirtualAlloc(LPVOID(old_header->OptionalHeader.ImageBase),......)修改为 VirtualAlloc(NULL,......)
内存加载b.dll
内存加载a.dll 在进行到MemoryResolveImportTable函数的时候GetProcAddress获取b.dll的函数有很高概率返回空 错误码126
Hi, thank you for your great job.
I compile MemoryModulePP to MemoryModulePP.dll
I have host.exe that is dynamically linked with MemoryModulePP.dll
Host.exe loads plugin.dll from byte[] using MemoryModulePP
App crash with Fail Fast exception after working for some time.
想问下,如何使用这个来实现注入dll到指定进程
The following modification of the test program crashes for me in Thread()
when accessing x
#include "../MemoryModule/stdafx.h"
#include <cstdio>
int main() {
typedef int(WINAPI* func)();
auto native = LoadLibraryW(L"a.dll");
func f = (func)GetProcAddress(native, "thread");
printf("thread result %d\n", f());
return 0;
}
This is run against an unchanged "a.dll" built as part of the project.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.