Skip to content

Commit

Permalink
using a general configuration file instead of global vars
Browse files Browse the repository at this point in the history
  • Loading branch information
axelle committed Mar 10, 2023
1 parent e672b4c commit dad2441
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 36 deletions.
13 changes: 13 additions & 0 deletions conf/general.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[tools]
apktool = /home/axelle/softs/apktool_2.7.0.jar
baksmali = /home/axelle/softs/baksmali-2.5.2.jar
dex2jar = /home/axelle/softs/dex-tools-2.2-SNAPSHOT/d2j-dex2jar.sh
procyon = /home/axelle/softs/procyon-decompiler-0.5.30.jar
keytool = /usr/bin/keytool

[general]
db_file = droidlysis.db
smali_config = ./smali.conf
wide_config = ./wide.conf
arm_config = ./arm.conf
kit_config = ./kit.conf
45 changes: 29 additions & 16 deletions droidconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,36 @@
logging.basicConfig(format='%(levelname)s:%(filename)s:%(message)s',
level=logging.INFO)

# ------------------------- DroidLysis Configuration file -----------------

APKTOOL_JAR = os.path.join(os.path.expanduser("~/softs"), "apktool_2.7.0.jar")
BAKSMALI_JAR = os.path.join(os.path.expanduser("~/softs"), "baksmali-2.5.2.jar")
DEX2JAR_CMD = os.path.join(os.path.expanduser("~/softs/dex-tools-2.2-SNAPSHOT"), "d2j-dex2jar.sh")
PROCYON_JAR = os.path.join(os.path.expanduser("~/softs"), "procyon-decompiler-0.5.30.jar")
INSTALL_DIR = os.path.dirname(__file__)
SQLALCHEMY = 'sqlite:///droidlysis.db' # https://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls
KEYTOOL = os.path.join("/usr/bin/keytool")

# ------------------------- Property configuration files -------------------
SMALI_CONFIGFILE = os.path.join(os.path.join(INSTALL_DIR, './conf/smali.conf'))
WIDE_CONFIGFILE = os.path.join(os.path.join(INSTALL_DIR, './conf/wide.conf'))
ARM_CONFIGFILE = os.path.join(os.path.join(INSTALL_DIR, './conf/arm.conf'))
KIT_CONFIGFILE = os.path.join(os.path.join(INSTALL_DIR, './conf/kit.conf'))

# ------------------------- Reading *.conf configuration files -----------
class generalconfig:
def __init__(self, filename='./conf/general.conf', verbose=False):
self.config = configparser.ConfigParser()
self.config.read(filename)

# get config
self.APKTOOL_JAR = self.config['tools']['apktool']
self.BAKSMALI_JAR = self.config['tools']['baksmali']
self.DEX2JAR_CMD = self.config['tools']['dex2jar']
self.PROCYON_JAR = self.config['tools']['procyon']
self.KEYTOOL = self.config['tools']['keytool']
self.SMALI_CONFIGFILE = os.path.join(os.path.dirname(filename),
self.config['general']['smali_config'])
self.WIDE_CONFIGFILE = os.path.join(os.path.dirname(filename), self.config['general']['wide_config'])
self.ARM_CONFIGFILE = os.path.join(os.path.dirname(filename), self.config['general']['arm_config'])
self.KIT_CONFIGFILE = os.path.join(os.path.dirname(filename), self.config['general']['kit_config'])

self.SQLALCHEMY = f'sqlite:///{self.config["general"]["db_file"]}'

# check files are accessible
for f in [self.APKTOOL_JAR, self.BAKSMALI_JAR,
self.DEX2JAR_CMD, self.PROCYON_JAR,
self.SMALI_CONFIGFILE, self.WIDE_CONFIGFILE,
self.ARM_CONFIGFILE, self.KIT_CONFIGFILE]:
if not os.access(f, os.R_OK):
logging.warning(f'Cannot access {f}')

if not os.access(self.KEYTOOL, os.X_OK):
logging.warning(f'Cannot access keytool at {self.KEYTOOL}')


class droidconfig:
Expand Down
18 changes: 13 additions & 5 deletions droidlysis3.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import sys
import logging
from droidsql import DroidSql
from droidconfig import generalconfig

property_dump_file = 'details.md'
report_file = 'report.md'
Expand Down Expand Up @@ -79,6 +80,9 @@ def get_arguments():
help='import ETIP Exodus Privacy trackers '
'and add them to kit config file',
action='store_true')
parser.add_argument('--config',
help='general configuration file for DroidLysis',
action='store', default='./conf/general.conf')

args = parser.parse_args()
if args.verbose:
Expand All @@ -98,6 +102,7 @@ def process_input(args):
each file in an input directory are processed, but not recursively.
each input file is process.
"""
config = generalconfig(filename=args.config, verbose=args.verbose)
sql = None
if args.enable_sql:
sql = DroidSql()
Expand All @@ -106,7 +111,8 @@ def process_input(args):
if os.path.isdir(element):
listing = os.listdir(element)
for file in listing:
process_file(os.path.join(element, file),
process_file(config,
os.path.join(element, file),
outdir=args.output,
verbose=args.verbose,
clear=args.clearoutput,
Expand All @@ -128,7 +134,8 @@ def process_input(args):
logging.debug("%s no longer present?: %s\n" % (file, str(e)))

if os.path.isfile(element):
process_file(os.path.join('.', element),
process_file(config,
os.path.join('.', element),
outdir=args.output,
verbose=args.verbose,
clear=args.clearoutput,
Expand All @@ -148,7 +155,8 @@ def process_input(args):
os.rename(os.path.join('.', element), os.path.join(args.movein, os.path.basename(element)))


def process_file(infile,
def process_file(config,
infile,
outdir='/tmp/analysis',
verbose=False,
clear=False,
Expand All @@ -164,7 +172,8 @@ def process_file(infile,
if os.access(infile, os.R_OK):
if not silent:
print("Processing file: " + infile + " ...")
sample = droidsample.droidsample(filename=infile,
sample = droidsample.droidsample(config=config,
filename=infile,
output=outdir,
verbose=verbose,
clear=clear,
Expand All @@ -191,7 +200,6 @@ def process_file(infile,
if not disable_json:
sample.properties.dump_json(os.path.join(sample.outdir, json_file))


if not silent and not clear:
report = droidreport.droidreport(sample, console=True, report_to_file=disable_report)
report.write(os.path.join(sample.outdir, report_file), verbose)
Expand Down
11 changes: 6 additions & 5 deletions droidproperties.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ class droidproperties:
dex = {}
kits = {}

def __init__(self, samplename='', sha256='', verbose=False, import_exodus=False):
def __init__(self, config, samplename='', sha256='', verbose=False, import_exodus=False):
"""Properties concern a given sample identified by a basename (to be helpful) and a sha256 (real reference)"""
self.config = config
self.verbose = verbose
if verbose:
logging.getLogger().setLevel(logging.DEBUG)
Expand Down Expand Up @@ -106,7 +107,7 @@ def clear_fields(self):

# automatically adding smali properties.
self.smali.clear()
self.smaliconfig = droidconfig.droidconfig(droidconfig.SMALI_CONFIGFILE, self.verbose)
self.smaliconfig = droidconfig.droidconfig(self.config.SMALI_CONFIGFILE, self.verbose)
for section in self.smaliconfig.get_sections():
self.smali[section] = False

Expand All @@ -120,13 +121,13 @@ def clear_fields(self):
self.wide['urls'] = []
self.wide['base64_strings'] = []
self.wide['apk_zip_url'] = False
self.wideconfig = droidconfig.droidconfig(droidconfig.WIDE_CONFIGFILE, self.verbose)
self.wideconfig = droidconfig.droidconfig(self.config.WIDE_CONFIGFILE, self.verbose)
for section in self.wideconfig.get_sections():
self.wide[section] = False

# automatically add ARM properties
self.arm.clear()
self.armconfig = droidconfig.droidconfig(droidconfig.ARM_CONFIGFILE, self.verbose)
self.armconfig = droidconfig.droidconfig(self.config.ARM_CONFIGFILE, self.verbose)
for section in self.armconfig.get_sections():
self.arm[section] = False

Expand All @@ -142,7 +143,7 @@ def clear_fields(self):

# automatically set to False kit properties
self.kits.clear()
self.kitsconfig = droidconfig.droidconfig(droidconfig.KIT_CONFIGFILE,
self.kitsconfig = droidconfig.droidconfig(self.config.KIT_CONFIGFILE,
self.verbose)
for section in self.kitsconfig.get_sections():
self.kits[section] = False
Expand Down
23 changes: 13 additions & 10 deletions droidsample.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class droidsample:
# Base class for an Android sample to analyze

def __init__(self,
config,
filename,
output='/tmp/analysis',
verbose=False,
Expand All @@ -47,6 +48,7 @@ def __init__(self,

assert filename is not None, "Filename is invalid"

self.config = config
self.absolute_filename = filename
self.clear = clear
self.enable_procyon = enable_procyon
Expand All @@ -63,6 +65,7 @@ def __init__(self,
os.path.basename(filename))

self.properties = droidproperties.droidproperties(
config=self.config,
samplename=sanitized_basename,
sha256=droidutil.sha256sum(filename),
verbose=verbose,
Expand Down Expand Up @@ -242,14 +245,14 @@ def disassemble(self):

if self.verbose:
logging.debug("Apktool command: java -jar %s d -f %s %s"
% (droidconfig.APKTOOL_JAR,
% (self.config.APKTOOL_JAR,
self.absolute_filename, apktool_outdir))
subprocess.call(["java", "-jar", droidconfig.APKTOOL_JAR,
subprocess.call(["java", "-jar", self.config.APKTOOL_JAR,
"d", "-f", self.absolute_filename,
"-o", apktool_outdir])
else:
# with quiet option
subprocess.call(["java", "-jar", droidconfig.APKTOOL_JAR,
subprocess.call(["java", "-jar", self.config.APKTOOL_JAR,
"-q", "d", "-f", self.absolute_filename,
"-o", apktool_outdir],
stdout=self.process_output,
Expand Down Expand Up @@ -307,7 +310,7 @@ def disassemble(self):
if os.access(d, os.R_OK):
logging.debug("Baksmali on {} -> {}".format(d, smali_dir))
try:
subprocess.call(["java", "-jar", droidconfig.BAKSMALI_JAR,
subprocess.call(["java", "-jar", self.config.BAKSMALI_JAR,
"d", "-o", smali_dir, d],
stdout=self.process_output, stderr=self.process_output)
except:
Expand All @@ -321,21 +324,21 @@ def disassemble(self):
if os.access(d, os.R_OK):
jar_file = os.path.join(self.outdir, '{}-dex2jar.jar'.format(
os.path.splitext(os.path.basename(d))[0]))
if os.access(droidconfig.DEX2JAR_CMD, os.X_OK):
if os.access(self.config.DEX2JAR_CMD, os.X_OK):
if self.verbose:
logging.debug("Dex2jar on " + d)
try:
subprocess.call([droidconfig.DEX2JAR_CMD, "--force", d, "-o", jar_file],
subprocess.call([self.config.DEX2JAR_CMD, "--force", d, "-o", jar_file],
stdout=self.process_output, stderr=self.process_output)
except:
logging.warning("[-] Dex2jar failed on {}".format(d))
else:
logging.warning("Dex2jar software is not executable, skipping (file: {0})".format(droidconfig.DEX2JAR_CMD))
logging.warning("Dex2jar software is not executable, skipping (file: {0})".format(self.config.DEX2JAR_CMD))

if os.access(jar_file, os.R_OK):
if self.enable_procyon and os.access(droidconfig.PROCYON_JAR, os.R_OK):
if self.enable_procyon and os.access(self.config.PROCYON_JAR, os.R_OK):
logging.debug("Procyon decompiler on " + jar_file)
subprocess.call(["java", "-jar", droidconfig.PROCYON_JAR,
subprocess.call(["java", "-jar", self.config.PROCYON_JAR,
jar_file, "-o", os.path.join(self.outdir, 'procyon')],
stdout=self.process_output, stderr=self.process_output)

Expand Down Expand Up @@ -412,7 +415,7 @@ def extract_meta_properties(self):

if list:
try:
keyout = subprocess.check_output([droidconfig.KEYTOOL, "-printcert", "-file",
keyout = subprocess.check_output([self.config.KEYTOOL, "-printcert", "-file",
os.path.join(self.outdir, list[0])],
stderr=self.process_output).decode('utf-8')
keyout = re.sub(': ', '#', keyout)
Expand Down

0 comments on commit dad2441

Please sign in to comment.