Closed felfert closed 3 years ago
BTW:
The whole thing should backwards-compatible, because in case that feature is not available, adb root
just prints an error and does nothing. Therefore, the second uid/gid-check turns false and the require_su flag is left unchanged (True).
Interesting, I was not aware of this change. I have usually been running LineageOS with Magisk, which does provide a su
binary, but I have yet to try out the native LineageOS rooting functionality.
I need to test the quoting a little bit but the other changes look good to me. shlex.quote
is not very complicated:
import re
_find_unsafe = re.compile(r'[^\w@%+=:,./-]', re.ASCII).search
def quote(s):
"""Return a shell-escaped version of the string *s*."""
if not s:
return "''"
if _find_unsafe(s) is None:
return s
# use single quotes, and put single quotes into double quotes
# the string $'b is then quoted as '$'"'"'b'
return "'" + s.replace("'", "'\"'\"'") + "'"
So the q
method effectively becomes:
def q(self, s):
if not s or _find_unsafe(s) is None:
return s
return '"' + s.replace("'", "'\"'\"'") + '"'
Yeah, the q
method doesn't work too well with reading bad filenames as root using sh
:
#!/usr/bin/env python3
import pprint
import logging
import coloredlogs
from android_otp_extractor import TRACE
from android_otp_extractor.cli import LOGGER
from android_otp_extractor.adb import guess_adb_interface
LOGGER.parent.setLevel(TRACE)
coloredlogs.install(level=TRACE)
adb = guess_adb_interface('/data/data/')
f = adb.read_file('$EXTERNAL_STORAGE/Download/test file (1).txt')
pprint.pprint(f.read())
The resulting path is not quoted properly:
su -c "toybox base64 "$EXTERNAL_STORAGE/Download/test file (1).txt"; echo 3bb22bb739c29e435151cb38"
Does merely replacing the call to su -c
with sh -c
if root is detected work for your phone?
Nice idea, let me give it a try
It does. See above commit, reverting the quoting stuff and using sh -c
instead.
Great! It passes my rudimentary test (admittedly a poor substitute for proper unit testing) so this change looks good to me.
Thank you
Hi,
This PR adds support for recent LineageOS. Since a while, LineageOS has an additional switch in its debugging setting called "Root-Debugging" which allows to enable/disable the adb root command. After enabling this, one first runs
adb root
and after that, anyadb shell ...
runs as root without the need for using asu
command. In fact, by default, there is nosu
command unless one installs something called addonsu (which appears to be broken for me, BTW).The PR introduces a new flag named require_su and 2 new methods in ADBInterface:
set_require_su(boolean)
allows to set/unset the flag.enable_root()
simply runsadb root
Furthermore, it adds 3 new methods in SingleBinaryADBInterface:
adb_uid()
runsid -u
to fetch the current effective uidadb_gid()
runsid -g
to fetch the current effective gidq(string)
is a wrapper for shlex.quote(string) (explained below)Finally,
adb_uid()
andadb_gid()
are used inguess_adb_interface()
to check the effective uid/gid and if it is not 0,enable_root()
is used to attempt to switch to root access. If the uid/gid is 0,set_require_su(False)
is used, to disable the use ofsu -c
About the wrapper for shlex.quote:
shlex.quote quotes with single quotes. Therefore, shell vaiables don't get expanded (at first). When using
su -c "cmd '$VAR/arg'"'
however, a second shell-invocation is performed, effectively eliminating the quotes alltogether which then allows expanding. In order to work withoutsu -c
, the outer single quotes have to be replaced by double quotes. That is exactly, what q(string) does.Cheers -Fritz