It is a technical write up of the writer’s investigation on how customers of Samsung phones in Hong Kong (and Macau), using firmware released in September 2020, will likely be forced to converse a public DNS service in Mainland China, which triggered unease and privateness concerns among some of its customers.

Whereas this turned into once investigated on a variant of a Galaxy Impress 10+ phone targetting the Hong Kong market, it turned into once reported that the sector exists for a huge collection of most up-to-date Samsung phones, collectively with these sold in completely different areas when outdated in Hong Kong.

(Replace: The firmware update released in Mid-October 2020 has mounted the DNS field discussed on this Section, nonetheless the sector of DNS queries for qq.com discussed in Section 2 remained unchanged.)

Shameless paddle (for Hong Kong customers): The writer is the developer of Headuck Name blocker (invaluable handiest in Hong Kong). Earlier it bought mistakenly flagged as malware by Google and lost many of its customers, nonetheless the enchantment turned into once a hit and the App is on Google Play all over again. Please re-private into consideration the App must to win anxious by the earlier Google Play malware warning.

Background

In early October 2020, a Samsung phone person in Hong Kong, local dialogue board (HKEPC) person dingwinslow209, reported that (link to dialogue board put up in Chinese) an additional DNS server entry, 114.114.114.114 turned into once added to the DNS environment of his Samsung cell phone, which turned into once updated with basically the most up-to-date firmware, whenever he turned into once using a WiFi connection.  This took self-discipline each and every when the DNS environment is static, or dynamic using DHCP (nonetheless no longer when VPN / mobile community turned into once outdated).  Even when each and every DNS1 and DNS2 had been map to legit DNS servers (e.g. Google public DNS service using DNS1 = 8.8.8.8 and DNS2 = 8.8.4.4), a novel DNS3 entry pointing to 114.114.114.114 would seem in some utility app.

This straight away raised privateness concerns among some Samsung customers in Hong Kong, because the general public DNS server 114.114.114.114 is owned by Cogent Communications, underneath Nanjing XinFeng Info Technologies Inc, in Mainland China.

Subsequently, in one other local dialogue board (lihkg), customers captured DNS requests to 114.114.114.114, and seen queries for “qq.com”  (arena owned by Chinese tech big Tencent), even when no diagram from Tencent is build in in the devices.  There had been experiences that these DNS queries had been despatched once per minute, as lengthy because the phone conceal remained on.

There are additional experiences that after DNS queries to qq.com had been blocked, the phone would characterize no web connectivity by strategy of the WiFi connection.

The observation of the additional DNS entry turned into once later independently confirmed by completely different dialogue board customers and the local media, using most up-to-date Samsung phones which agree with been updated in most up-to-date months.  (Consider the hyperlinks in the HKPEC put up above, in Chinese).  The topic endured even when customers reset their Samsung phone to factory settings. This confirmed that the sector originates from Samsung firmware as antagonistic to some third-celebration diagram malware.

The following paperwork the technical investigation and verification of the sector straight from analysing the code from firmware.  The records must be ample for the sector and its extent to be independently verified.

Getting and extracting the firmware

To confirm the sector, a most up-to-date Samsung Galaxy Impress 10+ firmware (SM-N9750 TGY, Hong Kong version), at Security Patch stage 2020-09-01 turned into once downloaded from a number of the Samsung firmware gain web sites. Galaxy Impress 10+ is with out doubt a number of the Samsung items reportedly affected.

After unzipping the downloaded firmware (in zip structure), increasing the tar file origin with “AP_N9750ZSU3CTH1“, decompressing the file diagram.img.ext4.lz4 using lz4, converting it to ext4 structure using simg2img, and mounting it as ext4 quantity underneath Linux, one has salvage entry to to the diagram image which will likely be build in when Impress 10+ customers update their phone to that patch stage. (The same is accessible if a Impress 10+ phone is rooted).

After some be taught, the perpetrator turned into once learned – a seller teach service stage ingredient, added by Samsung to the Android framework, located at /diagram/framework/wifi-service.jar. This appears to be to work at the android diagram service stage, supplementing the present products and providers.jar.

The decompiled supply of the jar file (using this map, with Jadx decompiler) has been uploaded to https://github.com/headuck/SM-N9750-TGY.  The following is a walkthrough of the relevant code when a person connects to a WiFi community, exhibiting how the DNS entries had been modified.

Relevant drift of DNS entry addition

The principle perpetrator is the class com.android.server.wifi.WifiConnectivityMonitor, located in the file WifiConnectivityMonitor.java. The decompiled code contains the next:

line 129: the hardcoded tackle 114.114.114.114

non-public static closing String CHN_PUBLIC_DNS_IP = "114.114.114.114";

line 878: addresses outdated for DNS probe (to be lined in next section).

public closing String DEFAULT_URL = "http://www.google.com";
public closing String DEFAULT_URL_CHINA = "http://www.qq.com";
public String DEFAULT_URL_STRING = "www.google.com";
public closing String DEFAULT_URL_STRING_CHINA = "www.qq.com";

This expansive class is mainly a philosophize machine of the assorted WiFi states. The philosophize hierarchy are defined, and initial philosophize map, at lines 1185-1197.

addState(this.mDefaultState);
addState(this.mNotConnectedState, this.mDefaultState);
addState(this.mConnectedState, this.mDefaultState);
addState(this.mCaptivePortalState, this.mConnectedState);
addState(this.mEvaluatedState, this.mConnectedState);
....
setInitialState(this.mNotConnectedState);

The noxious class for the StateMachine can even be learned underneath AOSP supply (StateMachine.java).

When the diagram is attached to WiFi, it would enter ConnectedState.

line 1976 (underneath processMessage() of the initial NotConnectedState) will likely be invoked when a novel WiFi connection is detected.

wifiConnectivityMonitor.transitionTo(wifiConnectivityMonitor.mConnectedState);

The mConnectedState variable is of sophistication ConnectedState, defined from line 1988. The enter() approach of ConnectedState contains the next code (from line 2090), which makes converse of CHN_PUBLIC_DNS_IP (i.e. the Mainland Chinese managed DNS server):

if (WifiConnectivityMonitor.this.mWifiManager != null && WifiConnectivityMonitor.this.inChinaNetwork()) {
    Message msg = novel Message();
    msg.what = 330;
    Bundle args = novel Bundle();
    args.putString("publicDnsServer", WifiConnectivityMonitor.CHN_PUBLIC_DNS_IP);
    msg.obj = args;
    WifiConnectivityMonitor.this.mWifiManager.callSECApi(msg);
}

From the code it appears to be to add the Mainland Chinese DNS service to the person’s list of DNS server automatically, when the diagram is attached to Chinese mobile community. There appears to be no technique to disable the behaviour.

WifiConnectivityMonitor.inChinaNetwork() is at line 11199.  As steered by its determine, it will private the ISO code and return true handiest if the diagram is attached to a mobile community in China:

public boolean inChinaNetwork() {
    String str = this.mCountryIso;
    if (str == null || str.length() != 2) {
        updateCountryIsoCode();
    }
    if (!isChineseIso(this.mCountryIso)) {
        return untrue;
    }
    if (!DBG) {
        return true;
    }
    Log.d(TAG, "Have to skip captive portal take a look at. CISO: " + this.mCountryIso);
    return true;
}

Digging deeper, right here is how the ISO code (mCountryIso) is obtained, underneath updateCountryIsoCode() at line 11219 (fallback skipped).

public void updateCountryIsoCode() {
    if (this.mTelephonyManager == null) {
        strive {
            this.mTelephonyManager = (TelephonyManager) this.mContext.getSystemService("phone");
        } rob (Exception e) {
            Log.e(TAG, "Exception occured at updateCountryIsoCode(), while retrieving Context.TELEPHONY_SERVICE");
        }
    }
    TelephonyManager telephonyManager = this.mTelephonyManager;
    if (telephonyManager != null) {
        this.mCountryIso = telephonyManager.getNetworkCountryIso();
        Log.i(TAG, "updateCountryIsoCode() by strategy of TelephonyManager : mCountryIso: " + this.mCountryIso);
    }
    /fallback when there is just not at all times a mobile community skipped. The fallback is to learn the CountryISO environment from a Samsung config file (cscfeature.xml) */
    ....
}

(Whereas no longer confirmed right here, this code is also invoked when initializing and when alternate in ISO code of cell telephone community is detected, so it needn’t be called all over each and every take a look at.) The country code is salvage from TelephonyManager.getNetworkCountryIso() which is a customary Android API, documented right here. It returns the ISO-3166-1 alpha-2 country code same of the MCC (Cell Nation Code) of the mobile operator. In Hong Kong, right here is “HK”, and in Mainland China right here is “CN”.

As one would possibly maybe maybe maybe suspect at this level, the mumble lies in isChineseIso(), at line 11214:

non-public boolean isChineseIso(String countryIso) {
    return "cn".equalsIgnoreCase(countryIso) || "hk".equalsIgnoreCase(countryIso) || "mo".equalsIgnoreCase(countryIso);
}

This plot that you simply’re treated as being linked to a Chinese mobile community must you’re linked to a Hong Kong mobile community for the aim of adding the 114 DNS service.  (BTW, “MO” is the ISO-3166-1 code for Macau.) Perchance Samsung would possibly maybe maybe maybe want to tackle conditions when folks saunter to Mainland China while forgetting to reset their hardcoded DNS settings, and appropriate “add” a DNS service which works interior the Expansive Firewall of China. But they gave the impact to neglect that every and every Hong Kong and Macau are out of doors the Expansive Firewall, a minimal of thus some distance.

Wait on to the DNS environment code above (line 2090). It makes a binder name to WifiManager.callSECApi(), with message code = 330, with a Bundle environment publicDnsServer to our friend 114.114.114.114. Whereas WifiManager is a customary Android class the approach callSECApi(), as steered by its determine, is Samsung teach.

The some distance flung name to WifiManager would cease up in the service class implementation at com.android.server.wifi.WifiServiceImpl, imposing WifiService, at WifiServiceImpl.java. (The class is Samsung’s extension to the AOSP service class of the same determine). Unfortunately the Samsung teach target approach callSECApi() at line 4957 of WifiServiceImpl.java failed to be decompiled to Java and handiest the smali code is available.

At line 5069, the case for message code 330 despatched above would department to tackle label L_0x052d, at line 5706

case 330: goto L_0x052d;

At L_0x052d, it appropriate forward the resolution to ClientModeImpl.callSECApi() representing the relevant wifi client connection (r12 being the long-established android.os.Message parameter)

L_0x052d:
    r11.enforceChangePermission()
    com.android.server.wifi.ClientModeImpl r0 = r11.mClientModeImpl
    int r0 = r0.callSECApi(r12)
    r1 = r0
    goto L_0x06b0

The class com.android.server.wifi.ClientModeImpl is at ClientModeImpl.java. The approach called, callSECApi(), is at line 10278 (and all over again can no longer be decompiled to Java). Message code 330 results in the label L_0x0124

L_0x0124:
    r1 = 131286(0x200d6, drift:1.83971E-40)
    java.lang.Object r2 = r14.obj     // Rep:{ all -> 0x02ef }
    android.os.Message r1 = r13.obtainMessage(r1, r4, r4, r2)     // Rep:{ all -> 0x02ef }
    r13.sendMessage(r1)     // Rep:{ all -> 0x02ef }
    show screen-exit(r13)
    return r4

The above code ship the message with code quantity 131286 to the (separate) philosophize machine underneath the class ClientModeImpl.

line 241 exhibits that this message is CMD_REPLACE_PUBLIC_DNS

non-public static closing int CMD_REPLACE_PUBLIC_DNS = 131286;

This message is processed in the L2ConnectedState of the philosophize machine (which covers the baby states of acquiring IP, linked, and roaming in the philosophize hierarchy).

case ClientModeImpl.CMD_REPLACE_PUBLIC_DNS /*131286*/:
    if (ClientModeImpl.this.mLinkProperties != null) {
        String publicDnsIp = ((Bundle) message2.obj).getString("publicDnsServer");
        ArrayList dnsList = novel ArrayList<>(ClientModeImpl.this.mLinkProperties.getDnsServers());
        dnsList.add(NetworkUtils.numericToInetAddress(publicDnsIp));
        ClientModeImpl.this.mLinkProperties.setDnsServers(dnsList);
        ClientModeImpl clientModeImpl13 = ClientModeImpl.this;
        clientModeImpl13.updateLinkProperties(clientModeImpl13.mLinkProperties);
        atomize;
    }
    atomize;

Right here, the code add the rate of publicDnsServer (i.e. 114.114.114.114 when the diagram is on Mainland China, Hong Kong or Macau mobile community) to the present list of DNS servers. LinkProperties is a customary AOSP class (supply link right here). The getDnsServers() name merely returns the list of existing DNS servers in the community link of the Wifi client, while setDnsServers() appropriate map the list, nonetheless also removes the duplicates.

From LinkProperties.java (AOSP supply):

/Replaces the DNS servers on this {@code LinkProperties} with
 the given {@link Sequence} of {@link InetAddress} objects.
 @param dnsServers The {@link Sequence} of DNS servers to map on this object.
 */
public void setDnsServers(@NonNull Sequence dnsServers) {
    mDnses.fine();
    for (InetAddress dnsServer: dnsServers) {
        addDnsServer(dnsServer);
    }
}
/Adds the given {@link InetAddress} to the list of DNS servers, if no longer present.
 @param dnsServer The {@link InetAddress} to add to the list of DNS servers.
 @return true if the DNS server turned into once added, untrue if it turned into once already present.
 @conceal
 */
public boolean addDnsServer(@NonNull InetAddress dnsServer) {
    if (dnsServer != null && !mDnses.contains(dnsServer)) {
        mDnses.add(dnsServer);
        return true;
    }
    return untrue;
}

Impress that unlike some interfaces, there is just not at all times a limit to the gathering of DNS servers underneath LinkProperties. In completely different phrases, this could power the addition of the server 114.114.114.114 on every occasion when called, if it does no longer exist already on the list.  It is frutile for customers to manually private away or alternate the environment, since the next name upon community philosophize alternate will invent obvious that the server is added encourage.

In the next section I am going to envision into the several field which concerns some customers – the background resolving of qq.com.