Skip to content

Instantly share code, notes, and snippets.

@atlantis0
Last active July 13, 2021 12:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atlantis0/854a8b73fd0f958e900b9eda1a6608da to your computer and use it in GitHub Desktop.
Save atlantis0/854a8b73fd0f958e900b9eda1a6608da to your computer and use it in GitHub Desktop.
App Detonator Permission Anslysis
import os
from typing import Sized
from pyasn1.type.constraint import SingleValueConstraint
import requests
import datetime
import logging
import time
import sys
import json
import operator
import csv
ANALYZE_API_ENDPOINT = 'https://api.appdetonator.run/analyze'
REPORT_API_ENDPOINT = 'https://api.appdetonator.run/apk/{0}'
DEX_REPORT_API_ENDPOINT = 'https://api.appdetonator.run/dex/{0}'
API_KEY = 'Get it from <https://appdetonator.run/>'
BUCKET_NAME = 'banking-troj'
SERVICE_ACCOUNT_FILE = 'app-pwned1-b07ef545c7f2.json'
DANGEROUS_PERMISSIONS = ['android.permission.RECEIVE_SMS', 'android.permission.READ_SMS',
'android.permission.SEND_SMS', 'android.permission.READ_CONTACTS', 'android.permission.CALL_PHONE']
MIN_NO_APPS_PER_CLUSTER = 200
FRAMEWORK_CLASSES = ['Landroid/support/', 'Landroidx/', 'Lcom/a;', 'Landroid/a;', 'Lcom/android/a;']
logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(message)s')
file_handler = logging.FileHandler('submit9.log')
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setLevel(logging.DEBUG)
stdout_handler.setFormatter(formatter)
# log to both file & std out
logger.addHandler(file_handler)
logger.addHandler(stdout_handler)
def analyze_api(apk_url):
payload = {'key': API_KEY, 'url': apk_url}
r = requests.get(ANALYZE_API_ENDPOINT, params=payload)
if r.status_code == 200:
#response = r.json()
logger.info('Success')
return r.json()
else:
logger.error('Error')
logging.error(r.content)
def apk_analysis_api(apk_sha256_hash):
payload = {'key': API_KEY}
r = requests.get(REPORT_API_ENDPOINT.format(apk_sha256_hash), params=payload)
if r.status_code == 200:
#response = r.json()
logger.info('Success')
return r.json()
else:
logger.error('Error')
logging.error(r.content)
def get_dex_report(apk_sha256_hash):
payload = {'key': API_KEY}
r = requests.get(DEX_REPORT_API_ENDPOINT.format(apk_sha256_hash), params=payload)
if r.status_code == 200:
#response = r.json()
logger.info('Success')
return r.json()
else:
logger.error('Error')
logging.error(r.content)
def process_permissions(dir_):
# assumes APK samples are stored in
# dir_ directory
apk_samples = os.listdir(dir_)
needed_permission = {}
count = 0
for sample_ in apk_samples:
sample_full_path = os.path.join(dir_, sample_)
print(sample_full_path)
if os.path.isfile(sample_full_path):
hash_ = sample_.split('.')[0]
count += 1
logging.info('[%d] processing %s',count, hash_)
# call app detonator API for apk static analysis
report = apk_analysis_api(hash_)
# confirm if report is availiable
if report is not None:
services = None
permissions = []
# check if permissions exist
if 'androidManifest' in report:
if 'usesPermissions' in report['androidManifest']:
permissions = report['androidManifest']['usesPermissions']
if 'application' in report['androidManifest']:
if 'services' in report['androidManifest']['application']:
services = report['androidManifest']['application']['services']
#logging.info(services)
accessabiblity_permission = False
notification_permission = False
if services is not None:
for service in services:
name = service['name']
perm = service['permission']
#logging.info(service)
if perm == 'android.permission.BIND_ACCESSIBILITY_SERVICE':
accessabiblity_permission = True
logging.info('accessabiblity permission found %s', name)
if perm == 'android.permission.BIND_NOTIFICATION_LISTENER_SERVICE':
notification_permission = True
logging.info('notification permission found %s', name)
needed_permission[hash_] = {'permissions': permissions,
'accessabiblity_permission': accessabiblity_permission,
'notification_permission':notification_permission}
#break
# collect statstics
accessabiblity_permission_count = 0
notification_permission_count = 0
dangerous_permission_count = 0
for hash1 in needed_permission:
if needed_permission[hash1]['accessabiblity_permission']:
accessabiblity_permission_count += 1
if needed_permission[hash1]['notification_permission']:
notification_permission_count += 1
perms = needed_permission[hash1]['permissions']
for p in perms:
# check if dangerous permission exist
if p in DANGEROUS_PERMISSIONS:
dangerous_permission_count += 1
break
logging.info('Accessabiblity permission count %d', accessabiblity_permission_count)
logging.info('Notification permission count %d', notification_permission_count)
logging.info('Dangerous permission count %d', dangerous_permission_count)
return needed_permission
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment