三星手机强制香港WiFi用户提供中国大陆DNS服务

2020-10-18 22:30:29

本文是作者对三星手机在香港(和澳门)使用2020年9月发布的固件的用户如何被迫在中国大陆使用公共DNS服务的调查的技术报告,这引起了一些用户的不安和隐私问题。

虽然这是针对针对香港市场的Galaxy Note 10+手机的一个变种进行的调查,但据报道,最近一系列三星手机都存在这个问题,包括在香港使用时在其他地方销售的手机。

(更新:2020年10月中旬发布的固件更新修复了本部分中讨论的DNS问题,但第2部分中讨论的qq.com DNS查询问题保持不变。)。

无耻插件(适用于香港用户):作者是Headuck呼叫拦截器(仅适用于香港)的开发者。早些时候,它被谷歌错误地标记为恶意软件,失去了许多用户,但上诉成功了,这款应用程序再次出现在Google Play上。如果你被之前的Google Play恶意软件警告吓到了,请重新考虑这款应用程序。

2020年10月初,香港的一位三星手机用户,当地论坛(HKEPC)用户dingwinslow209报告说,每当他使用WiFi连接时,他的三星手机的DNS设置中就增加了一个额外的DNS服务器条目114.114.114.114(中文链接到论坛帖子),该DNS设置已更新为最新固件。当DNS设置为静态时,即使DNS1和DNS2都设置为有效的DNS服务器(例如,使用DNS1=8.8.8.8和DNS2=8.8.4.4的Google公共DNS服务),指向114.114.114.114的新DNS3条目也会出现在某些实用程序应用程序中。

这立即引起了香港一些三星用户的隐私担忧,因为公共DNS服务器114.114.114.114属于中国大陆南京新风信息技术有限公司旗下的科兴通信(Cogent Communications)。

随后,在另一个本地论坛(Lihkg)上,用户捕捉到对114.114.114.114的DNS请求,并观察到“qq.com”(中国科技巨头腾讯拥有的域名)的查询,即使在设备上没有安装腾讯软件的情况下也是如此。有报道称,只要手机屏幕保持亮起,这些DNS查询每分钟发送一次。

还有更多的报道称,当qq.com的DNS查询被阻止时,手机将报告没有通过WiFi连接的互联网连接。

后来,其他论坛用户和当地媒体使用最近几个月更新的三星手机独立证实了观察到的额外DNS条目。(参见上面HKPEC帖子中的中文链接)。即使用户将三星手机重新设置为出厂设置,该问题仍然存在。这表明问题源于三星固件,而不是某些第三方软件恶意软件。

以下文档直接通过分析固件中的代码对问题进行技术调查和验证。这些信息应足以独立验证问题及其程度。

为了确认该问题,最近的三星Galaxy Note 10+固件(SM-N9750 TGY,香港版)安全补丁级别2020-09-01已从三星固件下载站点下载。据报道,Galaxy Note 10+是受影响的三星机型之一。

在解压下载的固件(zip格式),展开以“AP_N9750ZSU3CTH1”开头的tar文件,使用lz4解压缩文件system.img.ext4.lz4,使用simg2img将其转换为ext4格式,并将其挂载为Linux下的ext4卷之后,用户可以访问系统映像,该系统映像将在Note 10+用户将其手机更新到该补丁级别时安装。(如果Note 10+手机是根手机,也可以访问)。

经过一些研究,罪魁祸首被找到了--一个特定于供应商的服务级别组件,由三星添加到Android框架中,位于/system/framework/wifi-service.jar。这似乎适用于Android系统服务级别,补充了通常的services.jar。

JAR文件的反编译源代码(使用此站点,使用JADX反编译器)已上载到https://github.com/headuck/SM-N9750-TGY.。以下是用户连接到WiFi网络时的相关代码演练,显示如何修改DNS项。

主要罪魁祸首是位于文件WifiConnectivityMonitor or.java中的类com.android.server.wifi.WifiConnectivityMonitor,。反编译后的代码包含以下内容:

公共最终字符串DEFAULT_URL=";http://www.google.com";; 公共最终字符串DEFAULT_URL_CHINA=";http://www.qq.com";; 公共字符串DEFAULT_URL_STRING=";www.google.com";; 公共最终字符串DEFAULT_URL_STRING_CHINA=";www.qq.com";;

这个大类主要是各种WiFi状态的状态机。在行1185-1197定义状态分层结构并设置初始状态。

当检测到新的WiFi连接时,将调用行1976(在初始NotConnectedState的processMessage()下)。

MConnectedState变量属于类ConnectedState,从1988行定义。ConnectedState的enter()方法包含以下代码(从2090行开始),它使用CHN_PUBLIC_DNS_IP(即中国大陆控制的DNS服务器):

IF(WifiConnectivityMonitor or.this.mWifiManager!=空&;&;WifiConnectivityMonitor.this.inChinaNetwork()){ Message msg=new message(); 消息:什么=330; Bundle args=new Bundle(); Args.putString(";public DnsServer";,WifiConnectivityMonitor or.CHN_PUBLIC_DNS_IP); Msg.obj=参数; WifiConnectivityMonitor.this.mWifiManager.callSECApi(msg); }。

从代码上看,当设备连接到中国移动网络时,似乎会自动将中国大陆的DNS服务添加到用户的DNS服务器列表中。似乎没有禁用该行为的选项。

WifiConnectivityMonitor or.inChinaNetwork()在11199行。*顾名思义,只有当设备连接到中国的移动网络时,才会获取ISO码并返回TRUE:

ChinaNetwork()中的公共布尔值{ String str=this.mCountryIso; 如果(str==NULL||str.length()!=2){ UpdateCountryIsoCode(); } 如果(!is ChineseIso(this.mCountryIso)){ 报假; } 如果(!dbg){ 返回真; } Log.d(Tag,";需要跳过强制门户检查。CISO:";+this.mCountryIso); 返回真; }。

更深入地研究,这就是如何在11219行的updateCountryIsoCode()下获得ISO码(MCountryIso)的(跳过回退)。

Public void updateCountryIsoCode(){ 如果(this.mTelehonyManager==NULL){ 尝试{ This.mTelehonyManager=(电话管理器)this.mContext.getSystemService(";phone";); }捕获(异常e){ Log.e(tag,";updateCountryIsoCode()检索Context.TELEPHONY_SERVICE";时出现异常); } } TelehonyManager TelehonyManager=this.mTelehonyManager; IF(TelehonyManager!=NULL){ This.mCountryIso=TelehonyManager.getNetworkCountryIso(); Log.i(标记,";通过电话管理器更新CountryIsoCode():mCountryIso:";+this.mCountryIso); } /*没有跳过移动网络时回退。备用方法是从三星配置文件(cscfeature ure.xml)读取CountryISO设置*/ …… }。

(虽然这里没有显示,但在初始化和检测到电话网络的ISO代码变化时也会调用此代码,因此不需要在每次检查时调用此代码。)。国家代码是从TelehonyManager.getNetworkCountryIso()获得的,它是一个标准的Android API,记录在这里。它返回与移动运营商的MCC(移动国家代码)等效的ISO-3166-1 Alpha-2国家代码。在香港,这是“HK”,在中国大陆,这是“CN”。

正如您现在可能怀疑的那样,问题存在于isChineseIso()的11214行:

这意味着,如果您为了添加114 DNS服务而连接到香港移动网络,您将被视为连接到了中国移动网络。(顺便说一句,“MO”是澳门的ISO-3166-1代码。)。也许三星可能想要解决人们去中国大陆旅行时忘记重置他们的硬编码DNS设置的情况,并友好地“添加”一项在中国防火墙内工作的DNS服务。但他们似乎忘记了,香港和澳门都在防火墙之外,至少到目前为止是这样。

返回到上面的DNS设置代码(2090行)。它对WifiManager.callSECApi()进行活页夹调用,消息代码=330,对我们的朋友114.114.114.114设置为Bundle设置public DnsServer。虽然WifiManager是一个标准的Android类,但是顾名思义,方法callSECApi()是特定于三星的。

对WifiManager的远程调用将在com.android.server.wifi.WifiServiceImpl的服务类实现中结束,并在WifiServiceImpl.java实现WifiService。(该类是三星对同名AOSP服务类的扩展)。不幸的是,WifiServiceImpl.java第4957行的Samsung特定目标方法callSECApi()未能反编译成Java,并且只有smali代码可用。

在行5069处,上面发送的消息代码330的大小写将分支到行5706处的地址标签L_0x052d。

在L_0x052d,它只将调用转发给ClientModeImpl.callSECApi(),表示相关的wifi客户端连接(r12是原始的android.os.Message参数)

L_0x052d: R11.enforceChangePermission() Com.android.server.wifi.ClientModeImpl r0=r11.mClientModeImpl Int r0=r0.callSECApi(R12) R1=R0 转到L_0x06b0。

类com.android.server.wifi.ClientModeImpl位于ClientModeImpl.java。名为callSECApi()的方法位于10278行(同样不能反编译为JAVA)。消息代码330通向标签L_0x0124。

L_0x0124: R1=131286(0x200d6,浮点数:1.83971E-40) Java.lang.Object R2=r14.obj//catch:{all->;0x02ef} Android.os.Message r1=r13.obtainMessage(r1,r4,r4,r2)//catch:{all->;0x02ef} R13.sendMessage(R1)//catch:{all->;0x02ef} 监视器-退出(R13) 返回R4。

上面的代码将代码号为131286的消息发送到ClientModeImpl类下的(单独的)状态机。

此消息在状态机的L2ConnectedState中处理(该状态机涵盖状态层次结构中的获取IP、已连接和漫游的子状态)。

Case ClientModeImpl.CMD_REPLACE_PUBLIC_Dns/*131286*/: IF(ClientModeImpl.this.mLinkProperties!=NULL){ String public DnsIp=((捆绑包)message2.obj).getString(";publicDnsServer";); ArrayList dnsList=新ArrayList<;>;(ClientModeImpl.this.mLinkProperties.getDnsServers()); DnsList.add(NetworkUtils.numericToInetAddress(publicDnsIp)); ClientModeImpl.this.mLinkProperties.setDnsServers(dnsList); ClientModeImpl clientModeImpl13=ClientModeImpl.this; ClientModeImpl13.updateLinkProperties(clientModeImpl13.mLinkProperties); 断掉; } 断掉;

这里,代码将public DnsServer的值(即当设备在中国大陆、香港或澳门移动网络上时为114.114.114.114)添加到当前的DNS服务器列表中。LinkProperties是一个标准的AOSP类(这里有源链接)。GetDnsServers()调用只是返回Wifi客户端网络链接中现有DNS服务器的列表,而setDnsServers()只是设置列表,但也会删除重复项。

/** *将此{@code LinkProperties}中的DNS服务器替换为 *给定的{@link InetAddress}对象的{@link集合}。 * *@param dnsServers要在此对象中设置的DNS服务器的{@link Collection}。 */ Public void setDnsServers(@NonNull Collection dnsServers){ MDnses.clear(); For(InetAddress dnsServer:dnsServers){ AddDnsServer(DnsServer); } }

/** *将给定的{@link InetAddress}添加到DNS服务器列表(如果不存在)。 * *@param dnsServer要添加到DNS服务器列表的{@link InetAddress}。 *@如果DNS服务器已添加,则返回TRUE;如果DNS服务器已存在,则返回FALSE。 *@隐藏 */ 公共布尔addDnsServer(@NonNull InetAddress dnsServer){ IF(dnsServer!=NULL&;&;!mDnses.concludes(DnsServer)){ MDnses.add(DnsServer); 返回真; } 报假; }。

请注意,与某些接口不同,LinkProperties下的DNS服务器数量没有限制。换句话说,如果列表中还不存在服务器114.114.114.114,这将在每次被调用时强制添加服务器114.114.114.114。用户手动删除或更改设置是有效的,因为网络状态改变时的下一次调用将确保服务器被添加回来。

在接下来的部分中,我将研究一些用户关心的另一个问题-qq.com的背景解析。

你的電子郵件位址並不會被公開.。必要欄位標記為*。

若有跟進回覆,請以電郵通知我.。你亦可以不留言而選擇訂閱.