一个用于将 dll 加载到内存中的小型 x64 库。
标志可以组合使用
LIBRARYEX_NONE:从磁盘将模块映射到内存并执行入口点。
LIBRARYEX_BYPASS_LOAD_CALLBACK:从磁盘将模块映射到私有内存(无后备),从而绕过映像加载回调(PsSetLoadImageNotifyRoutine)
LIBRARYEX_NO_ENTRY:不执行模块的入口点。
LIBRARYEX_BUFFER:从内存而非磁盘映射模块。
LdrLibrary一个易于使用的函数,用于将库加载到内存中。根据所指定的标志,第一个参数可以是待加载模块的宽字符串名称,也可以是 PE 所在的内存地址。
/*!
* @brief
* load library into memory
*
* @param Buffer
* buffer context to load library
* either a wide string or a buffer pointer
* the to PE file to map (LIBRARYEX_BUFFER)
*
* @param Library
* loaded library pointer
*
* @param Flags
* flags
*
* @return
* status of function
*/
NTSTATUS LdrLibrary(
_In_ PVOID Buffer,
_Out_ PVOID* Library,
_In_ ULONG Flags
);
以下示例展示了如何从磁盘(System32 路径)加载模块:
PVOID Module = { 0 };
ULONG Flags = { 0 };
//
// mapping flags to be used by the library
//
Flags = LIBRARYEX_NONE;
//
// map file into memory
//
if ( ! NT_SUCCESS( Status = LdrLibrary( L"advapi32.dll", &Module, Flags ) ) ) {
printf( "[-] LdrLibraryEx Failed: %p\n", Status );
return;
}
printf( "[*] Module @ %p\n", Module );
以下示例展示了如何从内存缓冲区加载模块:
PVOID Module = { 0 };
ULONG Flags = { 0 };
//
// mapping flags to be used by the library
//
Flags = LIBRARYEX_NONE |
LIBRARYEX_BUFFER;
//
// read file on disk into memory
//
if ( ! ( Image = ReadFileBuffer( L"C:\\Windows\\System32\\advapi32.dll", NULL ) ) ) {
puts( "[-] ReadFileBuffer Failed" );
return;
}
//
// map file into memory
//
if ( ! NT_SUCCESS( Status = LdrLibrary( Image, &Module, Flags ) ) ) {
printf( "[-] LdrLibraryEx Failed: %p\n", Status );
return;
}
printf( "[*] Module @ %p\n", Module );
还可以根据模块的 api set 加载模块(仅支持 win10 及以上版本):
//
// map file into memory
//
if ( ! NT_SUCCESS( Status = LdrLibrary( L"api-ms-win-base-util-l1-1-0.dll", &Module, Flags ) ) ) {
printf( "[-] LdrLibraryEx Failed: %p\n", Status );
return;
}
printf( "[*] Module @ %p\n", );
LdrLibraryExLdrLibraryEx 允许挂钩某些函数,以修改库映射到内存时的行为。
//
// mapping flags to be used by the library
// and insert the loaded module into Peb
//
Flags = LIBRARYEX_BYPASS_LOAD_CALLBACK |
LIBRARYEX_NO_ENTRY;
//
// init LibraryEx context
//
if ( ! NT_SUCCESS( Status = LdrLibraryCtx( &Ctx, Flags ) ) ) {
printf( "[-] LdrLibraryCtx Failed: %d\n", Status );
goto END;
}
//
// hook function
//
Ctx.LdrLoadDll = C_PTR( HookLdrLoadDll );
//
// map file into memory
//
if ( ! NT_SUCCESS( Status = LdrLibraryEx( &Ctx, L"cryptsp.dll", &Module, Flags ) ) ) {
printf( "[-] LdrLibraryEx Failed: %p\n", Status );
return;
}
此代码库是为 x86_64-mingw 编写和优化的,很可能无法在 Visual Studio 下运行或编译。
特别感谢以下资源和项目:
此项目不应在真实环境或实际作战中使用。我编写它的主要目的是理解并学习 Windows 加载器的工作原理。我之所以将其写成库的形式,是因为我想将其用于其他类型的公开和私有项目。我已达成目标。再见。