import
os
import
random
import
subprocess
import
sys
import
time
import
requests
import
uuid
from
hashlib
import
*
import
zipfile
import
signal
import
string
isMacos
=
len
(sys.argv)
=
=
2
wordlist
=
string.ascii_letters
difficulty
=
4
random_hex
=
lambda
x: ''.join([random.choice(wordlist)
for
_
in
range
(x)])
ADB_PORT
=
int
(random.random()
*
60000
+
5000
)
EMULATOR_PORT
=
36666
if
isMacos
else
(ADB_PORT
+
1
)
EXPLOIT_TIME_SECS
=
30
APK_FILE
=
os.path.join(os.path.dirname(os.path.abspath(__file__)),
"app-debug.apk"
)
FLAG_FILE
=
os.path.join(os.path.dirname(os.path.abspath(__file__)),
"flag"
)
HOME
=
"/home/user"
VULER
=
"com.bytectf.silverdroid"
ENV
=
{}
ENV.update(os.environ)
if
not
isMacos:
ENV.update({
"ANDROID_ADB_SERVER_PORT"
:
"{}"
.
format
(ADB_PORT),
"ANDROID_SERIAL"
:
"emulator-{}"
.
format
(EMULATOR_PORT),
"ANDROID_SDK_ROOT"
:
"/opt/android/sdk"
,
"ANDROID_SDK_HOME"
: HOME,
"ANDROID_PREFS_ROOT"
: HOME,
"ANDROID_EMULATOR_HOME"
: HOME
+
"/.android"
,
"ANDROID_AVD_HOME"
: HOME
+
"/.android/avd"
,
"JAVA_HOME"
:
"/usr/lib/jvm/java-11-openjdk-amd64"
,
"PATH"
:
"/opt/android/sdk/cmdline-tools/latest/bin:/opt/android/sdk/emulator:/opt/android/sdk/platform-tools:/bin:/usr/bin:"
+
os.environ.get(
"PATH"
, "")
})
def
print_to_user(message):
print
(message)
sys.stdout.flush()
def
download_file(url):
try
:
download_dir
=
"download"
if
not
os.path.isdir(download_dir):
os.mkdir(download_dir)
tmp_file
=
os.path.join(download_dir, time.strftime(
"%m-%d-%H:%M:%S"
, time.localtime())
+
str
(uuid.uuid4())
+
'.apk'
)
f
=
requests.get(url)
if
len
(f.content) >
10
*
1024
*
1024
:
return
None
with
open
(tmp_file,
'wb'
) as fp:
fp.write(f.content)
return
tmp_file
except
:
return
None
def
proof_of_work():
print_to_user(f
"First, to ensure that the service will not be dos, please answer me a question."
)
prefix
=
random_hex(
6
)
suffix
=
random_hex(difficulty)
targetHash
=
sha256((prefix
+
suffix).encode()).hexdigest()
print_to_user(f
'Question: sha256(("{prefix}"+"{"x"*difficulty}").encode()).hexdigest() == "{targetHash}"'
)
print_to_user(f
'Please enter the {"x"*difficulty} to satisfy the above equation:'
)
proof
=
sys.stdin.readline().strip()
return
sha256((prefix
+
proof).encode()).hexdigest()
=
=
targetHash
def
check_apk(path):
try
:
z
=
zipfile.ZipFile(path)
for
f
in
z.filelist:
if
f.filename
=
=
"AndroidManifest.xml"
:
return
True
return
False
except
:
return
False
def
setup_emulator():
subprocess.call(
"avdmanager"
+
" create avd"
+
" --name 'pixel_xl_api_30'"
+
" --abi 'google_apis/x86_64'"
+
" --package 'system-images;android-30;google_apis;x86_64'"
+
" --device pixel_xl"
+
" --force"
+
("
" if isMacos else "
>
/
dev
/
null
2
>
/
dev
/
null"),
env
=
ENV,
close_fds
=
True
,
shell
=
True
)
return
subprocess.Popen(
"emulator"
+
" -avd pixel_xl_api_30"
+
" -no-cache"
+
" -no-snapstorage"
+
" -no-snapshot-save"
+
" -no-snapshot-load"
+
" -no-audio"
+
" -no-window"
+
" -no-snapshot"
+
" -no-boot-anim"
+
" -wipe-data"
+
" -accel on"
+
" -netdelay none"
+
" -no-sim"
+
" -netspeed full"
+
" -delay-adb"
+
" -port {}"
.
format
(EMULATOR_PORT)
+
("
" if isMacos else "
>
/
dev
/
null
2
>
/
dev
/
null ")
+
"",
env
=
ENV,
close_fds
=
True
,
shell
=
True
,
preexec_fn
=
os.setsid)
def
adb(args, capture_output
=
True
):
return
subprocess.run(
[
'adb'
]
+
([
'-s'
,
'emulator-36666'
]
+
args
if
isMacos
else
args),
env
=
ENV,
close_fds
=
True
,
capture_output
=
capture_output).stdout
def
adb_install(apk):
adb([
"install"
,
"-t"
, apk])
def
adb_activity(activity, extras
=
None
, wait
=
False
, data
=
None
):
args
=
[
"shell"
,
"am"
,
"start"
]
if
wait:
args
+
=
[
"-W"
]
args
+
=
[
"-n"
, activity]
if
extras:
for
key
in
extras:
args
+
=
[
"-e"
, key, extras[key]]
if
data:
args
+
=
[
"-d"
, data]
adb(args)
def
adb_broadcast(action, receiver, extras
=
None
):
args
=
[
"shell"
,
"su"
,
"root"
,
"am"
,
"broadcast"
,
"-W"
,
"-a"
, action,
"-n"
, receiver]
if
extras:
for
key
in
extras:
args
+
=
[
"-e"
, key, extras[key]]
adb(args)
print_to_user(r
)
if
not
isMacos:
if
not
proof_of_work():
print_to_user(
"Please proof of work again, exit...\n"
)
exit(
-
1
)
print_to_user(
"Please enter your poc url:"
)
url
=
sys.stdin.readline().strip()
if
url.strip(
'"'
)
=
=
url:
url
=
f
'"{url}"'
if
not
url.startswith(
'"https://'
):
print_to_user(
"Invalid poc url.\n"
)
exit(
-
1
)
print_to_user(
"Preparing android emulator. This may takes about 2 minutes...\n"
)
emulator
=
setup_emulator()
adb([
"wait-for-device"
])
adb_install(APK_FILE)
with
open
(FLAG_FILE,
"r"
) as f:
adb_broadcast(f
"com.wuhengctf.SET_FLAG"
, f
"{VULER}/.FlagReceiver"
, extras
=
{
"flag"
: f.read()})
adb_activity(f
"{VULER}/.MainActivity"
, wait
=
True
, data
=
url)
print_to_user(
"Launching! Let your apk fly for a while...\n"
)
if
isMacos:
input
(
'wait for debug'
)
else
:
time.sleep(EXPLOIT_TIME_SECS)
print_to_user(
"exiting......"
)
try
:
os.killpg(os.getpgid(emulator.pid), signal.SIGTERM)
os.killpg(os.getpgid(os.getpid()), signal.SIGTERM)
except
:
pass