I was (again, how privileged) given a phone! This one is a LG G3, also known as the "D-852" (the version distributed by Bell and Rogers in Canada). It is a nice device, although on the big side for me.


First step is to get root. Instructions for this vary: some forums tell you to run weird Windows executables to get "one-click root" on the device. This obviously won't work for me on Linux. The one option that's designed to run on Linux ("PurpleDrake", found in Reddit) relies on a vulnerability that seems to have been patched in the phone I have.

This guide seems a little better and I think I can break it down to a step-by-step process that basically consists of pushing a set of tools using adb, then rebooting in diagnostic mode and issuing commands over the serial console. The batch script basically goes like this:

  1. install adb:

    apt install adb
  2. push busybox - instead of using an arbitrary copy I found on the internet, I got a more trusted build from Debian packages:

    dpkg -x busybox-static_1.22.0-19+b3_armhf.deb armhf
    adb push armhf/bin/busybox /data/local/tmp
  3. push SuperSU

    adb push SuperSU-v2.82-201705271822.zip /data/local/tmp
  4. push a custom script to glue all this together:

     adb push lg_root.sh /data/local/tmp

    The script is in the LG_Root.zip file which also contains copies of busybox and SuperSU, but I prefered to use other trusted copies of those elsewhere. the script, however, I couldn't find but you can review it, at least. I found a link to the .zip file on this tutorial

  5. STOP ModemManager! otherwise it may garble the serial port:

    sudo service ModemManager stop
  6. switch to "download mode":

    1. unplug the USB cable
    2. power off the phone
    3. hold the "volume up" button and plug the USB cable

    the screen should now say "download mode" then "Firmware update". you're now in download mode

  7. find the serial port the device is attached to:

    dmesg | tail

    here it was /dev/ttyACM0

  8. attach to the serial port (e.g. with GNU Screen):

    screen /dev/ttyACM0
  9. run the magic command:

    sh /data/local/tmp/lg_root.sh dummy 1 /data/local/tmp/UPDATE-SuperSU-v2.46.zip /data/local/tmp/busybox

    the original command was:

    sh /data/local/tmp/lg_root.sh dummy 1 /data/local/tmp/SuperSU-v2.82-201705271822.zip /data/local/tmp/busybox
  10. pull the battery to get out of download mode, or hold volume up and power for 30 seconds

Step 8 doesn't work: I can't figure out the port speed or protocol to talk to the "download mode". I have also tried to run the magic "Send_Command.exe" under wine, but it fails:

#wine: Call from 0x7b83ae8c to unimplemented function msvcr100.dll.gets_s, aborting
wine: Unimplemented function msvcr100.dll.gets_s called at address 0x7b83ae8c (thread 0009), starting debugger...

The Send_Command.exe tool has a Python equivalent as well called lglaf which unfortunately doesn't seem to work, either because the phone is refusing this, or because the protocol is different enough this doesn't work.

Traceback (most recent call last):
  File "lglaf.py", line 404, in <module>
  File "lglaf.py", line 386, in main
  File "lglaf.py", line 279, in try_hello
    data = comm.read(0x20, timeout=HELLO_READ_TIMEOUT)
  File "lglaf.py", line 148, in read
    buff = self._read(need, timeout=timeout)
  File "lglaf.py", line 256, in _read
    array = self.usbdev.read(self.ep_in, 2**14, timeout=timeout)
  File "/usr/lib/python2.7/dist-packages/usb/core.py", line 988, in read
  File "/usr/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 833, in bulk_read
  File "/usr/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 936, in __read
  File "/usr/lib/python2.7/dist-packages/usb/backend/libusb1.py", line 595, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 110] Operation timed out

That's because the udev rules do not cover the 852 device, so this patch is required:

--- a/rules.d/42-usb-lglaf.rules
+++ b/rules.d/42-usb-lglaf.rules
@@ -5,3 +5,5 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="1004", ATTRS{idProduct}=="633e", TAG+="uacce
 SUBSYSTEM=="usb", ATTRS{idVendor}=="1004", ATTRS{idProduct}=="627f", TAG+="uaccess"
 # LG G4 (VS986) in download mode
 SUBSYSTEM=="usb", ATTRS{idVendor}=="1004", ATTRS{idProduct}=="6298", TAG+="uaccess"
+# LG G3 (D852) in download mode
+SUBSYSTEM=="usb", ATTRS{idVendor}=="1004", ATTRS{idProduct}=="631d", TAG+="uaccess"

With the patch (or running as root), it still fails, with:

LGLAF.py: WARNING: Command failed with error code 0x8000010a

So we need another patch (now merged) to send a proper challenge-response and then we get a prompt. Unfortunately, some clever thing is still refusing our commands:

# sh /data/local/tmp/lg_root.sh dummy 1 /data/local/tmp/UPDATE-SuperSU-v2.46.zip /data/local/tmp/busybox
Hello, I am LAF. Nice to meet you.#

So I'm stuck: there doesn't seem to be a way to root this device.

Update: I had a confirmation of my worst suspicions. It does seem like the above is a restriction on the recovery mode to keep people from doing exactly what I am trying to do. The new --rawshell argument helps a little: I can run some commands, but nothing that can allow me to sideload the root app that I would need.

Recovery setup

Next step is to setup TWRP, which seems to only be to install an app nowadays, if the device is rooted.

See also the noise about BUMP! - not sure what that's about. Maybe it's necessary to boot TWRP at all?

Custom ROM install

And then the next step is to install LineageOS, because the current firmware has all sorts of crappy apps like spam from Google and god knows what else. With LineageOS, I still have proprietary software, but at least I know exactly what those are and I'm confident it's the bare minimum to get the thing running. It's more than my previous device but it's not that bad.

The install instructions are pretty simple, once the device is rooted.


Created . Edited .