--- title: "Flash32以上版本无法打开外链问题说明" date: 2020-08-12T10:48:22+08:00 draft: false toc: true images: tags: [flash] categories: windows --- ## 问题背景 雷霆之怒在微端中无法打开外链,与CP方沟通发现,他们打开URL使用的方式是`flash.net.navigateToURL`,而从Flash32版本开始,增加了一个安全性控制字段`EnableInsecureActiveXNavigateToURL`,根据官方[Release Note](https://helpx.adobe.com/flash-player/release-note/fp_32_air_32_release_notes.html)描述,该字段是用于控制打开的外链URL跨域行为的,此次的问题正是由于这个字段引起的。 ## 问题调查 代码层的具体表现为,游戏中点击外链按钮之后,IE控件无法触发`NewWindow3`事件。根据官方论坛的[讨论](https://community.adobe.com/t5/flash-player/issue-with-navigatetourl/td-p/10641531?page=1),可以在系统的flash.ocx目录,创建`mms.cfg`文件用于对Flash做安全控制,32位进程路径为`C:\Windows\SysWOW64\Macromed\Flash\mms.cfg`,64位进程路径位`C:\Windows\System32\Macromed\Flash\mms.cfg`,文件内容为`EnableInsecureActiveXNavigateToURL=1`,必须要有管理员权限才能写入文件。 直接修改`mms.cfg`文件最简单,但是由于需要提权,所以在用户双击启动的时候,会弹UAC框,非常影响用户体验。同时,同样的Flash版本下,IE浏览器则不受影响,说明,不止修改`mms.cfg`文件一条路。 ## 问题解决 ### 暴力方式(Hook) Flash配置加载流程: 程序加载Flash控件 -> `CoreGlobals::Init`初始化 -> `CreateFileW`打开配置文件`mms.cfg` -> `CoreGlobals::ReadSecurityProperty`解析配置 -> 保存结果到全局结构体`globClass`中。 后续需要用到全局配置的时候,直接通过全局函数`GetPlatformGlobals`即可获取到`globClass`的指针。32.0.0.387版本的flash.ocx文件中,该指针的FA为`0x1398BF8`,RVA为`0x139b1f8`,对应成员变量偏移为`0xa234`。有了这些信息,即可在运行时,动态修改`EnableInsecureActiveXNavigateToURL`的值为1,即可绕过跨域的限制,成功收到`NewWindow3`的响应。 动态改内存的方式虽然可以达到目的,但是兼容性较差,一旦Flash升级了,前面算出来的偏移可能就废了。 分析上面的配置加载流程,我们发现Flash会调用系统API函数`CreateFileW`打开配置文件,这个API大家都很熟悉了,是导出函数,所以也不用担心偏移地址的问题,直接Hook该API,替换路径为我们本地的mms.cfg文件,这样我们就可以通过程序本地的文件控制Flash的行为了。 上面两种方式都已经实现并且验证可行,但都不算完美,所以只做简要介绍,下面详细说明我们今天的重头戏。 ### IE方式(白名单) `flash.net.navigateToURL`函数最终会调用Flash内部的`PlatformPlayer::DoNavigateToURLImpl`函数执行真正的逻辑。 ```c++ bool __thiscall PlatformPlayer::DoNavigateToURLImpl(PlatformPlayer *this, struct URLRequest *a2) { CorePlayer *v2; // esi char *v3; // ebx PlatformFileManager *v4; // eax const char **v5; // eax bool v6; // bl LPCWSTR v8; // esi const WCHAR *v9; // eax LPCVOID v10; // ecx const CHAR *v11; // eax unsigned int v12; // ecx int v13; // edi void *v14; // esp WCHAR *v15; // eax unsigned int v16; // ecx unsigned int v17; // edi void *v18; // esp const WCHAR *v19; // eax WCHAR *v20; // eax CorePlayer *v21; // edi PlatformFileManager *v22; // eax int v23; // eax int v24; // eax const char *v25; // edx char *v26; // ecx bool v27; // cf bool v28; // zf unsigned __int8 v29; // al int v30; // ecx char *v31; // ecx bool v32; // cf unsigned __int8 v33; // bl int v34; // ecx bool v35; // sf int v36; // eax int v37; // edi unsigned __int16 *v38; // eax int v39; // eax PlatformFileManager *v40; // eax struct URLRequest *v41; // edi DRM::AVEContentDecryptionCallbacks *v42; // ecx const char *v43; // edi SAFEARRAY *v44; // edi int v45; // ST18_4 const CHAR *v46; // edi int v47; // eax int v48; // eax struct PlatformGlobals *v49; // eax DRM::AVEContentDecryptionCallbacks *v50; // eax char *v51; // edi char *v52; // edi int v53; // eax int v54; // eax CorePlayer *v55; // ebx int v56; // edi int v57; // eax bool v58; // bl IUnknown *v59; // eax LPCWSTR v60; // edi HRESULT v61; // ebx WCHAR *v62; // ST1C_4 GUID *v63; // [esp+0h] [ebp-B0h] GUID *v64; // [esp+4h] [ebp-ACh] int *v65; // [esp+8h] [ebp-A8h] char *v66; // [esp+Ch] [ebp-A4h] BSTR bstrString; // [esp+10h] [ebp-A0h] LPCSTR v68; // [esp+14h] [ebp-9Ch] int v69; // [esp+18h] [ebp-98h] LPCVOID lpMem; // [esp+1Ch] [ebp-94h] int v71; // [esp+20h] [ebp-90h] LPCWSTR szTargetFrameName; // [esp+24h] [ebp-8Ch] struct URLRequest *v73; // [esp+28h] [ebp-88h] CorePlayer *v74; // [esp+2Ch] [ebp-84h] char v75; // [esp+32h] [ebp-7Eh] char v76; // [esp+33h] [ebp-7Dh] VARIANTARG v77; // [esp+34h] [ebp-7Ch] VARIANTARG v78; // [esp+44h] [ebp-6Ch] VARIANTARG pvarg; // [esp+54h] [ebp-5Ch] OLECHAR *psz; // [esp+64h] [ebp-4Ch] VARIANTARG v81; // [esp+68h] [ebp-48h] char *v82; // [esp+78h] [ebp-38h] int v83; // [esp+7Ch] [ebp-34h] int v84; // [esp+80h] [ebp-30h] int v85; // [esp+84h] [ebp-2Ch] int v86; // [esp+88h] [ebp-28h] _DWORD **v87; // [esp+8Ch] [ebp-24h] LPCSTR lpMultiByteStr; // [esp+90h] [ebp-20h] int v89; // [esp+94h] [ebp-1Ch] int v90; // [esp+98h] [ebp-18h] IMoniker *pmkTarget; // [esp+9Ch] [ebp-14h] int v92; // [esp+A0h] [ebp-10h] int v93; // [esp+A4h] [ebp-Ch] int v94; // [esp+A8h] [ebp-8h] v2 = this; v74 = this; v73 = a2; v3 = (char *)*((_DWORD *)a2 + 9); v94 = *((_DWORD *)a2 + 9); if ( !*((_BYTE *)GetPlatformGlobals() + 41524) ) { v4 = CorePlayer::FileMgr(v2); v5 = (const char **)PlatformGlobals::GetHostAppInternalName(&v82, v4); v6 = PlatformPlayer::RunningInBrowser(*v5) == 0; FlashString::Clear((FlashString *)&v82); if ( v6 ) return 0; v3 = (char *)v94; } v8 = 0; szTargetFrameName = 0; v69 = CorePlayer::CalcCorePlayerVersion(v74); if ( v69 > 5 ) { lpMem = CopyUTF8to16(*((const char **)a2 + 8)); v9 = CopyUTF8to16(v3); v10 = lpMem; szTargetFrameName = v9; goto LABEL_24; } v11 = (const CHAR *)*((_DWORD *)a2 + 8); v68 = v11; if ( v11 && (v12 = strlen(v11), v13 = 2 * (v12 + 1), v86 = (unsigned __int64)(2i64 * (signed int)(v12 + 1) + 0x80000000i64) >> 32, (unsigned __int64)(2i64 * (signed int)(v12 + 1) + 0x80000000i64) <= 0xFFFFFFFF) ) { if ( v13 <= 1024 && ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable((ATL::_ATL_SAFE_ALLOCA_IMPL *)v13, (unsigned int)v63) ) { v14 = alloca(v13); v15 = (WCHAR *)&v63; } else { v15 = (WCHAR *)ATL::_ATL_SAFE_ALLOCA_IMPL::CAtlSafeAllocBufferManager::Allocate(v13); v8 = szTargetFrameName; } lpMem = AtlA2WHelper(v15, v68, (unsigned int)v13 >> 1, 3u); } else { lpMem = 0; } if ( v3 && (v16 = strlen(v3), v17 = 2 * (v16 + 1), v86 = (unsigned __int64)(2i64 * (signed int)(v16 + 1) + 0x80000000i64) >> 32, (unsigned __int64)(2i64 * (signed int)(v16 + 1) + 0x80000000i64) <= 0xFFFFFFFF) ) { if ( (signed int)v17 <= 1024 && ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable((ATL::_ATL_SAFE_ALLOCA_IMPL *)v17, (unsigned int)v63) ) { v18 = alloca(v17); v19 = AtlA2WHelper((LPWSTR)&v63, v3, v17 >> 1, 3u); } else { v20 = (WCHAR *)ATL::_ATL_SAFE_ALLOCA_IMPL::CAtlSafeAllocBufferManager::Allocate(v17); v8 = szTargetFrameName; v19 = AtlA2WHelper(v20, v3, v17 >> 1, 3u); } } else { v19 = 0; } v10 = lpMem; szTargetFrameName = v19; if ( lpMem && v19 ) { LABEL_24: pmkTarget = 0; v71 = -2147467259; v21 = v74; PlatformPlayer::BuildRelativeMoniker(v10, &pmkTarget); if ( !pmkTarget ) { v61 = -2147467259; goto LABEL_146; } v76 = 0; if ( !*((_DWORD *)v73 + 10) && v69 < 8 ) { v22 = CorePlayer::FileMgr(v21); if ( !PlatformFileManager::IsIE7(v22) ) goto LABEL_141; } v23 = *((_DWORD *)v21 + 892); v92 = 0; v93 = 0; ATL::CComQIPtr::CComQIPtr(*(_DWORD *)(v23 + 16)); v24 = v93; if ( !v93 ) { LABEL_137: if ( v92 ) (*(void (__thiscall **)(_DWORD, int))(*(_DWORD *)v92 + 8))(*(_DWORD *)(*(_DWORD *)v92 + 8), v92); if ( !v76 ) { v21 = v74; LABEL_141: if ( coreplayer::View::GetFullScreen(*(coreplayer::View **)(*((_DWORD *)v21 + 22) + 628)) ) coreplayer::View::SetFullScreen(*(coreplayer::View **)(*((_DWORD *)v21 + 22) + 628), 0, 0); v59 = (IUnknown *)*((_DWORD *)v21 + 892); v60 = szTargetFrameName; v61 = HlinkSimpleNavigateToMoniker(pmkTarget, 0, szTargetFrameName, v59 + 27, 0, 0, 0, 0); goto LABEL_147; } v61 = v71; LABEL_146: v60 = szTargetFrameName; LABEL_147: if ( v69 > 5 ) { if ( lpMem ) MMgc::FixedMalloc::OutOfLineFree(dword_EDCACF8, lpMem); if ( v60 ) MMgc::FixedMalloc::OutOfLineFree(dword_EDCACF8, v60); } v58 = v61 >= 0; goto LABEL_153; } if ( !v3 ) goto LABEL_161; v25 = "_blank"; v26 = v3; while ( 1 ) { v27 = (unsigned __int8)*v26 < *v25; v28 = *v26 == *v25; v75 = *v26; v24 = v93; if ( !v28 ) break; if ( !v75 ) goto LABEL_35; v29 = v26[1]; v27 = v29 < v25[1]; v28 = v29 == v25[1]; v75 = v26[1]; v24 = v93; if ( !v28 ) break; v26 += 2; v25 += 2; if ( !v75 ) { LABEL_35: v30 = 0; goto LABEL_37; } } v30 = -v27 | 1; LABEL_37: if ( !v30 ) goto LABEL_162; v25 = "_new"; v31 = v3; while ( 1 ) { v32 = (unsigned __int8)*v31 < *v25; v28 = *v31 == *v25; v75 = *v31; v3 = (char *)v94; if ( !v28 ) break; if ( !v75 ) goto LABEL_43; v33 = v31[1]; v32 = v33 < v25[1]; v28 = v33 == v25[1]; v75 = v31[1]; v3 = (char *)v94; if ( !v28 ) break; v31 += 2; v25 += 2; if ( !v75 ) { LABEL_43: v34 = 0; goto LABEL_45; } } v34 = -v32 | 1; LABEL_45: if ( v34 ) { LABEL_161: v37 = (*(int (__thiscall **)(_DWORD, int, GUID *, GUID *, int *))(*(_DWORD *)v24 + 12))( *(_DWORD *)(*(_DWORD *)v24 + 12), v24, &IID_IWebBrowserApp, &IID_IWebBrowser2, &v92); v71 = v37; } else { LABEL_162: v94 = 0; v35 = (*(int (__fastcall **)(_DWORD, const char *, int, SID *, GUID *, int *, GUID *, GUID *, int *))(*(_DWORD *)v24 + 12))( *(_DWORD *)(*(_DWORD *)v24 + 12), v25, v24, &SID_STopLevelBrowser, &IID_IServiceProvider, &v94, v63, v64, v65) < 0; v36 = v94; v65 = &v92; v64 = &IID_IWebBrowser2; v63 = &IID_IWebBrowserApp; if ( v35 ) v36 = v93; v37 = (*(int (__thiscall **)(_DWORD, int))(*(_DWORD *)v36 + 12))(*(_DWORD *)(*(_DWORD *)v36 + 12), v36); v71 = v37; ATL::CComPtr::~CComPtr(&v94, v63, v64, v65); } if ( v37 < 0 ) { LABEL_135: if ( v93 ) (*(void (__thiscall **)(_DWORD, int))(*(_DWORD *)v93 + 8))(*(_DWORD *)(*(_DWORD *)v93 + 8), v93); goto LABEL_137; } VariantInit(&pvarg); if ( v3 ) { pvarg.vt = 8; if ( v69 <= 5 ) v38 = A2BSTR(v3); else v38 = UTF82BSTR(v3); pvarg.lVal = (LONG)v38; } v71 = ((int (__thiscall *)(HRESULT (__stdcall *)(IMoniker *, IBindCtx *, IMoniker *, LPOLESTR *), IMoniker *, _DWORD, IMoniker *, OLECHAR **))pmkTarget->lpVtbl->GetDisplayName)( pmkTarget->lpVtbl->GetDisplayName, pmkTarget, 0, pmkTarget, &psz); if ( v71 < 0 ) { LABEL_134: VariantClear(&pvarg); goto LABEL_135; } bstrString = SysAllocString(psz); CoTaskMemFree(psz); VariantInit(&v77); lpMultiByteStr = 0; v89 = 0; v90 = 0; v75 = IsWindowsVersion(5u, 0); v76 = 0; if ( IsWindowsVersion(5u, 1u) ) { v39 = strcmp(CommonPlayer::GetOSLanguage(v69), "ja"); if ( v39 ) v39 = -(v39 < 0) | 1; if ( !v39 ) { v40 = CorePlayer::FileMgr(v74); if ( !PlatformFileManager::IsIE7(v40) ) v76 = 1; } } v41 = v73; v42 = (DRM::AVEContentDecryptionCallbacks *)*((_DWORD *)v73 + 17); if ( !v42 ) { LABEL_76: if ( *((_DWORD *)v41 + 10) ) { FlashString::AppendString((FlashString *)&lpMultiByteStr, "Content-type: "); if ( *((_DWORD *)v41 + 12) ) FlashString::AppendString((FlashString *)&lpMultiByteStr, *((const char **)v41 + 12)); else FlashString::AppendString((FlashString *)&lpMultiByteStr, "application/x-www-form-urlencoded"); FlashString::AppendString((FlashString *)&lpMultiByteStr, "\r\n"); } if ( v89 ) { v77.vt = 8; v77.lVal = (LONG)A2BSTR(lpMultiByteStr); } VariantInit(&v78); if ( *((_DWORD *)v41 + 10) ) { v44 = SafeArrayCreateVector(0x11u, 0, *((_DWORD *)v41 + 11)); v78.vt = 8209; v78.lVal = (LONG)v44; SafeArrayLock(v44); memcpy(v44->pvData, *((const void **)v73 + 10), *((_DWORD *)v73 + 11)); SafeArrayUnlock(v44); v41 = v73; } VariantInit(&v81); v81.lVal = 0; v45 = *((_DWORD *)v41 + 12); v81.vt = 3; v85 = 0; v86 = 0; HttpHeaders::HttpHeaders(&v85, v45, 2); if ( HttpHeaders::HeadersPresent((HttpHeaders *)&v85) ) v81.lVal |= 0x8000u; if ( !coreplayer::View::GetFullScreen(*(coreplayer::View **)(*((_DWORD *)v74 + 22) + 628)) ) { if ( !SecurityContext::IsPlayerUI(*((SecurityContext **)v41 + 17)) ) v81.lVal |= 0x100u; if ( CommonPlayer::GetWindowsVersion() >= 14 && (*((_BYTE *)v41 + 77) || CorePlayer::DoesExecutionResultFromUserAction(v74)) ) { v81.lVal &= 0xFFFFFEFF; if ( PlatformPlayer::RunningInSpartan() ) v81.lVal |= 0x400000u; } } v76 = 1; v46 = CopyUTF16to8(bstrString, 0); v68 = v46; if ( !v3 ) goto LABEL_116; v47 = strcmp(v3, &byte_E8C6254); if ( v47 ) v47 = -(v47 < 0) | 1; if ( !v47 ) goto LABEL_116; v48 = strcmp(v3, "_self"); if ( v48 ) v48 = -(v48 < 0) | 1; if ( !v48 ) goto LABEL_116; v66 = *(char **)DRM::AVEContentDecryptionCallbacks::getVideoState(*((DRM::AVEContentDecryptionCallbacks **)v73 + 17)); v49 = GetPlatformGlobals(); if ( FlashSecurity::IsScriptingUrl(*((FlashSecurity **)v49 + 6), v46) ) { v50 = (DRM::AVEContentDecryptionCallbacks *)*((_DWORD *)v73 + 20); if ( !v50 ) { v50 = (DRM::AVEContentDecryptionCallbacks *)*((_DWORD *)v73 + 17); if ( !v50 ) goto LABEL_116; } v76 = PlatformPlayer::scriptingTargetIsSecure(v74, v50, v3); if ( v76 ) goto LABEL_116; v51 = CopyUTF16to8(pvarg.bstrVal, 0); FlashSecurity::ReportDeniedRequest(*(FlashSecurity **)(*((_DWORD *)v74 + 9) + 24), v74, v51, v66, 0); StrFree(v51); } else { v87 = 0; v71 = (*(int (__thiscall **)(_DWORD, int, _DWORD ***))(*(_DWORD *)v92 + 72))( *(_DWORD *)(*(_DWORD *)v92 + 72), v92, &v87); if ( v71 >= 0 && v87 ) { v94 = 0; v71 = ((int (__thiscall *)(_DWORD, _DWORD **, GUID *, int *))**v87)(**v87, v87, &IID_IHTMLDocument2, &v94); if ( v71 >= 0 && v94 ) v76 = PlatformPlayer::navigationTargetIsSecure(v74, v94, *((_DWORD *)v73 + 17), v3, (int)&pvarg); ATL::CComPtr::~CComPtr(&v94, v63, v64, v65); if ( !v76 ) { v52 = CopyUTF16to8(pvarg.bstrVal, 0); FlashSecurity::ReportDeniedRequest(*(FlashSecurity **)(*((_DWORD *)v74 + 9) + 24), v74, v52, v66, 0); StrFree(v52); } } ATL::CComPtr::~CComPtr(&v87, v63, v64, v65); } v46 = v68; LABEL_116: if ( v46 ) MMgc::FixedMalloc::OutOfLineFree(dword_EDCACF8, v46); if ( v76 ) { if ( v3 ) { v53 = strcmp(v3, &byte_E8C6254); if ( v53 ) v53 = -(v53 < 0) | 1; if ( !v53 ) goto LABEL_163; } v54 = strcmp(v3, "_self"); if ( v54 ) v54 = -(v54 < 0) | 1; if ( v54 ) { v55 = v74; } else { LABEL_163: v55 = v74; CorePlayer::UpdateClientSharedObjects(v74); } (*(void (__thiscall **)(_DWORD, int))(*(_DWORD *)(*((_DWORD *)v55 + 892) + 108) + 4))( *(_DWORD *)(*(_DWORD *)(*((_DWORD *)v55 + 892) + 108) + 4), *((_DWORD *)v55 + 892) + 108); v56 = (*(int (__thiscall **)(_DWORD, int, BSTR, VARIANTARG *, VARIANTARG *, VARIANTARG *, VARIANTARG *))(*(_DWORD *)v92 + 44))( *(_DWORD *)(*(_DWORD *)v92 + 44), v92, bstrString, &v81, &pvarg, &v78, &v77); v57 = *((_DWORD *)v55 + 892); v71 = v56; if ( *(_DWORD *)(v57 + 232) == 1 ) { CorePlayer::SetPlayerAbortStatus(v55, 1); *((_BYTE *)v55 + 2836) = 1; HttpHeaders::~HttpHeaders((HttpHeaders *)&v85); FlashString::Clear((FlashString *)&lpMultiByteStr); ATL::CComPtr::~CComPtr(&v93, v63, v64, v65); ATL::CComPtr::~CComPtr(&v92, v63, v64, v65); v58 = 0; LABEL_153: if ( pmkTarget ) ((void (__thiscall *)(ULONG (__stdcall *)(IMoniker *), IMoniker *))pmkTarget->lpVtbl->Release)( pmkTarget->lpVtbl->Release, pmkTarget); goto LABEL_156; } (*(void (__thiscall **)(_DWORD, int))(*(_DWORD *)(v57 + 108) + 8))( *(_DWORD *)(*(_DWORD *)(v57 + 108) + 8), v57 + 108); } v76 = 1; VariantClear(&v81); if ( bstrString ) SysFreeString(bstrString); VariantClear(&v78); VariantClear(&v77); HttpHeaders::~HttpHeaders((HttpHeaders *)&v85); FlashString::Clear((FlashString *)&lpMultiByteStr); goto LABEL_134; } v43 = *(const char **)DRM::AVEContentDecryptionCallbacks::getVideoState(v42); if ( v43 ) { if ( StripScheme(v43, "https:") == 0 ) { if ( !StripScheme(v43, "http:") ) goto LABEL_75; LABEL_69: v82 = 0; v83 = 0; v84 = 0; FlashString::FlashString((FlashString *)&v82, v43); if ( v76 ) { FlashString::Truncate((FlashString *)&v82, 0x64u); } else if ( v75 ) { FlashString::Truncate((FlashString *)&v82, 0x6Eu); } else { FlashString::Truncate((FlashString *)&v82, 0x8Cu); } FlashString::AppendString((FlashString *)&lpMultiByteStr, "Referer: "); FlashString::AppendString((FlashString *)&lpMultiByteStr, v82); FlashString::AppendString((FlashString *)&lpMultiByteStr, "\r\n"); FlashString::Clear((FlashString *)&v82); goto LABEL_75; } if ( StripScheme(*((const char **)v73 + 8), "https:") ) goto LABEL_69; } LABEL_75: v41 = v73; goto LABEL_76; } v58 = 0; LABEL_156: while ( v8 ) { v62 = (WCHAR *)v8; v8 = *(LPCWSTR *)v8; free(v62); } return v58; } ``` 该函数很长,但是目的却很简单,就是打开URL,我们只分析第一个`if`语句块即可 ```c++ if ( !*((_BYTE *)GetPlatformGlobals() + 41524) ) { v4 = CorePlayer::FileMgr(v2); v5 = (const char **)PlatformGlobals::GetHostAppInternalName(&v82, v4); v6 = PlatformPlayer::RunningInBrowser(*v5) == 0; FlashString::Clear((FlashString *)&v82); if ( v6 ) return 0; v3 = (char *)v94; } ``` 前面已经说过`GetPlatformGlobals`函数用于获取全局配置结构体地址,`41524`即十六进制的`0xa234`,就是我们的目标变量偏移,所以这条语句就是判断`EnableInsecureActiveXNavigateToURL`属性是否为真,如果为真则不会进入`if`内部,直接进行后续处理,否则进入`if`内部,准备返回`0`,而一旦返回,则意味着打开URL失败,在IE控件的表现则为收不到`NewWindow3`事件。我们如果不进行上面提到的暴力方式的处理,`EnableInsecureActiveXNavigateToURL`默认为0,则会直接进入`if`内部,此时,我们就要想办法让`v6`为假,否则就会失败,而`v6`的值由`v5`决定,所以需要看看`PlatformGlobals::GetHostAppInternalName`和`PlatformPlayer::RunningInBrowser`这两个函数的实现。 ```c++ _DWORD *__cdecl PlatformGlobals::GetHostAppInternalName(_DWORD *a1, PlatformFileManager *a2) { const char *v2; // edi const char *v3; // eax const void *v4; // esi unsigned __int16 *v5; // esi const char *v6; // eax char *v7; // esi char *v8; // eax LPCVOID pBlock; // [esp+28h] [ebp-130h] __int16 v11; // [esp+2Eh] [ebp-12Ah] LPVOID lpBuffer; // [esp+30h] [ebp-128h] LPVOID v13; // [esp+34h] [ebp-124h] unsigned int puLen; // [esp+38h] [ebp-120h] int v15; // [esp+3Ch] [ebp-11Ch] int v16; // [esp+40h] [ebp-118h] int v17; // [esp+44h] [ebp-114h] int v18; // [esp+48h] [ebp-110h] char v19; // [esp+4Ch] [ebp-10Ch] CHAR SubBlock[4]; // [esp+50h] [ebp-108h] char v21; // [esp+60h] [ebp-F8h] char v22; // [esp+64h] [ebp-F4h] int v23; // [esp+68h] [ebp-F0h] __int16 v24; // [esp+74h] [ebp-E4h] *a1 = 0; a1[1] = 0; a1[2] = 0; v19 = aStringfileinfo[16]; strcpy((char *)&v11, "e"); v15 = 0; v16 = 0; v17 = 0; v18 = 0; FlashFileString::FlashFileString((FlashFileString *)&v15); v2 = 0; pBlock = 0; v13 = 0; if ( PlatformFileManager::FileGetModuleFileName(a2, 0, (struct FlashFileString *)&v15) ) { v3 = FlashFileString::getMBCS((FlashFileString *)&v15); v2 = CreateStr(v3); v4 = PlatformFileManager::FileGetFileVersionInfo(a2, (const struct FlashFileString *)&v15); pBlock = v4; if ( v4 ) { if ( VerQueryValueA(v4, "\\VarFileInfo\\Translation", &lpBuffer, &puLen) ) { v5 = (unsigned __int16 *)lpBuffer; qmemcpy(SubBlock, "\\StringFileInfo\\", 16); FourCharacterHexCodeFromWord(&v21, *(unsigned __int16 *)lpBuffer); FourCharacterHexCodeFromWord(&v22, v5[1]); qmemcpy(&v23, "\\InternalNam", 12); v24 = v11; if ( VerQueryValueA(pBlock, SubBlock, &v13, &puLen) ) FlashString::operator=((char *)v13); } } } if ( !a1[1] ) { if ( v2 ) { if ( *v2 ) { v6 = FlashStrRChr(v2, 92); if ( v6 ) { v7 = (char *)(v6 + 1); v8 = (char *)FlashStrChr(v6 + 1, 46); if ( v8 ) { if ( v8 > v7 ) { *v8 = 0; FlashString::operator=(v7); } } } } } } if ( pBlock ) MMgc::FixedMalloc::OutOfLineFree(dword_EDCACF8, pBlock); if ( v2 ) MMgc::FixedMalloc::OutOfLineFree(dword_EDCACF8, v2); FlashFileString::~FlashFileString((FlashFileString *)&v15); return a1; } ``` ```c++ char __cdecl PlatformPlayer::RunningInBrowser(const char *a1) { char v1; // bl int v2; // esi char result; // al char *v4; // [esp+Ch] [ebp-30h] const char *v5; // [esp+10h] [ebp-2Ch] const char *v6; // [esp+14h] [ebp-28h] const char *v7; // [esp+18h] [ebp-24h] const char *v8; // [esp+1Ch] [ebp-20h] const char *v9; // [esp+20h] [ebp-1Ch] const char *v10; // [esp+24h] [ebp-18h] const char *v11; // [esp+28h] [ebp-14h] const char *v12; // [esp+2Ch] [ebp-10h] const char *v13; // [esp+30h] [ebp-Ch] const char *v14; // [esp+34h] [ebp-8h] const char *v15; // [esp+38h] [ebp-4h] v1 = 0; v4 = "explorer"; v5 = "iexplore"; v6 = "AOL"; v7 = "netscape"; v8 = "excel"; v9 = "powerpnt"; v10 = "pptview"; v11 = "winword"; v12 = "ybrowser"; v13 = "msn"; v14 = "msn6"; v15 = "iepreview.exe"; if ( a1 ) { v2 = 0; while ( FlashStrICmp(a1, (&v4)[v2]) ) { if ( (unsigned int)++v2 >= 0xC ) goto LABEL_5; } return 1; } LABEL_5: if ( byte_EDABB0C ) { if ( !byte_EDABB0D ) return v1; result = 1; } else { byte_EDABB0C = 1; if ( CommonPlayer::isWin10() && PlatformGlobals::platformInstance && PlatformGlobals::IsMetroMode(PlatformGlobals::platformInstance) ) { byte_EDABB0D = 1; result = 1; } else { result = 0; byte_EDABB0D = 0; } } return result; } ``` `GetHostAppInternalName`逻辑比较简单,就是取进程名,这里有一点要注意的是,它取的是`InternalNam`,即我们在`rc`文件中配置的`InternalName`。 `RunningInBrowser`就是判断进程是否在浏览器中运行,参数`a1`就是前面取到的`InternalName`,我们期望该函数返回1,才能使得`DoNavigateToURLImpl`中的`v6`为0,从而可以继续执行后续逻辑。首先,如果`a1`在代码中列的12个名单中(即白名单),则无条件返回1,所以,我们只需要修改`rc`文件中的`InternalName`为白名单中的任意一项即可。 ### 360方式(Hook+白名单) 360安全浏览器Hook了`GetModuleFileNameW`这个API,把自己伪装成IE浏览器,从而实现白名单效果。