LoginSignup
3
5

More than 5 years have passed since last update.

WindowsストアアプリへのDLL Inject

Posted at

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

Windowsストアアプリ(Windows Store Apps)は、サンドボックスからされるアプリです。Windows 10インストール後現れた「天気」、「カレンダー」などアプリはその例です。Windows Storeからインストールしたアプリもそのれです。
image

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

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

SetWindowsHookExの中に、[Windows Store Apps]に対して、特別な制限の記述があります。

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

例として、SetWindowsHookExでWindowsストアアプリにDLLをアタッチする要点をまとめます:

SetWindowsHookExを呼び出すEXEは以下の設定が必要です:

  1. EXEを作成する時に、VCの設定には、"UAC Bypass UI Protection"にYes。 image

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

3。署名  (自己署名を利用する場合は、自己署名の証明書をルート信頼機関として登録必要)
詳しい方法は、ここに記述されています。少し古かったので、証明書登録する方法を変更しました。

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が来るとロードされる。)

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

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5