Added tool to extract permission mappings from PScout data

This commit is contained in:
Yury Zhauniarovich 2015-06-16 17:08:07 +02:00
parent 48c3f7d218
commit ae52ec426e

View File

@ -0,0 +1,254 @@
#!/usr/bin/env python
# This file is part of Androguard.
#
# This is a tool to extract permissions and permission groups from Android Open Source Project.
# The information about the permissions and permission groups is appended to a file, which is
# later used in Androguard project.
#
# Author: Yury Zhauniarovich
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#CONSTANTS
PATH_TO_PSCOUT_FOLDER = "/home/yury/TMP/PScout/results/API_09"
API_VERSION = 9
MAPPINGS_MODULE_PATH = "../../androguard/core/api_specific_resources/api_permission_mappings/" #where to append the results
MAPPINGS_MODULE_NAME = "api_permission_mappings"
PSCOUT_METHOD_MAPPING_FILENAME = "allmappings"
PSCOUT_CONTENTPROVIDERFIELDS_MAPPING_FILENAME = "contentproviderfieldpermission"
METHODS_MAPPING_PARAM_NAME = "AOSP_PERMISSIONS_BY_METHODS"
FIELDS_MAPPING_PARAM_NAME = "AOSP_PERMISSIONS_BY_FIELDS"
#IMPORTS
import os, re, codecs
#auxiliary
TYPE_DESCRIPTOR = {
'V': 'void',
'Z': 'boolean',
'B': 'byte',
'S': 'short',
'C': 'char',
'I': 'int',
'J': 'long',
'F': 'float',
'D': 'double',
}
DESCRIPTOR_TYPE = {
'void' : 'V',
'boolean' : 'Z',
'byte' : 'B',
'short' : 'S',
'char' : 'C',
'int' : 'I',
'long' : 'J',
'float' : 'F',
'double' : 'D',
}
def countBrackets(atype):
res = re.findall('\[\s*\]', atype)
return len(res)
def transformClassParam(atype):
res = ""
arrDim = countBrackets(atype)
if arrDim > 0:
pos = atype.find('[')
atype = atype[0 : pos].strip()
res = '['*arrDim
if atype in DESCRIPTOR_TYPE:
res += DESCRIPTOR_TYPE[atype]
else:
res += FormatClassToJava(atype)
return res
def FormatClassToJava(input) :
"""
Transoform a typical xml format class into java format
:param input: the input class name
:rtype: string
"""
return "L" + input.replace(".", "/") + ";"
def parseMethod(methodString):
ms = methodString.strip()
mParamStartPos = ms.find('(')
mParamEndPos = ms.find(')')
paramString = ms[mParamStartPos + 1 : mParamEndPos].strip()
params = [l.strip() for l in paramString.split(',')]
retValue_mName = ms[0 : mParamStartPos].strip()
mNameStartPos = retValue_mName.rfind(' ')
returnValue = retValue_mName[0 : mNameStartPos].strip()
methodName = retValue_mName[mNameStartPos + 1 : ].strip()
return (methodName, params, returnValue)
#end of auxiliary
print "Starting conversion of PScout data: [%s]" % PATH_TO_PSCOUT_FOLDER
if not os.path.exists(MAPPINGS_MODULE_PATH):
os.makedirs(MAPPINGS_MODULE_PATH)
print "Checking if we already have the file with the version %d..." % API_VERSION
api_specific_mappings_module_name = "%s_api%s.py" % (MAPPINGS_MODULE_NAME, API_VERSION)
api_specific_mappings_module_path = os.path.join(MAPPINGS_MODULE_PATH, api_specific_mappings_module_name)
if os.path.exists(api_specific_mappings_module_path):
print "API specific file for this version already exists!"
print "If you want create a file for newer version, please, delete file: %s" % api_specific_mappings_module_path
exit(1)
print "Reading method mapping file..."
pscout_method_mapping_filepath = os.path.join(PATH_TO_PSCOUT_FOLDER, PSCOUT_METHOD_MAPPING_FILENAME)
methods_mapping_file_lines = []
with open(pscout_method_mapping_filepath, 'r') as pscout_file:
methods_mapping_file_lines = pscout_file.readlines()
print "Starting to parse file: [%s]" % pscout_method_mapping_filepath
perm_name = None
methods_mapping = {}
for line in methods_mapping_file_lines:
line = line.strip()
if line.startswith("Permission:"):
perm_name = line.split("Permission:")[1].strip()
print "PROCESSING PERMISSIONS: %s" % perm_name
elif line.startswith("<"):
class_method = line[line.find('<') + 1 : line.rfind('>')]
sepPos = class_method.find(':')
className = class_method[0 : sepPos].strip()
methodStr = class_method[sepPos + 1 :].strip()
methodName, params, returnValue = parseMethod(methodStr)
modParStr = ""
for par in params:
if par != "":
modParStr += transformClassParam(par) + ' '
modParStr = modParStr.strip()
method_identificator = "%s-%s-(%s)%s" % (transformClassParam(className), methodName, modParStr, transformClassParam(returnValue))
try:
methods_mapping[method_identificator].add(perm_name)
except KeyError:
methods_mapping[method_identificator] = set()
methods_mapping[method_identificator].add(perm_name)
print "Reading contentproviderfield mapping file..."
pscout_contentproviderfields_mapping_filepath = os.path.join(PATH_TO_PSCOUT_FOLDER, PSCOUT_CONTENTPROVIDERFIELDS_MAPPING_FILENAME)
contentproviderfields_mapping_file_lines = []
with open(pscout_contentproviderfields_mapping_filepath, 'r') as pscout_file:
contentproviderfields_mapping_file_lines = pscout_file.readlines()
perm_name = None
fields_mapping = {}
for line in contentproviderfields_mapping_file_lines:
line = line.strip()
if line.startswith("PERMISSION:"):
perm_name = line.split("PERMISSION:")[1].strip()
print "PROCESSING PERMISSIONS: %s" % perm_name
elif line.startswith("<"):
field_entry = line[line.find('<') + 1 : line.rfind('>')]
classNameSepPos = field_entry.find(':')
className = field_entry[0 : classNameSepPos].strip()
proto_name_str = field_entry[classNameSepPos + 1 :].strip()
proto_name_parts = proto_name_str.split()
proto = proto_name_parts[0].strip()
name = proto_name_parts[1].strip()
field_identificator = "%s-%s-%s" % (transformClassParam(className), name, transformClassParam(proto))
try:
fields_mapping[field_identificator].add(perm_name)
except KeyError:
fields_mapping[field_identificator] = set()
fields_mapping[field_identificator].add(perm_name)
print "Appending found information to the mappings file..."
with codecs.open(api_specific_mappings_module_path, 'w', 'utf-8') as perm_py_module:
perm_py_module.write('#!/usr/bin/python\n')
perm_py_module.write('# -*- coding: %s -*-\n\n' % 'utf-8')
perm_py_module.write('# This file is a part of Androguard.\n')
perm_py_module.write('#\n')
perm_py_module.write('# This file is generated automatically from the data\n')
perm_py_module.write('# provided by PScout tool [http://pscout.csl.toronto.edu/]\n')
perm_py_module.write('# using script: %s\n' % os.path.basename(__file__))
perm_py_module.write('#\n')
perm_py_module.write('# Author: Yury Zhauniarovich\n')
perm_py_module.write('#\n')
perm_py_module.write('#\n')
perm_py_module.write('# Licensed under the Apache License, Version 2.0 (the "License");\n')
perm_py_module.write('# you may not use this file except in compliance with the License.\n')
perm_py_module.write('# You may obtain a copy of the License at\n')
perm_py_module.write('#\n')
perm_py_module.write('# http://www.apache.org/licenses/LICENSE-2.0\n')
perm_py_module.write('#\n')
perm_py_module.write('# Unless required by applicable law or agreed to in writing, software\n')
perm_py_module.write('# distributed under the License is distributed on an "AS-IS" BASIS,\n')
perm_py_module.write('# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n')
perm_py_module.write('# See the License for the specific language governing permissions and\n')
perm_py_module.write('# limitations under the License"\n\n')
perm_py_module.write('#################################################\n')
perm_py_module.write('### API version: %d \n' % API_VERSION)
perm_py_module.write('#################################################\n\n\n')
perm_py_module.write("%s = {\n" % METHODS_MAPPING_PARAM_NAME)
for method in methods_mapping.keys():
permissions = methods_mapping.get(method)
perms_string = ", ".join(['"%s"' % prm for prm in permissions])
perm_py_module.write("\t'%s' : [%s],\n" % (method, perms_string))
perm_py_module.write("}\n\n")
perm_py_module.write("%s = {\n" % FIELDS_MAPPING_PARAM_NAME)
for field in fields_mapping.keys():
permissions = fields_mapping.get(field)
perms_string = ", ".join(['"%s"' % prm for prm in permissions])
perm_py_module.write("\t'%s' : [%s],\n" % (field, perms_string))
perm_py_module.write("}\n")
perm_py_module.write("#################################################\n")
print "Done..."