Giter Site home page Giter Site logo

lglaf's Introduction

WARNING

This is currently a work-in-progress especially for WRITING

LGLAF.py

LGLAF.py is a utility for communication with LG devices in Download Mode. This allows you to execute arbitrary shell commands on a LG phone as root.

Contents of this repository:

  • lglaf.py - main script for communication (see below).
  • partitions.py - manage (list / read / write) partitions.
  • extract-partitions.py - Dump all partitions (convenience script that uses partitions.py under the hood). By default the largest partitions (system, cache, cust, userdata) are not dumped though. This can be changed with the --max-size option.
  • dump-file.py - dumps a regular file from device.
  • protocol.md - Protocol documentation.
  • lglaf.lua - Wireshark dissector for LG LAF protocol.
  • scripts/ - Miscellaneous scripts.

Requirements

LGLAF.py depends on:

On Linux, you must also install rules.d/42-usb-lglaf.rules to /etc/udev/rules.d/ in order to give the regular user access to the USB device.

Tested with:

  • LG G3 (D855) on 64-bit Arch Linux (Python 3.5.1, pyusb 1.0.0b2, libusb 1.0.20)
  • LG G3 (D855) on 32-bit Windows XP (Python 3.4.4, LG drivers).
  • LG G2 (VS985).
  • LG G4 (VS986) on Linux (Python 3.5) and Windows.
  • LG G4 (H810,H811,H812,H815) on 64 bit Arch Linux | FWUL (Python 2.7.13, pyusb 1.0.0-5, libusb 1.0.21-2)
  • LG K10 2017 (M250N) on Linux (Both Python 2.7.13 and Python 3.5.3).

Usage

This tool provides an interactive shell where you can execute commands in Download Mode. To enter this mode:

  1. Power off the phone.
  2. Connect the phone to a computer using a USB cable.
  3. Press and hold Volume up.
  4. Briefly press the power button.
  5. Wait for the Download mode screen to appear.
  6. Release keys. You should now see a Firmware Update screen.

Now you can issue commands using the interactive shell:

(venv)[peter@al lglaf]$ python lglaf.py
LGLAF.py by Peter Wu (https://lekensteyn.nl/lglaf)
Type a shell command to execute or "exit" to leave.
# pwd
/
# uname -a
-: uname: not found
# cat /proc/version
Linux version 3.4.0-perf-gf95c7ee (lgmobile@LGEARND12B2) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Tue Aug 18 19:25:04 KST 2015
# exit

When commands are piped to stdin (or given via -c), the prompt is hidden:

(venv)[peter@al lglaf]$ echo mount | python lglaf.py
rootfs / rootfs rw 0 0
tmpfs /dev tmpfs rw,seclabel,nosuid,relatime,size=927232k,nr_inodes=87041,mode=755 0 0
devpts /dev/pts devpts rw,seclabel,relatime,mode=600 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,seclabel,relatime 0 0
selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0
debugfs /sys/kernel/debug debugfs rw,relatime 0 0
/dev/block/platform/msm_sdcc.1/by-name/system /system ext4 ro,seclabel,noatime,data=ordered 0 0
/dev/block/platform/msm_sdcc.1/by-name/userdata /data ext4 rw,seclabel,nosuid,nodev,noatime,noauto_da_alloc,resuid=1000,errors=continue,data=ordered 0 0
/dev/block/platform/msm_sdcc.1/by-name/persist /persist ext4 ro,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/block/platform/msm_sdcc.1/by-name/cache /cache ext4 rw,seclabel,nosuid,nodev,noatime,data=ordered 0 0
(venv)[peter@al lglaf]$ python lglaf.py -c date
Thu Jan  1 01:30:06 GMT 1970
(venv)[peter@al lglaf]$

Advanced usage

If you know the protocol, you can send commands directly. Each request has a command, zero to four arguments and possibly a body. The lglaf.py tool accepts this command:

![command] [arguments] [body]

All of these words accept escape sequences such as \0 (octal escape), \x00 (hex), \n, \r and \t. The command must be exactly four bytes, the arguments and body are optional.

Arguments are comma-separated and must either be four-byte sequences (such as \0\1\2\3) or numbers (such as 0x03020100). If no arguments are given, but a body is needed, keep two spaces between the command and argument.

Reboot device (command CTRL, arg1 RSET, no body):

$ ./lglaf.py  --debug -c '!CTRL RSET'
LGLAF.py: DEBUG: Hello done, proceeding with commands
LGLAF.py: DEBUG: Header: b'CTRL' b'RSET' b'\0\0\0\0' b'\0\0\0\0' b'\0\0\0\0' b'\0\0\0\0' b'\xc7\xeb\0\0' b'\xbc\xab\xad\xb3'

Execute a shell command (command EXEC, no args, with body):

$ ./lglaf.py --debug --skip-hello -c '!EXEC  id\0'
LGLAF.py: DEBUG: Header: b'EXEC' b'\0\0\0\0' b'\0\0\0\0' b'\0\0\0\0' b'\0\0\0\0' b'/\0\0\0' b'\x8dK\0\0' b'\xba\xa7\xba\xbc'
uid=0(root) gid=0(root) context=u:r:toolbox:s0

License

See the LICENSE file for the license (MIT).

lglaf's People

Contributors

anarcat avatar gijstimmers avatar kebianizao avatar kenkit avatar lekensteyn avatar mathnerd314 avatar mcirsta avatar renakunisaki avatar runningnak3d avatar smurfix avatar steadfasterx avatar tuxuser avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lglaf's Issues

laf_copy hangs

As write does not work for my H815 (I even tried and re-enabled it, but not a single byte got written), I tried misc-write, but this makes it hang in laf_copy() forever

bernd@t420-work-1 lglafng>python3 ./partitions.py --cr yes --debug --restoremisc /home/bernd/tmp/android/lg-g4/twrp-3.2.3-0-g4.img recovery
2019-01-13 00:54:16,663 LGLAF.py: DEBUG: product id in CR list: >LG_new<
2019-01-13 00:54:16,663 LGLAF.py: DEBUG: Device is: 633a, LG_new. Enabling Challenge/Response!
2019-01-13 00:54:16,663 LGLAF.py: DEBUG: forced CR detection to: yes / 1
2019-01-13 00:54:16,663 LGLAF.py: DEBUG: Final CR detection: yes / 1
2019-01-13 00:54:16,664 LGLAF.py: DEBUG: Detaching kernel driver for intf 0
2019-01-13 00:54:16,665 LGLAF.py: DEBUG: Using endpoints 83 (IN), 02 (OUT)
2019-01-13 00:54:16,667 partitions: DEBUG: Using Protocol version: 0x1000004
2019-01-13 00:54:17,071 LGLAF.py: DEBUG: Challenge: b'266fd642'
2019-01-13 00:54:17,072 LGLAF.py: DEBUG: Response: b'd23c6bf3ee9e612826ef50eef0398013'
2019-01-13 00:54:17,074 LGLAF.py: DEBUG: KILO METR Response -> Header: b'4b494c4f4d455452000000000200000000000000000000002f5d0000b4b6b3b0', Body: b''
2019-01-13 00:54:17,088 partitions: DEBUG: # Flags From(#s) To(#s) GUID/UID Type/Name
39 1152921504606846976 573440 655359 9D72D4E4-9958-42DA-AC26-BEA7A90B0434 Unknown
70349858-D9AB-5A65-5F45-AB1B2349F1F7 recovery
2019-01-13 00:54:17,088 partitions: DEBUG: # Flags From(#s) To(#s) GUID/UID Type/Name
39 1152921504606846976 573440 655359 9D72D4E4-9958-42DA-AC26-BEA7A90B0434 Unknown
70349858-D9AB-5A65-5F45-AB1B2349F1F7 recovery
2019-01-13 00:54:17,089 partitions: DEBUG: Opened fd 25 for disk
2019-01-13 00:54:17,089 partitions: DEBUG: Will write 33783808 bytes
2019-01-13 00:54:17,093 partitions: DEBUG: laf_copy: misc_start: 262144 chunksize: 512, write_offset 293601280, write_offset // BLOCKSIZE: 573440
2019-01-13 01:01:47,099 LGLAF.py: DEBUG: Challenge: b'07e8171c'
2019-01-13 01:01:47,099 LGLAF.py: DEBUG: Response: b'9e797d73f24bd68021de4eba4a638f1f'
2019-01-13 01:01:47,100 LGLAF.py: DEBUG: KILO METR Response -> Header: b'4b494c4f4d45545200000000040000000000000000000000f98e0000b4b6b3b0', Body: b''

This is on g4-develop with a minor diff

diff --git a/partitions.py b/partitions.py
index 865bd8a..ee74cfe 100755
--- a/partitions.py
+++ b/partitions.py
@@ -314,7 +314,7 @@ def write_misc_partition(comm, fd_num, local_path, part_offset, part_size, batch
         while write_offset < end_offset:
             # TODO: automatically get the size of misc, but it is hardcoded for now
             # Also, this MUST be divisable by BLOCK_SIZE
-            chunksize = 512
+            chunksize = BLOCK_SIZE
             data = f.read(chunksize)
             if not data:
                 break # End of file
@@ -325,6 +325,8 @@ def write_misc_partition(comm, fd_num, local_path, part_offset, part_size, batch
             # This enables write to the FD
             laf_ioct(comm, fd_num,0x1261)
             # This copies the data from misc to your destination partition
+            _logger.debug("laf_copy: misc_start: %d chunksize: %d, write_offset %d, write_offset // BLOCKSIZE: %d",
+                          misc_start, chunksize, write_offset, write_offset // BLOCK_SIZE)
             laf_copy(comm, fd_num, misc_start, chunksize, write_offset // BLOCK_SIZE)
             # This disables write on the FD.
             laf_ioct(comm, fd_num,0x1261)

Any ideas why the copy command hangs?

Thanks,
Bernd

Failure reading LMK200BMW (aka LG K22) partitions

Using the default branch can't list the partitions, but the develop branch can. Attempting to dump a partition using partitions.py results in the following error:

[arch@archlinux lglafng]$ python partitions.py --dump boot_a.img boot_a --debug
2021-11-07 22:44:27,229 LGLAF.py: DEBUG: product id in CR list: ><
2021-11-07 22:44:27,229 LGLAF.py: DEBUG: Final CR detection: None / 0
2021-11-07 22:44:27,230 LGLAF.py: DEBUG: Using endpoints 83 (IN), 02 (OUT)
2021-11-07 22:44:27,230 LGLAF.py: DEBUG: BASE_PROTOCOL_VERSION: 1000001
2021-11-07 22:44:27,231 LGLAF.py: DEBUG: DEV_PROTOCOL_VERSION: 1000001
2021-11-07 22:44:27,235 LGLAF.py: DEBUG: Switching to minimum version reported by lafd
2021-11-07 22:44:27,235 LGLAF.py: DEBUG: Negotiation in-use
2021-11-07 22:44:27,235 LGLAF.py: DEBUG: BASE_PROTOCOL_VERSION: 1000001
2021-11-07 22:44:27,236 LGLAF.py: DEBUG: DEV_PROTOCOL_VERSION: 1000008
2021-11-07 22:44:27,236 LGLAF.py: DEBUG: Switching protocol to 1000008
2021-11-07 22:44:27,279 LGLAF.py: DEBUG: Switching to minimum version reported by lafd
2021-11-07 22:44:27,279 LGLAF.py: DEBUG: Negotiation in-use
2021-11-07 22:44:27,280 partitions: DEBUG: Negotiated protocol version: 0x1000008
2021-11-07 22:44:27,283 LGLAF.py: DEBUG: using timeout value of: 2000
2021-11-07 22:44:27,296 LGLAF.py: DEBUG: Challenge: b'e8d0b55f'
2021-11-07 22:44:27,364 LGLAF.py: DEBUG: Response: b'e4df9b5a781d53b5e68f64f99a8f1a7c'
2021-11-07 22:44:27,365 LGLAF.py: DEBUG: using timeout value of: None
2021-11-07 22:44:27,367 LGLAF.py: DEBUG: KILO METR Response -> Header: b'4b494c4f4d455452000000000200000000000000000000002f5d0000b4b6b3b0', Body: b''
2021-11-07 22:44:27,371 LGLAF.py: DEBUG: using timeout value of: None
2021-11-07 22:44:27,375 partitions: DEBUG: opened a disk_fd: 58 on default
2021-11-07 22:44:27,375 partitions: DEBUG: check_block_size, read_offset: 0, end_offset: 24576, GPT_LBA_LEN: 6, BLOCK_SIZE: 4096, MAX_BLOCK_SIZE: 3
2021-11-07 22:44:27,375 partitions: DEBUG: Protocol based handling: 1000008
2021-11-07 22:44:27,379 LGLAF.py: DEBUG: using timeout value of: 3000
2021-11-07 22:44:27,387 partitions: DEBUG: No GPT header found for block size: 4096
2021-11-07 22:44:27,387 partitions: DEBUG: check_block_size, read_offset: 0, end_offset: 17408, GPT_LBA_LEN: 34, BLOCK_SIZE: 512, MAX_BLOCK_SIZE: 31
2021-11-07 22:44:27,387 partitions: DEBUG: Protocol based handling: 1000008
2021-11-07 22:44:27,390 LGLAF.py: DEBUG: using timeout value of: 3000
2021-11-07 22:44:27,418 partitions: DEBUG: GPT HEADER FOUND for block size: 512
2021-11-07 22:44:27,418 partitions: DEBUG: GPT_LBA_LEN: 34
2021-11-07 22:44:27,419 partitions: DEBUG: BLOCK_SIZE: 512 (EMMC), MAX_BLOCK_SIZE: 31
2021-11-07 22:44:27,419 partitions: DEBUG: Protocol based handling: 1000008
2021-11-07 22:44:27,422 LGLAF.py: DEBUG: using timeout value of: None
2021-11-07 22:44:27,438 LGLAF.py: DEBUG: using timeout value of: 2000
2021-11-07 22:44:27,442 LGLAF.py: DEBUG: Challenge: b'01205e1b'
2021-11-07 22:44:27,442 LGLAF.py: DEBUG: Response: b'8d9884296a2d584902b4b293b31f554e'
2021-11-07 22:44:27,445 LGLAF.py: DEBUG: using timeout value of: None
2021-11-07 22:44:27,449 LGLAF.py: DEBUG: KILO METR Response -> Header: b'4b494c4f4d45545200000000040000000000000000000000f98e0000b4b6b3b0', Body: b''
2021-11-07 22:44:27,453 LGLAF.py: DEBUG: using timeout value of: None
2021-11-07 22:44:27,456 partitions: DEBUG: Found partition on device: default
2021-11-07 22:44:27,457 partitions: DEBUG: part offset: 369098752, size: 67108864
2021-11-07 22:44:27,457 partitions: DEBUG: opener: b'\x00'
2021-11-07 22:44:27,460 LGLAF.py: DEBUG: using timeout value of: 2000
2021-11-07 22:44:27,464 LGLAF.py: DEBUG: Challenge: b'7bd3ae02'
2021-11-07 22:44:27,465 LGLAF.py: DEBUG: Response: b'9057545b38dfc2fc52e57416aa9d7a6d'
2021-11-07 22:44:27,468 LGLAF.py: DEBUG: using timeout value of: None
2021-11-07 22:44:27,472 LGLAF.py: DEBUG: KILO METR Response -> Header: b'4b494c4f4d455452000000000200000000000000000000002f5d0000b4b6b3b0', Body: b''
2021-11-07 22:44:27,477 LGLAF.py: DEBUG: using timeout value of: None
2021-11-07 22:44:27,480 partitions: DEBUG: opened a disk_fd: 58 on default
2021-11-07 22:44:27,485 partitions: DEBUG: Will read 67108864 bytes at disk offset 369098752
2021-11-07 22:44:27,488 LGLAF.py: DEBUG: using timeout value of: None
Traceback (most recent call last):
  File "/home/arch/programs/lglafng/partitions.py", line 752, in <module>
    main()
  File "/home/arch/programs/lglafng/partitions.py", line 732, in main
    dump_partition(comm, disk_fd, args.dump, part_offset, part_size, args.batch)
  File "/home/arch/programs/lglafng/partitions.py", line 344, in dump_partition
    data, disk_fd = laf_read(comm, disk_fd, read_offset // BLOCK_SIZE, chunksize)
  File "/home/arch/programs/lglafng/partitions.py", line 141, in laf_read
    header, response = comm.call(read_cmd, timeout=timeout)
  File "/home/arch/programs/lglafng/lglaf.py", line 349, in call
    raise RuntimeError('Command failed with error code %#x (%s)' % (errCode, msg))
RuntimeError: Command failed with error code 0x80000119 (LAF_ERROR_<unknown>)

This model appears to have only been released in Brazil (which is where I live) and Panama (under the model LMK200HMW) and information regarding its firmware is scarce, apart from LG not releasing any technical information asides from the modified Android kernel source.

issue to write on MM firmwares (again!)

unfortunately since an unknown change it is not possible to write on MM laf anymore.
atm it seems to write but finishes and nothing gets written actually.
I had that issue a while ago and fixed it .. but now its back due to some merges I guess.

@runningnak3d any idea? :p

Hidden dependency

Hi,

would it be possible to refactor the code in such a way that running the module A would not import another module B that imports from A?

In this case Guix/Nix modifies/replaces the original lglaf file and replaces it with a shell script that has paths to all the needed python modules and as last step executes the Python interpreter.

Fix would be to point/import to the real file/module .lglaf.py-real but IMHO the function that's imported should be part of some utils module.

A: lglaf.py
B: laf_crypto

pethod@CZPRGL-B18SYD3 ~/expanse/expanse/packages$ /gnu/store/qj9xjlrci45shbms6kkklmyck0pgflpx-lglaf-0.1/bin/lglaf.py
Traceback (most recent call last):
  File "/gnu/store/qj9xjlrci45shbms6kkklmyck0pgflpx-lglaf-0.1/bin/.lglaf.py-real", line 41, in <module>
    import laf_crypto
  File "/gnu/store/qj9xjlrci45shbms6kkklmyck0pgflpx-lglaf-0.1/lib/python3.10/site-packages/laf_crypto.py", line 4, in <module>
    from lglaf import int_as_byte
  File "/gnu/store/qj9xjlrci45shbms6kkklmyck0pgflpx-lglaf-0.1/bin/lglaf.py", line 2
    jr-python-packaging-bootstrap-21.3/lib/python3.10/site-packages:/gnu/store/k7svck56hhagdg3q4nqlk5z1j57w9sli-python-pycparser-2.21/lib/python3.10/site-packages:/gnu/store/ij3wk9likzyv9jbwx60rmi0vyjhdi2dw-python-six-bootstrap-1.16.0/lib/python3.10/site-packages:/gnu/store/wlmf5spfdmsjiw6cx30h0rpydfpz3gil-python-pyparsing-3.0.6/lib/python3.10/site-packages${GUIX_PYTHONPATH:+:}$GUIX_PYTHONPATH"
           ^^^^^^^^^^^^^^^
SyntaxError: invalid syntax

Trying to run auth.py results in TypeError

Trying to run auth.py on a LG K10 2017 (M250N):

$ python auth.py 
Traceback (most recent call last):
  File "auth.py", line 73, in <module>
    main()
  File "auth.py", line 64, in main
    comm = lglaf.autodetect_device()
TypeError: autodetect_device() missing 1 required positional argument: 'cr'

No real output to commands

Hi,
I've put the K40 into the updater mode and ran the tool

$ python3 lglaf.py
LGLAF.py by steadfasterX + Peter Wu (https://lekensteyn.nl/lglaf)
Type a shell command to execute or "exit" to leave.
# pwd
Hello, I am LAF. Nice to meet you.# uname -a
Hello, I am LAF. Nice to meet you.#

However, I'm unable to get any meaningful output.

Any idea what could be wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.