This exploit is made for LG K10 M250E although it should work any MediaTek based LG K10 (variants like M250 M250E M250N etc.). If you are still running on nougat consider updating to Oreo, as this exploit requires bootloader provided with Oreo. If you don't want to update to Oreo you can try installing only bootloader (bin\vuln_lk.img), albeit it has not been tested and may not work properly if at all. If you want to proceed to updating bootloader use tools provided in this repo (see below for instructions), in case something goes wrong you should be able to recover.
Exploit is composed of two parts: microloader and LK payload (as in Amonet). LK payload resides in preloader partition, so backup it before flashing (use read_boot0.py or on Android dump /dev/block/mmcblk0boot0).
Since preloader partition is write protected in Android you must use tools provided in this repo which may be tricky to setup, especially on Windows. So before proceeding to flashing LK payload you can do simple test, by flashing bin\test_recovery_with_exploit.img onto recovery partition and booting it. You should get "payload missing ...." on your phone screen, then proceed to flashing LK payload. If your device hangs without any message, or immediately reboots, then you need to flash bin\vuln_lk.img.
Tools require some dependencies (currently pyserial
only) to operate. You can
install them by doing
pip3 install -r requirements.txt
If you don't want to install dependencies globally you can use venv
:
python3 -m venv .venv
. .venv/bin/activate
pip3 install -r requirements.txt
Open powershell as administrator and run these commands:
Install-Module Watch
Get-PnpDevice -PresentOnly | Where-Object {$_.InstanceId -match '^USB\\'} | Format-Table -AutoSize | Watch-Command -Verbose -Cont
Poweroff phone and connect it to PC (to enter preloader). Device should appear Ports class, if it's unknown then install driver using Zadig. Otherwise run
Get-PnpDevice | Where-Object {$_.InstanceId -eq 'USB\VID_1004&PID_6000\5&16ACEB2E&0&1'} | Get-PnpDeviceProperty -KeyName DEVPKEY_Device_DriverInfPath | Format-Table -AutoSize
If your device is LG and VID is 1004 make sure the driver is generic usbser.inf. If not then replace it (or expect errors).
Note the COM port device is using, write it to config.py into PL_DEV_PATH variable.
Then run:
python pl.py -w --read32 0
This will crash preloader and make device enter BootROM. Your device should soon appear, (look for USB\VID_0E8D&PID_0003) If there is no driver then install it from bin\vcom (usbser does not work here), then enter into BootROM again and write COM port into BR_DEV_PATH.
Run:
python pl.py -w --bootcda
Poweroff phone, and connect it to PC.
Your device should boot into custom download agent, look for USB\VID_18D1&PID_DEED. It should use usbser driver. Write COM port into AG_DEV_PATH.
From that mode you can do various interesting things like:
python download.py -w bootinfo
[] Bootinfo at 0x448dc240 size 3328
[] Boot Reason: USB
[] Boot Mode: FASTBOOT
[] META COM ID: 0
[] META COM TYPE: 0x00000000
[] META COM PORT: 0x11002000
[] LOG Enable: 1
[] LOG Baud Rate: 921600
[] LOG Port: 0x11002000
[] Number of DRAM Ranks: 2
[] Rank sizes:
[] 0x448dc28c
[] 0x448dc28c
[] 0x448dc28c
[] 0x448dc28c
[] Number of M-Blocks: 2
[] Start End Rank
[] 0x0000000040000000 - 0x000000007fffffff 0
[] 0x0000000080000000 - 0x00000000bfffffff 1
[] LCA Reserved Memory: NONE
[] TEE Reserved Memory: 0x00000000fffc0000 - 0x00000000ffffffff
[] MD INFO: [0; 0; 0; 0]
[] DA Info:
[] Address: 0x00000000
[] Arg1: 0x00000000
[] Arg2: 0x00000000
[] Size: 0x0
[] Signature Size: 0x0
[] Unknown TAG 0x88610007 SIZE 3
python download.py -w efuse
[EFUSE] HW JTAG: Enabled
[EFUSE] SW JTAG: Enabled BLOWN
[EFUSE] SBC: Enabled BLOWN (Secure Boot)
[EFUSE] DAA: Enabled BLOWN (Download Agent Auth)
[EFUSE] SLA: Disabled (I don't know)
[EFUSE] JTAG BROM LOCK: Enabled
[EFUSE] Public key hash:
[EFUSE] 0x0f2bdbef
[EFUSE] 0xc4e52a01
[EFUSE] 0x2cff2c27
[EFUSE] 0x1aaaa98b
[EFUSE] 0x5f662ace
[EFUSE] 0xc7be7765
[EFUSE] 0x1b77f79c
[EFUSE] 0xbda8a101
And the key features: read/write
# Intialize MMC (currently only mmc0 is supported)
python .\download.py -w mmc init 0
[PT] Reading partition table.
[PT] Disk GUID: {00000000-0000-0000-0000-000000000000}
[PT] 50 partition entries of size 128 bytes starting at LBA 2 and occupying 13 blocks.
# # First LBA Last LBA Attributes Partition type GUID Unique GUID
[PT] 0 0x0000000000000400 0x0000000000001bff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {F57AD330-39C2-4488-9BB0-00CB43C9CCD4} proinfo
[PT] 1 0x0000000000001c00 0x0000000000003fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {FE686D97-3544-4A41-BE21-167E25B61B6F} spare1
[PT] 2 0x0000000000004000 0x0000000000007fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {1CB143A8-B1A8-4B57-B251-945C5119E8FE} misc2
[PT] 3 0x0000000000008000 0x000000000000bfff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {3B9E343B-CDC8-4D7F-9FA6-B6812E50AB62} ftm
[PT] 4 0x000000000000c000 0x000000000000e7ff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {5F6A2C79-6617-4B85-AC02-C2975A14D2D7} nvram
[PT] 5 0x000000000000e800 0x000000000000ffff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {4AE2050B-5DB5-4FF7-AAD3-5730534BE63D} spare2
[PT] 6 0x0000000000010000 0x0000000000013fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {1F9B0939-E16B-4BC9-A5BC-DC2EE969D801} protect1
[PT] 7 0x0000000000014000 0x0000000000017fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {D722C721-0DEE-4CB8-8A83-2C63CD1393C7} protect2
[PT] 8 0x0000000000018000 0x00000000000187ff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {E02179A8-CEB5-48A9-8831-4F1C9C5A8695} lk
[PT] 9 0x0000000000018800 0x0000000000018fff 0x0000000000000004 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {84B09A81-FAD2-41AC-890E-407C24975E74} lk2
[PT] 10 0x0000000000019000 0x0000000000026fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {E8F0A5EF-8D1B-42EA-9C2A-835CD77DE363} laf
[PT] 11 0x0000000000027000 0x00000000000273ff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {D5F0E175-A6E1-4DB7-94C0-F82AD032950B} para
[PT] 12 0x0000000000027400 0x000000000002ffff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {1D9056E1-E139-4FCA-8C0B-B75FD74D81C6} boot
[PT] 13 0x0000000000030000 0x00000000000397ff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {7792210B-B6A8-45D5-AD91-3361ED14C608} recovery
[PT] 14 0x0000000000039800 0x0000000000042fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {138A6DB9-1032-451D-91E9-0FA38FF94FBB} recoverybak
[PT] 15 0x0000000000043000 0x0000000000046fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {756D934C-50E3-4C91-AF46-02D824169CA7} logo
[PT] 16 0x0000000000047000 0x000000000004afff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {A3F3C267-5521-42DD-A724-3BDEC20C7C6F} lo_bak_go
[PT] 17 0x000000000004b000 0x000000000004ffff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {8C68CD2A-CCC9-4C5D-8B57-34AE9B2DD481} expdb
[PT] 18 0x0000000000050000 0x0000000000053fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {6A5CEBF8-54A7-4B89-8D1D-C5EB140B095B} seccfg
[PT] 19 0x0000000000054000 0x0000000000057fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {A0D65BF8-E8DE-4107-9434-1D318C843D37} oemkeystore
[PT] 20 0x0000000000058000 0x000000000005afff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {46F0C0BB-F227-4EB6-B82F-66408E13E36D} secro
[PT] 21 0x000000000005b000 0x000000000005bfff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {FBC2C131-6392-4217-B51E-548A6EDB03D0} spare3
[PT] 22 0x000000000005c000 0x000000000005ffff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {E195A981-E285-4734-8025-EC323E9589D9} keystore
[PT] 23 0x0000000000060000 0x00000000000627ff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {E29052F8-5D3A-4E97-ADB5-5F312CE6610A} tee1
[PT] 24 0x0000000000062800 0x0000000000064fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {9C3CABD7-A35D-4B45-8C57-B80775426B35} tee2
[PT] 25 0x0000000000065000 0x00000000000653ff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {E7099731-95A6-45A6-A1E5-1B6ABA032CF1} eksst
[PT] 26 0x0000000000065400 0x00000000000657ff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {8273E1AB-846F-4468-B999-EE2EA8E50A16} encrypt
[PT] 27 0x0000000000065800 0x0000000000067fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {D26472F1-9EBC-421D-BA14-311296457C90} spare4
[PT] 28 0x0000000000068000 0x000000000006bfff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {B72CCBE9-2055-46F4-A167-4A069C201738} persist_lg
[PT] 29 0x000000000006c000 0x0000000000076fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {9C1520F3-C2C5-4B89-8242-FE4C61208A9E} mpt
[PT] 30 0x0000000000077000 0x000000000007bfff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {902D5F3F-434A-4DE7-8988-321E88C9B8AA} lgfota
[PT] 31 0x000000000007c000 0x000000000007c7ff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {BECE74C8-D8E2-4863-9BFE-5B0B66BB920F} rct
[PT] 32 0x000000000007c800 0x00000000000987ff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {FF1342CF-B7BE-44D5-A25E-A435ADDD2702} factory
[PT] 33 0x0000000000098800 0x0000000000098bff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {A4DA8F1B-FE07-433B-95CB-84A5F23E477B} efuse
[PT] 34 0x0000000000098c00 0x000000000009bfff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {C2635E15-61AA-454E-9C40-EBE1BDF19B9B} spare5
[PT] 35 0x000000000009c000 0x00000000000b3fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {4D2D1290-36A3-4F5D-AFB4-319F8AB6DCD8} persist
[PT] 36 0x00000000000b4000 0x00000000000b7fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {FDCE12F0-A7EB-40F7-8350-960972E6CB57} nvcfg
[PT] 37 0x00000000000b8000 0x00000000000c7fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {0FBBAFA2-4AA9-4490-8983-5329328505FD} nvdata
[PT] 38 0x00000000000c8000 0x00000000000d7fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {A76E4B2F-31CB-40BA-826A-C0CB0B73C856} metadata
[PT] 39 0x00000000000d8000 0x00000000000e3fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {F54AC030-7004-4D02-9481-BBF982036807} md1img
[PT] 40 0x00000000000e4000 0x00000000000e5fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {08163743-03B6-0000-0000-000048371608} md1dsp
[PT] 41 0x00000000000e6000 0x00000000000e77ff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {000004E2-0000-0000-4F37-1608E3040000} md1arm7
[PT] 42 0x00000000000e7800 0x00000000000e9fff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {00000000-3756-0816-E404-000000000000} md3img
[PT] 43 0x00000000000ea000 0x000000000011bfff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {0816375D-04E5-0000-0000-000064371608} cust
[PT] 44 0x000000000011c000 0x000000000011ffff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {000004E6-0000-0000-6B37-1608E7040000} frp
[PT] 45 0x0000000000120000 0x00000000008dffff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {00000000-3772-0816-E804-000000000000} system
[PT] 46 0x00000000008e0000 0x00000000009dffff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {08163779-04E9-0000-0000-000080371608} cache
[PT] 47 0x00000000009e0000 0x0000000000a3ffff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {0000036A-0000-0000-8637-1608A4030000} OP
[PT] 48 0x0000000000a40000 0x0000000001d53bff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {00000000-378C-0816-C451-000000000000} userdata
[PT] 49 0x0000000001d53c00 0x0000000001d5bbff 0x0000000000000000 {EBD0A0A2-B9E5-4433-87C0-68B6B72699C7} {08163792-CAED-0000-0000-000098371608} flashinfo
[PT] 50 0x0000000000000000 0x0000000000000000 0x0000000000000000 {00000000-0000-0000-0000-000000000000} {00000000-0000-0000-0000-000000000000}
[PT] 51 0x0000000000000000 0x0000000000000000 0x0000000000000000 {00000000-0000-0000-0000-000000000000} {00000000-0000-0000-0000-000000000000}
# Note: on Windows this often does not work properly
# Some data randomly gets lost, then a bunch of red E
# will show to signal error
# It happens during mmc init, so far never it happened while reading or writing partitions
# If it does not work for you try on Linux
# Now you can use
python .\download.py -w partition read lk BACKUP\LK.IMG
python .\download.py -w partition read boot BACKUP\BOOT.IMG
# And so on
# When you done
python .\download.py -w reboot
In Linux (as compared to Windows) driver installation isn't required. When
connecting the device, Linux should automatically bind the correct drivers.
In dmesg
you should see something like this:
[ 2393.577147] usb 5-2.4.3: new high-speed USB device number 5 using xhci_hcd
[ 2393.657855] usb 5-2.4.3: New USB device found, idVendor=1004, idProduct=6000, bcdDevice= 1.00
[ 2393.657862] usb 5-2.4.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 2393.657863] usb 5-2.4.3: Product: MT65xx Preloader
[ 2393.657865] usb 5-2.4.3: Manufacturer: LGE
[ 2394.070800] cdc_acm 5-2.4.3:1.0: ttyACM0: USB ACM device
[ 2394.070823] usbcore: registered new interface driver cdc_acm
[ 2394.070824] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[ 2394.078930] usbcore: registered new interface driver usbserial_generic
[ 2394.078937] usbserial: USB Serial support registered for generic
[ 2394.084491] usbcore: registered new interface driver qcaux
[ 2394.084499] usbserial: USB Serial support registered for qcaux
[ 2394.084515] qcaux 5-2.4.3:1.2: qcaux converter detected
[ 2394.084574] usb 5-2.4.3: qcaux converter now attached to ttyUSB0
In that case, /dev/ttyUSB0
is the preloader port. This port can be accessed
directly without any further setup, however having a few udev rules will make
the process easier, especially will make the process easier when switching
between modes (preloader, download agent, BootROM), so it is strongly
recommended.
Create a file in /etc/udev/rules.d
(e. g. /etc/udev/rules.d/99-lgk10.rules
),
(file must have .rules
extension) with the following contents:
# Preloader
SUBSYSTEM=="tty", ATTRS{idVendor}=="1004", ATTRS{idProduct}=="6000", OWNER="<your username here>"
# Download agent
SUBSYSTEM=="tty", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="deed", OWNER="<your username here>"
# BootROM
SUBSYSTEM=="tty", ATTRS{idvendor}=="0e8d", ATTRS{idProduct}=="0003", OWNER="<your username here>"
# Preloader
ACTION=="add", KERNEL=="ttyUSB[0-9]*", ATTRS{idVendor}=="1004", ATTRS{idProduct}=="6000", SYMLINK+="ttyPL"
# Download agent
ACTION=="add", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="deed", SYMLINK+="ttyAG"
# BootROM
ACTION=="add", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="0e8d", ATTRS{idProduct}=="0003", SYMLINK+="ttyBR"
This Udev rule does two things, first it sets permissions so that you can access
device as a normal user (without sudo
). You need to replace the
<your username here>
part with an actual username you wish to grant permission
to (use whoami
command). This will grant permission to any process running as
a specified user, if this is not desired, remove the part which changes
ownership. The second parts sets custom symlinks to serial port for each mode,
/dev/ttyPL
, /dev/ttyAG
and /dev/ttyBR
for Preloader, Download Agent, and
BootROM respectively.
After saving Udev rules you need to run
sudo udevadm control --reload
for the rules to apply. Now, the next time you connect device you should have one of the symlinks created.
Operates in preloader and BootROM mode. Mostly used to boot download agent. Also can be used to check for example security settings
python .\pl.py -w --identify
Chip: 326, stepping: 0
Hardware version: 0x8a00, subversion: 0xcb00, extra: 0x10000
Security: OFF
Target Config: 0x5
SBC: Enabled
SLA: Disabled
DAA: Enabled
If security is on then auth file is required to flash anything, but only in SPFlashTool. This function is only implemented in BootROM, in preloader it's always OFF. SBC is Secure Boot DAA is Download Agent Authentication SLA I don't know
Reads preloader from device running in BootROM mode (very slow).
Measure-Command {python .\read_boot0.py BACKUP\BOOT0.IMG | Out-Default}
ocr = 0x40ff8080
ocr = 0x40030000
ocr = 0xc0ff8080
cid = 0x90014A48 0x41473461 0x32A404F8 0xE8F46479
REBOOT
Days : 0
Hours : 0
Minutes : 3
Seconds : 32
Milliseconds : 892
Ticks : 2128928925
TotalDays : 0,00246403810763889
TotalHours : 0,0591369145833333
TotalMinutes : 3,548214875
TotalSeconds : 212,8928925
TotalMilliseconds : 212892,8925
#################################################################################
Writes preloader. Can restore preloader on device stuck in BootROM. Bypasses security so can on work devices with authentication and DAA enabled.
python .\write_boot0.py --brom BACKUP\BOOT0.IMG
Note --brom
parameter, its required on broken devices.
Otherwise tool will expect device in preloader mode.
# backup files
mkdir BACKUP
python read_boot0.py BACKUP\BOOT0.BIN
python pl.py -w --bootcda && python download.py -w mmc init 0
python download.py -w partition read lk BACKUP\LK.IMG
# flash LK
python download.py -w partition write lk bin\vuln_lk.img
python download.py -w reboot
# flash payload
python flash_lk_payload.bin bin\lk_payload.bin
To boot anything microloader must be injected into BOOT.IMG To do that use microloader\inject_microloader_oreo.py tool
python -b BOOT.IMG --mode boot bin\microloader.bin BOOT_WITH_MICROLOADER.IMG
python -b RECOVERY.IMG --mode recovery bin\microloader.bin RECOVERY_WITH_MICROLOADER.IMG
Note: it's important to set proper mode (either boot or recovery) when injecting, as image prepared to boot from 'recovery' partition won't boot from 'boot' partition and vice-versa.