Skip to content

Commit

Permalink
documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
reox committed May 1, 2018
1 parent 08a1ca3 commit 73fc426
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 82 deletions.
177 changes: 96 additions & 81 deletions androarsc.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,94 +20,109 @@

from __future__ import print_function
import sys
from optparse import OptionParser
from xml.dom import minidom
from argparse import ArgumentParser
import lxml.etree as etree
import codecs

from androguard.core import androconf
from androguard.core.bytecodes import apk
from androguard.util import read

option_0 = {
'name': ('-i', '--input'),
'help': 'filename input (APK or android resources(arsc))',
'nargs': 1
}
option_1 = {
'name': ('-p', '--package'),
'help': 'select the package (optional)',
'nargs': 1
}
option_2 = {
'name': ('-l', '--locale'),
'help': 'select the locale (optional)',
'nargs': 1
}
option_3 = {
'name': ('-t', '--type'),
'help': 'select the type (string, interger, public, ...)',
'nargs': 1
}
option_4 = {'name': ('-o', '--output'), 'help': 'filename output', 'nargs': 1}
option_5 = {
'name': ('-v', '--version'),
'help': 'version of the API',
'action': 'count'
}
options = [option_0, option_1, option_2, option_3, option_4, option_5]


def main(options, arguments):
if options.input is not None:
buff = ""

arscobj = None
ret_type = androconf.is_android(options.input)
if ret_type == "APK":
a = apk.APK(options.input)
arscobj = a.get_android_resources()
elif ret_type == "ARSC":
arscobj = apk.ARSCParser(read(options.input))
else:
print("Unknown file type")
return

if not options.package and not options.type and not options.locale:
buff = ""
for package in arscobj.get_packages_names():
buff += package + "\n"
for locale in arscobj.get_locales(package):
buff += "\t" + repr(locale) + "\n"
for ttype in arscobj.get_types(package, locale):
buff += "\t\t" + ttype + "\n"

else:
package = options.package or arscobj.get_packages_names()[0]
ttype = options.type or "public"
locale = options.locale or '\x00\x00'

buff = minidom.parseString(getattr(
arscobj, "get_" + ttype + "_resources")(package,
locale)).toprettyxml()

if options.output is not None:
fd = codecs.open(options.output, "w", "utf-8")
fd.write(buff)
fd.close()
else:
print(buff)

elif options.version is not None:
print("Androarsc version %s" % androconf.ANDROGUARD_VERSION)
def main(arscobj, outp=None, package=None, typ=None, locale=None):
package = package or arscobj.get_packages_names()[0]
ttype = typ or "public"
locale = locale or '\x00\x00'

# TODO: be able to dump all locales of a specific type
# TODO: be able to recreate the structure of files when developing

x = getattr(arscobj, "get_" + ttype + "_resources")(package, locale)

buff = etree.tostring(etree.fromstring(x), pretty_print=True, encoding="UTF-8")

if outp is not None:
with open(outp, "w") as fd:
fd.write(buff)
else:
print(buff)


if __name__ == "__main__":
parser = OptionParser()
for option in options:
param = option['name']
del option['name']
parser.add_option(*param, **option)

options, arguments = parser.parse_args()
sys.argv[:] = arguments
main(options, arguments)
parser = ArgumentParser(description="Decode resources.arsc either directly"
"from a given file or from an APK.")

parser.add_argument("--version", "-v", action="store_true", default=False,
help="Print androguard version and exit")
parser.add_argument("--input", "-i",
help="resources.arsc or APK to parse (legacy option)")
parser.add_argument("file", nargs="?",
help="resources.arsc or APK to parse")
parser.add_argument("--output", "-o",
help="filename to save the decoded resources to")
parser.add_argument("--package", "-p",
help="Show only resources for the given package name")
parser.add_argument("--locale", "-l",
help="Show only resources for the given locale")
parser.add_argument("--type", "-t",
help="Show only resources of the given type (string, integer, public, ...")
group = parser.add_mutually_exclusive_group()
group.add_argument("--list-packages", action="store_true", default=False,
help="List all package names and exit")
group.add_argument("--list-locales", action="store_true", default=False,
help="List all locales and exit")
group.add_argument("--list-types", action="store_true", default=False,
help="List all types and exit")

args = parser.parse_args()

if args.file and args.input:
print("Can not give --input and positional argument! Please use only one of them!")
sys.exit(1)

if args.version:
print("Androaxml version %s" % androconf.ANDROGUARD_VERSION)
sys.exit(0)

if not args.input and not args.file:
print("Give one file to decode!")
sys.exit(1)

if args.input:
fname = args.input
else:
fname = args.file

ret_type = androconf.is_android(fname)
if ret_type == "APK":
a = apk.APK(fname)
arscobj = a.get_android_resources()
elif ret_type == "ARSC":
arscobj = apk.ARSCParser(read(fname))
else:
print("Unknown file type")
sys.exit(1)

if args.list_packages:
print("\n".join(arscobj.get_packages_names()))
sys.exit(0)

if args.list_locales:
for p in arscobj.get_packages_names():
print("In Package:", p)
print("\n".join(map(lambda x: " \\x00\\x00" if x == "\x00\x00" else
" {}".format(x), sorted(arscobj.get_locales(p)))))
sys.exit(0)

if args.list_types:
for p in arscobj.get_packages_names():
print("In Package:", p)
for locale in sorted(arscobj.get_locales(p)):
print(" In Locale: {}".format("\\x00\\x00" if locale == "\x00\x00" else
locale))
print("\n".join(map(" {}".format, sorted(arscobj.get_types(p,
locale)))))
sys.exit(0)


main(arscobj, package=args.package, typ=args.type, locale=args.locale)
86 changes: 85 additions & 1 deletion androguard/core/bytecodes/axml.py
Original file line number Diff line number Diff line change
Expand Up @@ -1116,17 +1116,42 @@ def get_resource_style(self, ate):
return ["", ""]

def get_packages_names(self):
"""
Retrieve a list of all package names, which are available
in the given resources.arsc.
"""
return list(self.packages.keys())

def get_locales(self, package_name):
"""
Retrieve a list of all available locales in a given packagename.
:param package_name: the package name to get locales of
"""
self._analyse()
return list(self.values[package_name].keys())

def get_types(self, package_name, locale):
def get_types(self, package_name, locale='\x00\x00'):
"""
Retrieve a list of all types which are available in the given
package and locale.
:param package_name: the package name to get types of
:param locale: the locale to get types of (default: '\x00\x00')
"""
self._analyse()
return list(self.values[package_name][locale].keys())

def get_public_resources(self, package_name, locale='\x00\x00'):
"""
Get the XML (as string) of all resources of type 'public'.
The public resources table contains the IDs for each item.
:param package_name: the package name to get the resources for
:param locale: the locale to get the resources for (default: '\x00\x00')
"""

self._analyse()

buff = '<?xml version="1.0" encoding="utf-8"?>\n'
Expand All @@ -1144,6 +1169,15 @@ def get_public_resources(self, package_name, locale='\x00\x00'):
return buff.encode('utf-8')

def get_string_resources(self, package_name, locale='\x00\x00'):
"""
Get the XML (as string) of all resources of type 'string'.
Read more about string resources:
https://developer.android.com/guide/topics/resources/string-resource.html
:param package_name: the package name to get the resources for
:param locale: the locale to get the resources for (default: '\x00\x00')
"""
self._analyse()

buff = '<?xml version="1.0" encoding="utf-8"?>\n'
Expand All @@ -1164,6 +1198,11 @@ def get_string_resources(self, package_name, locale='\x00\x00'):
return buff.encode('utf-8')

def get_strings_resources(self):
"""
Get the XML (as string) of all resources of type 'string'.
This is a combined variant, which has all locales and all package names
stored.
"""
self._analyse()

buff = '<?xml version="1.0" encoding="utf-8"?>\n'
Expand Down Expand Up @@ -1192,6 +1231,15 @@ def get_strings_resources(self):
return buff.encode('utf-8')

def get_id_resources(self, package_name, locale='\x00\x00'):
"""
Get the XML (as string) of all resources of type 'id'.
Read more about ID resources:
https://developer.android.com/guide/topics/resources/more-resources.html#Id
:param package_name: the package name to get the resources for
:param locale: the locale to get the resources for (default: '\x00\x00')
"""
self._analyse()

buff = '<?xml version="1.0" encoding="utf-8"?>\n'
Expand All @@ -1212,6 +1260,15 @@ def get_id_resources(self, package_name, locale='\x00\x00'):
return buff.encode('utf-8')

def get_bool_resources(self, package_name, locale='\x00\x00'):
"""
Get the XML (as string) of all resources of type 'bool'.
Read more about bool resources:
https://developer.android.com/guide/topics/resources/more-resources.html#Bool
:param package_name: the package name to get the resources for
:param locale: the locale to get the resources for (default: '\x00\x00')
"""
self._analyse()

buff = '<?xml version="1.0" encoding="utf-8"?>\n'
Expand All @@ -1228,6 +1285,15 @@ def get_bool_resources(self, package_name, locale='\x00\x00'):
return buff.encode('utf-8')

def get_integer_resources(self, package_name, locale='\x00\x00'):
"""
Get the XML (as string) of all resources of type 'integer'.
Read more about integer resources:
https://developer.android.com/guide/topics/resources/more-resources.html#Integer
:param package_name: the package name to get the resources for
:param locale: the locale to get the resources for (default: '\x00\x00')
"""
self._analyse()

buff = '<?xml version="1.0" encoding="utf-8"?>\n'
Expand All @@ -1244,6 +1310,15 @@ def get_integer_resources(self, package_name, locale='\x00\x00'):
return buff.encode('utf-8')

def get_color_resources(self, package_name, locale='\x00\x00'):
"""
Get the XML (as string) of all resources of type 'color'.
Read more about color resources:
https://developer.android.com/guide/topics/resources/more-resources.html#Color
:param package_name: the package name to get the resources for
:param locale: the locale to get the resources for (default: '\x00\x00')
"""
self._analyse()

buff = '<?xml version="1.0" encoding="utf-8"?>\n'
Expand All @@ -1260,6 +1335,15 @@ def get_color_resources(self, package_name, locale='\x00\x00'):
return buff.encode('utf-8')

def get_dimen_resources(self, package_name, locale='\x00\x00'):
"""
Get the XML (as string) of all resources of type 'dimen'.
Read more about Dimension resources:
https://developer.android.com/guide/topics/resources/more-resources.html#Dimension
:param package_name: the package name to get the resources for
:param locale: the locale to get the resources for (default: '\x00\x00')
"""
self._analyse()

buff = '<?xml version="1.0" encoding="utf-8"?>\n'
Expand Down

0 comments on commit 73fc426

Please sign in to comment.