Right here’s a technical write up of the author’s investigation on how customers of fresh Samsung phones in Hong Kong (and Macau) would be pressured to spend a public DNS provider in Mainland China, which precipitated unease and privateness issues among some of its customers.

While this used to be investigated on a variant of a Galaxy Point to 10+ cell phone targetting the Hong Kong market, it used to be reported that the scenario exists for a huge vary of fresh Samsung phones, including these supplied in different locations when veteran in Hong Kong.

Shameless walk (for Hong Kong customers): The writer is the developer of Headuck Name blocker (edifying easiest in Hong Kong). Earlier it got mistakenly flagged as malware by Google and misplaced a great deal of its customers, nonetheless the charm used to be triumphant and the App is on Google Play all all over again. Please re-defend into memoir the App if you happen to got alarmed by the sooner Google Play malware warning.

Background

In early October 2020, a Samsung cell phone user in Hong Kong, native dialogue board (HKEPC) user dingwinslow209, reported that (hyperlink to dialogue board put up in Chinese) an extra DNS server entry, 114.114.114.114 used to be added to the DNS surroundings of his Samsung cell cell phone, which used to be up up to now with the latest firmware, at any time when he used to be the utilization of a WiFi connection.  This took place both when the DNS surroundings is static, or dynamic the utilization of DHCP (nonetheless now not when VPN / cell community used to be veteran).  Even when both DNS1 and DNS2 contain been space to official DNS servers (e.g. Google public DNS provider the utilization of DNS1 = 8.8.8.8 and DNS2 = 8.8.4.4), a brand contemporary DNS3 entry pointing to 114.114.114.114 would seem in some utility app.

This immediately raised privateness issues among some Samsung customers in Hong Kong, as the final public DNS server 114.114.114.114 is owned by Cogent Communications, below Nanjing XinFeng Knowledge Applied sciences Inc, in Mainland China.

Subsequently, in every other native dialogue board (lihkg), customers captured DNS requests to 114.114.114.114, and noticed queries for “qq.com”  (area owned by Chinese tech big Tencent), even when no system from Tencent is installed within the devices.  There contain been reports that these DNS queries contain been despatched once per minute, goodbye as the cell phone screen remained on.

There are additional reports that once DNS queries to qq.com contain been blocked, the cell phone would file no files superhighway connectivity by means of the WiFi connection.

The observation of the extra DNS entry used to be later independently confirmed by different dialogue board customers and the native media, the utilization of fresh Samsung phones which contain been up up to now in fresh months.  (Look the links within the HKPEC put up above, in Chinese).  The scenario continued even when customers reset their Samsung cell phone to manufacturing facility settings. This confirmed that the scenario originates from Samsung firmware in decision to some third-celebration system malware.

The next documents the technical investigation and verification of the scenario right far off from analysing the code from firmware.  The guidelines must be ample for the scenario and its extent to be independently verified.

Getting and extracting the firmware

To ascertain the scenario, a fresh Samsung Galaxy Point to 10+ firmware (SM-N9750 TGY, Hong Kong version), at Safety Patch level 2020-09-01 used to be downloaded from one of many Samsung firmware download sites. Galaxy Point to 10+ is without doubt one of many Samsung items reportedly affected.

After unzipping the downloaded firmware (in zip layout), expanding the tar file foundation with “AP_N9750ZSU3CTH1“, decompressing the file system.img.ext4.lz4 the utilization of lz4, changing it to ext4 layout the utilization of simg2img, and mounting it as ext4 volume below Linux, one has earn admission to to the system image which would be installed when Point to 10+ customers substitute their cell phone to that patch level. (The the same is on the market if a Point to 10+ cell phone is rooted).

After a minute bit analysis, the offender used to be came throughout – a dealer instruct provider level component, added by Samsung to the Android framework, positioned at /system/framework/wifi-provider.jar. This appears to be like to work on the android system provider level, supplementing the customary companies.jar.

The decompiled supply of the jar file (the utilization of this living, with Jadx decompiler) has been uploaded to https://github.com/headuck/SM-N9750-TGY.  The next is a walkthrough of the associated code when a user connects to a WiFi community, exhibiting how the DNS entries contain been modified.

Relevant sprint of DNS entry addition

The principle offender is the class com.android.server.wifi.WifiConnectivityMonitor, positioned within the file WifiConnectivityMonitor.java. The decompiled code comprises the next:

line 129: the hardcoded deal with 114.114.114.114

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

line 878: addresses veteran for DNS probe (to be lined in next portion).

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

This natty class is especially a deliver machine of the a tall series of WiFi states. The deliver hierarchy are defined, and initial deliver space, at traces 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 infamous class for the StateMachine is also came throughout below AOSP supply (StateMachine.java).

When the tool is hooked as much as WiFi, it might most likely enter ConnectedState.

line 1976 (below processMessage() of the initial NotConnectedState) would be invoked when a brand contemporary WiFi connection is detected.

wifiConnectivityMonitor.transitionTo(wifiConnectivityMonitor.mConnectedState);

The mConnectedState variable is of sophistication ConnectedState, defined from line 1988. The enter() manner of ConnectedState comprises the next code (from line 2090), which makes spend of CHN_PUBLIC_DNS_IP (i.e. the Mainland Chinese controlled DNS server):

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

From the code it appears to be like so as to add the Mainland Chinese DNS provider to the user’s listing of DNS server robotically, when the tool is hooked as much as Chinese cell community. There appears to be like no strategy to disable the behaviour.

WifiConnectivityMonitor.inChinaNetwork() is at line 11199.  As suggested by its establish, it will aloof secure the ISO code and return well-behaved easiest if the tool is hooked as much as a cell community in China:

public boolean inChinaNetwork() {
    String str = this.mCountryIso;
    if (str == null || str.measurement() != 2) {
        updateCountryIsoCode();
    }
    if (!isChineseIso(this.mCountryIso)) {
        return faux;
    }
    if (!DBG) {
        return well-behaved;
    }
    Log.d(TAG, "Must skip captive portal evaluate. CISO: " + this.mCountryIso);
    return well-behaved;
}

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

public void updateCountryIsoCode() {
    if (this.mTelephonyManager == null) {
        are trying {
            this.mTelephonyManager = (TelephonyManager) this.mContext.getSystemService("cell phone");
        } defend (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 means of TelephonyManager : mCountryIso: " + this.mCountryIso);
    }
    /fallback when there's no such thing as a cell community skipped. The fallback is to study the CountryISO surroundings from a Samsung config file (cscfeature.xml) */
    ....
}

(While now not confirmed here, this code is additionally invoked when initializing and when swap in ISO code of cell phone community is detected, so it need now not be known as for the length of every evaluate.) The country code is earn from TelephonyManager.getNetworkCountryIso() which is an customary Android API, documented here. It returns the ISO-3166-1 alpha-2 country code identical of the MCC (Cell Country Code) of the cell operator. In Hong Kong, here’s “HK”, and in Mainland China here’s “CN”.

As one might presumably possibly also suspect at this level, the scenario lies in isChineseIso(), at line 11214:

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

This suggests that it’s likely you’ll presumably be handled as being connected to a Chinese cell community if you happen to might presumably be connected to a Hong Kong cell community for the honest of adding the 114 DNS provider.  (BTW, “MO” is the ISO-3166-1 code for Macau.) Presumably Samsung might presumably possibly are also searching for to address circumstances when folks bolt to Mainland China while forgetting to reset their hardcoded DNS settings, and effective “add” a DNS provider which works within the Big Firewall of China. But they looked to fail to recollect that both Hong Kong and Macau are outdoor the Big Firewall, now not lower than to this level.

Help to the DNS surroundings code above (line 2090). It makes a binder call to WifiManager.callSECApi(), with message code = 330, with a Bundle surroundings publicDnsServer to our buddy 114.114.114.114. While WifiManager is an customary Android class the manner callSECApi(), as suggested by its establish, is Samsung instruct.

The far off call to WifiManager would pause up within the provider class implementation at com.android.server.wifi.WifiServiceImpl, imposing WifiService, at WifiServiceImpl.java. (The class is Samsung’s extension to the AOSP provider class of the same establish). Sadly the Samsung instruct target manner callSECApi() at line 4957 of WifiServiceImpl.java failed to be decompiled to Java and easiest the smali code is obtainable.

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

case 330: goto L_0x052d;

At L_0x052d, it precise forward the call to ClientModeImpl.callSECApi() representing the associated wifi consumer connection (r12 being the new 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 fashion known as, callSECApi(), is at line 10278 (and all all over again cannot be decompiled to Java). Message code 330 ends within the label L_0x0124

L_0x0124:
    r1 = 131286(0x200d6, dawdle with the sprint:1.83971E-40)
    java.lang.Object r2 = r14.obj     // Receive:{ all -> 0x02ef }
    android.os.Message r1 = r13.obtainMessage(r1, r4, r4, r2)     // Receive:{ all -> 0x02ef }
    r13.sendMessage(r1)     // Receive:{ all -> 0x02ef }
    video display-exit(r13)
    return r4

The above code ship the message with code number 131286 to the (separate) deliver machine below the class ClientModeImpl.

line 241 presentations that this message is CMD_REPLACE_PUBLIC_DNS

non-public static final int CMD_REPLACE_PUBLIC_DNS = 131286;

This message is processed within the L2ConnectedState of the deliver machine (which covers the youngster states of acquiring IP, connected, and roaming within the deliver hierarchy).

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

Right here, the code add the worth of publicDnsServer (i.e. 114.114.114.114 when the tool is on Mainland China, Hong Kong or Macau cell community) to the fresh listing of DNS servers. LinkProperties is an customary AOSP class (supply hyperlink here). The getDnsServers() call merely returns the listing of present DNS servers within the community hyperlink of the Wifi consumer, while setDnsServers() precise space the listing, nonetheless additionally will get rid of the duplicates.

From LinkProperties.java (AOSP supply):

/Replaces the DNS servers on this {@code LinkProperties} with
 the given {@hyperlink Assortment} of {@hyperlink InetAddress} objects.
 @param dnsServers The {@hyperlink Assortment} of DNS servers to space on this object.
 */
public void setDnsServers(@NonNull Assortment dnsServers) {
    mDnses.definite();
    for (InetAddress dnsServer: dnsServers) {
        addDnsServer(dnsServer);
    }
}
/Provides the given {@hyperlink InetAddress} to the listing of DNS servers, if now not fresh.
 @param dnsServer The {@hyperlink InetAddress} so as to add to the listing of DNS servers.
 @return well-behaved if the DNS server used to be added, faux if it used to be already fresh.
 @cloak
 */
public boolean addDnsServer(@NonNull InetAddress dnsServer) {
    if (dnsServer != null && !mDnses.comprises(dnsServer)) {
        mDnses.add(dnsServer);
        return well-behaved;
    }
    return faux;
}

Point to that not like some interfaces, there’s no such thing as a restrict to the series of DNS servers below LinkProperties. In different phrases, this might possibly force the addition of the server 114.114.114.114 at any time when when known as, if it does now not already exist on the listing.  It’s miles frutile for customers to manually intention close or swap the surroundings, since the next call upon community deliver swap can be definite that that the server is added help.

Within the next portion I will judge about into different scenario which issues some customers – the background resolving of qq.com.