ariigate Hacking Android phona, How deep the rabbit hole goes.
kayrus
Hacking Android phone. How deep the
rabbit hole goes.
My first Android phone, a Galaxy Note N7ooo, was bought just after
the announcement in October 2011. Thanks to one German guy called
bauner, [had an opportunity to use the latest version of
CyanogenMod (now LineageOS). Unfortunately, my phone died after
using a cheap Chinese car charger about one and a half years ago.
1 spent a lot of time looking for a replacement and stopped at the
Kyocera (yes, they produce phones) KC-S7o1. It looks quite brutal and
doesn’t have touch buttons. I did not even think about having root
access to the phone. I was sure that nowadays every phone had a
possibility to obtain root. And there will always be some guy who can
port CyanogenMod to it. I was mistaken,
Within one and a half years, only one kernel update was released—fix
resolved kernel failure on a specially crafted ping packet. Besides, one
year ago Android KitKat was already considered to be pretty old.
Unfortunately, there was neither info, nor possibility to get root
access. The same hardware is used in the American version of the
phone called Kyocera Brigadier E6782. It has fastboot mode by default
and there is no way to boot unsigned kernels (boot only, not flash,
and only using an old vulnerable bootloader, CVE-2014~4325) and
besides it provides an opportunity to boot into fastboot and recovery
modes by pressing the phone's buttons. Through the efforts of Verizon
MostIJ/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20te%.20-abbIM%420N0Ie%20g008. him 1/27ariigate
Hacking Android phona, How deep the rabbit hole goes.
(or maybe Kyocera?) The Android version of Brigadier has been
updated to Lollipop.
So, I decided to deal with the process of obtaining root on Android
myself.
‘Two months ago I did not know anything about the Android internals
(actually, now I don't know even more). Most of the knowledge was
gained by reading the source code and by experiments, since there is
a lack of information about the Android hacking on the Internet. The
information below works on Android 4.4 KitKat, but I assume there is
also a possibility to apply it on newer versions.
I would like to draw your attention to the fact that the info described
in this article is only my personal experience of Android hacking on a
particular phone model, so be careful using it if you do not want to
brick the phone. If you wish to root your phone using this article, I
recommend that you forget that you are using your phone in everyday
life, make a backup, and then perform a hard reset. This will protect
your data in case of fatal mistakes.
The article describes not only the actions that led to success, but also
mistakes. I hope that my attempts to get to the desired result, and
numerous fails, will be interesting to you.
The research was conducted in the Linux environment,
Dirtycow (CVE-2016-5195)
In simple words dirtycow (working exploit for Android) allows you to
replace the memory of any process (useful if you are familiar with the
assembly), or any file available for reading, even if it is on the
readonly filesystem. It is recommended to spoof the file which size is
greater or equal to the size of the replacement. The main attack in
dirtycow for Android is the /systen/pin/sun-as spoofing, It is some
kind of sudo in Android which allows to debug applications. Since
the android-19 API (see the table of matching API and Android
versions) /eysten/bin/sun-as has CAP_SETUID and CAP_SETGID
capabilities flags (in older versions suid bit is used - 6755 )
§ geteap bin/ra
egid, cap_sotuidtep
MostIJ/CRACKINGIREVERSE%.20ENGINEERINGIacking%<20Android%20phone.%20How%20deep%20tne%.20-abbIM%420N0Ie%20g008. him 2/27ariigate Hacking Android phona, How deep the rabbit hole goes.
If the file system is mounted in read-write mode, everything which
was spoofed by dirtycow will be written to the file system. Thus you
have to make a backup of the original file and restore it after gaining
the root access, or just don't remount the file system in read-write
mode. Generally the /system partition in Android is mounted in read-
only mode by default
That is why dirtycow is considered to be one of the most serious
vulnerabilities found in
inux. And using the appropriate knowledge
you can bypass all security levels of the Kernel, including SELinux,
SELinux
Beginners should know how the SELinux context works. There is a
good article in the Gentoo wiki:
https://wiki.gentoo.org/wiki/SELinux/Tutorials/How_does_a_process
_getLinto_a_certain_context
Ina nutshell, you should know the following:
+ SELinux process context can be changed if such an operation is
described in sepolicy rules (context transition). Android 4.4
(KitKat) provides the possibility to elevate privileges by changing
the SELinux context. Since Android 5.x it is not possible
anymore,
+ There are file contexts
+ In addition to the process and file contexts, Android
implemented its own property_contexts.
+ The rules look as follows: source context (application) is allowed
to access target context (filesystem). In SELinux enforcement
mode applications are allowed to do only the explicitly granted
operations. The rest is forbidden.
Adbd and console
The only possible way to obtain a partly privileged shell in production
Android devices—developer mode. Developer mode starts adbd
daemon which can act as some kind of ssh / telnet server. In Android
KitKat /sbin/acha binary is located in the initramfs and it is not
readable for non-root users. Initially adbd is executed as the root user
and it runs in u:rs
init:s0 SELinux context (used by init and usually
has more privileges than other contexts). If the /:niz.re has the
explicitly specified process context, such as seclabel u:r:adbd:so, the
MostI/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20tne%.20-abbIM%420NoIe%20g008. him 3127ariigate
Hacking Android phona, How deep the rabbit hole goes.
process starts immediately in this context. In case of initializing,
depending on compile options (user, userdebug or eng and Android
settings (properties), adbd lowers the privileges: it changes the
current user to shell, sets the SELinux context to u:r:shell:so and
trims all system capabilities except CAP_SETUID and CAP_SETGID
(that is required for debugging applications via rus-as )
Capability Bounding Set does not allow applications to escalate the
capabilities, only to drop them. These privileges allow you to do a
he
little bit more than nothing. You can view capabilities of the current
process with the following command cat /proc/sels/status | grep
capsnd . And decrypt them with the caps command (not available
on Android), for example.:
§ capsh --decode-oo0v001sseeeetee
oxco0000isefresttfmcap_chown, cap de, cap_dac_read_s
earch, cap_foxner,cap_fsetid, cap_Kill,cap_setgid,cap_setuid,e
ap_se=peap, cap_1inux_innutable, cap_net_bind service, cap_not_
broadcast, cap net acnin,cap net raw,cap ipc lock,cap {pe own
sp_sys_rawio, cap_sys_chreot,cap_sys_ptrac
¢,cap_ays_pacct, cap_ays_adnin,cap_sys_boot, cap_sys_n
sys_resource, cap_sys_tine,cap_sys_tty_config, cap_mknod,cap_1
ase, cap_aud:t_write,cap_audit_control, cap_set‘c:
verride, cap_rac_adnin, cap_syslog,cap_wake_alarn,cap block sa
spend
er, cap_sys_nodule,
6 2ap_
cap Maco
You can view the current SELinux context using ia or ca
/proc/sel*/atte/eurcent commands. Previous context could be
viewed by cat /proc/self/attr/prev «
View context of the files: is -2
View context of the running processes: ps -2
Get root access
‘The first thing I did was to use dirtycow for its intended purpose—to
spoof the /systen/bin/run-as , which allows me to set UID / GID to 0
(same stuff ss does). However, [could not mount the file systems
(as well as tmpfs), could not load kernel modules and view reag .T
could not even browse the directory which had the 0700 permissions
and belonged to other system users. I could only read and write to a
block device. Viewing the files or directories was possible only when
appropriate UID / GID were set to a specified user (invented my own
wheel- ss alternative, which sets SELinux context and user / group.
This helped me to understand internals).
MostIJ/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20te%.20-abbIM%20N0Ie%20g008. him 4/27ariigate
Hacking Android phona, How deep the rabbit hole goes.
Then I made the dump of the entire firmware, boot and recovery:
ardl/smcb1k0. ing
foy-nama boo
orage/adeardl frock
v/bl:
x/platfos 1/by-nane/x:
You can examine the full dump using utilities such as ixeartx and
sooackbooting . The ipartx -a nnbblk0.ing command creates a
virtual block device which is available by /dev/mappe=/200p0_ path.
You can work with your dump like with a regular block device. Dumps
of the boot and recovery partitions can be unpacked using the
enpackboot
I
Then | tried to zero the recovery, just to check whether write
operations work, and then immediately restored recovery from the
dump.
If I could write into block devices, then I could also write the custom
recovery. I found the TWRP of Brigadier, flashed it into recovery
partition and restarted the phone: ad» rebo: -Ididn't see
anything related to TWRP, only Android icon with an exclamation
mark. It looked like a standard Android recovery, not like TWRP.
I rebooted my phone into normal mode, ran the exploit and checked
the hash of the recovery partiton—hash matched the original. I tried
to write the data again—hash changed! Then I remembered about the
Linux page cache and flushed it ( echo 3 >
es ) ~ hash value matched the original again.
Thus everything I wrote to a block device was “redirecte
éev/nstt without any error and sometimes settled in the Linux
cache. But how does the firmware update work? And how is the user
data stored into the internal memory? I had to dig further.
/proe/sys/vn/ dcop ot
into
Trying to disable SELinux
At that time | thought that all the restrictions were caused by the lack
of SELinux privileges (I totally forgot about the dropped capabilities).
Tcould not view dmesg, logcat didn’t show anything relevant. I started
to think how to disable SELinux.
The first clue I could find:
MosII/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phone.%20How%20deep%20te%.20-abbIM%420NoIe%20g008. him 5/27ariigate
Hacking Android phona, How deep the rabbit hole goes.
load_policy boot_initranfe/inst,
fon property: selinux.reload policy = 1
rostart ueventd
restart installa
Source code says that when you change this option, init rereads and
reloads the SELinux policy from the /sepoticy file
Since I'm using dirtycow I can overwrite the /serciicy and execute
the seterop selinux.seload policy 1 command to reload the
updated policy.
First of all you have to figure out what is inside the /sepoticy file.
You can read its rules using the sesearch_ command ( setools
package in Debian)
5 sosearch --allow sepolicy
§ sesearch --neverallow sepolicy
5 sesearch --auditaliow sepolicy
§ sosearch ~-dontaydit sepolicy
In my case the /sepoticy_ file contained only allow rules which
‘means - when SELinux is in Enforcement mode applications are
allowed to do only what is granted in the policy. And thus init process
is allowed to reload the policy, but it is not allowed to change the
enforcement mode
allow init kernel: security load policy:
My goal was to allow init context to set the enforcement mode into
permissive (setenforce 0).
The first step I did: built a standard policy from the stock Android
KitKat, replaced the original /scpo1icy , loaded (being root: set»rop
setinwe. reload policy 1 ) and received a message in the status bar
that the phone was in the unprotected mode (more details about this
notification later). After that the phone refused to run applications,
became very thoughtful, besides I was still unable to set the
MosIi:/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20te%.20-abbIM%420h0Ie%20g00s. him 6/27ariigate Hacking Android phona, How deep the rabbit hole goes.
permissive mode and thus the phone eventually rebooted. A negative
result is also a result,the /sopoiicy replacement worked.
My first thought: the stock policy does not fit this phone and it starts,
glitching due to lack of permissions.
Then I decided to rebuild the original policy and add as much
privileges to the shell context as possible.
1 found an article which explained how to “reverse engineer” the
policy. I was able to resolve all the dependencies and run the se:
utility. As a result I received a text file which I was able to compile
back into the binary format ( chec
policy.cont for KitKat) and even got the file with exactly the same
ley -M -c 26 -0 sepoliey.new
size as the original sepoticy , but different hex content. Loading of
the new policy file caused exactly the same results as before - the
phone rebooted after a couple of minutes.
1 decided to compile two policies from the following files: original
decompiled cy.cont with all the privileges
inside the a1iow init kernel: security , including setenforce. The
comparison of these files could tell me which bytes I have to replace
in the original sepo\ icy binary file.
icy-conf and po
Tt turned out that only two bytes were changed. I tried to find the
match in the original sepolicy but I could not. Then I just wrote a
brute force script which replaces two bytes to “oxFF, oxFF’, launches
ep "desired result" and if it doesn't meet the
result, tries to replace the bytes on the next incremented offset and so
on, After a couple of minutes the script found the necessary offset in.
the original policy. I replaced the bytes, spoofed the original policy on
the phone. At this time it worked fine and didn't reboot. But I still
could not disable the SELinux enforcement mode.
Abit later I found a sepolicy-inject utility which could modify binary
juicy file, It could add the new permissive SELinux context or
add capability into the existing rule, While adding the permissive
context increases the ego icy file, modification of the existing rule
does not increase the size. Unfortunately, the utility adds only one
permission per run. I had to write another script which granted all the
capabilities to each rule. The new policy file size matched the original
one. But again, the policy reload did not help.
Then I noticed that Android had. 10.
reloaded the policy from any path:
oticy command which
MostI/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phone.%20How%20deep%20te%.20-abbIM%420N0Ie%20g008. him 7/27ariigate Hacking Android phona, How deep the rabbit hole goes.
# since / cwned by § in my
arriinit:s0 load policy /data/local/tmp/sepolicy.new
cal /enp/evn
You can add any permissive domain, load the new policy and work in
the context of this domain (by the way, supersu from chainfire works
in the same manner for new Android versions). But even this didn’t
give me the possibility to disable SELinux. I decided to dig in another
direction,
Investigating recovery
I started from checking the difference between boot and recovery
partitions. They were identical except for initramfs. The initramfs of
the recovery partition has in:
re which has only one service which
executes
-ecovery . Investigation of the
ngs shin)
wery
| tess output and reading of the original recovery source code gave
the following results:
MosIi:/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon9.%20How%20deep%20tne%.20-abbIM%420n0Ie%20g00s. him 8/27ariigate
Hacking Android phona, How deep the rabbit hole goes.
+ the default recovery simply displays the Android logo and then
reboots after timeout
+ if you want to “enter” the recovery, you have to create the
‘cache/recovery/cosnand file with corresponding command
inside, i.e. —-shov_toxt_ which will show the recovery menu.
Iwrote the file and executed the act» rb:
The phone rebooted and I was able to see the standard recovery
‘menu. At least some result, | tried to flash the supersu ZIP file via 2a»
sidelosd . The operation terminated with an error. I did not really
look at this error and started to investigate the recovery code
responsible for the ZIP digital signature verification.
scevery command,
It turns out that the recovery initramfs contains a
key in minierypt format which checks the ZIP file digital signature
The public key appeared to be a standard Android fest key and so I
can sign any ZIP file using this key. You can check this key using the
commands below:
keys public
§ Gift -u mykey res/xeys.
1 tried to install the ZIP directly from sdcard, but the recovery caused
an error while mounting the sdcard. Investigation of the
ete/recovery.fetab file showed the actual problem: the sdcard in the
recovery mode was mounted as vfat:
§ grep mmeblk1 recovery/ramfs/ete/recovery. fstab
/aev/black/nnels1kIpL/s
My 64Gb sdcard was formatted in exFAT. I found an old 2Gb sdcard,
reformatted it as vfat, wrote the ZIP and inserted it into the phone.
This time the recovery was able to mount the volume and T could
view its contents on the phone, However, the ZIP installation caused
an error again: E: failed to set up expected mounts for install;
aborting.
MosIi:/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phone.%420How%20deep%20te%.20-abbIM%420N0Ie%20g00s. him 9127ariigate
Hacking Android phona, How deep the rabbit hole goes.
The strings re
hhad custom Kyocera strings, at least there were strings related to the
eata partition wipe command. After reading the original source
code I found that the error was caused in the s2:up
function of the :octs.cep file, For some reason the recovery failed to
‘unmount all the partitions listed in
‘command showed that this recovery
Investigating kernel sources
Unlike the AOSP’s Apache license, the GPLv2 license requires from
smartphones’ manufacturers to publish the Linux kernel source.
Thanks to Linus and Stallman for this opportunity. Sometimes
‘manufacturers publish a fake source code, sometimes a correct one,
but without the defcontis file, sometimes with defconfig and very
rarely with the instructions on how to build the source code (e.g. LG)
In my case the source code was distributed with the correct
but without instructions. Thus I spent some time to build
the kernel.
After a long time of the source code investigation I stopped at two
files:
+ hetps://github.com/kayrus/ke-s7o1-torque-
kernel/blob/master/security/selinux/hooks.c
+ hutps://github.com/kayrus/ke-s7o1-torque-
kernel/blob/master/arch/arm/mach-msm/restart.¢
hooks
To increase the phone's security Kyocera just implemented custom
SELinux hooks on potentially dangerous operations:
insnoa_ (the only module allowed to be loaded is wisn and only if it
is loaded by init process or non-root user) and some others. That's the
actual reason why the recovery failed. It could not unmount the
/systen partition! The mount/unmount operations of the /syscen
partition are allowed only for the init process. In particular, I could
not disable SELinux because this feature was disabled at the kernel
compilation. These hooks could be bypassed only if the kernel was
loaded with certain boot parameters (kedroidboot. mode=f-ksg or
androidboot.mode=kefactory).
MostIJ/CRACKINGIREVERSEY.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20te%.20-abbIM%420NoIe%20g00s. him 10127ariigate Hacking Android phona, How deep the rabbit hole goes.
restart
This file describes possible reboot options for the phone:
+ adb reboot bootloader—fastboot mode, not available in my
phone ( ox77668500 - oosse6e77 hex mark in sbi1_ partition)
+ adb reboot recovery—default Android recovery mode
- 02556677 hex mark in spi1_ partition)
( ox776655:
+ adb reboot rtc—the so-called suas soor . I did not understand
‘what this was for, there was no hex mark in Probably it
relates to
hutps://developer.android.com/reference/android/app/AlarmMa
pager: html
+ adb reboot oem-X (in my case oem, ox6=6
hex mark in se1 partition). The manufacturer defines what
happens in this mode. According to the sources, the phone
restarts into this mode in case of failed firmware files’ verification
which are located in soden partition.
+ o1eassee
+ adb reboot edl—emergency download, reboots into a default
Qualcomm download mode, The phone is identified as
QHSUSB_BULK COM port, which can be used to boot a custom
bootloader (but it should be signed by the private key
corresponding to the phone model ), and perform low-level
operations with your phone, including flashing, unlocking, ete.
Usually used in conjunction with QPST application. For some
phones these bootloaders have already leaked into the Internet.
+ Acertain download mode which could be triggered by kernel
boot parameter. Looks quite interesting,
Some info on how Qualcomm based phones are booted:
Built-in ROM Qualcomm bootloader (pbl—primary bootloader)
verifies and boots sb11 partition (secondary bootloader). sb11
verifies and boots 2 (trust zone), then ascot (Android boot, little
kernel, 1k), Then aboot can boot into built-in fastboot maintenance
mode, do the normal boot or boot into recovery or fota.
Partition description involved at boot:
+ tz—Qualcomm Trust Zone. It performs low-level operations,
including working with QFuses (rpmb secured mme partition)
MosIi:/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon9.%20How%20deep%20the%.20-abbIM%420noIe%20g00s. him 11/27ariigate
Hacking Android phona, How deep the rabbit hole goes.
+ tpm—Resource and Power Manager firmware. Firmware for
specialized SoC, responsible for resources and power.
+ sdi—trust zone storage partition. The data which is used by
‘Trust Zone.
All of these partitions are signed by a certificate chain.
fota
In some cases it is useful to ignore firmware updates.
FOTA—firmware over the air. Unlike the boot or recovery, fota is an
unofficial Android boot mode, Fota task is to update the firmware.
Kyocera uses Red Bend proprietary solution which fits the whole
update in 35Mb, It includes boot , 2, recovery
systen partitions’ updated. That is why the /sys:en partition is
available in read-only mode. If you modify this partition, the diff-
based fota update can brick the phone.
and even,
‘An update for my phone was available since September 2015. I didn't
update my phone because I was afraid to loose an opportunity to root
my phone. Now I can easily execute the update process since I have
full access to cache partition and abort the update procedure at any
time.
After examining the source code of the responsible Java based update
tool, it became clear to me how it functioned:
+ Java app downloads a special delta file into
delta.bin , creates a /cache/delta/Alt-
ot dicompiete file and verifies whether delta file was
successfully downloaded.
+ When you confirm the update procedure it verifies the file again.
+ If previous verification succeeds then fotanag_ partition is
modified using the iibjaiaito:a.so dynamic library.
+ Phone reboots.
The reboot does not happen instantly, so I can delete a file before the
reboot and see what will happen with the forsnng partition.
I wrote the script which continuously made fotamng partition dump
and renamed /cache/de1ta/boot_deita.bin file, Iran it immediately
MostI/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20tne%.20-abbIM%420NoIe%20g00s. him 12/27ariigate
Hacking Android phona, How deep the rabbit hole goes.
after the update confirmation. The phone rebooted into FOTA mode,
showed an error and rebooted into normal boot mode.
I started to investigate the dumped data. The /cache partition also
contained a bonus: fota and dmseg logs! It appeared that fota boot
could be initialized by couple of bytes set to
1" in sovanng partition:
‘ey-nane/fotanng seok-16
1 count=1
4 if=/data/local/enp/one,
0£=/dev/block/pLa
-nane/fotanng seek:
ta/local/=np/ot
seek=191096
These bytes are cleared after the reboot. I also noticed the
kedroidboot mode=f-ksg kernel parameter in fota dmesg logs. Here
it is! Thus, bootloader removes the phone protection for fota boot and
theoretically if I write a regular boot partiton instead of fota and
reboot the phone into this mode, I will get the kernel with disabled
Kyocera protection. But I still don’t have a write access to the system-
related partitions.
Investigating the little kernel (Ik) sources
Little kernel or Android bootloader is located inside the aboot
partition. Vanilla source code is available at:
hitps://source.codeaurora.org/quic/la/kernel/Ik/
There you can find information on how to boot into some of the
modes. For example, if you write the boot-recovery into the nisc
partition, the next boot will be the recovery mode and there is no
need to execute adb reboot recovery. When you boot into the
recovery using this method the boot-recovery label If
the recovery can not be booted, the phone will get the boot loop and
you'll lose it. So be careful and preferably avoid this option to reboot.
be reset
You can also find the code which enables read-only protection of the
the system-related emme area. This is an answer to the question why.
itis impossible to rewrite the recovery partition. This protection can
MostIJ/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phone.%20How%20deep%20tne%.20-abbIM%420NoIe%20g008. him 13/27ariigate
fle:INICRACKINGIREVERSEX.20ENGINEERING/Hacking!20Andeoid%20phone.%20How'%20deep%20theth
Hacking Android phona, How deep the rabbit hole goes.
be disabled in the Linux kernel. And such a module was already
written by another guy who was interested in Kyocera phones. This,
module works from time to time and sometimes hangs on mme claim
function. Ideally it requires the detailed investigation.
Here is how aboot verifies boot partitions:
hitps://source.codeaurora.org/quic/la/kernel/Ik/tree/platform/msm
eshared/image_verify.c7h=LA.BR.1.3.3.1b2.29
The first successes
Google helped me to answer the question why I could not read the
kernel log: /proc/sys/kernel/dmesq restrict . The value of this
parameter is set to 1 while the phone boots. If the user does not have
CAP_SYS_ADMIN capability, the logs are not available for it.
uevent_helper
In my case, surprisingly, I had the possibility to write into
eiper . If you write the path to some executable,
it will be executed under root user, init SELinux context and most
importantly with full capabilities (shell script also works)
/sys/kernel /uevent,
I wrote the following script:
#1 /systen/bin/
no 0 > /proc/sys/kernel/dnesg_rest
Uploaded it on the phone, wrote its path into
eiper and I got the possibility to read dmesg
logst
Patched adbd
rabbi%20nole%20goes. html 14/27ariigate
Hacking Android phona, How deep the rabbit hole goes.
Since I could not easily investigate the phone's internals because of
the capabilities restriction I decided to build my own adbd with
blackjack and hookers, To do this I had to download 70 Gb of Android
source code (I didn’t want to mess with each dependency
individually). I removed the check which drops the capabilities,
compiled adbd, replaced the /sbin/ade and received a full root
console. Now I can mount filesystems, read dmesg logs without
messing with dmesg_restrict, easily view or edit files which are not
owned by root, and much more. But I stil can not mount the
/sysven partition and load modules into the kernel.
By the way, this procedure can be avoided by compiling the Ish and
writing its path into the /sys/kerne
starting Ish wrapped in a script which sets the rar environment,
otherwise you'll have to specify the full path to each command.
avent_helper . I suggest
WiFi
‘WiFi in my phone works through the kernel module. When WiFi is
turned on—the module is loaded, When WiFi is turned off—the
module is unloaded. If you replace the module file with your own and
turn on WiFi—your spoofed module must be loaded. Fortunately, my
phone doesn’t check modules’ digital signatures. The first thing I tried
‘was to compile and load the module which disabled the SELinux by
replacing the kernel memory. The module was initially written for
Amazon Fire Phone:
https://github.com/chaosmaster/ford_selinux permissive
You need to have a more or less appropriate kernel sources and
Module. symvezs file in order to compile the module. If the source
code explicitly corresponds to the kernel which is used in the phone,
then you can use the woduie.
generated during the kernel compilation process
vere which is automatically
If the kernel module complains on disagrees about version of
symbol module layout, you will need to extract the Modis, symrers
from the boot partition. This could be done using
hitps://github.com/glandium/extract-symvers script:
jot img -0 boot
MosIiJ/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20te%.20-abbIM%420h0Ie%20g00s. him 18/27ariigate Hacking Android phona, How deep the rabbit hole goes.
ONE DOES NOT'SIMPLY,
CES Ca aC
Eerie
Do you remember this list? The module should be called wian . Here
is how I resolved this problem:
+ Created a wise.c symlink
+ Modified Makefile
MODULE_NAME = wlan
After applying these tricks and executing the svc wifi disable 6s
ave wifi enable the module has successfully loaded (memory used
bythe wan module reduced, it could be checked using 1ssoa
command), but SELinux was not disabled
The dmesg logs did not contain any information related to the new
module. It was caused by another kernel option:
/proc/sys/kernel/printk Which filters INFO logs including modules’
logs. I lowered the threshold for all logs: echo '8 8 8 8 >
/pz0c/sye/kernet /prinzk , reloaded the module and it appeared that
the module just could not find the required bytes pattern. I decided to
write own kernel module
Writing a module
Disabling security protection
Mosti:/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phone.%20How%20deep%20te%.20-abbIM%420h0Ie%20g00s. him 16/27ariigate
Hacking Android phona, How deep the rabbit hole goes.
| failed to disable SELinux, but by analogy with
https://github.com/chaosmaster/ford_selinux_permissive module I
could try to disable Kyocera hooks. I just needed to set a
ke_bootmode or ke_kbfm variable using the Linux kernel module.
The Linux kernel has the possibility to get the pointers’ addresses of
all the functions and variables: cat. /eroc/ka1 syns . By default, these
addresses are displayed as 0. It is yet another kernel protection and
can be disabled by the following command: echo 0 >
Once you get the address of the desired function, you can call it with
the appropriate parameter and function will set the corresponding
variable to 1, I noticed that not all Linux kernels display addresses for
the variables (d or D types, case says whether the variable is public or
not) that is why I used function pointers, but not actual variable
pointers. Perhaps it is determined by the coxrrc katzews ann option
during the kernel compilation.
First of all I had to declare the kernel function I'd like to call in the
module:
nt (* _ke_pootmode_setup) (char * buf) = (int (*) (0)
ogi 9884;
‘And then call it:
jotmeda_setup ("ikea")
You can also determine the addresses dynamically:
ke beotmode_setup = (Int (*} (char * buf))
kallsyns lookup name (
bo’
MostIJ/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20tne%.20-abbIM%20H0Ie%20g00s. him 17/27ariigate Hacking Android phona, How deep the rabbit hole goes.
Tloaded the module and it disabled the protection! Now I can mount
the /systen and load any kernel module regardless of its name.
Protected eMMC area is still in read-only mode and it does not allow
you to modify /systen partition on a regular basis. The files can be
edited, but when you clean the kernel cache everything goes to its
original state.
Finally disabling SELinux
Iwas already not required but just for fun, I decided to finally disable
the SELinux. I could not modify the defined setinux enabled
constant, but I could dereference the
hooks pointers,
12 structure with
This can be done by calling the reset_security ops function:
void (* _reset_security_ops) (void) = NULE:
peeea tet eerient eon Meets)
kallsyms_lookup_name(
£ (zeset_secarity ops! = NULL) {
reeot_ security ope 0)
inux hooks and functions, but the system still
thinks that SELinux is enabled since se1inux enabled contains 1
integer value. Thus there may be some issues related to SELinux
functions, ie. incorrect 1s -z output.
Reboot into download mode
bie dead mode) (char * ate) = (at (+) (0)
The same operation works with downtoad mode Twrote above. After
the module loading the phone reboot will boot it in a special mode
which operates as USB mass storage device. Thus I have full access to
all the phone's partitions! I tried to overwrite the recovery partition
and it worked even after clearing the kernel cache
Mosti:/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phone.%20How%20deep%20te%-20-abbIM%420h0Ie%20g00s. him 18/27ariigate
fleINICRACKINGIREVERSE%.20ENGINEERING/acking!20Andeoid%20phone.%20How%20deep%20the%20-abbit%20hole%20goes. him!
Hacking Android phona, How deep the rabbit hole goes.
Actually regular aa doesn’t work and phone's USB mass storage
device disconnects and the writing stops. Perhaps this is a result of an
internal cache overflow of the mass storage loader. I had to write a
workaround, An advanced script for the heavy systen partition is
available here:
httws://github,com/kayrus/ke s701 break free/blob/master/inject_s
upersu/write_rooted_system.sh. The primary trick is to read the data
which you'd like to overwrite, Reading is much faster than writing, so
I compare the source and destination hashes and if they differ I write
new data. This saves lot of time and 1.2Gb modified partition can be
flashed in 2-3 minutes instead of 35 minutes.
Using this method | installed the supersu binaries into the
downloaded /systen partition and flashed it back into the phone.
The phone booted, but I got the following message in the notification
bar: row security level. Inappropriate application may have been
se uninstall it and reboot the phone. . [had already
seen this message before when I loaded insecure SELinux policy. This
notification also causes the permanent red LED blinking and the
phone doesn’t turn off the screen on timeout (I guess to pay the user's
attention that the phone was hacked). I spent some time and figured
out that this notification was triggered by /systen/ve;
daemon. It is a small daemon which monitors su / sudo binaries
which can be found within rxrs , monitors SELinux state and
en partition is mounted in read-write mode. It writes
the security states into the /daca/sy
jor /bin/akecd
whether /sys
r/aksed/out_4s.dat_ and
triggers the notification mentioned above. I just disabled this service,
but there should be a better fix to disable ss / sudo detection only
and allow to monitor the /systen_ state since I still would like to
control my phone's security.
The initial task is completed: permanent root access and possibility to
write into the external sdcard were obtained. In addition I wrote a
utility which sets systen UID with the car_sys_soouse capability,
uloads original wisn module then loads my false wian module
which disables the security and finally loads the original via
module again.
My next goal was to boot custom kernel. I hoped there was no digital
signature verification and I decided to boot my custom boot partition.
Since it is dangerous to flash regular boot partition, I decided to flash
it into the recovery partition and reboot into the recovery using adb
reboot recovery command, Remember the aise partition, it is
not recommended to boot into recovery through the boot
912ariigate Hacking Android phona, How deep the rabbit hole goes.
recovery entry in this partition, it can cause a boot loop.
Unfortunately, the phone could not boot into recovery, it just vibrated
and then rebooted into normal mode.
Looks like I have to unlock the phone's bootloader. There is not much
info on how to do this, but I found a couple of methods which worked
for old phones:
+ hetps://github.com/beaups/SamsungCID.
+ hups://github.comy dirbliss/loki
+ hetps://bits-please.blogspot.com/2016/02/unlocking-motorola-
bootloader.html
Digital signatures of the aboot and boot
Iwas curious how exactly aboot verifies the boot partitions. So I
unpacked all the certificates from aboot partition ( inwatk ~«
shoot ), extracted images signatures and looped over all the public
keys trying to decrypt the signature. It turned out that all the boot
images were signed using the same key.
npackbootimg -i 09-boot.ing -0 boot
# binwalk -¢ 05-aboot. img
# openssl reautl ~raw -inkey <(openssl x509 —pubkey -noout ~
inform dex -in _0S-sboot.ing.excracted/46D2
2>/dev/nuil) ~pubin ~in signature.in 2>/dev/null | hd
# print cert in text mode: openssl x509 inform der ~in
168R.crt text -noau
{NAME} /nynew. img
IMG) | awk ‘(print $1)"
MostI/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon9.%20How%20deep%20te%.20-abbIM%420h0Ie%20g00s. him 20027ariigate Hacking Android phona, How deep the rabbit hole goes.
syonz¢_suna 2 then
This script prints the following output:
sha256 was decrypted using
aboot.ing.extracted/31464.crt key ~
0a? 56
si642 1994739403162¢7960
ove
Verification of the aboot partition appeared to be more complicated. I
‘was able to extract and decrypt the sha2s6 signature of the image. But
could not calculate this hash myself, Fortunately, Nikolay Elenkov, the
author of the Android security internals helped and forwarded me to
Qualcomm whitepaper:
https://www.qualcomm.com/media/documents/files/secure-boot-
and-image-authentication-technical-overview.pdf, It explains how
target sha2s6 is calculated. The hash depends on im ro and sw 10
which are defined inside the certificate's subject, i.e.
Subject: C=US, ST=CA, L=San Diego, OU=07 0001 SHA256, OU=06
001 MODEL_ID, OU=0s 00002000 SW_SIZE, OU=04 0039
OEM_ID, OU=03 0000000000000002 DEBUG, OU=02
009180E10039001F HW_ID, OU=o01 0000000000000009 SW_ID,
(O=Kyocera wireless corp CSMS, CN=Ayano Nakamura
‘The working script is available in Nikolay’s github repository.
Experimenting with the fota partition
MostIJ/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20tne%.20-abbIM%420H0I6%20g00s. him 21/27ariigate
fleINICRACKINGIREVERSE%.20ENGINEERING/acking!20Andeoid%20phone.%20How%20deep%20the%20-abbit%20hole%20goes. him!
Hacking Android phona, How deep the rabbit hole goes.
Since I know that boot/recovery and fota partitions are signed with
the same key and the fota partition is booted with the disabled kernel
security it’s worth trying to check whether flashing the boot partition
into the fota partition can work,
Itwas quite risky and I could get bootloop similar to recovery
bootloop. The boot-in-fota sign is written into the rotaneg partition
and if aboot did not boot the fota, it could try to boot it in the endless
loop.
Unfortunately, the boot partition written in fota could not be loaded,
but fortunately LK resets fota bytes on boot and I did not face the
bootloop. It is not clear why it doesn’t work, perhaps because of the
different ramdisk and tag offsets (most probably they are hardcoded
inside the LK)
boot / recovery:
tag:
fota:
tags: 0x0260000:
Experimenting with the Brigadier
bootloader
For the experiments I ordered a Kyocera Brigadier with a broken
screen.
I checked the digital signatures of KC-S701 and Brigadier aboot
partitions and it appeared that they were signed by the certificates
with the same subject, so aboot partitions should be interchangeable.
I decided to make an experiment: flash aboot from KC-S701 into the
Brigadier. The bootloader successfully booted. Surprisingly, the eMMC
write protection was not activated and I could easily restore the
original bootloader (I suppose read-only flag can be set by QFuses)
22aariigate
Hacking Android phona, How deep the rabbit hole goes.
‘Then I tried to flash the aboot from Brigadier into the KC-S7o1. I could
get the opportunity to use fastboot and boot any unsigned kernel. At
this time the phone didn’t boot.
At this point the story could end with the “phone didn’t boot” and a
black screen. But, fortunately, this black screen was the “download
mode”. I was able to flash the original aboot partition and the phone
was resurrected. I still wonder why it didn't boot. Both certificate
chains are valid and theoretically should be interchangeable. Most
probably I faced this issue because Brigadier is based on msm8928
and KC-$701 is based on msms226 SoC. They are both from one So
family but have some minor differences (msm8928 supports USB-
ors).
What should still be clarified
Why sepolicy recompilation doesn’t work? Imperfect sepolicy
decompiler?
What does aboot partition hide?
What hides behind the osm-1 reboot mode? Aboot partition contains
the fastboot code, atleast: fash, erase, oem deviceint
pteflash , oon snable-charger-sereen and oem disable-charger-
screen commands. How can I enter the fastboot mode?
How to disable camera shutter sound?
ve found at least 3 options which somehow control camera shutter
sound but none of these options works. The only way to disable it is to
replace the /systen/ned‘a/audio/us/canera_click.oug file. But | don't
like this solution and still want to find the way to disable this option
in a more elegant way. Most probably it is controlled by proprietary
Kyocera properties.
Explanation Kyocera properties
Kyocera along with Android system properties uses its own internal
properties, I'm pretty sure there can be some tricky options which can
influence the removal of bootloader protection or camera shutter
sound which can not be disabled (oh man, 1 just realized how many
restrictions are there in KC-S701). The phone has a libkejprop_jni.so
dynamic library and the kejprop_daemon daemon. I can write an
MostIJ/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20tne%.20-abbIM%420h0Ie%20g008. him 23/27ariigate Hacking Android phona, How deep the rabbit hole goes.
app which will use this library, but comparing to other TODOs this
task has low priority.
Options are written into the filesystem and look like binary data:
§ 1s 1a /syaprop/k
Kexec
Kexec allows the Linux kernel to load another kernel. By default, the
production kernel releases don't support Kexee, but it is possible to
enable it using the kernel module. Then, using the user-end utility
you can load any custom kernel which will replace the current one. It
looks like a hack, but if you want to load your custom kernel and
bypass digital signature verification—this is an option.
QSEE vulnerability
QSEE—Qualcomm TrustZone protection which could have a
vulnerability to execute custom code within the TrustZone context:
https://bits-please_blogspot.com/2016/o5/ qsee privilege-escalatior
vulnerability.html. Looks like I have to build a specially formatted
SCM command to burn the corresponding QFuse and unlock the
bootloader. Still to be done
Conclusion
MostIJ/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phon0.%20How%20deep%20te%.20-abbIM%420NoIe%20g00s. him 24/27ariigate Hacking Android phona, How deep the rabbit hole goes.
Every problem I resolve causes an amount of new problems and it is
hard to predict how deep the rabbit hole goes.
Modules’ source code, aboot loaders and the library to work with the
Kyocera Properties are available in my github repo:
httws://github,com/kayrus/ke s7o1 break free
T would like to express my gratitude to the Kyocera developers for the
excellent devices and high security. Otherwise, this article would not
have been written, On the other hand, the lack of regular updates
makes me really upset. If Kyocera has a new phone model with the
ability to unlock the bootloader, 1 will certainly buy it.
1 still haven’t given up to unlock the bootloader. The most profitable
time was on Christmas, but now it is hard for me to find some free
time and focus on this problem.
PS, Many thanks to Nikolay Elenkov. He explained to me how
Android boot chain works and helped me with the aboot digital
signature verification,
MostI/CRACKINGIREVERSEY.20ENGINEERING/acking%<20Android%20phone.%20How%20deep%20te%.20-abbIM%20hoIe%20g00s. him 25/27ariigate Hacking Android phona, How deep the rabbit hole goes.
Mosti:/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phone.%20How%20deep%20the%.20-abbIM%420hoIe%20g00s. him 26/27ariigate Hacking Android phona, How deep the rabbit hole goes.
MostIJ/CRACKINGIREVERSE%.20ENGINEERING/acking%<20Android%20phone.%20How%20deep%20tne%.20-abbIM%420N0Ie%20g00s. him 27/27