在《動態加載與插件化》中大概介紹了下,wp8加載非安裝包的下動態連接庫,此次詳細梳理下。html
加載外部DLL主要的原理:函數
相關的結構體:spa
typedef struct _CLIENT_ID 插件
{ 線程
PVOID UniqueProcess; 3d
PVOID UniqueThread; code
} CLIENT_ID; orm
//模塊鏈表實體htm
typedef struct _MODULE_LIST_ENTRYblog
{
struct _MODULE_LIST_ENTRY* Flink;
struct _MODULE_LIST_ENTRY* Blink;
DWORD* baseAddress;
}MODULE_LIST_ENTRY;
//進程加載的模塊信息
typedef struct _PEB_LDR_DATA
{
// BYTE fill[0x1c]; x86
ULONG Length;
BOOLEAN Initialized;
PVOID SsHandle ;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
MODULE_LIST_ENTRY* initModuleList;
}PEB_LDR_DATA;
//進程環境塊
typedef struct _PEB
{
// BYTE fill[0x0c]; x86
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PEB_LDR_DATA* ldr;
}PEB;
//線程環境塊
typedef struct _TEB
{
//BYTE fill[0x30]; x86
NT_TIB nt_tib;
PVOID EnvironmentPointer;
CLIENT_ID id;
PVOID ActiveRpcHandle;
PVOID ThreadLocalStoragePointer;
PEB* currentPEB;
}TEB;
typedef HMODULE(*LoadLibraryEx)(
LPCTSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags
);
獲取kernelbase.dll模塊句柄的類定義
namespace Anye
{
namespace Native
{
public ref class DllHandle sealed
{
friend ref class NativeInterop;
friend class NativeHelper;
public:
int GetModule();
private:
HMODULE _handle;
DllHandle(HMODULE handle);
//獲取指定名稱的函數地址
void* GetFunction(LPCSTR name);
};
public ref class NativeInterop sealed
{
public:
NativeInterop();
//加載指定路徑下的DLL
DllHandle^ LoadLibrary(Platform::String^ name);
//獲取KernelBase.dll的模塊句柄
DllHandle^ GetKernel();
int GetModule();
private:
DllHandle^ _kernel;
LoadLibraryEx _loadLibrary;
HMODULE getKernelModule();
};
class NativeHelper
{
public:
NativeHelper(const wchar_t* path);
void* GetFunction(LPCSTR name);
private:
DllHandle^ _interop;
};
}
}
主要的加載邏輯
HMODULE NativeInterop::getKernelModule()
{
//獲取線程環境快
TEB* teb = NtCurrentTeb();
獲取KernelBase.dll的模塊句柄PS:保險點的方法市歷遍DLL初始化鏈表經過模塊名稱肯定
return (HMODULE) teb->currentPEB->ldr->initModuleList->Flink->baseAddress;
}
DllHandle^ NativeInterop::LoadLibrary(Platform::String^ name)
{
if (_loadLibrary == nullptr)//獲取LoadLibraryExW函數地址
_loadLibrary = (LoadLibraryEx)_kernel->GetFunction("LoadLibraryExW");
HMODULE module = _loadLibrary(name->Data(), nullptr, 0);
if (module != nullptr)
return ref new DllHandle(module);
return nullptr;
}
void* DllHandle::GetFunction(LPCSTR name)
{
return GetProcAddress(_handle, name);
}
NativeHelper
NativeHelper::NativeHelper(const wchar_t* path)
{
auto inter = ref new NativeInterop();
String^ pathString = (Platform::String^)Platform::StringReference(path);
_interop = inter->LoadLibrary(pathString);
}
void* NativeHelper::GetFunction(LPCSTR name)
{
return _interop->GetFunction(name);
}
下面是加載wp手機SD卡上的plugin.dll的例子
動態庫項目
動態連接庫邏輯
extern "C"
{
__declspec(dllexport) void* Create();
}
namespace Plugin
{
class IPlugin
{
public:
virtual void Show(Platform::String^ msg) = 0;
};
class TestPlugin : public IPlugin
{
public:
TestPlugin()
{
}
void Show(Platform::String^ msg)
{
(ref new Windows::UI::Popups::MessageDialog(msg))->ShowAsync();
}
};
}
void* Create()
{
return new Plugin::TestPlugin();
}
加載外部動態連接庫
class IPlugin
{
public:
virtual void Show(Platform::String^ msg) = 0;
};
void NativeEntry::Load(Platform::String^ path)
{ //path 是 D:\\Downloads\\plugin.dll,D盤就是sd
Anye::Native::NativeHelper* h = new Anye::Native::NativeHelper(path->Data());
CreateFunc func;
func = (CreateFunc)h->GetFunction("Create");
IPlugin* plugin = (IPlugin*)func();
plugin->Show("我是"+path+"裏的插件^_^");
}
好了例子就到這了,咱們得到了LoadLibraryExW函數,不侷限於加載外部DLL,也能夠去加載系統的DLL,去訪問一些微軟未公開的API,如只讀訪問註冊表信息
Anye::Native::NativeInterop interop;
auto h = interop.LoadLibrary("ADVAPI32LEGACY.DLL");
Anye_RegCreateKeyEx = (RegCreateKeyFunc)GetFunc(h->GetModule(), "RegCreateKeyW");
Anye_RegSetValueEx = (RegSetValueFunc)GetFunc(h->GetModule(), "RegSetValueW");
Anye_RegQueryValueEx = (RegQueryValueFunc)GetFunc(h->GetModule(), "RegQueryValueW");
Anye_RegCloseKey = (RegCloseKeyFunc)GetFunc(h->GetModule(), "RegCloseKey");
Anye_RegOpenKey = (RegOpenKeyFunc)GetFunc(h->GetModule(), "RegOpenKeyW");
Anye_RegEnumKey = (RegEnumKeyFunc)GetFunc(h->GetModule(), "RegEnumKeyW");