Edge属于Universal App,这类程序不能简单的通过CreateProcess系列函数打开,有人问我打开Edge的几种方式,这里总结一下。如果要给它做Fuzz的话,可以考虑下面三种打开方式去启动Edge。
本文授权drops.wiki及本站共发
0x01 第一种方式——ShellExecute
第一种方式,利用系统自动调用默认浏览器的功能,即:
设置默认浏览器为Edge。
使用ShellExecute(0, L"OPEN", L"HTTP://YOUR-START-PAGE/", NULL, NULL, SW_SHOW);走系统的默认浏览器逻辑启动Edge。
(通过explorer 参数或者.url快捷方式等来启动Edge也属于同样的方式)
这里的流程如下:
ShellExecuteW(ShellExecuteW就是ShellExecuteExW的wrapper)
↓
ShellExecuteExW(ShellExecuteExW则是ShellExecuteNormal的wrapper)
↓
ShellExecuteNormal(可以当作是正式的启动了。在ShellExecuteNormal中,代码创建一个CShellExecute的类的实例,然后调用其ExecuteNormal方法)
↓
CShellExecute::ExecuteNormal(根据启动参数[要启动的文件后缀为.CMD时,或者调用者含有同步原语时不满足]决定是否要使用新线程来调用,传入OPEN打开URL时,满足该判断)
↓
CShellExecute::_RunThreadMaybeWait(执行线程代码简单,创建事件并在新线程中执行具体的启动代码)
↓
pfnThreadProc(调用启动进程的入口CShellExecute::_DoExecute)
↓
CShellExecute::_DoExecute
↓
CShellExecute::_InvokeCtxMenu(它会把获取到的IContextMenu[000214E4-0000-0000-C000-000000000046]接口传给InvokeInProcExec)
↓
CShellExecute::_InvokeInProcExec(根据操作获取CmdId,传给DefFolderMenu::InvokeCommand)
↓
DefFolderMenu::InvokeCommand(这是一个巨大的函数,检测到连接打开的这种情况时,使用HDXA_LetHandlerProcessCommandEx来处理)
↓
HDXA_LetHandlerProcessCommandEx
↓
SHELL32!CRegistryVerbsContextMenu::InvokeCommand(打开URL的这个动作需要读取注册表中指定的动词[open],这里开始都是根据注册表关联的动词来启动关联程序)
↓
SHELL32!CRegistryVerbsContextMenu::_Execute
↓
windows_storage!CRegDataDrivenCommand::InvokeFromContextMenu
↓
windows_storage!CRegDataDrivenCommand::_Invoke
↓
windows_storage!CRegDataDrivenCommand::_TryInvokeAssociation
↓
windows_storage!CBindAndInvokeStaticVerb::Execute
↓
windows_storage!CBindAndInvokeStaticVerb::_TryExecuteCommandHandler
↓
windows_storage!CBindAndInvokeStaticVerb::_DoCommand
↓
twinui!CAssociationLaunchExecuteCommand::Execute
0x02 第二种方式——microsoft-edge protocol
Win8开始Windows提供的Custom Protocol Activation技术让edge有了这个新启动方式,Windows允许桌面程序和runtime app注册成某个URL scheme name的默认打开程序。通过Manifest注册关联程序的方式可以参考:https://msdn.microsoft.com/en-us/library/windows/apps/hh452686.aspx
UWP Edge可以在:
打开%SYSTEMROOT%\SystemApps\Microsoft.MicrosoftEdge_8wekyb3d8bbwe,这是Edge的App目录,8wxxx就是它的APPID。
打开AppxManifest.xml, 可以看到与之关联的协议之一:
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="microsoft-edge">
<uap:Logo>Assets\MicrosoftEdgeFile.png</uap:Logo>
</uap:Protocol>
</uap:Extension>
HKEY_CURRENT_USER\SOFTWARE\Classes\Extensions\ContractId\Windows.Protocol\PackageId\Microsoft.MicrosoftEdge_25.10586.0.0_neutral__8wekyb3d8bbwe\ActivatableClassId\ 下即为支持的协议,MicrosoftEdge.AppXeb42j1vh6rk395pm0vmcx57dxqjhej5d.mca是microsoft-edge的项目。
使用microsof-edge protocol。这意味着在C++中只需要CreateProcess系列指定参数为explorer microsoft-edge:http://www.baidu.com/,或者ShellExecute中open microsoft-edge:http://xxx/即可启动。这种方式启动的Edge,不需要用户设置默认浏览器。
所以,许多更愿意把Edge当备胎的用户应该会比较喜欢使用这种方式。
0x03 第三种方式(正经的)——IApplicationActivationManager 接口
直接上代码吧。
// testCallApplicationActivationManager.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <shobjidl.h>
#include <windows.h>
#include <atlcomcli.h>
int main()
{
CComPtr<IApplicationActivationManager> piaam;
CComPtr<IUnknown> punk;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
LPCWSTR appId = L"Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge";
IApplicationActivationManager* paam = NULL;
HRESULT hr = E_FAIL;
LPCWSTR url = L"www.wooyun.org";
do
{
hr = CoCreateInstance(CLSID_ApplicationActivationManager, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&paam));
if (FAILED(hr))
break;
DWORD pid = 0;
hr = paam->ActivateApplication(appId, url, AO_NONE, &pid);
if (FAILED(hr))
break;
} while (0);
return 0;
}
参考资料
【1】UWP是什么:https://msdn.microsoft.com/en-us/windows/uwp/get-started/whats-a-uwp
【2】https://www.microsoft.com/msj/0199/com/com0199.aspx