Skip to main content

LG7304 "The One" Android Smart TV - tracking down the software update server

TL;DR: LG7304 Android Smart TV gets its software update server from somewhere in the Amazon cloud. The server name is not disclosed via regular DNS and most likely gets learned via some previous HTTPs connection.

I have a LG7304 Android Smart TV that I want to prevent from getting updates (in the hopes it will become rootable in the future). I've been getting an annoying update message for weeks now (even though automatic updates are disabled in the menu), so I tried to suppress it via DNS.

I set up port mirroring for the TV's ethernet port and captured boot traffic for analysis.

It seems the TV communicates with several hosts located in Amazon AWS cloud, but without making DNS requests that return those IPs. So, it must either have them hardcoded in its firmware or must be getting them through an encrypted channel. You can get a list of IP addresses that your TV communicates with by using Wireshark -> Statistics -> Conversations -> IPv4.
You can use whois (whois -h whois.radb.net 3.120.100.236) to find out who owns the IP that your TV talks to.
Here's the preliminary list:

"Address A" "Address B" 
"3.120.100.236" "192.168.1.61" - amazon
"3.124.238.28" "192.168.1.61"  - amazon
"8.8.8.8" "192.168.1.61"       - google
"34.252.118.97" "192.168.1.61" - amazon
"45.57.91.1" "192.168.1.61"    - netflix
"52.17.111.59" "192.168.1.61"  - amazon
"52.49.160.50" "192.168.1.61"  - amazon
"52.209.122.118" "192.168.1.61"- amazon
"172.217.16.110" "192.168.1.61"- google
"172.217.18.68" "192.168.1.61" - google
"172.217.20.3" "192.168.1.61"  - google
"172.217.20.14" "192.168.1.61" - google

Now, to find out if the IPs were returned via DNS, you can search the capture (manually, for each IP) with the filter "dns.a == 3.120.100.236". If you don't get anything, that IP was not obtained via DNS.

How do we block the amazon prefixes? Well - since they are not queried over DNS, we can try to blackhole them on the router by routing the IPs to 127.0.0.1 (route add -host 3.120.100.236 gw 127.0.0.1). Better alternatives include dropping traffic only from the TV's IP to those destinations using iptables rules.

I did this and validated that the traffic was not reaching the destination. I next rebooted the TV (twice) capturing boot traffic again.

So - on the first reboot I still got the Upgrade window. The capture shows that the TV tried to connect to 3.120.100.236, but since it couldn't, it switched to 3.121.138.154 instead. I blackholed that one, and rebooted again, and it connected to 3.124.127.185.

So - blocking individual IP addresses will not scale. Not against Amazon. How about we block the whole Amazon address space from my TV?
In order to try this we need to get all Amazon's prefixes (their ASN is 16509) - we can ask RADB for them with this script I wrote a decade ago (https://github.com/mad-ady/whois-query/blob/master/ripe-AS-prefixes.pl):


$ ./ripe-AS-prefixes.pl AS16509 | wc -l 
14120 
$ ./ripe-AS-prefixes.pl AS16509 > ~/amazon.txt

Quite a few, no? Thankfully they can be aggregated further with this beauty: https://github.com/mad-ady/aggregate-cidr/blob/master/aggregateCIDR.pl

$ cat ~/amazon.txt | ./aggregateCIDR.pl | wc -l 
662
$ cat ~/amazon.txt | ./aggregateCIDR.pl> ~/amazon-aggregated.txt


Much better, isn't it?
Now, let's turn those prefixes into iptables rules, so that only the TV traffic will be dropped (make sure your TV gets a static IP via DHCP).

We're going to create a new iptables chain that matches amazon address space:
$ sed 's/^/iptables -A AMAZON -d /' ~/amazon-aggregated.txt > ~/amazon-part1.txt
$ sed 's/$/ -j DROP/' ~/amazon-part1.txt > ~/amazon-iptables.txt
$ sed -i '1,2d' ~/amazon-iptables.txt 
$ head ~/amazon-iptables.txt 
iptables -A AMAZON -d 3.0.0.0/15 -j DROP 
iptables -A AMAZON -d 3.5.0.0/16 -j DROP 
iptables -A AMAZON -d 3.6.0.0/15 -j DROP 
iptables -A AMAZON -d 3.8.0.0/13 -j DROP 
iptables -A AMAZON -d 3.16.0.0/13 -j DROP 
iptables -A AMAZON -d 3.24.0.0/14 -j DROP 
iptables -A AMAZON -d 3.80.0.0/12 -j DROP 
iptables -A AMAZON -d 3.104.0.0/14 -j DROP 
iptables -A AMAZON -d 3.112.0.0/14 -j DROP 
iptables -A AMAZON -d 3.120.0.0/13 -j DROP

 Next, create a new chain and execute the iptables commands on your router (you can execute the text file as a script)

#iptables -N AMAZON
#iptables -A AMAZON -d 3.0.0.0/15 -j DROP 
#iptables -A AMAZON -d 3.5.0.0/16 -j DROP 
...

What's left is to add a FORWARD rule to match traffic from your TV and chan it to the AMAZON rule (I added it on position 3):
# iptables -I FORWARD 3 -s 192.168.1.61 -j AMAZON 


Now you're done. Time to reboot and enjoy!

... and I still got the upgrade message, though it did drop the traffic.

Looking at the capture I can see that it did try to connect to various amazon hosts and failed. Curiously, it knew the hosts to connect to - so they may be cached from previous attempts. This can only mean that the "Upgrade now" message is from local information and possibly the update has been already downloaded on the TV.

Oh, well. I may be able to get rid of it if I reset the TV to factory defaults, but I don't want to go through the trouble of setting it up again.

I'm going to try to run the upgrade with Amazon cut off. Let's see how that goes.
1%... 2%... 3%............ 99%... 100%

 Well - the upgrade went fine. It didn't download anything from the internet (the whole packet capture was about 3MB).

So - was this a complete failure? Yes. 
Did I learn something in the process? Yes!
Was it entertaining? Hell, yes!
Will it prevent futher upgrades? I'm guessing so - I'll have to see. In order to catch the upgrade server I need to capture all the TV traffic, all the time and dig through it when the next request appears. Not so much fun.
I plan on leaving amazon blocked for a while and to monitor what breaks.

Hope this was as entertaining for you as it was for me.
Cheers!

Comments

Popular posts from this blog

Home Assistant + Android TV = fun

Here's a quick setup guide for controlling your Android TV from within Home Assistant. I've used it to control a genuine Android TV (Philips 7304) and an Odroid N2 running Android TV. For this to work you need ADB access. It can usually be enabled from within Developer Settings. The great part is - you don't need root access! The most important things are described in the androidtv component for Home Assistant: https://www.home-assistant.io/integrations/androidtv/ Make sure you go through the adb setup. My configuration is simple (inside configuration.yaml): media_player:   - platform: androidtv     name: TV Bedroom ATV     host: 192.168.1.61     device_class: androidtv Once Home Assistant restarts, your TV might require you to accept the connection (adb authentication). This happens only once (or until you reset your ATV to factory settings). Once running the integration will show you the current ATV state (on or off) and allows you to turn it on or off.

SmokePing + InfluxDB export + docker + slaves + Grafana = fun

I've been working for a while on this project - with the purpose of getting SmokePing measurements from different hosts (slaves) into InfluxDB so that we can better graph them with Grafana. The slaves run multiple Smokeping instances inside Docker so that they have separate networking (measure through different uplinks, independently). This will not be a comprehensive configuration guide, but a quick "how to" to handle setup and basic troubleshooting. It assumes you already know how to set up and operate a regular Smokeping install with or without slaves and that you are fluent in Smokeping configuration syntax, know your way around Docker and aren't a stranger from InfluxDB and Grafana (sorry, there's a lot of information to take in). 1. Getting Smokeping with InfluxDB support - you can get it either from the official page (most changes have been merged) - https://github.com/oetiker/SmokePing (PR discussion here: https://github.com/oetiker/SmokePing/issues/

Installing Home Assistant Supervised on an old 32bit HP laptop

 I've received a challenge from my former boss: an old HP laptop that was born in 2005:  an HP-Compaq NC6220 ( https://www.pocket-lint.com/laptops/reviews/hp/68181-hp-compaq-nc6220-notebook-laptop/ ). The specs are abysmal: So, i386, 1.7GHz single-core CPU (remember those?), 1G of DDR2 RAM (2x512M) and a 40GB ATA (not SATA!) drive. But hey, at least it has a serial port!  The challenge is to install HomeAssistant ( https://www.home-assistant.io/ ) on it so that he can monitor some Zigbee temperature sensors and relays (via a gateway). The first hurdle was to remove the BIOS password - following this nice guide: https://www.youtube.com/watch?v=ZaGKyb0ntSg Next-up - install HASSOS. Unfortunately, it doesn't support i386, but only x86_64... So, I went the Home Assistant Supervised route, and installed Debian 11 i386 edition from a netinstall USB ( https://cdimage.debian.org/debian-cd/current/i386/iso-cd/debian-11.6.0-i386-netinst.iso ).   Once Debian was up and running (didn't