WindowsストアアプリへのDLL Inject

これは新しい技術ではありません。

Windowsストアアプリ(Windows Store Apps)は、サンドボックスからされるアプリです。Windows 10インストール後現れた「天気」、「カレンダー」などアプリはその例です。Windows Storeからインストールしたアプリもそのれです。
![image](https://qiita-image-store.s3.amazonaws.com/0/132451/dcdedebc-0863-8258-f787-6d99d833b413.png)


サンドボックス化されたので、普通のプロセスのように、簡単にOpenProcess(FullAccess...) + CreateRemoteThreadやMapViewOfSectionなどクロスプロセス操作はできません。普通のSetWindowsHookExやSetWinEventHook経由のDLLアタッチもできません。

原因は、UIAccessの制限です。WindowsストアアプリにDLLをアタッチするには、UIAccess=trueのプロセスからしかできない。

[SetWindowsHookEx](https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx)の中に、[Windows Store Apps]に対して、特別な制限の記述があります。

ただし、記述が不十分です。実際は、これはWindows 7(or Vista?)からの技術です。

例として、SetWindowsHookExでWindowsストアアプリにDLLをアタッチする要点をまとめます：
##SetWindowsHookExを呼び出すEXEは以下の設定が必要です：

1. EXEを作成する時に、VCの設定には、"UAC Bypass UI Protection"にYes。
![image](https://qiita-image-store.s3.amazonaws.com/0/132451/ffcfdbe8-0e6f-2b2b-9e0e-fd94ed4f9cb1.png)

２。EXE自体は信頼されるフォルダに置く必要。例えば"C:¥Programe Files¥TestHook"。

３。署名　　（自己署名を利用する場合は、自己署名の証明書をルート信頼機関として登録必要）
詳しい方法は、[ここ](http://www.hundredsoft.jp/win7blog/log/eid70.html)に記述されています。少し古かったので、証明書登録する方法を変更しました。

```
cd %userprofile%\Downloads
@rem ルート証明書作成：
makecert -n "CN=testroot,O=aaa,C=JP,E=foo@hoge.jp" -sv testroot.pvk -r testroot.cer	
@rem 証明書を作成
makecert -n "CN=test,O=aaa,C=JP,E=foo@hoge.jp" -sv test.pvk -ic testroot.cer -iv testroot.pvk test.cer	
@rem testroot.cerをルート証明機関として導入
certmgr.exe -add testroot.cer -s -r localMachine root	
rem test.pfxを作成：
pvk2pfx -pvk test.pvk -spc test.cer -pfx test.pfx	
@rem 最後に、関連ファイルを署名：	
cd "C:¥Program Files¥TestHook"
Signtool sign /f %userprofile%\Downloads\test.pfx /v .¥TestHook.exe
Signtool sign /f %userprofile%\Downloads\test.pfx /v .¥TestHook.dll
```

その他注意点：64bitのWindowsの中に、Windowsストアアプリは32bitである場合があります。事前に確認してから、32bitと64bitのDLLやEXEを作成必要です。

署名しないと、どうなるの？TestHook.exeを起動すると、main関数を入る前に、「invalid inferrer ....」みたいなエラーが出ます。


##テスト用ソース：
- TestHook.EXE（機能：パラメータで指定されたdllのapiを呼び出す)

```
int main(int argc, char** argv)
{
	argv++; argc--;
	printf("DLL: %s\n", argv[0]);
	printf("Function: %s\n", argv[1]);
	HMODULE hDll = LoadLibraryA(argv[0]);
	PROC proc = GetProcAddress(hDll, argv[1]);
	proc();
    return 0;
}

```

- TestHook.dll（機能：hookを設定。ロードされた時、当時のプロセス名が「天気」アプリの特徴と一致すれば強制終了する）

```
static HMODULE _hModule;
static wchar_t currentExePath[1024] = { 0 };

typedef struct _HOOK_INFO {
	int type;
	const wchar_t * name;
	HHOOK hHook;
} HOOK_INFO;

static HOOK_INFO hooks[] = {
	{WH_CALLWNDPROC, L"WH_CALLWNDPROC", 0},
	{WH_CBT, L"WH_CBT", 0},
	{WH_DEBUG, L"WH_DEBUG", 0},
	{WH_GETMESSAGE, L"WH_GETMESSAGE", 0},
	{WH_KEYBOARD, L"WH_KEYBOARD", 0},
	{WH_MOUSE, L"WH_MOUSE", 0},
	{WH_MSGFILTER, L"WH_MSGFILTER", 0}
};

LRESULT CALLBACK CommonCallback(int nCode, WPARAM wParam, LPARAM lParam) {
	return CallNextHookEx(0, nCode, wParam, lParam);
}

extern "C"
void __stdcall hook() {
	MessageBox(NULL, L"Click me to hook", L"test", MB_OK);
	for (int i = 0; i < _countof(hooks); i++) {
		hooks[i].hHook = SetWindowsHookEx(hooks[i].type, CommonCallback, _hModule, 0);
		if (!hooks[i].hHook) {
			DWORD err = GetLastError();
			wchar_t msg[2048] = { 0 };
			wsprintf(msg, L"Failed to set %s hook. Error %: ", hooks[i].name, err);
			FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), msg + wcslen(msg), _countof(msg), NULL);
			OutputDebugString(msg);
		}
	}
	MessageBox(NULL, L"Click me to unhook", L"test", MB_OK);
	for (int i = 0; i < _countof(hooks); i++) {
		if (hooks[i].hHook)
			UnhookWindowsHookEx(hooks[i].hHook);
		hooks[i].hHook = 0;
	}
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		_hModule = hModule;
		DisableThreadLibraryCalls(hModule);
		GetModuleFileName(NULL, currentExePath, _countof(currentExePath));

		{
			wchar_t msg[4096] = { 0 };
			wsprintf(msg, L"I am in process %s cmdline: %s", currentExePath, GetCommandLine());
			OutputDebugString(msg);
		}

		if (wcsstr(currentExePath, L"Microsoft.BingWeather_4.17.74.0_x86__8wekyb3d8bbwe")) {
			TerminateProcess(GetCurrentProcess(), 1);
		}

		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}
```

実行方法は、

```
cd "C:¥Program Files¥TestHook"
TestHook.exe .¥TestHook.dll hook
```
[click me to hook]のOKを押して。TestHook.dllを全てのGUIアプリにアタッチ(厳密に言うと、すぐにアタッチするではなく、何らかのWindows関連のMessageが来るとロードされる。)

この状態で、「天気」アプリを起動すると、一瞬画面が現れてすぐに終了されます。