2016年12月14日星期三

WindowsストアアプリへのDLL Inject

これは新しい技術ではありません。
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が来るとロードされる。)
この状態で、「天気」アプリを起動すると、一瞬画面が現れてすぐに終了されます。

没有评论:

发表评论