1 changed files with 819 additions and 4 deletions
@ -1,9 +1,824 @@
@@ -1,9 +1,824 @@
|
||||
--- |
||||
title: "Flash32以上版本无法打开外链问题说明" |
||||
date: 2020-08-12T10:48:22+08:00 |
||||
draft: true |
||||
draft: false |
||||
toc: true |
||||
images: |
||||
tags: [untagged] |
||||
categories: |
||||
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<ATL::CCRTAllocator>::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<ATL::CCRTAllocator>::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<IServiceProvider,&_GUID const IID_IServiceProvider>::CComQIPtr<IServiceProvider,&_GUID const IID_IServiceProvider>(*(_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<IHTMLLocation>::~CComPtr<IHTMLLocation>(&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<IHTMLLocation>::~CComPtr<IHTMLLocation>(&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<IHTMLLocation>::~CComPtr<IHTMLLocation>(&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<IHTMLLocation>::~CComPtr<IHTMLLocation>(&v93, v63, v64, v65); |
||||
ATL::CComPtr<IHTMLLocation>::~CComPtr<IHTMLLocation>(&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浏览器,从而实现白名单效果。 |
||||
Loading…
Reference in new issue