diff --git a/content/posts/2020/Flash32以上版本无法打开外链问题说明.md b/content/posts/2020/Flash32以上版本无法打开外链问题说明.md index f0e5048..f51f036 100644 --- a/content/posts/2020/Flash32以上版本无法打开外链问题说明.md +++ b/content/posts/2020/Flash32以上版本无法打开外链问题说明.md @@ -1,9 +1,824 @@ --- title: "Flash32以上版本无法打开外链问题说明" date: 2020-08-12T10:48:22+08:00 -draft: true +draft: false toc: true images: -tags: [untagged] -categories: ---- \ No newline at end of file +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浏览器,从而实现白名单效果。 \ No newline at end of file