*本文原创作者:浪子_三少,属Freebuf原创奖励计划,未经许可禁止转载

在win7时我们只需修改注册表就能设置默认浏览器,但是win8、win10下不能直接修改的因为同样的注册表项,win8、win10多了一个校验hash值。本文就以当下最流行的操作系统win10为例分析下,我们在设置默认浏览器一般会 操作:设置—默认应用—web浏览器,或者在使用chrome设置默认浏览器时都会弹出如下的对话框:

而国内的一些浏览器会绕过这个对话框设置默认浏览器,这个设置对话框就是systemsetting.exe进程来进行的。

下面我们就分析下systemsetting.exe是如何设置默认浏览器的。

一:首先我们要了解windows的默认浏览器设置在注册表里:

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice

项目:Progid 是浏览器的指向的chrome, hash是设置的hash校验值,只有校验值对了才会弹出指定的浏览器,如果随意修改这个注册表就会失效的,所以最关键是这个hash值。接下来我们开始分析过程,使用windbg我们挂接到systemsetting.exe

我们在注册表函数下断点: bp RegSetValueExW后,操作设置默认浏览器,这时windbg会自动停在RegSetValueExW的函数入口点,说明systemsetting.exe 达到了设置注册表的地方了,然后我们查看堆栈,输入命令kb:

发现函数调用过程由systemsetting.exe进入了shell32.dll的空间,看到几个关键函数名:

000002b8`4dc10000 :KERNELBASE!RegSetValueExW

00030018`000307e1 : SHELL32!_RegSetKeyValue+0×60

00007ff9`28b3c398 : SHELL32!SHRegSetString+0×39

000002b8`536394ac : SHELL32!SetProgIdAndHash+0x1fb

00000000`00000002 : SHELL32!_SetUserChoiceAndHash+0×63

000002b8`536394ac : SHELL32!UserAssocSet+0xf6

00007ff9`28842e00 : SHELL32!CAssocHandler::MakeDefaultPriv+0x16d

看到这个函数SetProgIdAndHash 我们大概就能知道这个的函数的作用了就是计算并且设置那个注册表了。

使用IDA 打开 shell32.dll,我们可以具体分析了:

在继续往下分析:

分别经过调用了IsBrowserExtension、SHGetValueW,前面都是一些条件判断与一些信息的获取最后经过了并且进入UerAssocSet函数

在继续进入分析:

_SetUserChoiceAndHash(ushort const *,ushort const *,bool)

然后继续进入

SetProgIdAndHash(HKEY__ *,ushort const *,ushort const *,ushort const *,ushort const *,bool)

下面我们就具体分析下这个函数,最开始经过第一个函数:call    ?_GetAssociationPath@@YAJPEBG_N1PEAGI@Z

第一个参数r9,   lea ,r9, [rbp+1E0h+SubKey] 这是从外部传进来的,这个具体干嘛的呢?

第二个参数是r8b

第三个参数dl,都是字节传入的应该属于bool类型

具体这些将干什么我们可以分析函数获取:

该函数就是根据不同传入类型拼接不同的路径,到这里我们显然知道了这个传进来的第一个参数就是注册表里的”ProgId”,返回原函数继续分析然后返回。

打开那个注册表项目后,获取当前时间GetSystemTime,接着根据传进来的浏览器类型字符串计算一个HashAssociation字符hash值

最后写入注册表UserChoice===hash,UserChoice == progid项目里,整个过程结束。这以上是大体设置过程的分析,下面我们就开始利用这些设置过程,看看是否能够直接使用接口是设置默认浏览器。

那我们从最开始的接口是CAssocHandler::MakeDefaultPriv(unsigned char );返回开始重新具体的分析,在此函数调用前下断点:

参数1是class指针rcx,参数2是 字节类型当前值为1。

进入MakeDefaultPrive函数

IsBrowserExtension ()函数判断当前是否是设置浏览器

查看[rcx +38h]

继续查看这个红框的地址内存

是L”https”,unicode字符串。

接下来在调用UserAssocSet函数时,传入了三个参数

第一个参数就是[rdi + 38h] 即:L”https”

第二个参数是:1

第三个参数是:[rdi+50h]  ,查看此内存

即L”ChromeHtml”的unicode编码。

那我们就可以假设了,我们是否能直接调用这个函数去调用设置呢,即UserAssocSet(L”http”,1,”ChromeHtml”);理论上是可以,但实际上这个函数不导出只在微软符号表里有,不太好调用,也就是说有点麻烦,写出来的代码会不是很简单,有没有更简单的方法呢,我们继续分析,我们可以看看是否也有其他导出的接口或者类调用了该函数。

鼠标点在函数UserAssocSet,按键盘”X”:

除了当前的CAssocHandler类还有一个比较可疑的函数_SetAssociation,仔细分析他的代码与刚才的MakeDefaultPrive函数类似:

我们再继续看谁调用了SetAssociation函数:

这里是不是看到很眼熟的函数:

CApplicationAssociationRegistration::_SetAppAsDefault(),google chrome浏览器就是调用的这个com类函数设置默认浏览器的,还有一个函数

SetProgIdAsDefault@?QIApplicationAssociationRegistrationInternal@@CApplicationAssociationRegistration,一个是CApplicationAssociationRegistration类,一个QIApplicationAssociationRegistrationInternal类,两个函数只有一个地方区别

我们看下IApplicationAssociationRegistrationInternal的结构定义怎样的:

发现CApplicationAssociationRegistration继承于IApplicationAssociationRegistrationInternal这个类,也就是说IApplicationAssociationRegistrationInternal,也是一个com接口,从结构看他也是继承于IUnknow:

我们可以获取其接口Id定义:

这就是intenal的id:_GUID_1c5c9d10_1225_4c97_8c51_98e1b6f0d4e0

从上我们大致能够知道其定义了:

MIDL_INTERFACE("1c5c9d10-1225-4c97-8c51-98e1b6f0d4e0")

IApplicationAssociationRegistrationInternalWin10: public IUnknown{

public:

virtual HRESULT STDMETHODCALLTYPE ClearUserAssociations(void) = 0;

virtual HRESULT STDMETHODCALLTYPE SetProgIdAsDefault(

/* [string][in] */ __RPC__in_string LPCWSTR pszAppRegistryName,

/* [string][in] */ __RPC__in_string LPCWSTR pszSet,

/* [in] */ ASSOCIATIONTYPE atSetType) = 0;

virtual HRESULT STDMETHODCALLTYPE SetAppAsDefault(

/* [string][in] */ __RPC__in_string LPCWSTR pszAppRegistryName,

/* [string][in] */ __RPC__in_string LPCWSTR pszSet,

/* [in] */ ASSOCIATIONTYPE atSetType) = 0;

// Only use this method. We can not gurantee other method is valid.

virtual HRESULT STDMETHODCALLTYPE SetAppAsDefaultAll(

/* [string][in] */ __RPC__in_string LPCWSTR pszAppRegistryName) = 0;

virtual HRESULT STDMETHODCALLTYPE QueryAppIsDefault(

/* [string][in] */ __RPC__in_string LPCWSTR pszQuery,

/* [in] */ ASSOCIATIONTYPE atQueryType,

/* [in] */ ASSOCIATIONLEVEL alQueryLevel,

/* [string][in] */ __RPC__in_string LPCWSTR pszAppRegistryName,

/* [out] */ __RPC__out BOOL *pfDefault) = 0;

virtual HRESULT STDMETHODCALLTYPE QueryAppIsDefaultAll(

/* [in] */ ASSOCIATIONLEVEL alQueryLevel,

/* [string][in] */ __RPC__in_string LPCWSTR pszAppRegistryName,

/* [out] */ __RPC__out BOOL *pfDefault) = 0;

virtual HRESULT STDMETHODCALLTYPE QueryCurrentDefault(

/* [string][in] */ __RPC__in_string LPCWSTR pszQuery,

/* [in] */ ASSOCIATIONTYPE atQueryType,

/* [in] */ ASSOCIATIONLEVEL alQueryLevel,

/* [string][out] */ __RPC__deref_out_opt_string LPWSTR *ppszAssociation) = 0;

virtual HRESULT STDMETHODCALLTYPE  GetDefaultBrowserInfo(

ASSOCIATIONTYPE atQueryType,

LPWSTR * ppszAssociation) = 0;

virtual HRESULT STDMETHODCALLTYPE  RestoreDefaultBrowserContractRegistration(void) = 0;

virtual HRESULT STDMETHODCALLTYPE  IsBrowserAssociation(LPCWSTR, int *) = 0;

virtual HRESULT STDMETHODCALLTYPE  ExportUserAssociations(LPCWSTR) = 0;

virtual HRESULT STDMETHODCALLTYPE  ApplyUserAssociations(LPCWSTR) = 0;

virtual HRESULT STDMETHODCALLTYPE  UpdateProtocolCapabilityCache(LPCWSTR, int) = 0;

};

我们要设置默认浏览器只需调用SetAppAsDefault这个函数,第一个是参数是pszAppRegistryName,第二个参数”https” 或者 “https”,第三个参数SetType,这个在微软sdk中有定义AT_URLPROTOCOL = 1,关键是第一个参数如何填写,在之前我们区分函数不同时函数内部函数:

_GetManifestedAppAssociation(a3, a4, AL_EFFECTIVE, a2, (unsigned __int16 **)&pv);

这个函数的作用就是判断第一个参数,我们进去看下:

v7 = _GetAppPathKey(a4, a3, &hKey); 传进去第一个参数的值,然后返回hKey,我们大概能想到这个一定是打开了什么注册表,再次进去

打开的是HKEY_CURRENT_USER或者HKEY_LOCAL_MACHINE

嗯?是不是发现了什么?对,L”SOFTWARE\\RegisteredApplications”这个注册表路径,我们去看看注册表信息

L“Google Chrome”这就是他要打开的路径,也就是上述函数的第一个参数。

下面我们可以具体写代码了,并且验证下该想法:

HRESULT SetAppAsDefault(const std::wstring& app_name){

IApplicationAssociationRegistration* pAAR;

HRESULT hr = CoCreateInstance(

CLSID_ApplicationAssociationRegistration,

NULL,

CLSCTX_INPROC,

__uuidof (IApplicationAssociationRegistration),

(void**)&pAAR);

if (SUCCEEDED(hr)) {

IApplicationAssociationRegistrationInternal *Paari = NULL;

HRESULT hr = pAAR->QueryInterface(

__uuidof(IApplicationAssociationRegistrationInternal),

(void**)&pAARI);

if (SUCCEEDED(hr)) {

hr = pAARI->SetAppAsDefault(

L"Goole Chrome",

L"http",

AT_URLPROTOCOL);

hr = pAARI->SetAppAsDefault(

L"Goole Chrome",

L"https",

AT_URLPROTOCOL);

pAARI->Release();

}

}

return hr;

}

我们可以看下运行结果:

运行中也不会弹出systemsetting.exe,直接就设置了,当然如果你再继续更加深入地话就去分析hash算法,这个不是今天的讨论的范围,留着读者们去分析,win8的分析过程与此一样,至此本文结束。

如何绕过Win8、Win10的systemsetting与注册表校验设置默认浏览器的更多相关文章

  1. How to:Installshield判断操作系统是否为64位,并且为操作注册表进行设置

    原文:How to:Installshield判断操作系统是否为64位,并且为操作注册表进行设置 IS脚本操作注册表在64位平台下必须有特殊的设置 if (SYSINFO.bIsWow64) then ...

  2. 将npm的注册表源设置为国内的镜像

    1.国内用户,建议将npm的注册表源设置为国内的镜像,可以大幅提升安装速度 2.国内优秀npm镜像推荐及使用:http://riny.net/2014/cnpm/ 淘宝npm镜像 ·搜索地址:http ...

  3. win7注册表常用设置

    win7注册表常用设置 一.总结 一句话总结:regedit可以修改很多东西,电脑时间,背景,u盘读写,鼠标右键情况. 二.win7注册表常用设置 一. 秀出自我风格的屏幕保护画面 1.气泡屏幕保护 ...

  4. win10家庭版的defender注册表关闭和开启

    关闭方法: 打开“命令提示符(管理员)”,然后输入: reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defe ...

  5. 通过cmd修改注册表并设置cmd窗口的大小

    设置cmd的窗口 mode: modem设置系统设备,主要是lpt1, com1/2, con: 启动时设置窗口大小: cmd /k "mode con: cols=120 lines=40 ...

  6. SqlDevlepor注册表监听器设置

      1.打开plsqldev.   2. 键入环境变量 NLS_LANG SIMPLIFIED CHINESE_CHINA.ZHS16GBK   3.下载sqldevclient. http://pa ...

  7. qt 操作注册表,设置ie代理

    void SetIEProxy(QString proxy) { QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Wi ...

  8. delphi 注册表操作(读取、添加、删除、修改)完全手册

    DELPHI VS PASCAL(87)  32位Delphi程序中可利用TRegistry对象来存取注册表文件中的信息. 一.创建和释放TRegistry对象 1.创建TRegistry对象.为了操 ...

  9. Delphi的注册表操作

    转帖:Delphi的注册表操作 2009-12-21 11:12:52 分类: Delphi的注册表操作 32位Delphi程序中可利用TRegistry对象来存取注册表文件中的信息.     一.创 ...

随机推荐

  1. DNS服务-主从架构搭建

    为了网站的可靠性,通常都会有多个DNS服务器,万一DNS服务器宕机了,可以实现DNS服务器容错 通常都会有一个主DNS服务器,后面配若干个辅助DNS服务器,这个主DNS服务器的数据库会同步给其他的DN ...

  2. python爬虫入门六:Selenium库

    在我们爬取网页过程中,经常发现我们想要获得的数据并不能简单的通过解析HTML代码获取,这些数据是通过AJAX异步加载方式或经过JS渲染后才呈现在页面上显示出来. selenuim是一种自动化测试工具, ...

  3. PAT Basic 1055

    1055 集体照 拍集体照时队形很重要,这里对给定的 N 个人 K 排的队形设计排队规则如下: 每排人数为 N/K(向下取整),多出来的人全部站在最后一排: 后排所有人的个子都不比前排任何人矮: 每排 ...

  4. DocView mode 3 -- 配置

    ;在当前页中滚动doc-view-continuous nil ;指定默认的字体大小doc-view-resolution ;gs生成的缓存的目录doc-view-cache-directory

  5. 在loadrunner中用头文件的形式对字符串进行MD5加密操作

    1.首先要有md5.h的头文件 2.然后在global.h中加入#include "md5.h" 3.在action中调用md5.h中的Change_to_Md5(const ch ...

  6. google F12

    谷歌浏览器(Google Chrome)开发调试详细介绍 博客分类: 前端 浏览器chromegoogle调试开发  很多Web前台开发者都喜欢这种浏览器自带的开发者工具,这对前台设计.代码调试很大帮 ...

  7. perl 处理文件路径的一些模块

    perl有句格言:There is more than one way to do it.意思就是任何问题用perl都有好几种解决方法.以前处理文件路径的时候都是自己写正则表达式,而用perl的模块来 ...

  8. oracle 安装 启动listener 建库相关

    安装 参考 http://www.cnblogs.com/gaojun/archive/2012/11/22/2783257.html 几个问题: 1. 用户删除问题 p001:~ # userdel ...

  9. BNUOJ 6727 Bone Collector

    Bone Collector Time Limit: 1000ms Memory Limit: 32768KB   This problem will be judged on HDU. Origin ...

  10. 一堆Offer怎么选?这样做就不纠结了

    有个朋友,工作了10年左右,春节后换工作,拿了三个Offer(西安): 通信行业的一家研究所,软件开发工程师,月薪7K,承诺有月奖金.年终奖金 一家做大数据的公司,软件开发工程师,月薪15K,13薪 ...