auto format code

This commit is contained in:
Sebastian Bachmann 2017-06-14 12:04:10 +02:00
parent 7f44b13e57
commit 1ce2a7f1ae
57 changed files with 4953 additions and 4891 deletions

View File

@ -36,14 +36,12 @@ options = [option_0, option_1]
class AndroLog(object):
def __init__(self, id_file, filename):
self.id_file = id_file
self.filename = filename
class AndroTest(auto.DirectoryAndroAnalysis):
def analysis_app(self, log, apkobj, dexobj, adexobj):
print(log.id_file, log.filename, apkobj, dexobj, adexobj)

View File

@ -105,12 +105,12 @@ def export_apps_to_format(filename,
if decompiler_type == "dex2jad":
vm.set_decompiler(decompiler.DecompilerDex2Jad(
vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"
], androconf.CONF["PATH_JAD"],
], androconf.CONF["PATH_JAD"],
androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"]))
elif decompiler_type == "dex2winejad":
vm.set_decompiler(decompiler.DecompilerDex2WineJad(
vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"
], androconf.CONF["PATH_JAD"],
], androconf.CONF["PATH_JAD"],
androconf.CONF["BIN_WINEJAD"], androconf.CONF["TMP_DIRECTORY"]))
elif decompiler_type == "ded":
vm.set_decompiler(decompiler.DecompilerDed(
@ -123,7 +123,7 @@ def export_apps_to_format(filename,
], androconf.CONF["PATH_FERNFLOWER"], androconf.CONF[
"BIN_FERNFLOWER"
], androconf.CONF["OPTIONS_FERNFLOWER"
], androconf.CONF["TMP_DIRECTORY"]))
], androconf.CONF["TMP_DIRECTORY"]))
print("End")

View File

@ -1,6 +1,7 @@
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import str
from builtins import range
@ -8,12 +9,12 @@ from builtins import object
import re, collections
import threading, queue, time
from androguard.core.androconf import error, warning, debug, is_ascii_problem,\
from androguard.core.androconf import error, warning, debug, is_ascii_problem, \
load_api_specific_resource_module
from androguard.core.bytecodes import dvm
from androguard.core.bytecodes.api_permissions import DVM_PERMISSIONS_BY_PERMISSION, DVM_PERMISSIONS_BY_ELEMENT
class DVMBasicBlock(object):
"""
A simple basic block of a dalvik method
@ -108,7 +109,7 @@ class DVMBasicBlock(object):
return self.last_length
def set_childs(self, values):
#print self, self.start, self.end, values
# print self, self.start, self.end, values
if values == []:
next_block = self.context.get_basic_block(self.end + 1)
if next_block != None:
@ -162,7 +163,6 @@ class DVMBasicBlock(object):
class Enum(object):
def __init__(self, names):
self.names = names
for value, name in enumerate(self.names):
@ -309,7 +309,6 @@ class BasicBlocks(object):
class ExceptionAnalysis(object):
def __init__(self, exception, bb):
self.start = exception[0]
self.end = exception[1]
@ -340,7 +339,6 @@ class ExceptionAnalysis(object):
class Exceptions(object):
def __init__(self, _vm):
self.__vm = _vm
self.exceptions = []
@ -514,14 +512,13 @@ class MethodAnalysis(object):
class StringAnalysis(object):
def __init__(self, value):
self.value = value
self.orig_value = value
self.xreffrom = set()
def AddXrefFrom(self, classobj, methodobj):
#debug("Added strings xreffrom for %s to %s" % (self.value, methodobj))
# debug("Added strings xreffrom for %s to %s" % (self.value, methodobj))
self.xreffrom.add((classobj, methodobj))
def get_xref_from(self):
@ -540,23 +537,22 @@ class StringAnalysis(object):
data = "XREFto for string %s in\n" % repr(self.get_value())
for ref_class, ref_method in self.xreffrom:
data += "%s:%s\n" % (ref_class.get_vm_class().get_name(), ref_method
)
)
return data
class MethodClassAnalysis(object):
def __init__(self, method):
self.method = method
self.xrefto = set()
self.xreffrom = set()
def AddXrefTo(self, classobj, methodobj, offset):
#debug("Added method xrefto for %s [%s] to %s" % (self.method, classobj, methodobj))
# debug("Added method xrefto for %s [%s] to %s" % (self.method, classobj, methodobj))
self.xrefto.add((classobj, methodobj, offset))
def AddXrefFrom(self, classobj, methodobj, offset):
#debug("Added method xreffrom for %s [%s] to %s" % (self.method, classobj, methodobj))
# debug("Added method xreffrom for %s [%s] to %s" % (self.method, classobj, methodobj))
self.xreffrom.add((classobj, methodobj, offset))
def get_xref_from(self):
@ -570,30 +566,29 @@ class MethodClassAnalysis(object):
for ref_class, ref_method, offset in self.xrefto:
data += "in\n"
data += "%s:%s @0x%x\n" % (ref_class.get_vm_class().get_name(), ref_method, offset
)
)
data += "XREFFrom for %s\n" % self.method
for ref_class, ref_method, offset in self.xreffrom:
data += "in\n"
data += "%s:%s @0x%x\n" % (ref_class.get_vm_class().get_name(), ref_method, offset
)
)
return data
class FieldClassAnalysis(object):
def __init__(self, field):
self.field = field
self.xrefread = set()
self.xrefwrite = set()
def AddXrefRead(self, classobj, methodobj):
#debug("Added method xrefto for %s [%s] to %s" % (self.method, classobj, methodobj))
# debug("Added method xrefto for %s [%s] to %s" % (self.method, classobj, methodobj))
self.xrefread.add((classobj, methodobj))
def AddXrefWrite(self, classobj, methodobj):
#debug("Added method xreffrom for %s [%s] to %s" % (self.method, classobj, methodobj))
# debug("Added method xreffrom for %s [%s] to %s" % (self.method, classobj, methodobj))
self.xrefwrite.add((classobj, methodobj))
def get_xref_read(self):
@ -607,19 +602,21 @@ class FieldClassAnalysis(object):
for ref_class, ref_method in self.xrefread:
data += "in\n"
data += "%s:%s\n" % (ref_class.get_vm_class().get_name(), ref_method
)
)
data += "XREFWrite for %s\n" % self.field
for ref_class, ref_method in self.xrefwrite:
data += "in\n"
data += "%s:%s\n" % (ref_class.get_vm_class().get_name(), ref_method
)
)
return data
REF_NEW_INSTANCE = 0
REF_CLASS_USAGE = 1
class ExternalClass(object):
def __init__(self, name):
self.name = name
@ -632,6 +629,7 @@ class ExternalClass(object):
return self.methods[key]
class ExternalMethod(object):
def __init__(self, class_name, name, descriptor):
self.class_name = class_name
@ -650,8 +648,8 @@ class ExternalMethod(object):
def __str__(self):
return "%s->%s%s" % (self.class_name, self.name, ''.join(self.descriptor))
class ClassAnalysis(object):
class ClassAnalysis(object):
def __init__(self, classobj, internal=False):
self.orig_class = classobj
self._inherits_methods = {}
@ -745,7 +743,6 @@ class ClassAnalysis(object):
class Analysis(object):
def __init__(self, vm):
self.vms = [vm]
self.classes = {}
@ -827,7 +824,7 @@ class Analysis(object):
current_method, off)
elif ((op_value >= 0x6e and op_value <= 0x72) or
(op_value >= 0x74 and op_value <= 0x78)):
(op_value >= 0x74 and op_value <= 0x78)):
idx_meth = instruction.get_ref_kind()
method_info = last_vm.get_cm_method(idx_meth)
if method_info:
@ -840,9 +837,10 @@ class Analysis(object):
# Seems to be an external classes
if not method_item:
if method_info[0] not in self.classes:
self.classes[method_info[0]] = ClassAnalysis(ExternalClass(method_info[0]), False)
method_item = self.classes[method_info[0]].GetFakeMethod(method_info[1], method_info[2])
self.classes[method_info[0]] = ClassAnalysis(ExternalClass(method_info[0]),
False)
method_item = self.classes[method_info[0]].GetFakeMethod(method_info[1],
method_info[2])
if method_item:
self.classes[current_class.get_name(
@ -886,7 +884,7 @@ class Analysis(object):
if field_item:
# read access to a field
if (op_value >= 0x52 and op_value <= 0x58) or (
op_value >= 0x60 and op_value <= 0x66):
op_value >= 0x60 and op_value <= 0x66):
self.classes[current_class.get_name(
)].AddFXrefRead(
current_method,
@ -959,6 +957,7 @@ class Analysis(object):
self.classes[current_class.get_name()] = ClassAnalysis(
current_class, True)
def is_ascii_obfuscation(vm):
for classe in vm.get_classes():
if is_ascii_problem(classe.get_name()):

View File

@ -1,4 +1,5 @@
from future import standard_library
standard_library.install_aliases()
from builtins import range
from builtins import object

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@ from __future__ import division
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import chr
from builtins import str
@ -42,6 +43,7 @@ ZIPMODULE = 1
if sys.hexversion < 0x2070000:
try:
import chilkat
ZIPMODULE = 0
# UNLOCK : change it with your valid key !
try:
@ -57,7 +59,6 @@ else:
################################################### CHILKAT ZIP FORMAT #####################################################
class ChilkatZip(object):
def __init__(self, raw):
self.files = []
self.zip = chilkat.CkZip()
@ -251,7 +252,6 @@ class APK(object):
self.permission_module = androconf.load_api_specific_resource_module(
"aosp_permissions", self.get_target_sdk_version())
def __getstate__(self):
# Upon pickling, we need to remove the ZipFile
x = self.__dict__
@ -587,7 +587,7 @@ class APK(object):
:rtype: string
"""
for i in self.xml:
if self.xml[i] is None :
if self.xml[i] is None:
continue
tag = self.xml[i].getElementsByTagName(tag_name)
if tag is None:
@ -686,7 +686,7 @@ class APK(object):
for item in self.xml[i].getElementsByTagName(category):
if self.format_value(
item.getAttributeNS(NS_ANDROID_URI, "name")
) == name:
) == name:
for sitem in item.getElementsByTagName("intent-filter"):
for ssitem in sitem.getElementsByTagName("action"):
if ssitem.getAttributeNS(NS_ANDROID_URI, "name") \
@ -853,9 +853,9 @@ class APK(object):
if not isinstance(l, int):
l = ord(l)
cert = cert[2 + (l & 0x7F) if l & 0x80 > 1 else 2:]
certificate = x509.load_der_x509_certificate(cert, default_backend())
return certificate
def new_zip(self, filename, deleted_files=None, new_files={}):
@ -1029,21 +1029,23 @@ def get_Name(name, short=False):
:rtype: str
"""
# For the shortform, we have a lookup table
# See RFC4514 for more details
sf = {
"countryName": "C",
"stateOrProvinceName": "ST",
"localityName": "L",
"organizationalUnitName": "OU",
"organizationName": "O",
"commonName": "CN",
"emailAddress": "E",
}
return ", ".join(["{}={}".format(attr.oid._name if not short or attr.oid._name not in sf else sf[attr.oid._name], attr.value) for attr in name])
"countryName": "C",
"stateOrProvinceName": "ST",
"localityName": "L",
"organizationalUnitName": "OU",
"organizationName": "O",
"commonName": "CN",
"emailAddress": "E",
}
return ", ".join(
["{}={}".format(attr.oid._name if not short or attr.oid._name not in sf else sf[attr.oid._name], attr.value) for
attr in name])
def show_Certificate(cert, short=False):
"""
Print Fingerprints, Issuer and Subject of an X509 Certificate.
@ -1054,12 +1056,13 @@ def show_Certificate(cert, short=False):
:type cert: :class:`cryptography.x509.Certificate`
:type short: Boolean
"""
for h in [hashes.MD5, hashes.SHA1, hashes.SHA256, hashes.SHA512]:
print("{}: {}".format(h.name, binascii.hexlify(cert.fingerprint(h())).decode("ascii")))
print("Issuer: {}".format(get_Name(cert.issuer, short=short)))
print("Subject: {}".format(get_Name(cert.subject, short=short)))
################################## AXML FORMAT ########################################
# Translated from
# http://code.google.com/p/android4me/source/browse/src/android/content/res/AXmlResourceParser.java
@ -1068,7 +1071,6 @@ UTF8_FLAG = 0x00000100
class StringBlock(object):
def __init__(self, buff, header):
self._cache = {}
self.header = header
@ -1213,7 +1215,6 @@ TEXT = 4
class AXMLParser(object):
def __init__(self, raw_buff):
self.reset()
@ -1379,7 +1380,7 @@ class AXMLParser(object):
def getName(self):
if self.m_name == -1 or (self.m_event != START_TAG and
self.m_event != END_TAG):
self.m_event != END_TAG):
return u''
return self.sb.getString(self.m_name)
@ -1567,7 +1568,6 @@ def format_value(_type, _data, lookup_string=lambda ix: "<string>"):
class AXMLPrinter(object):
def __init__(self, raw_buff):
self.axml = AXMLParser(raw_buff)
self.xmlns = False
@ -1675,7 +1675,6 @@ ACONFIGURATION_UI_MODE = 0x1000
class ARSCParser(object):
def __init__(self, raw_buff):
self.analyzed = False
self._resolved_strings = None
@ -1755,7 +1754,7 @@ class ARSCParser(object):
a_res_type = ARSCResType(self.buff, pc)
self.packages[package_name].append(a_res_type)
self.resource_configs[package_name][a_res_type].add(
a_res_type.config)
a_res_type.config)
entries = []
for i in range(0, a_res_type.entryCount):
@ -1898,7 +1897,7 @@ class ARSCParser(object):
ate.get_value(), "%s%s" % (
complexToFloat(ate.key.get_data()),
DIMENSION_UNITS[ate.key.get_data() & COMPLEX_UNIT_MASK])
]
]
except IndexError:
androconf.debug("Out of range dimension unit index for %s: %s" % (
complexToFloat(ate.key.get_data()),
@ -2202,14 +2201,13 @@ class ARSCParser(object):
for res_type, configs in list(self.resource_configs[package_name].items()):
if res_type.get_package_name() == package_name and (
type_name is None or res_type.get_type() == type_name):
type_name is None or res_type.get_type() == type_name):
result[res_type.get_type()].extend(configs)
return result
class PackageContext(object):
def __init__(self, current_package, stringpool_main, mTableStrings,
mKeyStrings):
self.stringpool_main = stringpool_main
@ -2238,7 +2236,6 @@ class ARSCHeader(object):
class ARSCResTablePackage(object):
def __init__(self, buff, header):
self.header = header
self.start = buff.get_idx()
@ -2257,7 +2254,6 @@ class ARSCResTablePackage(object):
class ARSCResTypeSpec(object):
def __init__(self, buff, parent=None):
self.start = buff.get_idx()
self.parent = parent
@ -2272,7 +2268,6 @@ class ARSCResTypeSpec(object):
class ARSCResType(object):
def __init__(self, buff, parent=None):
self.start = buff.get_idx()
self.parent = parent
@ -2412,7 +2407,6 @@ class ARSCResTableConfig(object):
class ARSCResTableEntry(object):
def __init__(self, buff, mResId, parent=None):
self.start = buff.get_idx()
self.mResId = mResId
@ -2452,7 +2446,6 @@ class ARSCResTableEntry(object):
class ARSCComplex(object):
def __init__(self, buff, parent=None):
self.start = buff.get_idx()
self.parent = parent
@ -2470,7 +2463,6 @@ class ARSCComplex(object):
class ARSCResStringPoolRef(object):
def __init__(self, buff, parent=None):
self.start = buff.get_idx()
self.parent = parent

File diff suppressed because it is too large Load Diff

View File

@ -2,322 +2,493 @@
DVM_PERMISSIONS = {
"MANIFEST_PERMISSION": {
# MESSAGES
"SEND_SMS": ["dangerous", "send SMS messages", "Allows application to send SMS messages. Malicious applications may cost you money by sending messages without your confirmation."],
"SEND_SMS_NO_CONFIRMATION": ["signatureOrSystem", "send SMS messages", "send SMS messages via the Messaging app with no user input or confirmation"],
"RECEIVE_SMS": ["dangerous", "receive SMS", "Allows application to receive and process SMS messages. Malicious applications may monitor your messages or delete them without showing them to you."],
"RECEIVE_MMS": ["dangerous", "receive MMS", "Allows application to receive and process MMS messages. Malicious applications may monitor your messages or delete them without showing them to you."],
"RECEIVE_EMERGENCY_BROADCAST": [ "signatureOrSystem", "", "Allows an application to receive emergency cell broadcast messages, to record or display them to the user. Reserved for system apps." ],
"READ_CELL_BROADCASTS" : [ "dangerous", "received cell broadcast messages", "Allows an application to read previously received cell broadcast "\
"messages and to register a content observer to get notifications when "\
"a cell broadcast has been received and added to the database. For "\
"emergency alerts, the database is updated immediately after the "\
"alert dialog and notification sound/vibration/speech are presented."\
"The \"read\" column is then updated after the user dismisses the alert."\
"This enables supplementary emergency assistance apps to start loading "\
"additional emergency information (if Internet access is available) "\
"when the alert is first received, and to delay presenting the info "\
"to the user until after the initial alert dialog is dismissed." ],
"READ_SMS" : [ "dangerous" , "read SMS or MMS" , "Allows application to read SMS messages stored on your phone or SIM card. Malicious applications may read your confidential messages." ],
"WRITE_SMS" : [ "dangerous" , "edit SMS or MMS" , "Allows application to write to SMS messages stored on your phone or SIM card. Malicious applications may delete your messages." ],
"RECEIVE_WAP_PUSH" : [ "dangerous" , "receive WAP" , "Allows application to receive and process WAP messages. Malicious applications may monitor your messages or delete them without showing them to you." ],
"BROADCAST_SMS" : [ "signature" , "send SMS-received broadcast" , "Allows an application to broadcast a notification that an SMS message has been received. Malicious applications may use this to forge incoming SMS messages." ],
"BROADCAST_WAP_PUSH" : [ "signature" , "send WAP-PUSH-received broadcast" , "Allows an application to broadcast a notification that a WAP-PUSH message has been received. Malicious applications may use this to forge MMS message receipt or to replace the content of any web page silently with malicious variants." ],
# MESSAGES
"SEND_SMS": ["dangerous", "send SMS messages",
"Allows application to send SMS messages. Malicious applications may cost you money by sending messages without your confirmation."],
"SEND_SMS_NO_CONFIRMATION": ["signatureOrSystem", "send SMS messages",
"send SMS messages via the Messaging app with no user input or confirmation"],
"RECEIVE_SMS": ["dangerous", "receive SMS",
"Allows application to receive and process SMS messages. Malicious applications may monitor your messages or delete them without showing them to you."],
"RECEIVE_MMS": ["dangerous", "receive MMS",
"Allows application to receive and process MMS messages. Malicious applications may monitor your messages or delete them without showing them to you."],
"RECEIVE_EMERGENCY_BROADCAST": ["signatureOrSystem", "",
"Allows an application to receive emergency cell broadcast messages, to record or display them to the user. Reserved for system apps."],
"READ_CELL_BROADCASTS": ["dangerous", "received cell broadcast messages",
"Allows an application to read previously received cell broadcast " \
"messages and to register a content observer to get notifications when " \
"a cell broadcast has been received and added to the database. For " \
"emergency alerts, the database is updated immediately after the " \
"alert dialog and notification sound/vibration/speech are presented." \
"The \"read\" column is then updated after the user dismisses the alert." \
"This enables supplementary emergency assistance apps to start loading " \
"additional emergency information (if Internet access is available) " \
"when the alert is first received, and to delay presenting the info " \
"to the user until after the initial alert dialog is dismissed."],
"READ_SMS": ["dangerous", "read SMS or MMS",
"Allows application to read SMS messages stored on your phone or SIM card. Malicious applications may read your confidential messages."],
"WRITE_SMS": ["dangerous", "edit SMS or MMS",
"Allows application to write to SMS messages stored on your phone or SIM card. Malicious applications may delete your messages."],
"RECEIVE_WAP_PUSH": ["dangerous", "receive WAP",
"Allows application to receive and process WAP messages. Malicious applications may monitor your messages or delete them without showing them to you."],
"BROADCAST_SMS": ["signature", "send SMS-received broadcast",
"Allows an application to broadcast a notification that an SMS message has been received. Malicious applications may use this to forge incoming SMS messages."],
"BROADCAST_WAP_PUSH": ["signature", "send WAP-PUSH-received broadcast",
"Allows an application to broadcast a notification that a WAP-PUSH message has been received. Malicious applications may use this to forge MMS message receipt or to replace the content of any web page silently with malicious variants."],
# SOCIAL_INFO
"READ_CONTACTS" : [ "dangerous" , "read contact data" , "Allows an application to read all of the contact (address) data stored on your phone. Malicious applications can use this to send your data to other people." ],
"WRITE_CONTACTS" : [ "dangerous" , "write contact data" , "Allows an application to modify the contact (address) data stored on your phone. Malicious applications can use this to erase or modify your contact data." ],
"BIND_DIRECTORY_SEARCH" : [ "signatureOrSystem", "execute contacts directory search", "Allows an application to execute contacts directory search. This should only be used by ContactsProvider." ],
"READ_CALL_LOG": [ "dangerous", "read the user's call log.", "Allows an application to read the user's call log." ],
"WRITE_CALL_LOG": [ "dangerous", "write (but not read) the user's contacts data.", "Allows an application to write (but not read) the user's contacts data." ],
"READ_SOCIAL_STREAM" : [ "dangerous", "read from the user's social stream", "Allows an application to read from the user's social stream." ],
"WRITE_SOCIAL_STREAM" : [ "dangerous", "write the user's social stream", "Allows an application to write (but not read) the user's social stream data." ],
# SOCIAL_INFO
"READ_CONTACTS": ["dangerous", "read contact data",
"Allows an application to read all of the contact (address) data stored on your phone. Malicious applications can use this to send your data to other people."],
"WRITE_CONTACTS": ["dangerous", "write contact data",
"Allows an application to modify the contact (address) data stored on your phone. Malicious applications can use this to erase or modify your contact data."],
"BIND_DIRECTORY_SEARCH": ["signatureOrSystem", "execute contacts directory search",
"Allows an application to execute contacts directory search. This should only be used by ContactsProvider."],
"READ_CALL_LOG": ["dangerous", "read the user's call log.",
"Allows an application to read the user's call log."],
"WRITE_CALL_LOG": ["dangerous", "write (but not read) the user's contacts data.",
"Allows an application to write (but not read) the user's contacts data."],
"READ_SOCIAL_STREAM": ["dangerous", "read from the user's social stream",
"Allows an application to read from the user's social stream."],
"WRITE_SOCIAL_STREAM": ["dangerous", "write the user's social stream",
"Allows an application to write (but not read) the user's social stream data."],
# PERSONAL_INFO
"READ_PROFILE" : [ "dangerous", "read the user's personal profile data", "Allows an application to read the user's personal profile data."],
"WRITE_PROFILE" : [ "dangerous", "write the user's personal profile data", "Allows an application to write (but not read) the user's personal profile data."],
"RETRIEVE_WINDOW_CONTENT": [ "signatureOrSystem", "", "Allows an application to retrieve the content of the active window An active window is the window that has fired an accessibility event. " ],
"BIND_APPWIDGET" : [ "signatureOrSystem" , "choose widgets" , "Allows the application to tell the system which widgets can be used by which application. With this permission, applications can give access to personal data to other applications. Not for use by normal applications." ],
"BIND_KEYGUARD_APPWIDGET" : [ "signatureOrSystem", "", "Private permission, to restrict who can bring up a dialog to add a new keyguard widget" ],
# PERSONAL_INFO
"READ_PROFILE": ["dangerous", "read the user's personal profile data",
"Allows an application to read the user's personal profile data."],
"WRITE_PROFILE": ["dangerous", "write the user's personal profile data",
"Allows an application to write (but not read) the user's personal profile data."],
"RETRIEVE_WINDOW_CONTENT": ["signatureOrSystem", "",
"Allows an application to retrieve the content of the active window An active window is the window that has fired an accessibility event. "],
"BIND_APPWIDGET": ["signatureOrSystem", "choose widgets",
"Allows the application to tell the system which widgets can be used by which application. With this permission, applications can give access to personal data to other applications. Not for use by normal applications."],
"BIND_KEYGUARD_APPWIDGET": ["signatureOrSystem", "",
"Private permission, to restrict who can bring up a dialog to add a new keyguard widget"],
# CALENDAR
"READ_CALENDAR" : [ "dangerous" , "read calendar events" , "Allows an application to read all of the calendar events stored on your phone. Malicious applications can use this to send your calendar events to other people." ],
"WRITE_CALENDAR": [ "dangerous" , "add or modify calendar events and send emails to guests" , "Allows an application to add or change the events on your calendar, which may send emails to guests. Malicious applications can use this to erase or modify your calendar events or to send emails to guests." ],
# CALENDAR
"READ_CALENDAR": ["dangerous", "read calendar events",
"Allows an application to read all of the calendar events stored on your phone. Malicious applications can use this to send your calendar events to other people."],
"WRITE_CALENDAR": ["dangerous", "add or modify calendar events and send emails to guests",
"Allows an application to add or change the events on your calendar, which may send emails to guests. Malicious applications can use this to erase or modify your calendar events or to send emails to guests."],
# USER_DICTIONARY
"READ_USER_DICTIONARY": ["dangerous", "read user-defined dictionary",
"Allows an application to read any private words, names and phrases that the user may have stored in the user dictionary."],
# USER_DICTIONARY
"READ_USER_DICTIONARY" : [ "dangerous" , "read user-defined dictionary" , "Allows an application to read any private words, names and phrases that the user may have stored in the user dictionary." ],
# WRITE_USER_DICTIONARY
"WRITE_USER_DICTIONARY": ["normal", "write to user-defined dictionary",
"Allows an application to write new words into the user dictionary."],
# WRITE_USER_DICTIONARY
"WRITE_USER_DICTIONARY" : [ "normal" , "write to user-defined dictionary" , "Allows an application to write new words into the user dictionary." ],
# BOOKMARKS
"READ_HISTORY_BOOKMARKS": ["dangerous", "read Browser\'s history and bookmarks",
"Allows the application to read all the URLs that the browser has visited and all of the browser\'s bookmarks."],
"WRITE_HISTORY_BOOKMARKS": ["dangerous", "write Browser\'s history and bookmarks",
"Allows an application to modify the browser\'s history or bookmarks stored on your phone. Malicious applications can use this to erase or modify your browser\'s data."],
# BOOKMARKS
"READ_HISTORY_BOOKMARKS" : [ "dangerous" , "read Browser\'s history and bookmarks" , "Allows the application to read all the URLs that the browser has visited and all of the browser\'s bookmarks." ],
"WRITE_HISTORY_BOOKMARKS" : [ "dangerous" , "write Browser\'s history and bookmarks" , "Allows an application to modify the browser\'s history or bookmarks stored on your phone. Malicious applications can use this to erase or modify your browser\'s data." ],
# DEVICE_ALARMS
"SET_ALARM": ["normal", "set alarm in alarm clock",
"Allows the application to set an alarm in an installed alarm clock application. Some alarm clock applications may not implement this feature."],
# DEVICE_ALARMS
"SET_ALARM" : [ "normal" , "set alarm in alarm clock" , "Allows the application to set an alarm in an installed alarm clock application. Some alarm clock applications may not implement this feature." ],
# VOICEMAIL
"ADD_VOICEMAIL": ["dangerous", "add voicemails into the system",
"Allows an application to add voicemails into the system."],
# VOICEMAIL
"ADD_VOICEMAIL" : [ "dangerous", "add voicemails into the system", "Allows an application to add voicemails into the system." ],
# LOCATION
"ACCESS_FINE_LOCATION": ["dangerous", "fine (GPS) location",
"Access fine location sources, such as the Global Positioning System on the phone, where available. Malicious applications can use this to determine where you are and may consume additional battery power."],
"ACCESS_COARSE_LOCATION": ["dangerous", "coarse (network-based) location",
"Access coarse location sources, such as the mobile network database, to determine an approximate phone location, where available. Malicious applications can use this to determine approximately where you are."],
"ACCESS_MOCK_LOCATION": ["dangerous", "mock location sources for testing",
"Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real-location sources such as GPS or Network providers."],
"ACCESS_LOCATION_EXTRA_COMMANDS": ["normal", "access extra location provider commands",
"Access extra location provider commands. Malicious applications could use this to interfere with the operation of the GPS or other location sources."],
"INSTALL_LOCATION_PROVIDER": ["signatureOrSystem", "permission to install a location provider",
"Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real-location sources such as GPS or Network providers, or monitor and report your location to an external source."],
# LOCATION
"ACCESS_FINE_LOCATION" : [ "dangerous" , "fine (GPS) location" , "Access fine location sources, such as the Global Positioning System on the phone, where available. Malicious applications can use this to determine where you are and may consume additional battery power." ],
"ACCESS_COARSE_LOCATION" : [ "dangerous" , "coarse (network-based) location" , "Access coarse location sources, such as the mobile network database, to determine an approximate phone location, where available. Malicious applications can use this to determine approximately where you are." ],
"ACCESS_MOCK_LOCATION" : [ "dangerous" , "mock location sources for testing" , "Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real-location sources such as GPS or Network providers." ],
"ACCESS_LOCATION_EXTRA_COMMANDS" : [ "normal" , "access extra location provider commands" , "Access extra location provider commands. Malicious applications could use this to interfere with the operation of the GPS or other location sources." ],
"INSTALL_LOCATION_PROVIDER" : [ "signatureOrSystem" , "permission to install a location provider" , "Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real-location sources such as GPS or Network providers, or monitor and report your location to an external source." ],
# NETWORK
"INTERNET": ["dangerous", "full Internet access", "Allows an application to create network sockets."],
"ACCESS_NETWORK_STATE": ["normal", "view network status",
"Allows an application to view the status of all networks."],
"ACCESS_WIFI_STATE": ["normal", "view Wi-Fi status",
"Allows an application to view the information about the status of Wi-Fi."],
"CHANGE_WIFI_STATE": ["dangerous", "change Wi-Fi status",
"Allows an application to connect to and disconnect from Wi-Fi access points and to make changes to configured Wi-Fi networks."],
"CHANGE_NETWORK_STATE": ["normal", "change network connectivity",
"Allows an application to change the state of network connectivity."],
"ACCESS_WIMAX_STATE": ["normal", "", ""],
"CHANGE_WIMAX_STATE": ["dangerous", "", ""],
"NFC": ["dangerous", "control Near-Field Communication",
"Allows an application to communicate with Near-Field Communication (NFC) tags, cards and readers."],
"CONNECTIVITY_INTERNAL": ["signatureOrSystem", "use privileged ConnectivityManager API",
"Allows an internal user to use privileged ConnectivityManager API"],
"RECEIVE_DATA_ACTIVITY_CHANGE": ["signatureOrSystem", "", ""],
# BLUETOOTH_NETWORK
"BLUETOOTH": ["dangerous", "create Bluetooth connections",
"Allows an application to view configuration of the local Bluetooth phone and to make and accept connections with paired devices."],
"BLUETOOTH_ADMIN": ["dangerous", "bluetooth administration",
"Allows an application to configure the local Bluetooth phone and to discover and pair with remote devices."],
# NETWORK
"INTERNET" : [ "dangerous" , "full Internet access" , "Allows an application to create network sockets." ],
"ACCESS_NETWORK_STATE" : [ "normal" , "view network status" , "Allows an application to view the status of all networks." ],
"ACCESS_WIFI_STATE" : [ "normal" , "view Wi-Fi status" , "Allows an application to view the information about the status of Wi-Fi." ],
"CHANGE_WIFI_STATE" : [ "dangerous" , "change Wi-Fi status" , "Allows an application to connect to and disconnect from Wi-Fi access points and to make changes to configured Wi-Fi networks." ],
"CHANGE_NETWORK_STATE" : [ "normal" , "change network connectivity" , "Allows an application to change the state of network connectivity." ],
"ACCESS_WIMAX_STATE": [ "normal", "", "" ],
"CHANGE_WIMAX_STATE": [ "dangerous", "", "" ],
"NFC" : [ "dangerous" , "control Near-Field Communication" , "Allows an application to communicate with Near-Field Communication (NFC) tags, cards and readers." ],
"CONNECTIVITY_INTERNAL": [ "signatureOrSystem", "use privileged ConnectivityManager API", "Allows an internal user to use privileged ConnectivityManager API" ],
"RECEIVE_DATA_ACTIVITY_CHANGE": [ "signatureOrSystem", "", "" ],
# BLUETOOTH_NETWORK
"BLUETOOTH" : [ "dangerous" , "create Bluetooth connections" , "Allows an application to view configuration of the local Bluetooth phone and to make and accept connections with paired devices." ],
"BLUETOOTH_ADMIN" : [ "dangerous" , "bluetooth administration" , "Allows an application to configure the local Bluetooth phone and to discover and pair with remote devices." ],
# SYSTEM TOOLS
"BLUETOOTH_STACK": [ "signature", "", "" ],
"NET_ADMIN": [ "signature", "configure network interfaces, configure/use IPSec, etc", "Allows access to configure network interfaces, configure/use IPSec, etc." ],
"REMOTE_AUDIO_PLAYBACK": [ "signature", "remote audio playback", "Allows registration for remote audio playback" ],
"READ_EXTERNAL_STORAGE" : [ "normal", "read from external storage", "Allows an application to read from external storage" ],
"INTERACT_ACROSS_USERS": [ "signatureOrSystemOrDevelopment", "", "Allows an application to call APIs that allow it to do interactions across the users on the device, using singleton services and user-targeted broadcasts. This permission is not available to third party applications." ],
"INTERACT_ACROSS_USERS_FULL": [ "signature", "", "Fuller form of INTERACT_ACROSS_USERS that removes restrictions on where broadcasts can be sent and allows other types of interactions." ],
"MANAGE_USERS": [ "signatureOrSystem", "", "Allows an application to call APIs that allow it to query and manage users on the device. This permission is not available to third party applications." ],
"GET_DETAILED_TASKS": [ "signature", "", "Allows an application to get full detailed information about recently running tasks, with full fidelity to the real state." ],
"START_ANY_ACTIVITY": [ "signature", "", "Allows an application to start any activity, regardless of permission protection or exported state." ],
"SET_SCREEN_COMPATIBILITY": [ "signature", "", "Change the screen compatibility mode of applications" ],
"CHANGE_CONFIGURATION" : [ "signatureOrSystemOrDevelopment" , "change your UI settings" , "Allows an application to change the current configuration, such as the locale or overall font size." ],
"FORCE_STOP_PACKAGES" : [ "signature" , "force-stop other applications" , "Allows an application to stop other applications forcibly." ],
"SET_ANIMATION_SCALE" : [ "signatureOrSystemOrDevelopment" , "modify global animation speed" , "Allows an application to change the global animation speed (faster or slower animations) at any time." ],
"GET_PACKAGE_SIZE" : [ "normal" , "measure application storage space" , "Allows an application to retrieve its code, data and cache sizes" ],
"SET_PREFERRED_APPLICATIONS" : [ "signature" , "set preferred applications" , "Allows an application to modify your preferred applications. This can allow malicious applications to silently change the applications that are run, spoofing your existing applications to collect private data from you." ],
"BROADCAST_STICKY" : [ "normal" , "send sticky broadcast" , "Allows an application to send sticky broadcasts, which remain after the broadcast ends. Malicious applications can make the phone slow or unstable by causing it to use too much memory." ],
"MOUNT_UNMOUNT_FILESYSTEMS" : [ "signatureOrSystem" , "mount and unmount file systems" , "Allows the application to mount and unmount file systems for removable storage." ],
"MOUNT_FORMAT_FILESYSTEMS" : [ "signatureOrSystem" , "format external storage" , "Allows the application to format removable storage." ],
"ASEC_ACCESS" : [ "signature" , "get information on internal storage" , "Allows the application to get information on internal storage." ],
"ASEC_CREATE" : [ "signature" , "create internal storage" , "Allows the application to create internal storage." ],
"ASEC_DESTROY" : [ "signature" , "destroy internal storage" , "Allows the application to destroy internal storage." ],
"ASEC_MOUNT_UNMOUNT" : [ "signature" , "mount/unmount internal storage" , "Allows the application to mount/unmount internal storage." ],
"ASEC_RENAME" : [ "signature" , "rename internal storage" , "Allows the application to rename internal storage." ],
"WRITE_APN_SETTINGS" : [ "signatureOrSystem" , "write Access Point Name settings" , "Allows an application to modify the APN settings, such as Proxy and Port of any APN." ],
"SUBSCRIBED_FEEDS_READ" : [ "normal" , "read subscribed feeds" , "Allows an application to receive details about the currently synced feeds." ],
"SUBSCRIBED_FEEDS_WRITE" : [ "dangerous" , "write subscribed feeds" , "Allows an application to modify your currently synced feeds. This could allow a malicious application to change your synced feeds." ],
"CLEAR_APP_CACHE" : [ "dangerous" , "delete all application cache data" , "Allows an application to free phone storage by deleting files in application cache directory. Access is usually very restricted to system process." ],
"DIAGNOSTIC" : [ "signature" , "read/write to resources owned by diag" , "Allows an application to read and write to any resource owned by the diag group; for example, files in /dev. This could potentially affect system stability and security. This should ONLY be used for hardware-specific diagnostics by the manufacturer or operator." ],
"BROADCAST_PACKAGE_REMOVED" : [ "signature" , "send package removed broadcast" , "Allows an application to broadcast a notification that an application package has been removed. Malicious applications may use this to kill any other application running." ],
"BATTERY_STATS" : [ "dangerous" , "modify battery statistics" , "Allows the modification of collected battery statistics. Not for use by normal applications." ],
"MODIFY_APPWIDGET_BIND_PERMISSIONS" : [ "signatureOrSystem", "query/set which applications can bind AppWidgets.", "Internal permission allowing an application to query/set which applications can bind AppWidgets." ],
"CHANGE_BACKGROUND_DATA_SETTING" : [ "signature" , "change background data usage setting" , "Allows an application to change the background data usage setting." ],
"GLOBAL_SEARCH" : [ "signatureOrSystem" , "" , "This permission can be used on content providers to allow the global search " \
"system to access their data. Typically it used when the provider has some " \
# SYSTEM TOOLS
"BLUETOOTH_STACK": ["signature", "", ""],
"NET_ADMIN": ["signature", "configure network interfaces, configure/use IPSec, etc",
"Allows access to configure network interfaces, configure/use IPSec, etc."],
"REMOTE_AUDIO_PLAYBACK": ["signature", "remote audio playback",
"Allows registration for remote audio playback"],
"READ_EXTERNAL_STORAGE": ["normal", "read from external storage",
"Allows an application to read from external storage"],
"INTERACT_ACROSS_USERS": ["signatureOrSystemOrDevelopment", "",
"Allows an application to call APIs that allow it to do interactions across the users on the device, using singleton services and user-targeted broadcasts. This permission is not available to third party applications."],
"INTERACT_ACROSS_USERS_FULL": ["signature", "",
"Fuller form of INTERACT_ACROSS_USERS that removes restrictions on where broadcasts can be sent and allows other types of interactions."],
"MANAGE_USERS": ["signatureOrSystem", "",
"Allows an application to call APIs that allow it to query and manage users on the device. This permission is not available to third party applications."],
"GET_DETAILED_TASKS": ["signature", "",
"Allows an application to get full detailed information about recently running tasks, with full fidelity to the real state."],
"START_ANY_ACTIVITY": ["signature", "",
"Allows an application to start any activity, regardless of permission protection or exported state."],
"SET_SCREEN_COMPATIBILITY": ["signature", "", "Change the screen compatibility mode of applications"],
"CHANGE_CONFIGURATION": ["signatureOrSystemOrDevelopment", "change your UI settings",
"Allows an application to change the current configuration, such as the locale or overall font size."],
"FORCE_STOP_PACKAGES": ["signature", "force-stop other applications",
"Allows an application to stop other applications forcibly."],
"SET_ANIMATION_SCALE": ["signatureOrSystemOrDevelopment", "modify global animation speed",
"Allows an application to change the global animation speed (faster or slower animations) at any time."],
"GET_PACKAGE_SIZE": ["normal", "measure application storage space",
"Allows an application to retrieve its code, data and cache sizes"],
"SET_PREFERRED_APPLICATIONS": ["signature", "set preferred applications",
"Allows an application to modify your preferred applications. This can allow malicious applications to silently change the applications that are run, spoofing your existing applications to collect private data from you."],
"BROADCAST_STICKY": ["normal", "send sticky broadcast",
"Allows an application to send sticky broadcasts, which remain after the broadcast ends. Malicious applications can make the phone slow or unstable by causing it to use too much memory."],
"MOUNT_UNMOUNT_FILESYSTEMS": ["signatureOrSystem", "mount and unmount file systems",
"Allows the application to mount and unmount file systems for removable storage."],
"MOUNT_FORMAT_FILESYSTEMS": ["signatureOrSystem", "format external storage",
"Allows the application to format removable storage."],
"ASEC_ACCESS": ["signature", "get information on internal storage",
"Allows the application to get information on internal storage."],
"ASEC_CREATE": ["signature", "create internal storage", "Allows the application to create internal storage."],
"ASEC_DESTROY": ["signature", "destroy internal storage",
"Allows the application to destroy internal storage."],
"ASEC_MOUNT_UNMOUNT": ["signature", "mount/unmount internal storage",
"Allows the application to mount/unmount internal storage."],
"ASEC_RENAME": ["signature", "rename internal storage", "Allows the application to rename internal storage."],
"WRITE_APN_SETTINGS": ["signatureOrSystem", "write Access Point Name settings",
"Allows an application to modify the APN settings, such as Proxy and Port of any APN."],
"SUBSCRIBED_FEEDS_READ": ["normal", "read subscribed feeds",
"Allows an application to receive details about the currently synced feeds."],
"SUBSCRIBED_FEEDS_WRITE": ["dangerous", "write subscribed feeds",
"Allows an application to modify your currently synced feeds. This could allow a malicious application to change your synced feeds."],
"CLEAR_APP_CACHE": ["dangerous", "delete all application cache data",
"Allows an application to free phone storage by deleting files in application cache directory. Access is usually very restricted to system process."],
"DIAGNOSTIC": ["signature", "read/write to resources owned by diag",
"Allows an application to read and write to any resource owned by the diag group; for example, files in /dev. This could potentially affect system stability and security. This should ONLY be used for hardware-specific diagnostics by the manufacturer or operator."],
"BROADCAST_PACKAGE_REMOVED": ["signature", "send package removed broadcast",
"Allows an application to broadcast a notification that an application package has been removed. Malicious applications may use this to kill any other application running."],
"BATTERY_STATS": ["dangerous", "modify battery statistics",
"Allows the modification of collected battery statistics. Not for use by normal applications."],
"MODIFY_APPWIDGET_BIND_PERMISSIONS": ["signatureOrSystem", "query/set which applications can bind AppWidgets.",
"Internal permission allowing an application to query/set which applications can bind AppWidgets."],
"CHANGE_BACKGROUND_DATA_SETTING": ["signature", "change background data usage setting",
"Allows an application to change the background data usage setting."],
"GLOBAL_SEARCH": ["signatureOrSystem", "",
"This permission can be used on content providers to allow the global search " \
"system to access their data. Typically it used when the provider has some " \
"permissions protecting it (which global search would not be expected to hold)," \
"and added as a read-only permission to the path in the provider where global "\
"search queries are performed. This permission can not be held by regular applications; "\
"it is used by applications to protect themselves from everyone else besides global search" ],
"GLOBAL_SEARCH_CONTROL" : [ "signature" , "" , "Internal permission protecting access to the global search " \
"system: ensures that only the system can access the provider " \
"to perform queries (since this otherwise provides unrestricted " \
"access to a variety of content providers), and to write the " \
"search statistics (to keep applications from gaming the source " \
"ranking)." ],
"SET_WALLPAPER_COMPONENT" : [ "signatureOrSystem" , "set a live wallpaper" , "Allows applications to set a live wallpaper." ],
"READ_DREAM_STATE" : [ "signature", "", "Allows applications to read dream settings and dream state." ],
"WRITE_DREAM_STATE" : [ "signature", "", "Allows applications to write dream settings, and start or stop dreaming." ],
"WRITE_SETTINGS" : [ "normal" , "modify global system settings" , "Allows an application to modify the system\'s settings data. Malicious applications can corrupt your system\'s configuration." ],
"and added as a read-only permission to the path in the provider where global " \
"search queries are performed. This permission can not be held by regular applications; " \
"it is used by applications to protect themselves from everyone else besides global search"],
"GLOBAL_SEARCH_CONTROL": ["signature", "", "Internal permission protecting access to the global search " \
"system: ensures that only the system can access the provider " \
"to perform queries (since this otherwise provides unrestricted " \
"access to a variety of content providers), and to write the " \
"search statistics (to keep applications from gaming the source " \
"ranking)."],
"SET_WALLPAPER_COMPONENT": ["signatureOrSystem", "set a live wallpaper",
"Allows applications to set a live wallpaper."],
"READ_DREAM_STATE": ["signature", "", "Allows applications to read dream settings and dream state."],
"WRITE_DREAM_STATE": ["signature", "",
"Allows applications to write dream settings, and start or stop dreaming."],
"WRITE_SETTINGS": ["normal", "modify global system settings",
"Allows an application to modify the system\'s settings data. Malicious applications can corrupt your system\'s configuration."],
# ACCOUNTS
"GET_ACCOUNTS" : [ "normal" , "discover known accounts" , "Allows an application to access the list of accounts known by the phone." ],
"AUTHENTICATE_ACCOUNTS" : [ "dangerous" , "act as an account authenticator" , "Allows an application to use the account authenticator capabilities of the Account Manager, including creating accounts as well as obtaining and setting their passwords." ],
"USE_CREDENTIALS" : [ "dangerous" , "use the authentication credentials of an account" , "Allows an application to request authentication tokens." ],
"MANAGE_ACCOUNTS" : [ "dangerous" , "manage the accounts list" , "Allows an application to perform operations like adding and removing accounts and deleting their password." ],
"ACCOUNT_MANAGER" : [ "signature" , "act as the Account Manager Service" , "Allows an application to make calls to Account Authenticators" ],
# ACCOUNTS
"GET_ACCOUNTS": ["normal", "discover known accounts",
"Allows an application to access the list of accounts known by the phone."],
"AUTHENTICATE_ACCOUNTS": ["dangerous", "act as an account authenticator",
"Allows an application to use the account authenticator capabilities of the Account Manager, including creating accounts as well as obtaining and setting their passwords."],
"USE_CREDENTIALS": ["dangerous", "use the authentication credentials of an account",
"Allows an application to request authentication tokens."],
"MANAGE_ACCOUNTS": ["dangerous", "manage the accounts list",
"Allows an application to perform operations like adding and removing accounts and deleting their password."],
"ACCOUNT_MANAGER": ["signature", "act as the Account Manager Service",
"Allows an application to make calls to Account Authenticators"],
# AFFECTS_BATTERY
"CHANGE_WIFI_MULTICAST_STATE" : [ "dangerous" , "allow Wi-Fi Multicast reception" , "Allows an application to receive packets not directly addressed to your device. This can be useful when discovering services offered nearby. It uses more power than the non-multicast mode." ],
"VIBRATE" : [ "normal" , "control vibrator" , "Allows the application to control the vibrator." ],
"FLASHLIGHT" : [ "normal" , "control flashlight" , "Allows the application to control the flashlight." ],
"WAKE_LOCK" : [ "normal" , "prevent phone from sleeping" , "Allows an application to prevent the phone from going to sleep." ],
# AFFECTS_BATTERY
"CHANGE_WIFI_MULTICAST_STATE": ["dangerous", "allow Wi-Fi Multicast reception",
"Allows an application to receive packets not directly addressed to your device. This can be useful when discovering services offered nearby. It uses more power than the non-multicast mode."],
"VIBRATE": ["normal", "control vibrator", "Allows the application to control the vibrator."],
"FLASHLIGHT": ["normal", "control flashlight", "Allows the application to control the flashlight."],
"WAKE_LOCK": ["normal", "prevent phone from sleeping",
"Allows an application to prevent the phone from going to sleep."],
# AUDIO_SETTINGS
"MODIFY_AUDIO_SETTINGS" : [ "normal" , "change your audio settings" , "Allows application to modify global audio settings, such as volume and routing." ],
# AUDIO_SETTINGS
"MODIFY_AUDIO_SETTINGS": ["normal", "change your audio settings",
"Allows application to modify global audio settings, such as volume and routing."],
# HARDWARE_CONTROLS
"MANAGE_USB": [ "signatureOrSystem", "manage preferences and permissions for USB devices", "Allows an application to manage preferences and permissions for USB devices" ],
"ACCESS_MTP": [ "signatureOrSystem", "access the MTP USB kernel driver", "Allows an application to access the MTP USB kernel driver. For use only by the device side MTP implementation." ],
"HARDWARE_TEST" : [ "signature" , "test hardware" , "Allows the application to control various peripherals for the purpose of hardware testing." ],
# HARDWARE_CONTROLS
"MANAGE_USB": ["signatureOrSystem", "manage preferences and permissions for USB devices",
"Allows an application to manage preferences and permissions for USB devices"],
"ACCESS_MTP": ["signatureOrSystem", "access the MTP USB kernel driver",
"Allows an application to access the MTP USB kernel driver. For use only by the device side MTP implementation."],
"HARDWARE_TEST": ["signature", "test hardware",
"Allows the application to control various peripherals for the purpose of hardware testing."],
# MICROPHONE
"RECORD_AUDIO" : [ "dangerous" , "record audio" , "Allows application to access the audio record path." ],
# MICROPHONE
"RECORD_AUDIO": ["dangerous", "record audio", "Allows application to access the audio record path."],
# CAMERA
"CAMERA" : [ "dangerous" , "take pictures and videos" , "Allows application to take pictures and videos with the camera. This allows the application to collect images that the camera is seeing at any time." ],
# CAMERA
"CAMERA": ["dangerous", "take pictures and videos",
"Allows application to take pictures and videos with the camera. This allows the application to collect images that the camera is seeing at any time."],
# PHONE_CALLS
"PROCESS_OUTGOING_CALLS" : [ "dangerous" , "intercept outgoing calls" , "Allows application to process outgoing calls and change the number to be dialled. Malicious applications may monitor, redirect or prevent outgoing calls." ],
"MODIFY_PHONE_STATE" : [ "signatureOrSystem" , "modify phone status" , "Allows modification of the telephony state - power on, mmi, etc. Does not include placing calls." ],
"READ_PHONE_STATE" : [ "dangerous" , "read phone state and identity" , "Allows the application to access the phone features of the device. An application with this permission can determine the phone number and serial number of this phone, whether a call is active, the number that call is connected to and so on." ],
"READ_PRIVILEGED_PHONE_STATE": [ "signatureOrSystem", "read access to privileged phone state", "Allows read access to privileged phone state." ],
"CALL_PHONE" : [ "dangerous" , "directly call phone numbers" , "Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call being placed. " ],
"USE_SIP" : [ "dangerous" , "make/receive Internet calls" , "Allows an application to use the SIP service to make/receive Internet calls." ],
# PHONE_CALLS
"PROCESS_OUTGOING_CALLS": ["dangerous", "intercept outgoing calls",
"Allows application to process outgoing calls and change the number to be dialled. Malicious applications may monitor, redirect or prevent outgoing calls."],
"MODIFY_PHONE_STATE": ["signatureOrSystem", "modify phone status",
"Allows modification of the telephony state - power on, mmi, etc. Does not include placing calls."],
"READ_PHONE_STATE": ["dangerous", "read phone state and identity",
"Allows the application to access the phone features of the device. An application with this permission can determine the phone number and serial number of this phone, whether a call is active, the number that call is connected to and so on."],
"READ_PRIVILEGED_PHONE_STATE": ["signatureOrSystem", "read access to privileged phone state",
"Allows read access to privileged phone state."],
"CALL_PHONE": ["dangerous", "directly call phone numbers",
"Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call being placed. "],
"USE_SIP": ["dangerous", "make/receive Internet calls",
"Allows an application to use the SIP service to make/receive Internet calls."],
# STORAGE
"WRITE_EXTERNAL_STORAGE" : [ "dangerous" , "modify/delete SD card contents" , "Allows an application to write to the SD card." ],
"WRITE_MEDIA_STORAGE": [ "signatureOrSystem", "write to internal media storage", "Allows an application to write to internal media storage" ],
# STORAGE
"WRITE_EXTERNAL_STORAGE": ["dangerous", "modify/delete SD card contents",
"Allows an application to write to the SD card."],
"WRITE_MEDIA_STORAGE": ["signatureOrSystem", "write to internal media storage",
"Allows an application to write to internal media storage"],
# SCREENLOCK
"DISABLE_KEYGUARD" : [ "dangerous" , "disable key lock" , "Allows an application to disable the key lock and any associated password security. A legitimate example of this is the phone disabling the key lock when receiving an incoming phone call, then re-enabling the key lock when the call is finished." ],
# SCREENLOCK
"DISABLE_KEYGUARD": ["dangerous", "disable key lock",
"Allows an application to disable the key lock and any associated password security. A legitimate example of this is the phone disabling the key lock when receiving an incoming phone call, then re-enabling the key lock when the call is finished."],
# APP_INFO
"GET_TASKS" : [ "dangerous" , "retrieve running applications" , "Allows application to retrieve information about currently and recently running tasks. May allow malicious applications to discover private information about other applications." ],
"REORDER_TASKS" : [ "normal" , "reorder applications running" , "Allows an application to move tasks to the foreground and background. Malicious applications can force themselves to the front without your control." ],
"REMOVE_TASKS": [ "signature", "", "Allows an application to change to remove/kill tasks" ],
"RESTART_PACKAGES" : [ "normal" , "kill background processes" , "Allows an application to kill background processes of other applications, even if memory is not low." ],
"KILL_BACKGROUND_PROCESSES" : [ "normal" , "kill background processes" , "Allows an application to kill background processes of other applications, even if memory is not low." ],
"PERSISTENT_ACTIVITY" : [ "normal" , "make application always run" , "Allows an application to make parts of itself persistent, so that the system can\'t use it for other applications." ],
"RECEIVE_BOOT_COMPLETED" : [ "normal" , "automatically start at boot" , "Allows an application to start itself as soon as the system has finished booting. This can make it take longer to start the phone and allow the application to slow down the overall phone by always running." ],
# APP_INFO
"GET_TASKS": ["dangerous", "retrieve running applications",
"Allows application to retrieve information about currently and recently running tasks. May allow malicious applications to discover private information about other applications."],
"REORDER_TASKS": ["normal", "reorder applications running",
"Allows an application to move tasks to the foreground and background. Malicious applications can force themselves to the front without your control."],
"REMOVE_TASKS": ["signature", "", "Allows an application to change to remove/kill tasks"],
"RESTART_PACKAGES": ["normal", "kill background processes",
"Allows an application to kill background processes of other applications, even if memory is not low."],
"KILL_BACKGROUND_PROCESSES": ["normal", "kill background processes",
"Allows an application to kill background processes of other applications, even if memory is not low."],
"PERSISTENT_ACTIVITY": ["normal", "make application always run",
"Allows an application to make parts of itself persistent, so that the system can\'t use it for other applications."],
"RECEIVE_BOOT_COMPLETED": ["normal", "automatically start at boot",
"Allows an application to start itself as soon as the system has finished booting. This can make it take longer to start the phone and allow the application to slow down the overall phone by always running."],
# DISPLAY
"SYSTEM_ALERT_WINDOW" : [ "dangerous" , "display system-level alerts" , "Allows an application to show system-alert windows. Malicious applications can take over the entire screen of the phone." ],
# DISPLAY
"SYSTEM_ALERT_WINDOW": ["dangerous", "display system-level alerts",
"Allows an application to show system-alert windows. Malicious applications can take over the entire screen of the phone."],
# WALLPAPER
"SET_WALLPAPER" : [ "normal" , "set wallpaper" , "Allows the application to set the system wallpaper." ],
"SET_WALLPAPER_HINTS" : [ "normal" , "set wallpaper size hints" , "Allows the application to set the system wallpaper size hints." ],
# WALLPAPER
"SET_WALLPAPER": ["normal", "set wallpaper", "Allows the application to set the system wallpaper."],
"SET_WALLPAPER_HINTS": ["normal", "set wallpaper size hints",
"Allows the application to set the system wallpaper size hints."],
# SYSTEM_CLOCK
"SET_TIME_ZONE" : [ "normal" , "set time zone" , "Allows an application to change the phone\'s time zone." ],
# SYSTEM_CLOCK
"SET_TIME_ZONE": ["normal", "set time zone", "Allows an application to change the phone\'s time zone."],
# STATUS_BAR
"EXPAND_STATUS_BAR" : [ "normal" , "expand/collapse status bar" , "Allows application to expand or collapse the status bar." ],
# STATUS_BAR
"EXPAND_STATUS_BAR": ["normal", "expand/collapse status bar",
"Allows application to expand or collapse the status bar."],
# SYNC_SETTINGS
"READ_SYNC_SETTINGS" : [ "normal" , "read sync settings" , "Allows an application to read the sync settings, such as whether sync is enabled for Contacts." ],
"WRITE_SYNC_SETTINGS" : [ "normal" , "write sync settings" , "Allows an application to modify the sync settings, such as whether sync is enabled for Contacts." ],
"READ_SYNC_STATS" : [ "normal" , "read sync statistics" , "Allows an application to read the sync stats; e.g. the history of syncs that have occurred." ],
# SYNC_SETTINGS
"READ_SYNC_SETTINGS": ["normal", "read sync settings",
"Allows an application to read the sync settings, such as whether sync is enabled for Contacts."],
"WRITE_SYNC_SETTINGS": ["normal", "write sync settings",
"Allows an application to modify the sync settings, such as whether sync is enabled for Contacts."],
"READ_SYNC_STATS": ["normal", "read sync statistics",
"Allows an application to read the sync stats; e.g. the history of syncs that have occurred."],
# DEVELOPMENT_TOOLS
"WRITE_SECURE_SETTINGS" : [ "signatureOrSystemOrDevelopment" , "modify secure system settings" , "Allows an application to modify the system\'s secure settings data. Not for use by normal applications." ],
"DUMP" : [ "signatureOrSystemOrDevelopment" , "retrieve system internal status" , "Allows application to retrieve internal status of the system. Malicious applications may retrieve a wide variety of private and secure information that they should never normally need." ],
"READ_LOGS" : [ "signatureOrSystemOrDevelopment" , "read sensitive log data" , "Allows an application to read from the system\'s various log files. This allows it to discover general information about what you are doing with the phone, potentially including personal or private information." ],
"SET_DEBUG_APP" : [ "signatureOrSystemOrDevelopment" , "enable application debugging" , "Allows an application to turn on debugging for another application. Malicious applications can use this to kill other applications." ],
"SET_PROCESS_LIMIT" : [ "signatureOrSystemOrDevelopment" , "limit number of running processes" , "Allows an application to control the maximum number of processes that will run. Never needed for normal applications." ],
"SET_ALWAYS_FINISH" : [ "signatureOrSystemOrDevelopment" , "make all background applications close" , "Allows an application to control whether activities are always finished as soon as they go to the background. Never needed for normal applications." ],
"SIGNAL_PERSISTENT_PROCESSES" : [ "signatureOrSystemOrDevelopment" , "send Linux signals to applications" , "Allows application to request that the supplied signal be sent to all persistent processes." ],
"ACCESS_ALL_EXTERNAL_STORAGE" : [ "signature", "", "Allows an application to access all multi-user external storage" ],
# DEVELOPMENT_TOOLS
"WRITE_SECURE_SETTINGS": ["signatureOrSystemOrDevelopment", "modify secure system settings",
"Allows an application to modify the system\'s secure settings data. Not for use by normal applications."],
"DUMP": ["signatureOrSystemOrDevelopment", "retrieve system internal status",
"Allows application to retrieve internal status of the system. Malicious applications may retrieve a wide variety of private and secure information that they should never normally need."],
"READ_LOGS": ["signatureOrSystemOrDevelopment", "read sensitive log data",
"Allows an application to read from the system\'s various log files. This allows it to discover general information about what you are doing with the phone, potentially including personal or private information."],
"SET_DEBUG_APP": ["signatureOrSystemOrDevelopment", "enable application debugging",
"Allows an application to turn on debugging for another application. Malicious applications can use this to kill other applications."],
"SET_PROCESS_LIMIT": ["signatureOrSystemOrDevelopment", "limit number of running processes",
"Allows an application to control the maximum number of processes that will run. Never needed for normal applications."],
"SET_ALWAYS_FINISH": ["signatureOrSystemOrDevelopment", "make all background applications close",
"Allows an application to control whether activities are always finished as soon as they go to the background. Never needed for normal applications."],
"SIGNAL_PERSISTENT_PROCESSES": ["signatureOrSystemOrDevelopment", "send Linux signals to applications",
"Allows application to request that the supplied signal be sent to all persistent processes."],
"ACCESS_ALL_EXTERNAL_STORAGE": ["signature", "",
"Allows an application to access all multi-user external storage"],
# No groups ...
"SET_TIME": [ "signatureOrSystem" , "set time" , "Allows an application to change the phone\'s clock time." ],
"ALLOW_ANY_CODEC_FOR_PLAYBACK": [ "signatureOrSystem", "", "Allows an application to use any media decoder when decoding for playback." ],
"STATUS_BAR" : [ "signatureOrSystem" , "disable or modify status bar" , "Allows application to disable the status bar or add and remove system icons." ],
"STATUS_BAR_SERVICE" : [ "signature" , "status bar" , "Allows the application to be the status bar." ],
"FORCE_BACK" : [ "signature" , "force application to close" , "Allows an application to force any activity that is in the foreground to close and go back. Should never be needed for normal applications." ],
"UPDATE_DEVICE_STATS" : [ "signatureOrSystem" , "modify battery statistics" , "Allows the modification of collected battery statistics. Not for use by normal applications." ],
"INTERNAL_SYSTEM_WINDOW" : [ "signature" , "display unauthorised windows" , "Allows the creation of windows that are intended to be used by the internal system user interface. Not for use by normal applications." ],
"MANAGE_APP_TOKENS" : [ "signature" , "manage application tokens" , "Allows applications to create and manage their own tokens, bypassing their normal Z-ordering. Should never be needed for normal applications." ],
"FREEZE_SCREEN": [ "signature", "", "Allows the application to temporarily freeze the screen for a full-screen transition." ],
"INJECT_EVENTS" : [ "signature" , "inject user events" , "Allows an application to inject user events (keys, touch, trackball) into the event stream and deliver them to ANY window. Without this permission, you can only deliver events to windows in your own process. Very few applications should need to use this permission" ],
"FILTER_EVENTS": [ "signature", "", "Allows an application to register an input filter which filters the stream of user events (keys, touch, trackball) before they are dispatched to any window" ],
"RETRIEVE_WINDOW_INFO" : [ "signature", "", "Allows an application to retrieve info for a window from the window manager." ],
"TEMPORARY_ENABLE_ACCESSIBILITY": [ "signature", "", "Allows an application to temporary enable accessibility on the device." ],
"MAGNIFY_DISPLAY": [ "signature", "", "Allows an application to magnify the content of a display." ],
"SET_ACTIVITY_WATCHER" : [ "signature" , "monitor and control all application launching" , "Allows an application to monitor and control how the system launches activities. Malicious applications may compromise the system completely. This permission is needed only for development, never for normal phone usage." ],
"SHUTDOWN" : [ "signatureOrSystem" , "partial shutdown" , "Puts the activity manager into a shut-down state. Does not perform a complete shut down." ],
"STOP_APP_SWITCHES" : [ "signatureOrSystem" , "prevent app switches" , "Prevents the user from switching to another application." ],
"READ_INPUT_STATE" : [ "signature" , "record what you type and actions that you take" , "Allows applications to watch the keys that you press even when interacting with another application (such as entering a password). Should never be needed for normal applications." ],
"BIND_INPUT_METHOD" : [ "signature" , "bind to an input method" , "Allows the holder to bind to the top-level interface of an input method. Should never be needed for normal applications." ],
"BIND_ACCESSIBILITY_SERVICE" : [ "signature", "", "Must be required by an android.accessibilityservice.AccessibilityService to ensure that only the system can bind to it. " ],
"BIND_TEXT_SERVICE" : [ "signature", "", "Must be required by a TextService (e.g. SpellCheckerService) to ensure that only the system can bind to it." ],
"BIND_VPN_SERVICE" : [ "signature", "", "Must be required by an {@link android.net.VpnService}, to ensure that only the system can bind to it." ],
"BIND_WALLPAPER" : [ "signatureOrSystem" , "bind to wallpaper" , "Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications." ],
"BIND_DEVICE_ADMIN" : [ "signature" , "interact with device admin" , "Allows the holder to send intents to a device administrator. Should never be needed for normal applications." ],
"SET_ORIENTATION" : [ "signature" , "change screen orientation" , "Allows an application to change the rotation of the screen at any time. Should never be needed for normal applications." ],
"SET_POINTER_SPEED" : [ "signature", "", "Allows low-level access to setting the pointer speed. Not for use by normal applications. " ],
"SET_KEYBOARD_LAYOUT" : [ "signature", "", "Allows low-level access to setting the keyboard layout. Not for use by normal applications." ],
"INSTALL_PACKAGES" : [ "signatureOrSystem" , "directly install applications" , "Allows an application to install new or updated Android packages. Malicious applications can use this to add new applications with arbitrarily powerful permissions." ],
"CLEAR_APP_USER_DATA" : [ "signature" , "delete other applications\' data" , "Allows an application to clear user data." ],
"DELETE_CACHE_FILES" : [ "signatureOrSystem" , "delete other applications\' caches" , "Allows an application to delete cache files." ],
"DELETE_PACKAGES" : [ "signatureOrSystem" , "delete applications" , "Allows an application to delete Android packages. Malicious applications can use this to delete important applications." ],
"MOVE_PACKAGE" : [ "signatureOrSystem" , "Move application resources" , "Allows an application to move application resources from internal to external media and vice versa." ],
"CHANGE_COMPONENT_ENABLED_STATE" : [ "signatureOrSystem" , "enable or disable application components" , "Allows an application to change whether or not a component of another application is enabled. Malicious applications can use this to disable important phone capabilities. It is important to be careful with permission, as it is possible to bring application components into an unusable, inconsistent or unstable state." ],
"GRANT_REVOKE_PERMISSIONS" : [ "signature", "", "Allows an application to grant or revoke specific permissions." ],
"ACCESS_SURFACE_FLINGER" : [ "signature" , "access SurfaceFlinger" , "Allows application to use SurfaceFlinger low-level features." ],
"READ_FRAME_BUFFER" : [ "signatureOrSystem" , "read frame buffer" , "Allows application to read the content of the frame buffer." ],
"CONFIGURE_WIFI_DISPLAY" : [ "signature", "", "Allows an application to configure and connect to Wifi displays" ],
"CONTROL_WIFI_DISPLAY" : [ "signature", "", "Allows an application to control low-level features of Wifi displays such as opening an RTSP socket. This permission should only be used by the display manager." ],
"BRICK" : [ "signature" , "permanently disable phone" , "Allows the application to disable the entire phone permanently. This is very dangerous." ],
"REBOOT" : [ "signatureOrSystem" , "force phone reboot" , "Allows the application to force the phone to reboot." ],
"DEVICE_POWER" : [ "signature" , "turn phone on or off" , "Allows the application to turn the phone on or off." ],
"NET_TUNNELING" : [ "signature", "", "Allows low-level access to tun tap driver " ],
"FACTORY_TEST" : [ "signature" , "run in factory test mode" , "Run as a low-level manufacturer test, allowing complete access to the phone hardware. Only available when a phone is running in manufacturer test mode." ],
"MASTER_CLEAR" : [ "signatureOrSystem" , "reset system to factory defaults" , "Allows an application to completely reset the system to its factory settings, erasing all data, configuration and installed applications." ],
"CALL_PRIVILEGED" : [ "signatureOrSystem" , "directly call any phone numbers" , "Allows the application to call any phone number, including emergency numbers, without your intervention. Malicious applications may place unnecessary and illegal calls to emergency services." ],
"PERFORM_CDMA_PROVISIONING" : [ "signatureOrSystem" , "directly start CDMA phone setup" , "Allows the application to start CDMA provisioning. Malicious applications may start CDMA provisioning unnecessarily" ],
"CONTROL_LOCATION_UPDATES" : [ "signatureOrSystem" , "control location update notifications" , "Allows enabling/disabling location update notifications from the radio. Not for use by normal applications." ],
"ACCESS_CHECKIN_PROPERTIES" : [ "signatureOrSystem" , "access check-in properties" , "Allows read/write access to properties uploaded by the check-in service. Not for use by normal applications." ],
"PACKAGE_USAGE_STATS" : [ "signatureOrSystem" , "update component usage statistics" , "Allows the modification of collected component usage statistics. Not for use by normal applications." ],
"BACKUP" : [ "signatureOrSystem" , "control system back up and restore" , "Allows the application to control the system\'s back-up and restore mechanism. Not for use by normal applications." ],
"CONFIRM_FULL_BACKUP" : [ "signature", "", "Allows a package to launch the secure full-backup confirmation UI. ONLY the system process may hold this permission." ],
"BIND_REMOTEVIEWS" : [ "signatureOrSystem", "", "Must be required by a {@link android.widget.RemoteViewsService}, to ensure that only the system can bind to it." ],
"ACCESS_CACHE_FILESYSTEM" : [ "signatureOrSystem" , "access the cache file system" , "Allows an application to read and write the cache file system." ],
"COPY_PROTECTED_DATA" : [ "signature" , "Allows to invoke default container service to copy content. Not for use by normal applications." , "Allows to invoke default container service to copy content. Not for use by normal applications." ],
"CRYPT_KEEPER" : [ "signatureOrSystem", "access to the encryption methods", "Internal permission protecting access to the encryption methods" ],
"READ_NETWORK_USAGE_HISTORY" : [ "signatureOrSystem", "read historical network usage for specific networks and applications.", "Allows an application to read historical network usage for specific networks and applications."],
"MANAGE_NETWORK_POLICY": [ "signature", "manage network policies and to define application-specific rules.", "Allows an application to manage network policies and to define application-specific rules."],
"MODIFY_NETWORK_ACCOUNTING" : [ "signatureOrSystem", "account its network traffic against other UIDs.", "Allows an application to account its network traffic against other UIDs."],
"C2D_MESSAGE" : [ "signature" , "C2DM permission." , "C2DM permission." ],
"PACKAGE_VERIFICATION_AGENT" : [ "signatureOrSystem", "Package verifier needs to have this permission before the PackageManager will trust it to verify packages.", "Package verifier needs to have this permission before the PackageManager will trust it to verify packages."],
"BIND_PACKAGE_VERIFIER" : [ "signature", "", "Must be required by package verifier receiver, to ensure that only the system can interact with it.."],
"SERIAL_PORT" : [ "signature", "", "Allows applications to access serial ports via the SerialManager." ],
"ACCESS_CONTENT_PROVIDERS_EXTERNALLY": [ "signature", "", "Allows the holder to access content providers from outside an ApplicationThread. This permission is enforced by the ActivityManagerService on the corresponding APIs,in particular ActivityManagerService#getContentProviderExternal(String) and ActivityManagerService#removeContentProviderExternal(String)."],
"UPDATE_LOCK" : [ "signatureOrSystem", "", "Allows an application to hold an UpdateLock, recommending that a headless OTA reboot "\
"*not* occur while the lock is held"],
"WRITE_GSERVICES" : [ "signatureOrSystem" , "modify the Google services map" , "Allows an application to modify the Google services map. Not for use by normal applications." ],
# No groups ...
"SET_TIME": ["signatureOrSystem", "set time", "Allows an application to change the phone\'s clock time."],
"ALLOW_ANY_CODEC_FOR_PLAYBACK": ["signatureOrSystem", "",
"Allows an application to use any media decoder when decoding for playback."],
"STATUS_BAR": ["signatureOrSystem", "disable or modify status bar",
"Allows application to disable the status bar or add and remove system icons."],
"STATUS_BAR_SERVICE": ["signature", "status bar", "Allows the application to be the status bar."],
"FORCE_BACK": ["signature", "force application to close",
"Allows an application to force any activity that is in the foreground to close and go back. Should never be needed for normal applications."],
"UPDATE_DEVICE_STATS": ["signatureOrSystem", "modify battery statistics",
"Allows the modification of collected battery statistics. Not for use by normal applications."],
"INTERNAL_SYSTEM_WINDOW": ["signature", "display unauthorised windows",
"Allows the creation of windows that are intended to be used by the internal system user interface. Not for use by normal applications."],
"MANAGE_APP_TOKENS": ["signature", "manage application tokens",
"Allows applications to create and manage their own tokens, bypassing their normal Z-ordering. Should never be needed for normal applications."],
"FREEZE_SCREEN": ["signature", "",
"Allows the application to temporarily freeze the screen for a full-screen transition."],
"INJECT_EVENTS": ["signature", "inject user events",
"Allows an application to inject user events (keys, touch, trackball) into the event stream and deliver them to ANY window. Without this permission, you can only deliver events to windows in your own process. Very few applications should need to use this permission"],
"FILTER_EVENTS": ["signature", "",
"Allows an application to register an input filter which filters the stream of user events (keys, touch, trackball) before they are dispatched to any window"],
"RETRIEVE_WINDOW_INFO": ["signature", "",
"Allows an application to retrieve info for a window from the window manager."],
"TEMPORARY_ENABLE_ACCESSIBILITY": ["signature", "",
"Allows an application to temporary enable accessibility on the device."],
"MAGNIFY_DISPLAY": ["signature", "", "Allows an application to magnify the content of a display."],
"SET_ACTIVITY_WATCHER": ["signature", "monitor and control all application launching",
"Allows an application to monitor and control how the system launches activities. Malicious applications may compromise the system completely. This permission is needed only for development, never for normal phone usage."],
"SHUTDOWN": ["signatureOrSystem", "partial shutdown",
"Puts the activity manager into a shut-down state. Does not perform a complete shut down."],
"STOP_APP_SWITCHES": ["signatureOrSystem", "prevent app switches",
"Prevents the user from switching to another application."],
"READ_INPUT_STATE": ["signature", "record what you type and actions that you take",
"Allows applications to watch the keys that you press even when interacting with another application (such as entering a password). Should never be needed for normal applications."],
"BIND_INPUT_METHOD": ["signature", "bind to an input method",
"Allows the holder to bind to the top-level interface of an input method. Should never be needed for normal applications."],
"BIND_ACCESSIBILITY_SERVICE": ["signature", "",
"Must be required by an android.accessibilityservice.AccessibilityService to ensure that only the system can bind to it. "],
"BIND_TEXT_SERVICE": ["signature", "",
"Must be required by a TextService (e.g. SpellCheckerService) to ensure that only the system can bind to it."],
"BIND_VPN_SERVICE": ["signature", "",
"Must be required by an {@link android.net.VpnService}, to ensure that only the system can bind to it."],
"BIND_WALLPAPER": ["signatureOrSystem", "bind to wallpaper",
"Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications."],
"BIND_DEVICE_ADMIN": ["signature", "interact with device admin",
"Allows the holder to send intents to a device administrator. Should never be needed for normal applications."],
"SET_ORIENTATION": ["signature", "change screen orientation",
"Allows an application to change the rotation of the screen at any time. Should never be needed for normal applications."],
"SET_POINTER_SPEED": ["signature", "",
"Allows low-level access to setting the pointer speed. Not for use by normal applications. "],
"SET_KEYBOARD_LAYOUT": ["signature", "",
"Allows low-level access to setting the keyboard layout. Not for use by normal applications."],
"INSTALL_PACKAGES": ["signatureOrSystem", "directly install applications",
"Allows an application to install new or updated Android packages. Malicious applications can use this to add new applications with arbitrarily powerful permissions."],
"CLEAR_APP_USER_DATA": ["signature", "delete other applications\' data",
"Allows an application to clear user data."],
"DELETE_CACHE_FILES": ["signatureOrSystem", "delete other applications\' caches",
"Allows an application to delete cache files."],
"DELETE_PACKAGES": ["signatureOrSystem", "delete applications",
"Allows an application to delete Android packages. Malicious applications can use this to delete important applications."],
"MOVE_PACKAGE": ["signatureOrSystem", "Move application resources",
"Allows an application to move application resources from internal to external media and vice versa."],
"CHANGE_COMPONENT_ENABLED_STATE": ["signatureOrSystem", "enable or disable application components",
"Allows an application to change whether or not a component of another application is enabled. Malicious applications can use this to disable important phone capabilities. It is important to be careful with permission, as it is possible to bring application components into an unusable, inconsistent or unstable state."],
"GRANT_REVOKE_PERMISSIONS": ["signature", "", "Allows an application to grant or revoke specific permissions."],
"ACCESS_SURFACE_FLINGER": ["signature", "access SurfaceFlinger",
"Allows application to use SurfaceFlinger low-level features."],
"READ_FRAME_BUFFER": ["signatureOrSystem", "read frame buffer",
"Allows application to read the content of the frame buffer."],
"CONFIGURE_WIFI_DISPLAY": ["signature", "", "Allows an application to configure and connect to Wifi displays"],
"CONTROL_WIFI_DISPLAY": ["signature", "",
"Allows an application to control low-level features of Wifi displays such as opening an RTSP socket. This permission should only be used by the display manager."],
"BRICK": ["signature", "permanently disable phone",
"Allows the application to disable the entire phone permanently. This is very dangerous."],
"REBOOT": ["signatureOrSystem", "force phone reboot", "Allows the application to force the phone to reboot."],
"DEVICE_POWER": ["signature", "turn phone on or off", "Allows the application to turn the phone on or off."],
"NET_TUNNELING": ["signature", "", "Allows low-level access to tun tap driver "],
"FACTORY_TEST": ["signature", "run in factory test mode",
"Run as a low-level manufacturer test, allowing complete access to the phone hardware. Only available when a phone is running in manufacturer test mode."],
"MASTER_CLEAR": ["signatureOrSystem", "reset system to factory defaults",
"Allows an application to completely reset the system to its factory settings, erasing all data, configuration and installed applications."],
"CALL_PRIVILEGED": ["signatureOrSystem", "directly call any phone numbers",
"Allows the application to call any phone number, including emergency numbers, without your intervention. Malicious applications may place unnecessary and illegal calls to emergency services."],
"PERFORM_CDMA_PROVISIONING": ["signatureOrSystem", "directly start CDMA phone setup",
"Allows the application to start CDMA provisioning. Malicious applications may start CDMA provisioning unnecessarily"],
"CONTROL_LOCATION_UPDATES": ["signatureOrSystem", "control location update notifications",
"Allows enabling/disabling location update notifications from the radio. Not for use by normal applications."],
"ACCESS_CHECKIN_PROPERTIES": ["signatureOrSystem", "access check-in properties",
"Allows read/write access to properties uploaded by the check-in service. Not for use by normal applications."],
"PACKAGE_USAGE_STATS": ["signatureOrSystem", "update component usage statistics",
"Allows the modification of collected component usage statistics. Not for use by normal applications."],
"BACKUP": ["signatureOrSystem", "control system back up and restore",
"Allows the application to control the system\'s back-up and restore mechanism. Not for use by normal applications."],
"CONFIRM_FULL_BACKUP": ["signature", "",
"Allows a package to launch the secure full-backup confirmation UI. ONLY the system process may hold this permission."],
"BIND_REMOTEVIEWS": ["signatureOrSystem", "",
"Must be required by a {@link android.widget.RemoteViewsService}, to ensure that only the system can bind to it."],
"ACCESS_CACHE_FILESYSTEM": ["signatureOrSystem", "access the cache file system",
"Allows an application to read and write the cache file system."],
"COPY_PROTECTED_DATA": ["signature",
"Allows to invoke default container service to copy content. Not for use by normal applications.",
"Allows to invoke default container service to copy content. Not for use by normal applications."],
"CRYPT_KEEPER": ["signatureOrSystem", "access to the encryption methods",
"Internal permission protecting access to the encryption methods"],
"READ_NETWORK_USAGE_HISTORY": ["signatureOrSystem",
"read historical network usage for specific networks and applications.",
"Allows an application to read historical network usage for specific networks and applications."],
"MANAGE_NETWORK_POLICY": ["signature", "manage network policies and to define application-specific rules.",
"Allows an application to manage network policies and to define application-specific rules."],
"MODIFY_NETWORK_ACCOUNTING": ["signatureOrSystem", "account its network traffic against other UIDs.",
"Allows an application to account its network traffic against other UIDs."],
"C2D_MESSAGE": ["signature", "C2DM permission.", "C2DM permission."],
"PACKAGE_VERIFICATION_AGENT": ["signatureOrSystem",
"Package verifier needs to have this permission before the PackageManager will trust it to verify packages.",
"Package verifier needs to have this permission before the PackageManager will trust it to verify packages."],
"BIND_PACKAGE_VERIFIER": ["signature", "",
"Must be required by package verifier receiver, to ensure that only the system can interact with it.."],
"SERIAL_PORT": ["signature", "", "Allows applications to access serial ports via the SerialManager."],
"ACCESS_CONTENT_PROVIDERS_EXTERNALLY": ["signature", "",
"Allows the holder to access content providers from outside an ApplicationThread. This permission is enforced by the ActivityManagerService on the corresponding APIs,in particular ActivityManagerService#getContentProviderExternal(String) and ActivityManagerService#removeContentProviderExternal(String)."],
"UPDATE_LOCK": ["signatureOrSystem", "",
"Allows an application to hold an UpdateLock, recommending that a headless OTA reboot " \
"*not* occur while the lock is held"],
"WRITE_GSERVICES": ["signatureOrSystem", "modify the Google services map",
"Allows an application to modify the Google services map. Not for use by normal applications."],
"ACCESS_USB" : [ "signatureOrSystem" , "access USB devices" , "Allows the application to access USB devices." ],
"ACCESS_USB": ["signatureOrSystem", "access USB devices", "Allows the application to access USB devices."],
},
"MANIFEST_PERMISSION_GROUP":
{
"ACCOUNTS": "Permissions for direct access to the accounts managed by the Account Manager.",
"AFFECTS_BATTERY": "Used for permissions that provide direct access to the hardware on the device that has an effect on battery life. This includes vibrator, flashlight, etc.",
"APP_INFO": "Group of permissions that are related to the other applications installed on the system.",
"AUDIO_SETTINGS": "Used for permissions that provide direct access to speaker settings the device.",
"BLUETOOTH_NETWORK": "Used for permissions that provide access to other devices through Bluetooth.",
"BOOKMARKS": "Used for permissions that provide access to the user bookmarks and browser history.",
"CALENDAR": "Used for permissions that provide access to the device calendar to create / view events",
"CAMERA": "Used for permissions that are associated with accessing camera or capturing images/video from the device.",
"COST_MONEY": "Used for permissions that can be used to make the user spend money without their direct involvement.",
"DEVICE_ALARMS": "Used for permissions that provide access to the user voicemail box.",
"DEVELOPMENT_TOOLS": "Group of permissions that are related to development features.",
"DISPLAY": "Group of permissions that allow manipulation of how another application displays UI to the user.",
"HARDWARE_CONTROLS": "Used for permissions that provide direct access to the hardware on the device.",
"LOCATION": "Used for permissions that allow access to the user's current location.",
"MESSAGES": "Used for permissions that allow an application to send messages on behalf of the user or intercept messages being received by the user.",
"MICROPHONE": "Used for permissions that are associated with accessing microphone audio from the device. Note that phone calls also capture audio but are in a separate (more visible) permission group.",
"NETWORK": "Used for permissions that provide access to networking services.",
"PERSONAL_INFO": "Used for permissions that provide access to the user's private data, such as contacts, calendar events, e-mail messages, etc.",
"PHONE_CALLS": "Used for permissions that are associated with accessing and modifyign telephony state: intercepting outgoing calls, reading and modifying the phone state.",
"STORAGE": "Group of permissions that are related to SD card access.",
"SOCIAL_INFO": "Used for permissions that provide access to the user's social connections, such as contacts, call logs, social stream, etc. This includes both reading and writing of this data (which should generally be expressed as two distinct permissions)",
"SCREENLOCK": "Group of permissions that are related to the screenlock.",
"STATUS_BAR": "Used for permissions that change the status bar.",
"SYSTEM_CLOCK": "Group of permissions that are related to system clock.",
"SYSTEM_TOOLS": "Group of permissions that are related to system APIs.",
"SYNC_SETTINGS": "Used for permissions that access the sync settings or sync related information.",
"USER_DICTIONARY": "Used for permissions that provide access to the user calendar to create / view events.",
"VOICEMAIL": "Used for permissions that provide access to the user voicemail box.",
"WALLPAPER": "Group of permissions that allow manipulation of how another application displays UI to the user.",
"WRITE_USER_DICTIONARY": "Used for permissions that provide access to the user calendar to create / view events.",
},
"ACCOUNTS": "Permissions for direct access to the accounts managed by the Account Manager.",
"AFFECTS_BATTERY": "Used for permissions that provide direct access to the hardware on the device that has an effect on battery life. This includes vibrator, flashlight, etc.",
"APP_INFO": "Group of permissions that are related to the other applications installed on the system.",
"AUDIO_SETTINGS": "Used for permissions that provide direct access to speaker settings the device.",
"BLUETOOTH_NETWORK": "Used for permissions that provide access to other devices through Bluetooth.",
"BOOKMARKS": "Used for permissions that provide access to the user bookmarks and browser history.",
"CALENDAR": "Used for permissions that provide access to the device calendar to create / view events",
"CAMERA": "Used for permissions that are associated with accessing camera or capturing images/video from the device.",
"COST_MONEY": "Used for permissions that can be used to make the user spend money without their direct involvement.",
"DEVICE_ALARMS": "Used for permissions that provide access to the user voicemail box.",
"DEVELOPMENT_TOOLS": "Group of permissions that are related to development features.",
"DISPLAY": "Group of permissions that allow manipulation of how another application displays UI to the user.",
"HARDWARE_CONTROLS": "Used for permissions that provide direct access to the hardware on the device.",
"LOCATION": "Used for permissions that allow access to the user's current location.",
"MESSAGES": "Used for permissions that allow an application to send messages on behalf of the user or intercept messages being received by the user.",
"MICROPHONE": "Used for permissions that are associated with accessing microphone audio from the device. Note that phone calls also capture audio but are in a separate (more visible) permission group.",
"NETWORK": "Used for permissions that provide access to networking services.",
"PERSONAL_INFO": "Used for permissions that provide access to the user's private data, such as contacts, calendar events, e-mail messages, etc.",
"PHONE_CALLS": "Used for permissions that are associated with accessing and modifyign telephony state: intercepting outgoing calls, reading and modifying the phone state.",
"STORAGE": "Group of permissions that are related to SD card access.",
"SOCIAL_INFO": "Used for permissions that provide access to the user's social connections, such as contacts, call logs, social stream, etc. This includes both reading and writing of this data (which should generally be expressed as two distinct permissions)",
"SCREENLOCK": "Group of permissions that are related to the screenlock.",
"STATUS_BAR": "Used for permissions that change the status bar.",
"SYSTEM_CLOCK": "Group of permissions that are related to system clock.",
"SYSTEM_TOOLS": "Group of permissions that are related to system APIs.",
"SYNC_SETTINGS": "Used for permissions that access the sync settings or sync related information.",
"USER_DICTIONARY": "Used for permissions that provide access to the user calendar to create / view events.",
"VOICEMAIL": "Used for permissions that provide access to the user voicemail box.",
"WALLPAPER": "Group of permissions that allow manipulation of how another application displays UI to the user.",
"WRITE_USER_DICTIONARY": "Used for permissions that provide access to the user calendar to create / view events.",
},
}

View File

@ -36,7 +36,7 @@ class DexViewer(object):
def add_exception_node(self, exception, id_i):
buff = ""
# 9933FF
# 9933FF
height = 2
width = 0
label = ""
@ -49,7 +49,7 @@ class DexViewer(object):
width = max(len(c_label), width)
height += 1
return self._create_node( id_i, height, width, "9333FF", label )
return self._create_node(id_i, height, width, "9333FF", label)
def add_method_node(self, i, id_i):
height = 0
@ -62,7 +62,7 @@ class DexViewer(object):
height = 3
width = len(label)
return self._create_node( id_i, height, width, "FF0000", label )
return self._create_node(id_i, height, width, "FF0000", label)
def add_node(self, i, id_i):
height = 0
@ -79,7 +79,7 @@ class DexViewer(object):
if height < 10:
height += 3
return self._create_node( id_i, height, width, "FFCC00", label )
return self._create_node(id_i, height, width, "FFCC00", label)
def add_edge(self, i, id_i, j, id_j, l_eid, val):
buff = "<edge id=\"%d\" source=\"%d\" target=\"%d\">\n" % (len(l_eid), id_i, id_j)
@ -100,7 +100,7 @@ class DexViewer(object):
buff += "</edge>\n"
l_eid[ "%d+%d" % (id_i, id_j) ] = len(l_eid)
l_eid["%d+%d" % (id_i, id_j)] = len(l_eid)
return buff
def new_id(self, i, l):
@ -136,7 +136,7 @@ class DexViewer(object):
l_eid = {}
for method in _class.get_methods():
mx = self.vmx.get_method( method )
mx = self.vmx.get_method(method)
exceptions = mx.exceptions
id_method = self.new_id(method, l_id)
@ -146,7 +146,7 @@ class DexViewer(object):
id_i = self.new_id(i, l_id)
print(i, id_i, i.exception_analysis)
buff_nodes += self.add_node( i, id_i )
buff_nodes += self.add_node(i, id_i)
# add childs nodes
val = 0
@ -169,18 +169,18 @@ class DexViewer(object):
buff_nodes += self.add_exception_node(i.exception_analysis, id_exceptions)
buff_edges += self.add_edge(None, id_exceptions, None, id_i, l_eid, 2)
buff_edges += self.add_edge(None, id_method, None, id_method+1, l_eid, 2)
buff_edges += self.add_edge(None, id_method, None, id_method + 1, l_eid, 2)
buff += buff_nodes
buff += buff_edges
buff += "</graph>\n"
buff += "</graphml>\n"
H[ name ] = buff
H[name] = buff
return H
class Directory(object):
def __init__(self, name):
self.name = name
@ -192,6 +192,7 @@ class Directory(object):
def set_color(self, color):
self.color = color
class File(object):
def __init__(self, name, file_type, file_crc):
self.name = name
@ -203,15 +204,17 @@ class File(object):
self.width = max(len(self.name), len(self.file_type))
def splitall(path, z):
if len(path) == 0:
return
l = os.path.split( path )
l = os.path.split(path)
z.append(l[0])
for i in l:
return splitall( i, z )
return splitall(i, z)
class ApkViewer(object):
def __init__(self, a):
@ -221,38 +224,37 @@ class ApkViewer(object):
self.all_files = {}
self.ids = {}
root = Directory( "APK" )
root.set_color( "00FF00" )
root = Directory("APK")
root.set_color("00FF00")
self.ids[ root ] = len(self.ids)
self.G.add_node( root )
self.ids[root] = len(self.ids)
self.G.add_node(root)
for x, y, z in self.a.get_files_information():
print(x, y, z, os.path.basename(x))
l = []
splitall( x, l )
splitall(x, l)
l.reverse()
l.pop(0)
last = root
for i in l:
if i not in self.all_files:
tmp = Directory( i )
self.ids[ tmp ] = len(self.ids)
self.all_files[ i ] = tmp
tmp = Directory(i)
self.ids[tmp] = len(self.ids)
self.all_files[i] = tmp
else:
tmp = self.all_files[ i ]
tmp = self.all_files[i]
self.G.add_edge(last, tmp)
last = tmp
n1 = last
n2 = File( x, y, z )
n2 = File(x, y, z)
self.G.add_edge(n1, n2)
self.ids[ n2 ] = len(self.ids)
self.ids[n2] = len(self.ids)
def export_to_gml(self):
buff = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
@ -261,10 +263,8 @@ class ApkViewer(object):
buff += "<key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"d5\"/>\n"
buff += "<key for=\"node\" id=\"d6\" yfiles.type=\"nodegraphics\"/>\n"
buff += "<graph edgedefault=\"directed\" id=\"G\">\n"
for node in self.G.nodes():
print(node)

File diff suppressed because it is too large Load Diff

View File

@ -90,6 +90,7 @@ def var_decl(typen, var):
def dummy(*args):
return ['Dummy', args]
################################################################################
@ -142,6 +143,7 @@ def _append(sb, stmt):
if stmt is not None:
sb[2].append(stmt)
################################################################################
TYPE_DESCRIPTOR = {
'V': 'void',
@ -449,7 +451,6 @@ def visit_ins(op, isCtor=False):
class JSONWriter(object):
def __init__(self, graph, method):
self.graph = graph
self.method = method
@ -624,8 +625,8 @@ class JSONWriter(object):
self.add(if_stmt(cond_expr, scopes))
elif follow is not None:
if cond.true in (follow, self.next_case) or\
cond.num > cond.true.num:
if cond.true in (follow, self.next_case) or \
cond.num > cond.true.num:
# or cond.true.num > cond.false.num:
cond.neg()
cond.true, cond.false = cond.false, cond.true

View File

@ -29,7 +29,6 @@ logger = logging.getLogger('dad.basic_blocks')
class BasicBlock(Node):
def __init__(self, name, block_ins):
super(BasicBlock, self).__init__(name)
self.ins = block_ins
@ -68,7 +67,6 @@ class BasicBlock(Node):
class StatementBlock(BasicBlock):
def __init__(self, name, block_ins):
super(StatementBlock, self).__init__(name, block_ins)
self.type.is_stmt = True
@ -81,7 +79,6 @@ class StatementBlock(BasicBlock):
class ReturnBlock(BasicBlock):
def __init__(self, name, block_ins):
super(ReturnBlock, self).__init__(name, block_ins)
self.type.is_return = True
@ -94,7 +91,6 @@ class ReturnBlock(BasicBlock):
class ThrowBlock(BasicBlock):
def __init__(self, name, block_ins):
super(ThrowBlock, self).__init__(name, block_ins)
self.type.is_throw = True
@ -107,7 +103,6 @@ class ThrowBlock(BasicBlock):
class SwitchBlock(BasicBlock):
def __init__(self, name, switch, block_ins):
super(SwitchBlock, self).__init__(name, block_ins)
self.switch = switch
@ -146,7 +141,6 @@ class SwitchBlock(BasicBlock):
class CondBlock(BasicBlock):
def __init__(self, name, block_ins):
super(CondBlock, self).__init__(name, block_ins)
self.true = None
@ -176,7 +170,6 @@ class CondBlock(BasicBlock):
class Condition(object):
def __init__(self, cond1, cond2, isand, isnot):
self.cond1 = cond1
self.cond2 = cond2
@ -213,7 +206,6 @@ class Condition(object):
class ShortCircuitBlock(CondBlock):
def __init__(self, name, cond):
super(ShortCircuitBlock, self).__init__(name, None)
self.cond = cond
@ -235,7 +227,6 @@ class ShortCircuitBlock(CondBlock):
class LoopBlock(CondBlock):
def __init__(self, name, cond):
super(LoopBlock, self).__init__(name, None)
self.cond = cond
@ -272,7 +263,6 @@ class LoopBlock(CondBlock):
class TryBlock(BasicBlock):
def __init__(self, node):
super(TryBlock, self).__init__('Try-%s' % node.name, None)
self.try_start = node
@ -298,7 +288,6 @@ class TryBlock(BasicBlock):
class CatchBlock(BasicBlock):
def __init__(self, node):
first_ins = node.ins[0]
self.exception_ins = None

View File

@ -54,7 +54,7 @@ def intervals(graph):
change = False
for node in graph.rpo[1:]:
if all(
p in interv_heads[head] for p in graph.all_preds(node)):
p in interv_heads[head] for p in graph.all_preds(node)):
change |= interv_heads[head].add_node(node)
# At this stage, a node which is not in the interval, but has one
@ -63,7 +63,7 @@ def intervals(graph):
for node in graph:
if node not in interv_heads[head] and node not in heads:
if any(
p in interv_heads[head] for p in graph.all_preds(node)):
p in interv_heads[head] for p in graph.all_preds(node)):
edges[interv_heads[head]].append(node)
assert (node not in heads)
heads.append(node)
@ -165,11 +165,11 @@ def loop_follow(start, end, nodes_in_loop):
for node in nodes_in_loop:
if node.type.is_cond:
if (node.true.num < num_next and
node.true not in nodes_in_loop):
node.true not in nodes_in_loop):
follow = node.true
num_next = follow.num
elif (node.false.num < num_next and
node.false not in nodes_in_loop):
node.false not in nodes_in_loop):
follow = node.false
num_next = follow.num
start.follow['loop'] = follow
@ -239,7 +239,6 @@ def switch_struct(graph, idoms):
# TODO: deal with preds which are in catch
def short_circuit_struct(graph, idom, node_map):
def MergeNodes(node1, node2, is_and, is_not):
lpreds = set()
ldests = set()

View File

@ -27,7 +27,6 @@ logger = logging.getLogger('dad.control_flow')
class BasicReachDef(object):
def __init__(self, graph, params):
self.g = graph
self.A = defaultdict(set)
@ -313,7 +312,6 @@ def register_propagation(graph, du, ud):
class DummyNode(Node):
def __init__(self, name):
super(DummyNode, self).__init__(name)
@ -465,7 +463,7 @@ def place_declarations(graph, dvars, du, ud):
for loc, ins in node.get_loc_with_ins():
for var in ins.get_used_vars():
if (not isinstance(dvars[var], Variable) or
isinstance(dvars[var], Param)):
isinstance(dvars[var], Param)):
continue
var_defs_locs = ud[var, loc]
def_nodes = set()

View File

@ -23,6 +23,7 @@ from builtins import str
from builtins import range
from builtins import object
import sys
sys.path.append('./')
import logging
@ -82,7 +83,6 @@ def get_field_ast(field):
class DvMethod(object):
def __init__(self, methanalysis):
method = methanalysis.get_method()
self.method = method
@ -122,7 +122,7 @@ class DvMethod(object):
if not __debug__:
from androguard.core import bytecode
bytecode.method2png('/tmp/dad/graphs/%s#%s.png' % \
(self.cls_name.split('/')[-1][:-1], self.name), methanalysis)
(self.cls_name.split('/')[-1][:-1], self.name), methanalysis)
def process(self, doAST=False):
logger.debug('METHOD : %s', self.name)
@ -194,12 +194,11 @@ class DvMethod(object):
return []
def __repr__(self):
#return 'Method %s' % self.name
# return 'Method %s' % self.name
return 'class DvMethod(object): %s' % self.name
class DvClass(object):
def __init__(self, dvclass, vma):
name = dvclass.get_name()
if name.find('/') > 0:
@ -270,8 +269,8 @@ class DvClass(object):
fields = [get_field_ast(f) for f in self.fields]
methods = []
for m in self.methods:
if isinstance(m, DvMethod) and m.ast:
methods.append(m.get_ast())
if isinstance(m, DvMethod) and m.ast:
methods.append(m.get_ast())
isInterface = 'interface' in self.access
return {
'rawname': self.thisclass[1:-1],
@ -338,7 +337,7 @@ class DvClass(object):
source.append(
('PACKAGE', [('PACKAGE_START', 'package '), (
'NAME_PACKAGE', '%s' % self.package), ('PACKAGE_END', ';\n')
]))
]))
list_proto = []
list_proto.append(
('PROTOTYPE_ACCESS', '%s class ' % ' '.join(self.access)))
@ -391,14 +390,14 @@ class DvClass(object):
source.append(
('FIELD', [('FIELD_ACCESS', access_str), (
'FIELD_TYPE', '%s' % f_type), ('SPACE', ' '), (
'NAME_FIELD', '%s' % name, f_type, field), ('FIELD_VALUE', value), ('FIELD_END',
';\n')]))
'NAME_FIELD', '%s' % name, f_type, field), ('FIELD_VALUE', value), ('FIELD_END',
';\n')]))
else:
source.append(
('FIELD', [('FIELD_ACCESS', access_str), (
'FIELD_TYPE', '%s' % f_type), ('SPACE', ' '), (
'NAME_FIELD', '%s' % name, f_type, field), ('FIELD_END',
';\n')]))
'NAME_FIELD', '%s' % name, f_type, field), ('FIELD_END',
';\n')]))
for method in self.methods:
if isinstance(method, DvMethod):
@ -414,7 +413,6 @@ class DvClass(object):
class DvMachine(object):
def __init__(self, name):
vm = auto_vm(name)
if vm is None:
@ -422,7 +420,7 @@ class DvMachine(object):
self.vma = analysis.Analysis(vm)
self.classes = dict((dvclass.get_name(), dvclass)
for dvclass in vm.get_classes())
#util.merge_inner(self.classes)
# util.merge_inner(self.classes)
def get_classes(self):
return list(self.classes.keys())

View File

@ -30,7 +30,6 @@ logger = logging.getLogger('dad.graph')
class Graph(object):
def __init__(self):
self.entry = None
self.exit = None
@ -289,8 +288,8 @@ def simplify(graph):
graph.entry = suc
graph.remove_node(node)
elif (suc.type.is_stmt and len(graph.all_preds(suc)) == 1 and
not (suc in graph.catch_edges) and not (
(node is suc) or (suc is graph.entry))):
not (suc in graph.catch_edges) and not (
(node is suc) or (suc is graph.entry))):
ins_to_merge = suc.get_ins()
node.add_ins(ins_to_merge)
for var in suc.var_to_declare:
@ -389,7 +388,6 @@ def bfs(start):
class GenInvokeRetName(object):
def __init__(self):
self.num = 0
self.ret = None

View File

@ -20,7 +20,6 @@ import androguard.decompiler.dad.util as util
class IRForm(object):
def __init__(self):
self.var_map = {}
self.type = None
@ -75,7 +74,6 @@ class IRForm(object):
class Constant(IRForm):
def __init__(self, value, atype, int_value=None, descriptor=None):
self.v = 'c%s' % value
self.cst = value
@ -117,7 +115,6 @@ class Constant(IRForm):
class BaseClass(IRForm):
def __init__(self, name, descriptor=None):
self.v = 'c%s' % name
self.cls = name
@ -135,7 +132,6 @@ class BaseClass(IRForm):
class Variable(IRForm):
def __init__(self, value):
self.v = value
self.declared = False
@ -162,7 +158,6 @@ class Variable(IRForm):
class Param(Variable):
def __init__(self, value, atype):
super(Param, self).__init__(value)
self.declared = True
@ -180,7 +175,6 @@ class Param(Variable):
class ThisParam(Param):
def __init__(self, value, atype):
super(ThisParam, self).__init__(value, atype)
self.this = True
@ -188,7 +182,7 @@ class ThisParam(Param):
def visit(self, visitor):
if self.super:
return visitor.visit_super()
return visitor.visit_super()
return visitor.visit_this()
def __str__(self):
@ -196,7 +190,6 @@ class ThisParam(Param):
class AssignExpression(IRForm):
def __init__(self, lhs, rhs):
super(AssignExpression, self).__init__()
if lhs:
@ -246,7 +239,6 @@ class AssignExpression(IRForm):
class MoveExpression(IRForm):
def __init__(self, lhs, rhs):
super(MoveExpression, self).__init__()
self.lhs = lhs.v
@ -303,7 +295,6 @@ class MoveExpression(IRForm):
class MoveResultExpression(MoveExpression):
def __init__(self, lhs, rhs):
super(MoveResultExpression, self).__init__(lhs, rhs)
@ -323,7 +314,6 @@ class MoveResultExpression(MoveExpression):
class ArrayStoreInstruction(IRForm):
def __init__(self, rhs, array, index, _type):
super(ArrayStoreInstruction, self).__init__()
self.rhs = rhs.v
@ -387,7 +377,6 @@ class ArrayStoreInstruction(IRForm):
class StaticInstruction(IRForm):
def __init__(self, rhs, klass, ftype, name):
super(StaticInstruction, self).__init__()
self.rhs = rhs.v
@ -433,7 +422,6 @@ class StaticInstruction(IRForm):
class InstanceInstruction(IRForm):
def __init__(self, rhs, lhs, klass, atype, name):
super(InstanceInstruction, self).__init__()
self.lhs = lhs.v
@ -499,7 +487,6 @@ class InstanceInstruction(IRForm):
class NewInstance(IRForm):
def __init__(self, ins_type):
super(NewInstance, self).__init__()
self.type = ins_type
@ -521,7 +508,6 @@ class NewInstance(IRForm):
class InvokeInstruction(IRForm):
def __init__(self, clsname, name, base, rtype, ptype, args, triple):
super(InvokeInstruction, self).__init__()
self.cls = clsname
@ -611,7 +597,6 @@ class InvokeInstruction(IRForm):
class InvokeRangeInstruction(InvokeInstruction):
def __init__(self, clsname, name, rtype, ptype, args, triple):
base = args.pop(0)
super(InvokeRangeInstruction, self).__init__(clsname, name, base, rtype,
@ -619,14 +604,12 @@ class InvokeRangeInstruction(InvokeInstruction):
class InvokeDirectInstruction(InvokeInstruction):
def __init__(self, clsname, name, base, rtype, ptype, args, triple):
super(InvokeDirectInstruction, self).__init__(
clsname, name, base, rtype, ptype, args, triple)
class InvokeStaticInstruction(InvokeInstruction):
def __init__(self, clsname, name, base, rtype, ptype, args, triple):
super(InvokeStaticInstruction, self).__init__(
clsname, name, base, rtype, ptype, args, triple)
@ -640,7 +623,6 @@ class InvokeStaticInstruction(InvokeInstruction):
class ReturnInstruction(IRForm):
def __init__(self, arg):
super(ReturnInstruction, self).__init__()
self.arg = arg
@ -686,7 +668,6 @@ class ReturnInstruction(IRForm):
class NopExpression(IRForm):
def __init__(self):
pass
@ -701,7 +682,6 @@ class NopExpression(IRForm):
class SwitchExpression(IRForm):
def __init__(self, src, branch):
super(SwitchExpression, self).__init__()
self.src = src.v
@ -736,7 +716,6 @@ class SwitchExpression(IRForm):
class CheckCastExpression(IRForm):
def __init__(self, arg, _type, descriptor=None):
super(CheckCastExpression, self).__init__()
self.arg = arg.v
@ -777,13 +756,11 @@ class CheckCastExpression(IRForm):
class ArrayExpression(IRForm):
def __init__(self):
super(ArrayExpression, self).__init__()
class ArrayLoadExpression(ArrayExpression):
def __init__(self, arg, index, _type):
super(ArrayLoadExpression, self).__init__()
self.array = arg.v
@ -839,7 +816,6 @@ class ArrayLoadExpression(ArrayExpression):
class ArrayLengthExpression(ArrayExpression):
def __init__(self, array):
super(ArrayLengthExpression, self).__init__()
self.array = array.v
@ -876,7 +852,6 @@ class ArrayLengthExpression(ArrayExpression):
class NewArrayExpression(ArrayExpression):
def __init__(self, asize, atype):
super(NewArrayExpression, self).__init__()
self.size = asize.v
@ -914,7 +889,6 @@ class NewArrayExpression(ArrayExpression):
class FilledArrayExpression(ArrayExpression):
def __init__(self, asize, atype, args):
super(FilledArrayExpression, self).__init__()
self.size = asize
@ -972,7 +946,6 @@ class FilledArrayExpression(ArrayExpression):
class FillArrayExpression(ArrayExpression):
def __init__(self, reg, value):
super(FillArrayExpression, self).__init__()
self.reg = reg.v
@ -1010,7 +983,6 @@ class FillArrayExpression(ArrayExpression):
class RefExpression(IRForm):
def __init__(self, ref):
super(RefExpression, self).__init__()
self.ref = ref.v
@ -1041,7 +1013,6 @@ class RefExpression(IRForm):
class MoveExceptionExpression(RefExpression):
def __init__(self, ref, _type):
super(MoveExceptionExpression, self).__init__(ref)
self.type = _type
@ -1069,7 +1040,6 @@ class MoveExceptionExpression(RefExpression):
class MonitorEnterExpression(RefExpression):
def __init__(self, ref):
super(MonitorEnterExpression, self).__init__(ref)
@ -1078,7 +1048,6 @@ class MonitorEnterExpression(RefExpression):
class MonitorExitExpression(RefExpression):
def __init__(self, ref):
super(MonitorExitExpression, self).__init__(ref)
@ -1087,7 +1056,6 @@ class MonitorExitExpression(RefExpression):
class ThrowExpression(RefExpression):
def __init__(self, ref):
super(ThrowExpression, self).__init__(ref)
@ -1099,7 +1067,6 @@ class ThrowExpression(RefExpression):
class BinaryExpression(IRForm):
def __init__(self, op, arg1, arg2, _type):
super(BinaryExpression, self).__init__()
self.op = op
@ -1158,7 +1125,6 @@ class BinaryExpression(IRForm):
class BinaryCompExpression(BinaryExpression):
def __init__(self, op, arg1, arg2, _type):
super(BinaryCompExpression, self).__init__(op, arg1, arg2, _type)
@ -1169,19 +1135,16 @@ class BinaryCompExpression(BinaryExpression):
class BinaryExpression2Addr(BinaryExpression):
def __init__(self, op, dest, arg, _type):
super(BinaryExpression2Addr, self).__init__(op, dest, arg, _type)
class BinaryExpressionLit(BinaryExpression):
def __init__(self, op, arg1, arg2):
super(BinaryExpressionLit, self).__init__(op, arg1, arg2, 'I')
class UnaryExpression(IRForm):
def __init__(self, op, arg, _type):
super(UnaryExpression, self).__init__()
self.op = op
@ -1220,7 +1183,6 @@ class UnaryExpression(IRForm):
class CastExpression(UnaryExpression):
def __init__(self, op, atype, arg):
super(CastExpression, self).__init__(op, arg, atype)
self.clsdesc = atype
@ -1241,11 +1203,10 @@ class CastExpression(UnaryExpression):
return 'CAST_%s(%s)' % (self.op, self.var_map[self.arg])
CONDS = {'==': '!=', '!=': '==', '<': '>=', '<=': '>', '>=': '<', '>': '<=',}
CONDS = {'==': '!=', '!=': '==', '<': '>=', '<=': '>', '>=': '<', '>': '<=', }
class ConditionalExpression(IRForm):
def __init__(self, op, arg1, arg2):
super(ConditionalExpression, self).__init__()
self.op = op
@ -1307,7 +1268,6 @@ class ConditionalExpression(IRForm):
class ConditionalZExpression(IRForm):
def __init__(self, op, arg):
super(ConditionalZExpression, self).__init__()
self.op = op
@ -1351,7 +1311,6 @@ class ConditionalZExpression(IRForm):
class InstanceExpression(IRForm):
def __init__(self, arg, klass, ftype, name):
super(InstanceExpression, self).__init__()
self.arg = arg.v
@ -1396,7 +1355,6 @@ class InstanceExpression(IRForm):
class StaticExpression(IRForm):
def __init__(self, cls_name, field_type, field_name):
super(StaticExpression, self).__init__()
self.cls = util.get_type(cls_name)

View File

@ -18,8 +18,9 @@
from builtins import object
from future.utils import with_metaclass
class MakeProperties(type):
class MakeProperties(type):
def __init__(cls, name, bases, dct):
def _wrap_set(names, name):
@ -82,7 +83,6 @@ class NodeType(with_metaclass(MakeProperties, object)):
class Node(object):
def __init__(self, name):
self.name = name
self.num = 0
@ -123,7 +123,6 @@ class Node(object):
class Interval(object):
def __init__(self, head):
self.name = 'Interval-%s' % head.name
self.content = set([head])

View File

@ -543,7 +543,7 @@ def iflez(ins, vmap):
return ConditionalZExpression(Op.LEQUAL, get_variables(vmap, ins.AA))
#TODO: check type for all aget
# TODO: check type for all aget
# aget vAA, vBB, vCC ( 8b, 8b, 8b )
def aget(ins, vmap):
logger.debug('AGet : %s', ins.get_output())

View File

@ -1,6 +1,7 @@
"""Tests for def_use."""
import sys
sys.path.append('.')
import collections
@ -14,7 +15,6 @@ from androguard.decompiler.dad import basic_blocks
class DataflowTest(unittest.TestCase):
def assertItemsEqual(self, a, b):
"""
This method was renamed in python3.

View File

@ -1,6 +1,7 @@
"""Tests for graph."""
import sys
sys.path.append('.')
import unittest
@ -9,7 +10,6 @@ from androguard.decompiler.dad import node
class DominatorTest(unittest.TestCase):
def setUp(self):
self.graph = graph.Graph()

View File

@ -1,6 +1,7 @@
"""Tests for rpo."""
import sys
sys.path.append('.')
import unittest
@ -9,7 +10,6 @@ from androguard.decompiler.dad import node
class NodeTest(node.Node):
def __init__(self, name):
super(NodeTest, self).__init__(name)
@ -18,7 +18,6 @@ class NodeTest(node.Node):
class RpoTest(unittest.TestCase):
def _getNode(self, node_map, n):
ret_node = node_map.get(n)
if not ret_node:
@ -67,7 +66,7 @@ class RpoTest(unittest.TestCase):
}
n_map = self._createGraphFrom(edges)
self.graph.compute_rpo()
#self.graph.draw('_testTarjan_graph', '/tmp')
# self.graph.draw('_testTarjan_graph', '/tmp')
expected_rpo = {
'r': 1,
'a': 7,
@ -111,7 +110,7 @@ class RpoTest(unittest.TestCase):
}
n_map = self._createGraphFrom(edges)
self.graph.compute_rpo()
#self.graph.draw('_testFirst_graph', '/tmp')
# self.graph.draw('_testFirst_graph', '/tmp')
expected_rpo = {
'r': 1,
'x1': 2,
@ -150,7 +149,7 @@ class RpoTest(unittest.TestCase):
}
n_map = self._createGraphFrom(edges)
self.graph.compute_rpo()
#self.graph.draw('_testSecond_graph', '/tmp')
# self.graph.draw('_testSecond_graph', '/tmp')
expected_rpo = {
'r': 1,
'x11': 3,
@ -186,7 +185,7 @@ class RpoTest(unittest.TestCase):
}
n_map = self._createGraphFrom(edges)
self.graph.compute_rpo()
#self.graph.draw('_testFourth_graph', '/tmp')
# self.graph.draw('_testFourth_graph', '/tmp')
expected_rpo = {'r': 1, 'x1': 2, 'x2': 3, 'y1': 5, 'y2': 4}
self._verifyRpo(n_map, expected_rpo)
@ -205,7 +204,7 @@ class RpoTest(unittest.TestCase):
}
n_map = self._createGraphFrom(edges)
self.graph.compute_rpo()
#self.graph.draw('_testFifth_graph', '/tmp')
# self.graph.draw('_testFifth_graph', '/tmp')
expected_rpo = {
'r': 1,
'a': 2,
@ -236,7 +235,7 @@ class RpoTest(unittest.TestCase):
}
n_map = self._createGraphFrom(edges)
self.graph.compute_rpo()
#self.graph.draw('_testLinearVit_graph', '/tmp')
# self.graph.draw('_testLinearVit_graph', '/tmp')
expected_rpo = {
'r': 1,
'w': 3,
@ -264,7 +263,7 @@ class RpoTest(unittest.TestCase):
}
n_map = self._createGraphFrom(edges)
self.graph.compute_rpo()
#self.graph.draw('_testCross_graph', '/tmp')
# self.graph.draw('_testCross_graph', '/tmp')
expected_rpo = {
'r': 1,
'a': 2,
@ -295,7 +294,7 @@ class RpoTest(unittest.TestCase):
}
n_map = self._createGraphFrom(edges)
self.graph.compute_rpo()
#self.graph.draw('_testTVerify_graph', '/tmp')
# self.graph.draw('_testTVerify_graph', '/tmp')
expected_rpo = {
'n1': 1,
'n2': 2,

View File

@ -76,7 +76,7 @@ ACCESS_FLAGS_METHODS = {
ACCESS_ORDER = [0x1, 0x4, 0x2, 0x400, 0x8, 0x10, 0x80, 0x40, 0x20, 0x100, 0x800,
0x200, 0x1000, 0x2000, 0x4000, 0x10000, 0x20000]
TYPE_LEN = {'J': 2, 'D': 2,}
TYPE_LEN = {'J': 2, 'D': 2, }
def get_access_class(access):

View File

@ -32,7 +32,6 @@ logger = logging.getLogger('dad.writer')
class Writer(object):
def __init__(self, graph, method):
self.graph = graph
self.method = method
@ -104,7 +103,7 @@ class Writer(object):
rhs.visit(self)
self.end_ins()
#TODO: prefer this class as write_ind_visit_end that should be deprecated
# TODO: prefer this class as write_ind_visit_end that should be deprecated
# at the end
def write_ind_visit_end_ext(self,
lhs,
@ -127,8 +126,8 @@ class Writer(object):
def write_inplace_if_possible(self, lhs, rhs):
if isinstance(rhs, BinaryExpression) and lhs == rhs.var_map[rhs.arg1]:
exp_rhs = rhs.var_map[rhs.arg2]
if rhs.op in '+-' and isinstance(exp_rhs, Constant) and\
exp_rhs.get_int_value() == 1:
if rhs.op in '+-' and isinstance(exp_rhs, Constant) and \
exp_rhs.get_int_value() == 1:
return self.write_ind_visit_end(lhs, rhs.op * 2, data=rhs)
return self.write_ind_visit_end(
lhs,
@ -172,7 +171,7 @@ class Writer(object):
self.write_ext(('PARENTHESIS_START', '('))
if self.method.params_type:
proto = ', '.join(['%s p%s' % (get_type(p_type), param) for p_type,
param in zip(self.method.params_type, params)])
param in zip(self.method.params_type, params)])
first = True
for p_type, param in zip(self.method.params_type, params):
if not first:
@ -288,8 +287,8 @@ class Writer(object):
self.write('%s}\n' % self.space(), data="IF_END_2")
self.visit_node(cond.false)
elif follow is not None:
if cond.true in (follow, self.next_case) or\
cond.num > cond.true.num:
if cond.true in (follow, self.next_case) or \
cond.num > cond.true.num:
# or cond.true.num > cond.false.num:
cond.neg()
cond.true, cond.false = cond.false, cond.true
@ -525,7 +524,7 @@ class Writer(object):
call_name = "%s -> %s" % (base2base.type, name)
break
elif (hasattr(base2base, "base") and
hasattr(base2base, "var_map")):
hasattr(base2base, "var_map")):
continue
else:
call_name = "UNKNOWN_TODO"

View File

@ -37,12 +37,12 @@ try:
except ImportError:
PYGMENTS = False
class Filter(object):
pass
class Dex2Jar(object):
def __init__(self,
vm,
path_dex2jar="./decompiler/dex2jar/",
@ -70,7 +70,6 @@ class Dex2Jar(object):
class DecompilerDex2Jad(object):
def __init__(self,
vm,
path_dex2jar="./decompiler/dex2jar/",
@ -164,7 +163,6 @@ class DecompilerDex2Jad(object):
class DecompilerDex2WineJad(object):
def __init__(self,
vm,
path_dex2jar="./decompiler/dex2jar/",
@ -258,7 +256,6 @@ class DecompilerDex2WineJad(object):
class DecompilerDed(object):
def __init__(self,
vm,
path="./decompiler/ded/",
@ -298,7 +295,7 @@ class DecompilerDed(object):
for i in vm.get_classes():
fname = findsrc + "/" + i.get_name()[1:-1] + ".java"
#print fname
# print fname
if os.path.isfile(fname) == True:
self.classes[i.get_name()] = read(fname, binary=False)
else:
@ -339,7 +336,6 @@ class DecompilerDed(object):
class DecompilerDex2Fernflower(object):
def __init__(self,
vm,
path_dex2jar="./decompiler/dex2jar/",
@ -440,15 +436,14 @@ class DecompilerDex2Fernflower(object):
class MethodFilter(Filter):
def __init__(self, **options):
Filter.__init__(self, **options)
self.method_name = options["method_name"]
#self.descriptor = options["descriptor"]
# self.descriptor = options["descriptor"]
self.present = False
self.get_desc = True #False
self.get_desc = True # False
def filter(self, lexer, stream):
a = []
@ -457,8 +452,8 @@ class MethodFilter(Filter):
for ttype, value in stream:
if self.method_name == value and (ttype is Token.Name.Function or
ttype is Token.Name):
#print ttype, value
ttype is Token.Name):
# print ttype, value
item_decl = -1
for i in range(len(a) - 1, 0, -1):
@ -504,7 +499,6 @@ class MethodFilter(Filter):
class DecompilerDAD(object):
def __init__(self, vm, vmx):
self.vm = vm
self.vmx = vmx

View File

@ -9,6 +9,7 @@ import os, sys, inspect
from .TextDecorators import *
class Banner(object):
def getOrientation(self):
NotImplementedError('method not implemented.')
@ -32,11 +33,11 @@ class Banner(object):
Orientation = enum(Left=0, Bottom=1, Top=2)
class Observer(object):
def changeViewMode(self, viewMode):
self.setViewMode(viewMode)
class Banners(Observer):
BOTTOM_SEPARATOR = 5
@ -51,7 +52,7 @@ class Banners(Observer):
def banners(self):
return self._Banners
def getLeftOffset(self):
offset = 0
for banner in self._Banners:
@ -84,7 +85,7 @@ class Banners(Observer):
for banner in self._Banners:
# banners are not resizeable actually
if banner.getOrientation() == Orientation.Left:
banner.resize(banner.getDesiredGeometry(), height - limit + 4) # +4 , make to look nice
banner.resize(banner.getDesiredGeometry(), height - limit + 4) # +4 , make to look nice
if banner.getOrientation() == Orientation.Bottom:
banner.resize(width, banner.getDesiredGeometry())
@ -101,7 +102,7 @@ class Banners(Observer):
for banner in self._Banners:
if banner.getOrientation() == Orientation.Top:
banner.draw()
qp.drawPixmap(offsetLeft-4, offsetBottom, banner.getPixmap())
qp.drawPixmap(offsetLeft - 4, offsetBottom, banner.getPixmap())
offsetBottom += banner.getDesiredGeometry() + self.separatorLeft
for banner in self._Banners:
@ -120,7 +121,6 @@ class Banners(Observer):
offsetBottom += banner.getDesiredGeometry() + self.separatorBottom
class FileAddrBanner(Banner):
def __init__(self, themes, dataModel, viewMode):
self.width = 0
@ -137,7 +137,7 @@ class FileAddrBanner(Banner):
self.font.setKerning(False)
self.font.setFixedPitch(True)
fm = QtGui.QFontMetrics(self.font)
self.fontWidth = fm.width('a')
self.fontWidth = fm.width('a')
self.fontHeight = fm.height()
self.textPen = QtGui.QPen(QtGui.QColor(192, 192, 192), 0, QtCore.Qt.SolidLine)
@ -164,16 +164,15 @@ class FileAddrBanner(Banner):
columns, rows = self.viewMode.getGeometry()
qp.begin(self.qpix)
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
qp.setPen(self.textPen)
qp.setFont(self.font)
for i in range(rows):
s = '{0:08x}'.format(offset)
qp.drawText(0+5, (i+1) * self.fontHeight, s)
qp.drawText(0 + 5, (i + 1) * self.fontHeight, s)
columns = self.viewMode.getColumnsbyRow(i)
offset += columns
qp.end()
@ -182,7 +181,6 @@ class FileAddrBanner(Banner):
self.height = height
self.qpix = self._getNewPixmap(self.width, self.height)
class BottomBanner(Banner):
@ -194,16 +192,15 @@ class BottomBanner(Banner):
self.backgroundBrush = QtGui.QBrush(themes['background'])
self.qpix = self._getNewPixmap(self.width, self.height)
# text font
self.font = themes['font']
# font metrics. assume font is monospaced
self.font.setKerning(False)
self.font.setFixedPitch(True)
fm = QtGui.QFontMetrics(self.font)
self.fontWidth = fm.width('a')
self.fontWidth = fm.width('a')
self.fontHeight = fm.height()
self.textPen = QtGui.QPen(themes['pen'], 0, QtCore.Qt.SolidLine)
@ -221,7 +218,7 @@ class BottomBanner(Banner):
qp = QtGui.QPainter()
qp.begin(self.qpix)
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
qp.setPen(self.textPen)
qp.setFont(self.font)
@ -235,8 +232,6 @@ class BottomBanner(Banner):
pos = 'POS: {0:08x}'.format(self.viewMode.getCursorAbsolutePosition())
qword = self.dataModel.getQWORD(self.viewMode.getCursorAbsolutePosition(), asString=True)
if qword is None:
qword = '----'
@ -248,7 +243,7 @@ class BottomBanner(Banner):
sb = 'BYTE: {0}'.format(byte)
cemu.writeAt(1, 0, pos)
cemu.writeAt(1, 0, pos)
cemu.writeAt(17, 0, sd)
cemu.writeAt(35, 0, sq)
cemu.writeAt(62, 0, sb)
@ -265,7 +260,7 @@ class BottomBanner(Banner):
qp.setPen(pen)
cemu.writeAt(73, 0, 'Selection: ')
cemu.write('{0:x}:{1}'.format(u, v-u))
cemu.write('{0:x}:{1}'.format(u, v - u))
else:
pen = QtGui.QPen(QtGui.QColor(128, 128, 128), 0, QtCore.Qt.SolidLine)
qp.setPen(pen)
@ -278,9 +273,9 @@ class BottomBanner(Banner):
qp.drawLine(self.fontWidth*(len(pos + sd + sq) + 1) + 5*15, 0, self.fontWidth*(len(pos + sd + sq) + 1) + 5*15, 50)
qp.drawLine(self.fontWidth*(len(pos + sd + sq + sb) + 1) + 8*15, 0, self.fontWidth*(len(pos + sd + sq + sb) + 1) + 8*15, 50)
"""
#qp.drawLine(270, 0, 270, 50)
#qp.drawLine(480, 0, 480, 50)
#qp.drawLine(570, 0, 570, 50)
# qp.drawLine(270, 0, 270, 50)
# qp.drawLine(480, 0, 480, 50)
# qp.drawLine(570, 0, 570, 50)
"""
# position
qp.drawText(0 + 5, self.fontHeight, pos)
@ -302,10 +297,11 @@ class BottomBanner(Banner):
# separator
qp.drawLine(570, 0, 570, 50)
"""
qp.end()
pass
def getPixmap(self):
return self.qpix
@ -328,7 +324,6 @@ class TopBanner(Banner):
self.qpix = self._getNewPixmap(self.width, self.height)
self.backgroundBrush = QtGui.QBrush(themes['background'])
# text font
self.font = themes['font']
@ -336,7 +331,7 @@ class TopBanner(Banner):
self.font.setKerning(False)
self.font.setFixedPitch(True)
fm = QtGui.QFontMetrics(self.font)
self.fontWidth = fm.width('a')
self.fontWidth = fm.width('a')
self.fontHeight = fm.height()
self.textPen = QtGui.QPen(themes['pen'], 0, QtCore.Qt.SolidLine)
@ -345,7 +340,7 @@ class TopBanner(Banner):
return Orientation.Top
def getDesiredGeometry(self):
return 26#22
return 26 # 22
def setViewMode(self, viewMode):
self.viewMode = viewMode
@ -358,7 +353,7 @@ class TopBanner(Banner):
qp = QtGui.QPainter()
qp.begin(self.qpix)
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
qp.fillRect(0, 0, self.width, self.height, self.backgroundBrush)
qp.setPen(self.textPen)
qp.setFont(self.font)
@ -371,7 +366,7 @@ class TopBanner(Banner):
text = self.viewMode.getHeaderInfo()
cemu.writeAt(offset, 0, text)
qp.end()
def getPixmap(self):
@ -384,4 +379,3 @@ class TopBanner(Banner):
self.width = width
self.height = height
self.qpix = self._getNewPixmap(self.width, self.height)

View File

@ -5,15 +5,16 @@ from builtins import range
from .ViewMode import *
from .cemu import *
from . import TextSelection
from .TextDecorators import *
from .TextDecorators import *
from PyQt5 import QtGui, QtCore
import PyQt5
from time import time
from time import time
import sys
import threading
import string
class BinViewMode(ViewMode):
def __init__(self, themes, width, height, data, cursor, widget=None):
super(BinViewMode, self).__init__()
@ -41,11 +42,9 @@ class BinViewMode(ViewMode):
self.font.setKerning(False)
self.font.setFixedPitch(True)
fm = QtGui.QFontMetrics(self.font)
self._fontWidth = fm.width('a')
self._fontWidth = fm.width('a')
self._fontHeight = fm.height()
self.textPen = QtGui.QPen(self.themes['pen'], 0, QtCore.Qt.SolidLine)
self.resize(width, height)
@ -64,8 +63,8 @@ class BinViewMode(ViewMode):
def startCaching(self):
# cache
self.cache()
#t = threading.Thread(target=self.cache)
#t.start()
# t = threading.Thread(target=self.cache)
# t.start()
def isInCache(self, page):
if page in self.Paints:
@ -73,13 +72,13 @@ class BinViewMode(ViewMode):
def cache(self):
for i in [1,2]:
#pix = self._getNewPixmap(self.width, self.height)
for i in [1, 2]:
# pix = self._getNewPixmap(self.width, self.height)
if not self.isInCache(self.dataModel.getPageOffset(i)):
pix = QtGui.QImage(self.width, self.height, QtGui.QImage.Format_ARGB32)
self.scrollPages(1, cachePix=pix, pageOffset=i)
self.Paints[self.dataModel.getPageOffset(i)] = pix
#print 'cache'
# print 'cache'
def _getNewPixmap(self, width, height):
return QtGui.QPixmap(width, height)
@ -90,7 +89,7 @@ class BinViewMode(ViewMode):
def computeTextArea(self):
self.COLUMNS = self.width // self.fontWidth
self.ROWS = self.height // self.fontHeight
self.ROWS = self.height // self.fontHeight
self.notify(self.ROWS, self.COLUMNS)
def drawAdditionals(self):
@ -99,7 +98,7 @@ class BinViewMode(ViewMode):
qp.begin(self.newPix)
qp.drawPixmap(0, 0, self.qpix)
#self.transformationEngine.decorateText()
# self.transformationEngine.decorateText()
# highlight selected text
self.selector.highlightText()
@ -133,33 +132,32 @@ class BinViewMode(ViewMode):
if self.dataModel.getOffset() in self.Paints:
self.refresh = False
self.qpix = QtGui.QPixmap(self.Paints[self.dataModel.getOffset()])
#print 'hit'
# print 'hit'
self.drawAdditionals()
return
if self.refresh or refresh:
qp = QtGui.QPainter()
qp.begin(self.qpix)
#start = time()
# start = time()
if not howMany:
howMany = self.ROWS
self.drawTextMode(qp, row=row, howMany=howMany)
#end = time() - start
#print 'Time ' + str(end)
# end = time() - start
# print 'Time ' + str(end)
self.refresh = False
qp.end()
# self.Paints[self.dataModel.getOffset()] = QtGui.QPixmap(self.qpix)
# self.Paints[self.dataModel.getOffset()] = QtGui.QPixmap(self.qpix)
self.drawAdditionals()
def draw2(self, qp, refresh=False):
if self.refresh or refresh:
start = time()
self.drawTextMode(qp, howMany=self.ROWS)
end = time() - start
#print 'Time ' + str(end)
# print 'Time ' + str(end)
qp = QtGui.QPainter()
qp.begin(self.qpix)
@ -173,24 +171,24 @@ class BinViewMode(ViewMode):
qp.setBrush(QtGui.QColor(255, 102, 179))
qp.setOpacity(0.8)
qp.drawRect(cursorX*self.fontWidth, cursorY*self.fontHeight, self.fontWidth, self.fontHeight + 2)
qp.setOpacity(1)
qp.drawRect(cursorX * self.fontWidth, cursorY * self.fontHeight, self.fontWidth, self.fontHeight + 2)
qp.setOpacity(1)
def scroll_h(self, dx):
self.qpix.scroll(dx*self.fontWidth, 0, self.qpix.rect())
self.qpix.scroll(dx * self.fontWidth, 0, self.qpix.rect())
qp = QtGui.QPainter()
qp.begin(self.qpix)
qp.setFont(self.font)
qp.setPen(self.textPen)
factor = abs(dx)
if dx < 0:
qp.fillRect((self.COLUMNS - 1*factor)*self.fontWidth, 0, factor * self.fontWidth, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
qp.fillRect((self.COLUMNS - 1 * factor) * self.fontWidth, 0, factor * self.fontWidth,
self.ROWS * self.fontHeight + self.SPACER, self.backgroundBrush)
if dx > 0:
qp.fillRect(0, 0, factor * self.fontWidth, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
qp.fillRect(0, 0, factor * self.fontWidth, self.ROWS * self.fontHeight + self.SPACER, self.backgroundBrush)
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
@ -202,11 +200,11 @@ class BinViewMode(ViewMode):
if dx < 0:
# cu (column) selectam coloana
idx = (i+1)*(self.COLUMNS) - (column + 1)
idx = (i + 1) * (self.COLUMNS) - (column + 1)
if dx > 0:
idx = (i)*(self.COLUMNS) + (column)
idx = (i) * (self.COLUMNS) + (column)
#c = self.dataModel.getDisplayablePage()[idx]
# c = self.dataModel.getDisplayablePage()[idx]
c = self.transformationEngine.getChar(idx)
qp.setPen(self.transformationEngine.choosePen(idx))
@ -215,7 +213,7 @@ class BinViewMode(ViewMode):
qp.setBackground(self.transformationEngine.chooseBrush(idx))
# self.decorate(qp, (idx, c), self.dataModel.getDisplayablePage())
# self.decorate(qp, (idx, c), self.dataModel.getDisplayablePage())
if dx < 0:
cemu.writeAt(self.COLUMNS - (column + 1), i, self.cp437(c))
@ -225,15 +223,14 @@ class BinViewMode(ViewMode):
qp.setBackgroundMode(0)
qp.end()
def scroll_v(self, dy, cachePix=None, pageOffset=None):
start = time()
start = time()
# if cachePix:
# print 'da'
# if cachePix:
# print 'da'
if not cachePix:
self.qpix.scroll(0, dy*self.fontHeight, self.qpix.rect())
self.qpix.scroll(0, dy * self.fontHeight, self.qpix.rect())
qp = QtGui.QPainter()
@ -242,7 +239,7 @@ class BinViewMode(ViewMode):
else:
qp.begin(self.qpix)
#self.font.setStyleHint(QtGui.QFont.AnyStyle, QtGui.QFont.PreferAntialias)
# self.font.setStyleHint(QtGui.QFont.AnyStyle, QtGui.QFont.PreferAntialias)
qp.setFont(self.font)
qp.setPen(self.textPen)
@ -250,17 +247,17 @@ class BinViewMode(ViewMode):
# same problem when scrolling up.
factor = abs(dy)
if dy < 0:
qp.fillRect(0, (self.ROWS-factor)*self.fontHeight, self.fontWidth*self.COLUMNS, factor * self.fontHeight + self.SPACER, self.backgroundBrush)
qp.fillRect(0, (self.ROWS - factor) * self.fontHeight, self.fontWidth * self.COLUMNS,
factor * self.fontHeight + self.SPACER, self.backgroundBrush)
if dy > 0:
qp.fillRect(0, 0, self.fontWidth*self.COLUMNS, factor * self.fontHeight, self.backgroundBrush)
qp.fillRect(0, 0, self.fontWidth * self.COLUMNS, factor * self.fontHeight, self.backgroundBrush)
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
#page = self.dataModel.getDisplayablePage()
# page = self.dataModel.getDisplayablePage()
page = self.transformationEngine.decorate(pageOffset=pageOffset)
lastPen = None
lastBrush = None
@ -268,25 +265,23 @@ class BinViewMode(ViewMode):
k = time()
for row in range(factor):
# desenam caracterele
#cemu.writeAt(0, row, str(page[row*self.COLUMNS:row*self.COLUMNS+self.COLUMNS]))
# cemu.writeAt(0, row, str(page[row*self.COLUMNS:row*self.COLUMNS+self.COLUMNS]))
for i in range(self.COLUMNS):
if dy < 0:
idx = (self.ROWS - (row + 1))*self.COLUMNS + i
idx = (self.ROWS - (row + 1)) * self.COLUMNS + i
if dy > 0:
idx = i + (self.COLUMNS*row)
idx = i + (self.COLUMNS * row)
c = self.transformationEngine.getChar(idx)
nextPen = self.transformationEngine.choosePen(idx)
if nextPen != lastPen:
qp.setPen(nextPen)
lastPen = nextPen
qp.setBackgroundMode(0)
nextBrush = self.transformationEngine.chooseBrush(idx)
if nextBrush != None:
@ -296,20 +291,19 @@ class BinViewMode(ViewMode):
qp.setBackground(nextBrush)
lastBrush = nextBrush
if dy < 0:
cemu.writeAt_c(i, self.ROWS - 1 - row, self.cp437(c))
if dy > 0:
cemu.writeAt_c(i, row, self.cp437(c))
# TODO: text decorator is taking too much! print time() - k
qp.end()
end = time() - start
# print end
# sys.exit()
# print end
# sys.exit()
def scroll(self, dx, dy, cachePix=None, pageOffset=None):
@ -324,16 +318,16 @@ class BinViewMode(ViewMode):
self.scroll_h(dx)
if dy != 0:
if self.dataModel.inLimits((self.dataModel.getOffset() - dy*self.COLUMNS)):
self.dataModel.slide(-dy*self.COLUMNS)
#import time
#k = time.time()
if self.dataModel.inLimits((self.dataModel.getOffset() - dy * self.COLUMNS)):
self.dataModel.slide(-dy * self.COLUMNS)
# import time
# k = time.time()
self.scroll_v(dy, cachePix, pageOffset)
#print time.time() - k
# print time.time() - k
else:
if dy <= 0:
pass
#self.dataModel.slideToLastPage()
# self.dataModel.slideToLastPage()
else:
self.dataModel.slideToFirstPage()
@ -343,9 +337,8 @@ class BinViewMode(ViewMode):
if not cachePix:
self.draw()
def scrollPages(self, number, cachePix=None, pageOffset=None):
self.scroll(0, -number*self.ROWS, cachePix=cachePix, pageOffset=pageOffset)
self.scroll(0, -number * self.ROWS, cachePix=cachePix, pageOffset=pageOffset)
def getPixmap(self):
for t in self.Ops:
@ -356,38 +349,39 @@ class BinViewMode(ViewMode):
t[0](*t[1:])
self.Ops = []
if not self.newPix:
self.draw()
return self.newPix
def resize(self, width, height):
self.width = width - width%self.fontWidth
self.height = height - height%self.fontHeight
self.width = width - width % self.fontWidth
self.height = height - height % self.fontHeight
self.computeTextArea()
self.qpix = self._getNewPixmap(self.width, self.height + self.SPACER)
self.refresh = True
def drawTextMode(self, qp, row=0, howMany=1):
# draw background
qp.fillRect(0, row * self.fontHeight, self.COLUMNS * self.fontWidth, howMany * self.fontHeight + self.SPACER, self.backgroundBrush)
qp.fillRect(0, row * self.fontHeight, self.COLUMNS * self.fontWidth, howMany * self.fontHeight + self.SPACER,
self.backgroundBrush)
# set text pen&font
qp.setFont(self.font)
qp.setPen(self.textPen)
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
self.page = self.transformationEngine.decorate()
cemu.gotoXY(0, row)
for i, c in enumerate(self.getDisplayablePage()[row*self.COLUMNS:(row + howMany)*self.COLUMNS]):
x = i + row*self.COLUMNS
for i, c in enumerate(self.getDisplayablePage()[row * self.COLUMNS:(row + howMany) * self.COLUMNS]):
x = i + row * self.COLUMNS
c = self.transformationEngine.getChar(x)
qp.setPen(self.transformationEngine.choosePen(x))
if self.transformationEngine.chooseBrush(x) != None:
@ -395,12 +389,11 @@ class BinViewMode(ViewMode):
qp.setBackground(self.transformationEngine.chooseBrush(x))
cemu.write(self.cp437(c))
qp.setBackgroundMode(0)
qp.setBackgroundMode(0)
def getCursorAbsolutePosition(self):
x, y = self.cursor.getPosition()
return self.dataModel.getOffset() + y*self.COLUMNS + x
return self.dataModel.getOffset() + y * self.COLUMNS + x
def moveCursor(self, direction):
cursorX, cursorY = self.cursor.getPosition()
@ -410,31 +403,29 @@ class BinViewMode(ViewMode):
if cursorY == 0:
self.scroll(1, 0)
else:
self.cursor.moveAbsolute(self.COLUMNS-1, cursorY - 1)
self.cursor.moveAbsolute(self.COLUMNS - 1, cursorY - 1)
else:
self.cursor.move(-1, 0)
if direction == Directions.Right:
if self.getCursorAbsolutePosition() + 1 >= self.dataModel.getDataSize():
return
if cursorX == self.COLUMNS-1:
if cursorY == self.ROWS-1:
if cursorX == self.COLUMNS - 1:
if cursorY == self.ROWS - 1:
self.scroll(-1, 0)
else:
self.cursor.moveAbsolute(0, cursorY + 1)
else:
self.cursor.move(1, 0)
if direction == Directions.Down:
if self.getCursorAbsolutePosition() + self.COLUMNS >= self.dataModel.getDataSize():
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize()-1)
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize() - 1)
self.cursor.moveAbsolute(x, y)
return
if cursorY == self.ROWS-1:
if cursorY == self.ROWS - 1:
self.scroll(0, -1)
else:
self.cursor.move(0, 1)
@ -447,11 +438,11 @@ class BinViewMode(ViewMode):
if direction == Directions.End:
if self.dataModel.getDataSize() < self.getCursorAbsolutePosition() + self.ROWS * self.COLUMNS:
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize()-1)
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize() - 1)
self.cursor.moveAbsolute(x, y)
else:
self.cursor.moveAbsolute(self.COLUMNS-1, self.ROWS-1)
self.cursor.moveAbsolute(self.COLUMNS - 1, self.ROWS - 1)
if direction == Directions.Home:
self.cursor.moveAbsolute(0, 0)
@ -468,25 +459,23 @@ class BinViewMode(ViewMode):
def keyFilter(self):
return [
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Right),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Left),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Up),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Down),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_End),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Home),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Right),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Left),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Up),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Down),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_End),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Home),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Right),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Left),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Up),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Down),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_End),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Home),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageDown),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageUp)
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Right),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Left),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Up),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Down),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_End),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Home),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageDown),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageUp)
]
]
def anon(self, dx, dy):
self.scroll(dx, dy)
@ -510,17 +499,18 @@ class BinViewMode(ViewMode):
self.dataModel.setData_b(self.dataModel.getOffset() + offs, str(event.text()))
z = self.dataModel.getOffset() + offs
#TODO: sa nu se repete, tre original_transformengine
self.transformationEngine = RangePen(self.original_textdecorator, z, z + 0, QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine), ignoreHighlights=True)
z = self.dataModel.getOffset() + offs
# TODO: sa nu se repete, tre original_transformengine
self.transformationEngine = RangePen(self.original_textdecorator, z, z + 0,
QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine),
ignoreHighlights=True)
self.moveCursor(Directions.Right)
x, y = self.cursor.getPosition()
self.draw(refresh=True, row=y, howMany=1)
def handleKeyEvent(self, modifiers, key, event=None):
if event.type() == QtCore.QEvent.KeyRelease:
if key == QtCore.Qt.Key_Shift:
@ -529,11 +519,11 @@ class BinViewMode(ViewMode):
if event.type() == QtCore.QEvent.KeyPress:
if modifiers & QtCore.Qt.ShiftModifier:
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up, QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up,
QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
if key in keys:
self.startSelection()
if modifiers & QtCore.Qt.ControlModifier:
if key == QtCore.Qt.Key_Right:
self.addop((self.anon, -1, 0))
@ -555,10 +545,9 @@ class BinViewMode(ViewMode):
self.moveCursor(Directions.CtrlHome)
self.addop((self.draw,))
return True
else:#elif modifiers == QtCore.Qt.NoModifier or modifiers == QtCore.Qt.ShiftModifier::
else: # elif modifiers == QtCore.Qt.NoModifier or modifiers == QtCore.Qt.ShiftModifier::
if key == QtCore.Qt.Key_Escape:
self.selector.resetSelections()
@ -571,15 +560,15 @@ class BinViewMode(ViewMode):
if key == QtCore.Qt.Key_Right:
self.moveCursor(Directions.Right)
self.addop((self.draw,))
if key == QtCore.Qt.Key_Down:
self.moveCursor(Directions.Down)
self.addop((self.draw,))
if key == QtCore.Qt.Key_End:
self.moveCursor(Directions.End)
self.addop((self.draw,))
if key == QtCore.Qt.Key_Home:
self.moveCursor(Directions.Home)
self.addop((self.draw,))
@ -587,10 +576,10 @@ class BinViewMode(ViewMode):
if key == QtCore.Qt.Key_Up:
self.moveCursor(Directions.Up)
self.addop((self.draw,))
if key == QtCore.Qt.Key_PageDown:
self.addop((self.scrollPages, 1))
if key == QtCore.Qt.Key_PageUp:
self.addop((self.scrollPages, -1))
@ -615,7 +604,6 @@ class BinViewMode(ViewMode):
self.transformationEngine.reset()
self.draw(refresh=True)
"""
def handleKeyPressEvent(self, modifier, key):
if modifier == QtCore.Qt.ShiftModifier:
@ -627,6 +615,7 @@ class BinViewMode(ViewMode):
self.stopSelection()
return True
"""
def addop(self, t):
self.Ops.append(t)

View File

@ -2,6 +2,7 @@ from __future__ import division
from __future__ import print_function
from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
from builtins import str
from builtins import object
@ -13,10 +14,12 @@ from .HexViewMode import *
from .DisasmViewMode import *
from .SourceViewMode import *
class Observer(object):
def update_geometry(self):
NotImplementedError('method not implemented.')
class DataModel(Observer):
def __init__(self, data):
self._dataOffset = 0
@ -28,7 +31,7 @@ class DataModel(Observer):
@property
def dataOffset(self):
return self._dataOffset
@dataOffset.setter
def dataOffset(self, value):
print("DATA OFFSET", value)
@ -53,7 +56,7 @@ class DataModel(Observer):
self.dataOffset = off
def offsetInPage(self, off):
if off >= self.dataOffset and off <= self.dataOffset + self.rows*self.cols:
if off >= self.dataOffset and off <= self.dataOffset + self.rows * self.cols:
return True
return False
@ -63,87 +66,87 @@ class DataModel(Observer):
self.cols = cols
def slideLine(self, factor):
self.slide(factor*self.cols)
self.slide(factor * self.cols)
def slidePage(self, factor):
self.slide(factor*self.cols*self.rows)
self.slide(factor * self.cols * self.rows)
def slideToLastPage(self):
if self.rows*self.cols > len(self.data):
if self.rows * self.cols > len(self.data):
return
self.dataOffset = len(self.data) - self.cols*self.rows
self.dataOffset = len(self.data) - self.cols * self.rows
def slideToFirstPage(self):
self.dataOffset = 0
def getXYInPage(self, off):
off -= self.dataOffset
x, y = off // self.cols, off%self.cols
x, y = off // self.cols, off % self.cols
return x, y
def getPageOffset(self, page):
return self.getOffset() + (page)*self.rows*self.cols
return self.getOffset() + (page) * self.rows * self.cols
def getQWORD(self, offset, asString=False):
if offset + 8 > len(self.data):
return None
b = bytearray(self.data[offset:offset+8])
b = bytearray(self.data[offset:offset + 8])
d = ((b[7] << 56) | (b[6] << 48) | (b[5] << 40) | (b[4] << 32) | (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0])) & 0xFFFFFFFFFFFFFFFF
d = ((b[7] << 56) | (b[6] << 48) | (b[5] << 40) | (b[4] << 32) | (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (
b[0])) & 0xFFFFFFFFFFFFFFFF
if not asString:
if not asString:
return d
s = '{0:016X}'.format(d)
return s
def getDWORD(self, offset, asString=False):
if offset + 4 >= len(self.data):
return None
b = bytearray(self.data[offset:offset+4])
b = bytearray(self.data[offset:offset + 4])
d = ((b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0])) & 0xFFFFFFFF
if not asString:
if not asString:
return d
s = '{0:08X}'.format(d)
return s
def getWORD(self, offset, asString=False):
if offset + 2 > len(self.data):
return None
b = bytearray(self.data[offset:offset+2])
b = bytearray(self.data[offset:offset + 2])
d = ((b[1] << 8) | (b[0])) & 0xFFFF
if not asString:
if not asString:
return d
s = '{0:04X}'.format(d)
return s
def getBYTE(self, offset, asString=False):
if offset + 1 > len(self.data):
return None
b = bytearray(self.data[offset:offset+1])
b = bytearray(self.data[offset:offset + 1])
d = (b[0]) & 0xFF
if not asString:
if not asString:
return d
s = '{0:02X}'.format(d)
return s
def getChar(self, offset):
@ -199,6 +202,7 @@ class DataModel(Observer):
def size(self):
pass
class FileDataModel(DataModel):
def __init__(self, filename):
self._filename = filename
@ -237,7 +241,10 @@ class FileDataModel(DataModel):
def size(self):
return os.path.getsize(self._filename)
import io
class MyStringIO(io.StringIO, object):
def __init__(self, data):
self.raw = data
@ -246,6 +253,7 @@ class MyStringIO(io.StringIO, object):
def __len__(self):
return len(self.raw)
class MyByte(bytearray):
def __init__(self, data):
self.raw = data
@ -275,6 +283,7 @@ class MyByte(bytearray):
self._pointer += size
return data
class BufferDataModel(DataModel):
def __init__(self, data, name):
self._filename = name
@ -291,13 +300,14 @@ class BufferDataModel(DataModel):
def close(self):
return
# def write(self, offset, stream):
# self._mapped.seek(offset)
# self._mapped.write(stream)
# def write(self, offset, stream):
# self._mapped.seek(offset)
# self._mapped.write(stream)
def size(self):
return len(self.data)
class ApkModel(DataModel):
def __init__(self, apkobj):
print(apkobj)
@ -323,6 +333,7 @@ class ApkModel(DataModel):
def size(self):
return len(self.data)
class DexClassModel(DataModel):
def __init__(self, current_class):
self.current_class = current_class

View File

@ -27,14 +27,14 @@ class InstructionView(object):
def AddComment(self, cmt):
self._Comments.append(cmt)
def Load(self):
if self.loaded:
return
H = self.get_hex().split(' ')
for i, h in enumerate(H):
self._indexTable += [(i*3, len(h), h)]
self._indexTable += [(i * 3, len(h), h)]
self._indexTable += [(MNEMONIC_COLUMN, len(self.get_name()), self.get_name())]
@ -151,7 +151,6 @@ class InstructionView(object):
return idx, 0
def getSelectedToken(self, cx):
for i, t in enumerate(self._indexTable):
idx, length, value = t
@ -209,8 +208,8 @@ class DisasmViewMode(ViewMode):
for method in methods:
mx = vm_analysis.get_method(method)
for DVMBasicMethodBlockInstruction in method.get_instructions():
#for DVMBasicMethodBlock in mx.basic_blocks.gets():
# for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions():
# for DVMBasicMethodBlock in mx.basic_blocks.gets():
# for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions():
ins = InstructionView(DVMBasicMethodBlockInstruction)
self.CACHE_OPCODES.append(ins)
self.CACHE_IDX_OPCODES[offset] = ins
@ -246,7 +245,6 @@ class DisasmViewMode(ViewMode):
ins.Load()
self.OPCODES.append(ins)
@property
def fontWidth(self):
return self._fontWidth
@ -259,8 +257,8 @@ class DisasmViewMode(ViewMode):
self.transformationEngine = engine
def resize(self, width, height):
self.width = width - width%self.fontWidth
self.height = height - height%self.fontHeight
self.width = width - width % self.fontWidth
self.height = height - height % self.fontHeight
self.computeTextArea()
self.qpix = self._getNewPixmap(self.width, self.height + self.SPACER)
self.refresh = True
@ -374,9 +372,8 @@ class DisasmViewMode(ViewMode):
brush)
qp.setOpacity(1)
def drawBranch(self, qp):
qp.fillRect(-50, 0, 50, self.ROWS * self.fontHeight, self.backgroundBrush)
qp.fillRect(-50, 0, 50, self.ROWS * self.fontHeight, self.backgroundBrush)
def drawBranch2(self, qp):
@ -400,29 +397,30 @@ class DisasmViewMode(ViewMode):
return
screenVA = self._getVA(self.dataModel.getOffset())
if target > screenVA and target < self._getVA(self.dataModel.getOffset()) + tsize - self.OPCODES[-1].size:
if target > screenVA and target < self._getVA(self.dataModel.getOffset()) + tsize - self.OPCODES[-1].size:
# branch target is in screen
sz = 0
for i, t in enumerate(self.OPCODES):
sz += t.size
if sz+self._getVA(self.dataModel.getOffset()) >= target:
if sz + self._getVA(self.dataModel.getOffset()) >= target:
break
qp.setPen(QtGui.QPen(QtGui.QColor(0, 192, 0), 1, QtCore.Qt.SolidLine))
# draw the three lines
qp.drawLine(-5, cursorY*self.fontHeight + self.fontHeight // 2, -30, cursorY*self.fontHeight + half)
qp.drawLine(-5, cursorY * self.fontHeight + self.fontHeight // 2, -30, cursorY * self.fontHeight + half)
qp.drawLine(-30, cursorY*self.fontHeight + self.fontHeight // 2, -30, (i + 1)*self.fontHeight + half)
qp.drawLine(-30, cursorY * self.fontHeight + self.fontHeight // 2, -30,
(i + 1) * self.fontHeight + half)
qp.drawLine(-30, (i + 1)*self.fontHeight + half, -15, (i + 1)*self.fontHeight + half)
qp.drawLine(-30, (i + 1) * self.fontHeight + half, -15, (i + 1) * self.fontHeight + half)
# draw arrow
points = [QtCore.QPoint(-15, (i + 1)*self.fontHeight + half - 5),
QtCore.QPoint(-15, (i + 1)*self.fontHeight + half + 5),
QtCore.QPoint(-5, (i + 1)*self.fontHeight + half), ]
points = [QtCore.QPoint(-15, (i + 1) * self.fontHeight + half - 5),
QtCore.QPoint(-15, (i + 1) * self.fontHeight + half + 5),
QtCore.QPoint(-5, (i + 1) * self.fontHeight + half), ]
needle = QtGui.QPolygon(points)
qp.setBrush(QtGui.QBrush(QtGui.QColor(0, 128, 0)))
qp.drawPolygon(needle)
@ -435,13 +433,14 @@ class DisasmViewMode(ViewMode):
qp.setPen(QtGui.QPen(QtGui.QColor(0, 192, 0), 1, QtCore.Qt.DotLine))
# draw the two lines
qp.drawLine(-5, cursorY*self.fontHeight + self.fontHeight // 2, -30, cursorY*self.fontHeight + half)
qp.drawLine(-30, cursorY*self.fontHeight + self.fontHeight // 2, -30, (self.ROWS - 2)*self.fontHeight + half)
qp.drawLine(-5, cursorY * self.fontHeight + self.fontHeight // 2, -30, cursorY * self.fontHeight + half)
qp.drawLine(-30, cursorY * self.fontHeight + self.fontHeight // 2, -30,
(self.ROWS - 2) * self.fontHeight + half)
# draw arrow
points = [QtCore.QPoint(-25, (self.ROWS - 2)*self.fontHeight + half),
QtCore.QPoint(-35, (self.ROWS - 2)*self.fontHeight + half),
QtCore.QPoint(-30, (self.ROWS - 2)*self.fontHeight + 2*half), ]
points = [QtCore.QPoint(-25, (self.ROWS - 2) * self.fontHeight + half),
QtCore.QPoint(-35, (self.ROWS - 2) * self.fontHeight + half),
QtCore.QPoint(-30, (self.ROWS - 2) * self.fontHeight + 2 * half), ]
needle = QtGui.QPolygon(points)
qp.setBrush(QtGui.QBrush(QtGui.QColor(0, 128, 0)))
qp.drawPolygon(needle)
@ -453,24 +452,22 @@ class DisasmViewMode(ViewMode):
qp.setPen(QtGui.QPen(QtGui.QColor(0, 192, 0), 1, QtCore.Qt.DotLine))
# draw the two lines
qp.drawLine(-5, cursorY*self.fontHeight + self.fontHeight // 2, -30, cursorY*self.fontHeight + half)
qp.drawLine(-30, cursorY*self.fontHeight + self.fontHeight // 2, -30, (1)*self.fontHeight + half)
qp.drawLine(-5, cursorY * self.fontHeight + self.fontHeight // 2, -30, cursorY * self.fontHeight + half)
qp.drawLine(-30, cursorY * self.fontHeight + self.fontHeight // 2, -30, (1) * self.fontHeight + half)
# draw arrow
points = [QtCore.QPoint(-25, (1)*self.fontHeight + half),
QtCore.QPoint(-35, (1)*self.fontHeight + half),
QtCore.QPoint(-30, (1)*self.fontHeight), ]
points = [QtCore.QPoint(-25, (1) * self.fontHeight + half),
QtCore.QPoint(-35, (1) * self.fontHeight + half),
QtCore.QPoint(-30, (1) * self.fontHeight), ]
needle = QtGui.QPolygon(points)
qp.setBrush(QtGui.QBrush(QtGui.QColor(0, 128, 0)))
qp.drawPolygon(needle)
def draw(self, refresh=False):
if self.dataModel.getOffset() in self.Paints:
self.refresh = False
self.qpix = QtGui.QPixmap(self.Paints[self.dataModel.getOffset()])
#print 'hit'
# print 'hit'
self.drawAdditionals()
return
@ -478,27 +475,27 @@ class DisasmViewMode(ViewMode):
qp = QtGui.QPainter()
qp.begin(self.qpix)
# viewport
#qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
# qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
#start = time()
# start = time()
self.drawTextMode(qp)
#end = time() - start
#print 'Time ' + str(end)
# end = time() - start
# print 'Time ' + str(end)
self.refresh = False
qp.end()
# self.Paints[self.dataModel.getOffset()] = QtGui.QPixmap(self.qpix)
# self.Paints[self.dataModel.getOffset()] = QtGui.QPixmap(self.qpix)
self.drawAdditionals()
def drawAdditionals(self):
self.newPix = self._getNewPixmap(self.width, self.height + self.SPACER)
qp = QtGui.QPainter()
qp.begin(self.newPix)
qp.setWindow(-50, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight)
qp.setWindow(-50, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight)
qp.drawPixmap(0, 0, self.qpix)
#self.transformationEngine.decorateText()
# self.transformationEngine.decorateText()
# highlight selected text
self.selector.highlightText()
@ -529,7 +526,6 @@ class DisasmViewMode(ViewMode):
return self.plugin.hintDisasmVA(offset)
return 0
def _drawRow(self, qp, cemu, row, asm, offset=-1):
print('DRAW AN INSTRUCTION', asm, row, asm.get_name(), len(asm.get_operands(offset)), hex(self.getPageOffset()))
@ -541,12 +537,12 @@ class DisasmViewMode(ViewMode):
cemu.writeAt(0, row, hex_data)
# fill with spaces
cemu.write((MNEMONIC_COLUMN - len(hex_data))*' ')
cemu.write((MNEMONIC_COLUMN - len(hex_data)) * ' ')
# let's color some branch instr
#if asm.isBranch():
# if asm.isBranch():
# qp.setPen(QtGui.QPen(QtGui.QColor(255, 80, 0)))
#else:
# else:
qp.setPen(QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine))
mnemonic = asm.get_name()
@ -577,7 +573,7 @@ class DisasmViewMode(ViewMode):
cemu.write('; "{0}"'.format(' '.join(comments)))
def _write_operands(self, asm, qp, cemu, offset):
qp.setPen(QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine))
qp.setPen(QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine))
operands = asm.get_operands(offset)
for operand in operands:
@ -632,7 +628,7 @@ class DisasmViewMode(ViewMode):
qp.save()
if tok.type == 'REGISTER':
qp.setPen(QtGui.QPen(QtGui.QColor('white')))
if tok.type == 'NUMBER':
qp.setPen(QtGui.QPen(QtGui.QColor('green')))
@ -647,12 +643,12 @@ class DisasmViewMode(ViewMode):
def drawTextMode(self, qp):
print('OFFSET', self.dataModel.getOffset())
# draw background
qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
# set text pen&font
qp.setFont(self.font)
qp.setPen(self.textPen)
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
offset = 0
@ -662,7 +658,6 @@ class DisasmViewMode(ViewMode):
self._drawRow(qp, cemu, i, asm, offset)
offset += asm.get_length()
def _getRowInPage(self, offset):
offset -= self.dataModel.getOffset()
@ -681,23 +676,23 @@ class DisasmViewMode(ViewMode):
if i == row:
return size
size += asm.get_length()
size += asm.get_length()
return None
def goTo(self, offset):
print("GOTO ", offset)
tsize = sum([opcode.get_length() for opcode in self.OPCODES])
if offset < self.dataModel.getOffset() + tsize and offset > self.dataModel.getOffset():
# if in current page, move cursor
row = self._getRowInPage(offset)
off_row = self._getOffsetOfRow(row)
diff = offset - self.dataModel.getOffset() - off_row# self.OPCODES[row].size
diff = offset - self.dataModel.getOffset() - off_row # self.OPCODES[row].size
if row is not None:
self.cursor.moveAbsolute((diff)*3, row)
self.cursor.moveAbsolute((diff) * 3, row)
self.draw(refresh=False)
else:
@ -707,15 +702,14 @@ class DisasmViewMode(ViewMode):
self.cursor.moveAbsolute(0, 0)
self.draw(refresh=True)
#TODO: getDisplayablePage() won't contain what we want to disasm. we will use dataModel
# TODO: getDisplayablePage() won't contain what we want to disasm. we will use dataModel
# in this view, getDisplayablePage will contain disasm text, because that is what is displayed
if self.widget:
self.widget.update()
def scrollPages(self, number, cachePix=None, pageOffset=None):
self.scroll(0, -number*self.ROWS, cachePix=cachePix, pageOffset=pageOffset)
self.scroll(0, -number * self.ROWS, cachePix=cachePix, pageOffset=pageOffset)
def scroll_v(self, dy, cachePix=None, pageOffset=None):
print('scroll_v', dy, cachePix, pageOffset, hex(self.getCursorAbsolutePosition()))
@ -745,7 +739,7 @@ class DisasmViewMode(ViewMode):
current_offset = self.dataModel.getOffset()
current_idx = self.CACHE_IDX_OPCODES_OFF[current_offset]
print("IDX", current_idx, hex(current_offset))
#start = self.CACHE_OPCODES[self.CACHE_IDX_OPCODES_OFF[self.getCursorAbsolutePosition()]-1]
# start = self.CACHE_OPCODES[self.CACHE_IDX_OPCODES_OFF[self.getCursorAbsolutePosition()]-1]
current_idx -= 1
newins = self.CACHE_OPCODES[current_idx]
@ -754,7 +748,6 @@ class DisasmViewMode(ViewMode):
self.dataModel.slide(self.OPCODES[0].get_length())
del self.OPCODES[0]
if dy >= 0:
self.dataModel.slide(-newins.get_length())
del self.OPCODES[len(self.OPCODES) - 1]
@ -774,11 +767,11 @@ class DisasmViewMode(ViewMode):
print('ROW TO DRAW', RowsToDraw)
if len(RowsToDraw) < abs(dy):
# maybe we couldn't draw dy rows (possible we reached the beginning of the data to early), recalculate dy
dy = len(RowsToDraw)*dy/abs(dy)
dy = len(RowsToDraw) * dy / abs(dy)
factor = abs(dy)
if not cachePix:
self.qpix.scroll(0, dy*self.fontHeight, self.qpix.rect())
self.qpix.scroll(0, dy * self.fontHeight, self.qpix.rect())
qp = QtGui.QPainter()
if cachePix:
@ -791,10 +784,11 @@ class DisasmViewMode(ViewMode):
# erase rows that will disappear
if dy < 0:
qp.fillRect(0, (self.ROWS-factor)*self.fontHeight, self.fontWidth*self.COLUMNS, factor * self.fontHeight, self.backgroundBrush)
qp.fillRect(0, (self.ROWS - factor) * self.fontHeight, self.fontWidth * self.COLUMNS,
factor * self.fontHeight, self.backgroundBrush)
if dy > 0:
qp.fillRect(0, 0, self.fontWidth*self.COLUMNS, factor * self.fontHeight, self.backgroundBrush)
qp.fillRect(0, 0, self.fontWidth * self.COLUMNS, factor * self.fontHeight, self.backgroundBrush)
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
@ -806,12 +800,13 @@ class DisasmViewMode(ViewMode):
print('')
def scroll(self, dx, dy, cachePix=None, pageOffset=None):
print('scroll ', dx, dy, self.dataModel.inLimits((self.dataModel.getOffset() - dx)), 'offset', self.dataModel.getOffset())
print('scroll ', dx, dy, self.dataModel.inLimits((self.dataModel.getOffset() - dx)), 'offset',
self.dataModel.getOffset())
if dx != 0:
if self.dataModel.inLimits((self.dataModel.getOffset() - dx)):
self.dataModel.slide(dx)
self.draw(refresh=True)
#self.scroll_h(dx)
# self.scroll_h(dx)
if dy != 0:
if dy > 0:
@ -822,13 +817,12 @@ class DisasmViewMode(ViewMode):
if dy < 0:
tsize = sum([asm.get_length() for asm in self.OPCODES])
if self.dataModel.getOffset() + tsize == self.dataModel.getDataSize():
if self.dataModel.getOffset() + tsize == self.dataModel.getDataSize():
print('END')
return
self.scroll_v(dy, cachePix, pageOffset)
def moveCursor(self, direction):
cursorX, cursorY = self.cursor.getPosition()
@ -847,14 +841,13 @@ class DisasmViewMode(ViewMode):
self.cursor.moveAbsolute(idx, cursorY - 1)
else:
x, dy = asm.getNextCursor(cursorX, direction=Directions.Left)
self.cursor.move(-(cursorX-x), dy)
self.cursor.move(-(cursorX - x), dy)
if direction == Directions.Right:
asm = self.OPCODES[cursorY]
x, dy = asm.getNextCursor(cursorX, direction=Directions.Right)
if cursorY == self.ROWS-1 and dy > 0:
if cursorY == self.ROWS - 1 and dy > 0:
self.scroll(0, -1)
self.cursor.moveAbsolute(0, cursorY)
@ -862,10 +855,10 @@ class DisasmViewMode(ViewMode):
if cursorY + dy >= len(self.OPCODES):
dy = 0
self.cursor.move(x-cursorX, dy)
self.cursor.move(x - cursorX, dy)
if direction == Directions.Down:
if cursorY == self.ROWS-1:
if cursorY == self.ROWS - 1:
# move cursor to first token
self.scroll(0, -1)
self.cursor.moveAbsolute(0, cursorY)
@ -893,14 +886,13 @@ class DisasmViewMode(ViewMode):
if direction == Directions.Home:
self.cursor.moveAbsolute(0, 0)
if direction == Directions.CtrlHome:
self.goTo(0)
if direction == Directions.CtrlEnd:
self.dataModel.slideToLastPage()
self.draw(refresh=True)
self.cursor.moveAbsolute(self.COLUMNS-1, self.ROWS-1)
self.cursor.moveAbsolute(self.COLUMNS - 1, self.ROWS - 1)
def _followBranch(self):
cursorX, cursorY = self.cursor.getPosition()
@ -931,7 +923,8 @@ class DisasmViewMode(ViewMode):
if event.type() == QtCore.QEvent.KeyPress:
if modifiers == QtCore.Qt.ShiftModifier:
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up, QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up,
QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
if key in keys:
self.startSelection()
@ -959,11 +952,11 @@ class DisasmViewMode(ViewMode):
if key == QtCore.Qt.Key_Home:
self.moveCursor(Directions.CtrlHome)
self.addop((self.draw,))
#self.draw()
# self.draw()
return True
else:#elif modifiers == QtCore.Qt.NoModifier:
else: # elif modifiers == QtCore.Qt.NoModifier:
if key == QtCore.Qt.Key_Escape:
self.selector.resetSelections()
@ -972,37 +965,37 @@ class DisasmViewMode(ViewMode):
if key == QtCore.Qt.Key_Left:
self.moveCursor(Directions.Left)
self.addop((self.draw,))
#self.draw()
# self.draw()
if key == QtCore.Qt.Key_Right:
self.moveCursor(Directions.Right)
self.addop((self.draw,))
#self.draw()
# self.draw()
if key == QtCore.Qt.Key_Down:
self.moveCursor(Directions.Down)
self.addop((self.draw,))
#self.draw()
# self.draw()
if key == QtCore.Qt.Key_End:
self.moveCursor(Directions.End)
self.addop((self.draw,))
#self.draw()
# self.draw()
if key == QtCore.Qt.Key_Home:
self.moveCursor(Directions.Home)
self.addop((self.draw,))
#self.draw()
# self.draw()
if key == QtCore.Qt.Key_Up:
self.moveCursor(Directions.Up)
self.addop((self.draw,))
#self.draw()
# self.draw()
if key == QtCore.Qt.Key_PageDown:
self.addop((self.scrollPages, 1))
self.addop((self.draw,))
if key == QtCore.Qt.Key_PageUp:
self.addop((self.scrollPages, -1))
self.addop((self.draw,))

View File

@ -35,12 +35,12 @@ class HexViewMode(ViewMode):
# text font
self.font = themes['font']
# font metrics. assume font is monospaced
self.font.setKerning(False)
self.font.setFixedPitch(True)
fm = QtGui.QFontMetrics(self.font)
self._fontWidth = fm.width('a')
self._fontWidth = fm.width('a')
self._fontHeight = fm.height()
self.Special = string.ascii_letters + string.digits + ' .;\':;=\"?-!()/\\_'
@ -50,7 +50,7 @@ class HexViewMode(ViewMode):
self.cursor = cursor
self.HexColumns = [1, 4, 8, 16, 32, 36, 40]
self.idxHexColumns = 3 # 32 columns
self.idxHexColumns = 3 # 32 columns
self.newPix = None
self.Ops = []
@ -69,7 +69,6 @@ class HexViewMode(ViewMode):
def fontHeight(self):
return self._fontHeight
def setTransformationEngine(self, engine):
self.transformationEngine = engine
self.original_textdecorator = engine
@ -78,7 +77,7 @@ class HexViewMode(ViewMode):
return QtGui.QPixmap(width, height)
def getPixmap(self):
#return self.qpix
# return self.qpix
for t in self.Ops:
if len(t) == 1:
@ -114,7 +113,7 @@ class HexViewMode(ViewMode):
def getCursorAbsolutePosition(self):
x, y = self.cursor.getPosition()
return self.dataModel.getOffset() + y*self.COLUMNS + x
return self.dataModel.getOffset() + y * self.COLUMNS + x
def computeTextArea(self):
self.COLUMNS = self.HexColumns[self.idxHexColumns]
@ -123,8 +122,8 @@ class HexViewMode(ViewMode):
self.notify(self.ROWS, self.COLUMNS)
def resize(self, width, height):
self.width = width - width%self.fontWidth
self.height = height - height%self.fontHeight
self.width = width - width % self.fontWidth
self.height = height - height % self.fontHeight
self.computeTextArea()
self.qpix = self._getNewPixmap(self.width, self.height + self.SPACER)
self.refresh = True
@ -136,13 +135,12 @@ class HexViewMode(ViewMode):
self.idxHexColumns += 1
# if screen is ont big enough, retry
if self.HexColumns[self.idxHexColumns]*(3+1) + self.gap >= self.CON_COLUMNS:
if self.HexColumns[self.idxHexColumns] * (3 + 1) + self.gap >= self.CON_COLUMNS:
self.changeHexColumns()
return
self.resize(self.width, self.height)
def scroll(self, dx, dy):
if dx != 0:
if self.dataModel.inLimits((self.dataModel.getOffset() - dx)):
@ -150,13 +148,13 @@ class HexViewMode(ViewMode):
self.scroll_h(dx)
if dy != 0:
if self.dataModel.inLimits((self.dataModel.getOffset() - dy*self.COLUMNS)):
self.dataModel.slide(-dy*self.COLUMNS)
if self.dataModel.inLimits((self.dataModel.getOffset() - dy * self.COLUMNS)):
self.dataModel.slide(-dy * self.COLUMNS)
self.scroll_v(dy)
else:
if dy <= 0:
pass
#self.dataModel.slideToLastPage()
# self.dataModel.slideToLastPage()
else:
self.dataModel.slideToFirstPage()
self.draw(refresh=True)
@ -164,7 +162,7 @@ class HexViewMode(ViewMode):
self.draw()
def scrollPages(self, number):
self.scroll(0, -number*self.ROWS)
self.scroll(0, -number * self.ROWS)
def drawAdditionals(self):
self.newPix = self._getNewPixmap(self.width, self.height + self.SPACER)
@ -172,7 +170,7 @@ class HexViewMode(ViewMode):
qp.begin(self.newPix)
qp.drawPixmap(0, 0, self.qpix)
#self.transformationEngine.decorateText()
# self.transformationEngine.decorateText()
# highlight selected text
self.selector.highlightText()
@ -187,19 +185,20 @@ class HexViewMode(ViewMode):
for i in range(self.COLUMNS // 4)[1:]:
xw = i * 4 * 3 * self.fontWidth - 4
qp.setPen(QtGui.QColor(0, 255, 0))
qp.drawLine(xw, 0, xw, self.ROWS*self.fontHeight)
qp.drawLine(xw, 0, xw, self.ROWS * self.fontHeight)
qp.end()
def scroll_h(self, dx):
gap = self.gap
# hex part
self.qpix.scroll(dx*3*self.fontWidth, 0, QtCore.QRect(0, 0, self.COLUMNS*3*self.fontWidth, self.ROWS*self.fontHeight + self.SPACER))
self.qpix.scroll(dx * 3 * self.fontWidth, 0, QtCore.QRect(0, 0, self.COLUMNS * 3 * self.fontWidth,
self.ROWS * self.fontHeight + self.SPACER))
# text part
self.qpix.scroll(dx*self.fontWidth, 0, QtCore.QRect((self.COLUMNS*3 + gap)*self.fontWidth , 0, self.COLUMNS*self.fontWidth, self.ROWS*self.fontHeight + self.SPACER))
self.qpix.scroll(dx * self.fontWidth, 0,
QtCore.QRect((self.COLUMNS * 3 + gap) * self.fontWidth, 0, self.COLUMNS * self.fontWidth,
self.ROWS * self.fontHeight + self.SPACER))
qp = QtGui.QPainter()
@ -212,17 +211,21 @@ class HexViewMode(ViewMode):
# There are some trails from the characters, when scrolling. trail == number of pixel to erase near the character
trail = 5
textBegining = self.COLUMNS*3 + gap
textBegining = self.COLUMNS * 3 + gap
if dx < 0:
# hex
qp.fillRect((self.COLUMNS - 1*factor)*3*self.fontWidth, 0, factor * self.fontWidth * 3, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
qp.fillRect((self.COLUMNS - 1 * factor) * 3 * self.fontWidth, 0, factor * self.fontWidth * 3,
self.ROWS * self.fontHeight + self.SPACER, self.backgroundBrush)
# text
qp.fillRect((textBegining + self.COLUMNS - 1*factor)*self.fontWidth, 0, factor * self.fontWidth+trail, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
qp.fillRect((textBegining + self.COLUMNS - 1 * factor) * self.fontWidth, 0, factor * self.fontWidth + trail,
self.ROWS * self.fontHeight + self.SPACER, self.backgroundBrush)
if dx > 0:
# hex
qp.fillRect(0, 0, factor * 3 * self.fontWidth, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
qp.fillRect(0, 0, factor * 3 * self.fontWidth, self.ROWS * self.fontHeight + self.SPACER,
self.backgroundBrush)
# text
qp.fillRect(textBegining*self.fontWidth - trail, 0, factor * self.fontWidth + trail, self.ROWS*self.fontHeight + self.SPACER, self.backgroundBrush)
qp.fillRect(textBegining * self.fontWidth - trail, 0, factor * self.fontWidth + trail,
self.ROWS * self.fontHeight + self.SPACER, self.backgroundBrush)
cemu = ConsoleEmulator(qp, self.ROWS, self.CON_COLUMNS)
@ -234,9 +237,9 @@ class HexViewMode(ViewMode):
if dx < 0:
# cu (column) selectam coloana
idx = (i+1)*(self.COLUMNS) - (column + 1)
idx = (i + 1) * (self.COLUMNS) - (column + 1)
if dx > 0:
idx = (i)*(self.COLUMNS) + (column)
idx = (i) * (self.COLUMNS) + (column)
if len(self.getDisplayablePage()) > idx:
qp.setPen(self.transformationEngine.choosePen(idx))
@ -252,11 +255,11 @@ class HexViewMode(ViewMode):
hex_s = str(hex(c)[2:]).zfill(2) + ' '
if dx < 0:
cemu.writeAt((self.COLUMNS - (column + 1))*3, i, hex_s, noBackgroudOnSpaces=True)
cemu.writeAt((self.COLUMNS - (column + 1)) * 3, i, hex_s, noBackgroudOnSpaces=True)
cemu.writeAt(textBegining + self.COLUMNS - (column + 1), i, self.cp437(c))
if dx > 0:
cemu.writeAt((column)*3, i, hex_s, noBackgroudOnSpaces=True)
cemu.writeAt((column) * 3, i, hex_s, noBackgroudOnSpaces=True)
cemu.writeAt(textBegining + column, i, self.cp437(c))
qp.setBackgroundMode(0)
@ -264,7 +267,7 @@ class HexViewMode(ViewMode):
qp.end()
def scroll_v(self, dy):
self.qpix.scroll(0, dy*self.fontHeight, self.qpix.rect())
self.qpix.scroll(0, dy * self.fontHeight, self.qpix.rect())
qp = QtGui.QPainter()
@ -278,12 +281,12 @@ class HexViewMode(ViewMode):
if dy < 0:
cemu.gotoXY(0, self.ROWS - factor)
qp.fillRect(0, (self.ROWS-factor)*self.fontHeight, self.fontWidth*self.CON_COLUMNS, factor * self.fontHeight + self.SPACER, self.backgroundBrush)
qp.fillRect(0, (self.ROWS - factor) * self.fontHeight, self.fontWidth * self.CON_COLUMNS,
factor * self.fontHeight + self.SPACER, self.backgroundBrush)
if dy > 0:
cemu.gotoXY(0, 0)
qp.fillRect(0, 0, self.fontWidth*self.CON_COLUMNS, factor * self.fontHeight, self.backgroundBrush)
qp.fillRect(0, 0, self.fontWidth * self.CON_COLUMNS, factor * self.fontHeight, self.backgroundBrush)
page = self.transformationEngine.decorate()
@ -295,9 +298,9 @@ class HexViewMode(ViewMode):
if dy < 0:
# we write from top-down, so get index of the first row that will be displayed
# this is why we have factor - row
idx = i + (self.ROWS - (factor - row))*self.COLUMNS
idx = i + (self.ROWS - (factor - row)) * self.COLUMNS
if dy > 0:
idx = i + (self.COLUMNS*row)
idx = i + (self.COLUMNS * row)
qp.setPen(self.transformationEngine.choosePen(idx))
@ -321,14 +324,13 @@ class HexViewMode(ViewMode):
# save hex position
x, y = cemu.getXY()
# write text
cemu.writeAt(self.COLUMNS*3 + self.gap + (i%self.COLUMNS), y, self.cp437(c))
cemu.writeAt(self.COLUMNS * 3 + self.gap + (i % self.COLUMNS), y, self.cp437(c))
# go back to hex chars
cemu.gotoXY(x, y)
qp.setBackgroundMode(0)
cemu.writeLn()
qp.end()
@ -349,7 +351,8 @@ class HexViewMode(ViewMode):
def drawTextMode(self, qp, row=0, howMany=1):
# draw background
qp.fillRect(0, row * self.fontHeight, self.CON_COLUMNS * self.fontWidth, howMany * self.fontHeight + self.SPACER, self.backgroundBrush)
qp.fillRect(0, row * self.fontHeight, self.CON_COLUMNS * self.fontWidth,
howMany * self.fontHeight + self.SPACER, self.backgroundBrush)
# set text pen&font
qp.setFont(self.font)
@ -361,11 +364,12 @@ class HexViewMode(ViewMode):
cemu.gotoXY(0, row)
for i, c in enumerate(self.getDisplayablePage()[row*self.COLUMNS:(row + howMany)*self.COLUMNS]): #TODO: does not apply all decorators
for i, c in enumerate(self.getDisplayablePage()[row * self.COLUMNS:(
row + howMany) * self.COLUMNS]): # TODO: does not apply all decorators
w = i + row*self.COLUMNS
w = i + row * self.COLUMNS
if (w+1)%self.COLUMNS == 0:
if (w + 1) % self.COLUMNS == 0:
hex_s = str(hex(c)[2:]).zfill(2)
else:
hex_s = str(hex(c)[2:]).zfill(2) + ' '
@ -381,16 +385,16 @@ class HexViewMode(ViewMode):
# save hex position
x, y = cemu.getXY()
# write text
cemu.writeAt(self.COLUMNS*3 + self.gap + (w%self.COLUMNS), y, self.cp437(c))
cemu.writeAt(self.COLUMNS * 3 + self.gap + (w % self.COLUMNS), y, self.cp437(c))
# go back to hex chars
cemu.gotoXY(x, y)
if (w+1)%self.COLUMNS == 0:
if (w + 1) % self.COLUMNS == 0:
cemu.writeLn()
qp.setBackgroundMode(0)
def moveCursor(self, direction):
#TODO: have to move this, don't like it
# TODO: have to move this, don't like it
if self.isInEditMode():
if self.highpart == False:
self.highpart = True
@ -402,31 +406,29 @@ class HexViewMode(ViewMode):
if cursorY == 0:
self.scroll(1, 0)
else:
self.cursor.moveAbsolute(self.COLUMNS-1, cursorY - 1)
self.cursor.moveAbsolute(self.COLUMNS - 1, cursorY - 1)
else:
self.cursor.move(-1, 0)
if direction == Directions.Right:
if self.getCursorAbsolutePosition() + 1 >= self.dataModel.getDataSize():
return
if cursorX == self.COLUMNS-1:
if cursorY == self.ROWS-1:
if cursorX == self.COLUMNS - 1:
if cursorY == self.ROWS - 1:
self.scroll(-1, 0)
else:
self.cursor.moveAbsolute(0, cursorY + 1)
else:
self.cursor.move(1, 0)
if direction == Directions.Down:
if self.getCursorAbsolutePosition() + self.COLUMNS >= self.dataModel.getDataSize():
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize()-1)
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize() - 1)
self.cursor.moveAbsolute(x, y)
return
if cursorY == self.ROWS-1:
if cursorY == self.ROWS - 1:
self.scroll(0, -1)
else:
self.cursor.move(0, 1)
@ -439,11 +441,11 @@ class HexViewMode(ViewMode):
if direction == Directions.End:
if self.dataModel.getDataSize() < self.getCursorAbsolutePosition() + self.ROWS * self.COLUMNS:
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize()-1)
y, x = self.dataModel.getXYInPage(self.dataModel.getDataSize() - 1)
self.cursor.moveAbsolute(x, y)
else:
self.cursor.moveAbsolute(self.COLUMNS-1, self.ROWS-1)
self.cursor.moveAbsolute(self.COLUMNS - 1, self.ROWS - 1)
if direction == Directions.Home:
self.cursor.moveAbsolute(0, 0)
@ -458,8 +460,6 @@ class HexViewMode(ViewMode):
self.draw(refresh=True)
self.moveCursor(Directions.End)
def drawCursor(self, qp):
qp.setBrush(QtGui.QColor(255, 255, 0))
if self.isInEditMode():
@ -469,7 +469,7 @@ class HexViewMode(ViewMode):
columns = self.HexColumns[self.idxHexColumns]
if cursorX > columns:
self.cursor.moveAbsolute(columns-1, cursorY)
self.cursor.moveAbsolute(columns - 1, cursorY)
# get cursor position again, maybe it was moved
cursorX, cursorY = self.cursor.getPosition()
@ -478,41 +478,42 @@ class HexViewMode(ViewMode):
if self.isInEditMode():
qp.setOpacity(0.5)
# cursor on text
qp.drawRect((self.COLUMNS*3 + self.gap + cursorX)*self.fontWidth, cursorY*self.fontHeight+2, self.fontWidth, self.fontHeight)
qp.drawRect((self.COLUMNS * 3 + self.gap + cursorX) * self.fontWidth, cursorY * self.fontHeight + 2,
self.fontWidth, self.fontHeight)
# cursor on hex
if not self.isInEditMode():
qp.drawRect(cursorX*3*self.fontWidth, cursorY*self.fontHeight+2, 2*self.fontWidth, self.fontHeight)
qp.drawRect(cursorX * 3 * self.fontWidth, cursorY * self.fontHeight + 2, 2 * self.fontWidth,
self.fontHeight)
else:
if self.highpart:
qp.drawRect(cursorX*3*self.fontWidth, cursorY*self.fontHeight+2, 1*self.fontWidth, self.fontHeight)
qp.drawRect(cursorX * 3 * self.fontWidth, cursorY * self.fontHeight + 2, 1 * self.fontWidth,
self.fontHeight)
else:
qp.drawRect(cursorX*3*self.fontWidth + self.fontWidth, cursorY*self.fontHeight+2, 1*self.fontWidth, self.fontHeight)
qp.drawRect(cursorX * 3 * self.fontWidth + self.fontWidth, cursorY * self.fontHeight + 2,
1 * self.fontWidth, self.fontHeight)
qp.setOpacity(1)
def keyFilter(self):
return [
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Right),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Left),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Up),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Down),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_End),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Home),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Right),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Left),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Up),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Down),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_End),
(QtCore.Qt.ControlModifier, QtCore.Qt.Key_Home),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Right),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Left),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Up),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Down),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_End),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Home),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageDown),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageUp)
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Right),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Left),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Up),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Down),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_End),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_Home),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageDown),
(QtCore.Qt.NoModifier, QtCore.Qt.Key_PageUp)
]
]
def anon(self, dx, dy):
self.scroll(dx, dy)
@ -532,7 +533,8 @@ class HexViewMode(ViewMode):
def handleEditMode(self, modifiers, key, event):
if str(event.text()).lower() in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']:
if str(event.text()).lower() in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
'f']:
offs = self.getCursorOffsetInPage()
@ -544,10 +546,9 @@ class HexViewMode(ViewMode):
# compute nibble
if self.highpart:
b = ((z << 4) | (b & 0x0F)) & 0xFF
b = ((z << 4) | (b & 0x0F)) & 0xFF
else:
b = ((b & 0xF0) | (z & 0x0F)) & 0xFF
b = ((b & 0xF0) | (z & 0x0F)) & 0xFF
block = modifiers == QtCore.Qt.AltModifier and self.selector.getCurrentSelection()
@ -560,20 +561,24 @@ class HexViewMode(ViewMode):
for x in range(u, v):
b = self.dataModel.getBYTE(x)
if self.highpart:
b = ((z << 4) | (b & 0x0F)) & 0xFF
b = ((z << 4) | (b & 0x0F)) & 0xFF
else:
b = ((b & 0xF0) | (z & 0x0F)) & 0xFF
b = ((b & 0xF0) | (z & 0x0F)) & 0xFF
self.dataModel.setData_b(x, chr(b))
else:
self.dataModel.setData_b(self.dataModel.getOffset() + offs, chr(b))
if block:
self.transformationEngine = RangePen(self.original_textdecorator, u, v, QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine), ignoreHighlights=True)
self.transformationEngine = RangePen(self.original_textdecorator, u, v,
QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine),
ignoreHighlights=True)
else:
z = self.dataModel.getOffset() + offs
#TODO: sa nu se repete, tre original_transformengine
self.transformationEngine = RangePen(self.original_textdecorator, z, z + 0, QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine), ignoreHighlights=True)
# TODO: sa nu se repete, tre original_transformengine
self.transformationEngine = RangePen(self.original_textdecorator, z, z + 0,
QtGui.QPen(QtGui.QColor(218, 94, 242), 0, QtCore.Qt.SolidLine),
ignoreHighlights=True)
# se if we are at end of row, we must also redraw previous line
highpart = self.highpart
@ -597,8 +602,7 @@ class HexViewMode(ViewMode):
else:
self.draw(refresh=True, row=y, howMany=1)
if y > old_y:
self.draw(refresh=True, row=y-1, howMany=1)
self.draw(refresh=True, row=y - 1, howMany=1)
def handleKeyEvent(self, modifiers, key, event=None):
if event.type() == QtCore.QEvent.KeyRelease:
@ -609,7 +613,8 @@ class HexViewMode(ViewMode):
if event.type() == QtCore.QEvent.KeyPress:
if modifiers == QtCore.Qt.ShiftModifier:
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up, QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
keys = [QtCore.Qt.Key_Right, QtCore.Qt.Key_Left, QtCore.Qt.Key_Down, QtCore.Qt.Key_Up,
QtCore.Qt.Key_End, QtCore.Qt.Key_Home]
if key in keys:
self.startSelection()
@ -621,7 +626,6 @@ class HexViewMode(ViewMode):
self.add_annotation(1)
return True
if modifiers == QtCore.Qt.ControlModifier:
if key == QtCore.Qt.Key_A:
self.add_annotation(2)
@ -632,7 +636,6 @@ class HexViewMode(ViewMode):
if key == QtCore.Qt.Key_Left:
self.addop((self.scroll, 1, 0))
if key == QtCore.Qt.Key_Down:
self.addop((self.anon, 0, -1))
@ -649,7 +652,7 @@ class HexViewMode(ViewMode):
return True
else:#selif modifiers == QtCore.Qt.NoModifier:
else: # selif modifiers == QtCore.Qt.NoModifier:
if key == QtCore.Qt.Key_Escape:
self.selector.resetSelections()
@ -691,7 +694,7 @@ class HexViewMode(ViewMode):
columns = self.HexColumns[self.idxHexColumns]
if x > columns:
self.cursor.moveAbsolute(columns-1, y)
self.cursor.moveAbsolute(columns - 1, y)
self.addop((self.draw,))
if self.isInEditMode():
@ -720,10 +723,9 @@ class HexViewMode(ViewMode):
for i in range(self.HexColumns[self.idxHexColumns]):
s += '{0} '.format('{0:x}'.format(i).zfill(2))
s += self.gap*' ' + 'Text'
s += self.gap * ' ' + 'Text'
return s
def annotationWindow(self):
w = self.ann_w.treeWidget
@ -733,18 +735,18 @@ class HexViewMode(ViewMode):
self.ann_w.show()
@QtCore.pyqtSlot("QItemSelection, QItemSelection")
def selectionChanged(self, selected, deselected):
item = self.ann_w.treeWidget.currentItem()
item = self.ann_w.treeWidget.currentItem()
if item:
if item:
offset = item.getOffset()
size = item.getSize()
u = offset
v = offset + size
self.selector.addSelection((u, v, QtGui.QBrush(QtGui.QColor(125, 255, 0)), 0.2), type=TextSelection.SelectionType.NORMAL)
self.selector.addSelection((u, v, QtGui.QBrush(QtGui.QColor(125, 255, 0)), 0.2),
type=TextSelection.SelectionType.NORMAL)
self.goTo(u)
@QtCore.pyqtSlot("QTreeWidgetItem*, int")
@ -753,7 +755,6 @@ class HexViewMode(ViewMode):
ID_NAME = 0
ID_DESCRIPTION = 4
s = str(item.text(column))
if column == ID_NAME:
@ -762,11 +763,11 @@ class HexViewMode(ViewMode):
if column == ID_DESCRIPTION:
item.setDescription(s)
def add_annotation(self, mode):
QtCore.QObject.connect(self.ann_w.treeWidget.selectionModel(), QtCore.SIGNAL('selectionChanged(QItemSelection, QItemSelection)'), self.selectionChanged)
QtCore.QObject.connect(self.ann_w.treeWidget, QtCore.SIGNAL('itemChanged(QTreeWidgetItem*, int)'), self.itemChanged)
QtCore.QObject.connect(self.ann_w.treeWidget.selectionModel(),
QtCore.SIGNAL('selectionChanged(QItemSelection, QItemSelection)'), self.selectionChanged)
QtCore.QObject.connect(self.ann_w.treeWidget, QtCore.SIGNAL('itemChanged(QTreeWidgetItem*, int)'),
self.itemChanged)
ID_NAME = 0
ID_OFFSET = 1
@ -790,19 +791,20 @@ class HexViewMode(ViewMode):
opacity = 0.25
qcolor = QtGui.QColor(r, g, b)
added = self.selector.addSelection((u, v, QtGui.QBrush(qcolor), opacity), type=TextSelection.SelectionType.PERMANENT)
added = self.selector.addSelection((u, v, QtGui.QBrush(qcolor), opacity),
type=TextSelection.SelectionType.PERMANENT)
# if not added:
# return
# if not added:
# return
t = self.ann_w.treeWidget
row = AnnonItem(None, self.ann_w.treeWidget, qcolor.name())
row.setFlags(QtCore.Qt.ItemIsSelectable |
QtCore.Qt.ItemIsEnabled |
QtCore.Qt.ItemIsEditable |
QtCore.Qt.ItemIsDropEnabled |
QtCore.Qt.ItemIsDragEnabled)
QtCore.Qt.ItemIsEnabled |
QtCore.Qt.ItemIsEditable |
QtCore.Qt.ItemIsDropEnabled |
QtCore.Qt.ItemIsDragEnabled)
t.setAcceptDrops(True)
t.setDragEnabled(True)
@ -814,14 +816,13 @@ class HexViewMode(ViewMode):
t.setItemDelegateForColumn(3, delegate)
t.setItemDelegateForColumn(5, delegate)
row.setName(self.ann_w.newFieldName())
row.setOffset(u)
#row.setText(ID_NAME, 'field_0')
#row.setText(ID_OFFSET, hex(u))
# row.setText(ID_NAME, 'field_0')
# row.setText(ID_OFFSET, hex(u))
size = v - u
#row.setText(ID_SIZE, hex(size))
# row.setText(ID_SIZE, hex(size))
row.setSize(size)
value = ''
@ -834,11 +835,10 @@ class HexViewMode(ViewMode):
else:
value = repr(str(self.dataModel.getStream(u, v)))
#row.setText(ID_VALUE, value)
# row.setText(ID_VALUE, value)
row.setValue(value)
#cmb.setCurrentIndex(cmb.findData(w))
# cmb.setCurrentIndex(cmb.findData(w))
if mode == 2:
self.ann_w.treeWidget.addTopLevelItem(row)
@ -855,15 +855,16 @@ class HexViewMode(ViewMode):
t.expandItem(row)
#cmb = QColorButton()
#cmb.setColor(qcolor.name())
#self.ann_w.treeWidget.setItemWidget(row, ID_COLOR, cmb)
# cmb = QColorButton()
# cmb.setColor(qcolor.name())
# self.ann_w.treeWidget.setItemWidget(row, ID_COLOR, cmb)
self.ann_w.treeWidget.setItemWidget(row, ID_COLOR, row.cmb)
#self.ann_w.treeWidget.openPersistentEditor(row, 0)
#self.ann_w.treeWidget.editItem(row, 0)
#self.ann_w.treeWidget.editItem(row, 3)
# self.ann_w.treeWidget.openPersistentEditor(row, 0)
# self.ann_w.treeWidget.editItem(row, 0)
# self.ann_w.treeWidget.editItem(row, 3)
class NoEditDelegate(QtWidgets.QStyledItemDelegate):
def __init__(self, parent=None):
@ -872,6 +873,7 @@ class NoEditDelegate(QtWidgets.QStyledItemDelegate):
def createEditor(self, parent, option, index):
return None
class AnnonItem(QtWidgets.QTreeWidgetItem):
ID_NAME = 0
ID_OFFSET = 1
@ -880,7 +882,6 @@ class AnnonItem(QtWidgets.QTreeWidgetItem):
ID_DESCRIPTION = 4
ID_COLOR = 5
def __init__(self, x, parent, color):
super(AnnonItem, self).__init__(x)
self._color = color
@ -889,9 +890,7 @@ class AnnonItem(QtWidgets.QTreeWidgetItem):
self.cmb = QColorButton()
self.cmb.setColor(self._color)
#self._t_parent.setItemWidget(self, self.ID_COLOR, self.cmb)
# self._t_parent.setItemWidget(self, self.ID_COLOR, self.cmb)
def setName(self, name):
self._name = name
@ -971,7 +970,7 @@ class QColorButton(QtWidgets.QPushButton):
'''
dlg = QtGui.QColorDialog(QtGui.QColor(self._color), None)
#if self._color:
# if self._color:
# dlg.setCurrentColor(QtGui.QColor(self._color))
if dlg.exec_():
@ -983,6 +982,7 @@ class QColorButton(QtWidgets.QPushButton):
return super(QColorButton, self).mousePressEvent(e)
class ComboBoxItem(QtWidgets.QComboBox):
def __init__(self, item, column):
super(ComboBoxItem, self).__init__()
@ -990,9 +990,10 @@ class ComboBoxItem(QtWidgets.QComboBox):
self.item = item
self.column = column
class Annotation(QtWidgets.QDialog):
class Annotation(QtWidgets.QDialog):
_fieldIdx = 0
def __init__(self, parent, view):
super(Annotation, self).__init__(parent)
@ -1004,7 +1005,7 @@ class Annotation(QtWidgets.QDialog):
root = os.path.dirname(sys.argv[0])
self.ui = loadUi(os.path.join(CONF['data_prefix'], 'annotation.ui'), baseinstance=self)
# self.ei = ImportsEventFilter(plugin, self.ui.treeWidgetImports)
# self.ei = ImportsEventFilter(plugin, self.ui.treeWidgetImports)
self.ei = treeEventFilter(view, self.ui.treeWidget)
self.ui.treeWidget.installEventFilter(self.ei)
@ -1015,15 +1016,14 @@ class Annotation(QtWidgets.QDialog):
name = 'field_{}'.format(self._fieldIdx)
self._fieldIdx += 1
return name
def show(self):
def show(self):
# TODO: remember position? resize plugin windows when parent resize?
pwidth = self.parent.parent.size().width()
pheight = self.parent.parent.size().height()
width = self.ui.treeWidget.size().width()+15
height = self.ui.treeWidget.size().height()+15
width = self.ui.treeWidget.size().width() + 15
height = self.ui.treeWidget.size().height() + 15
self.setGeometry(pwidth - width - 15, pheight - height, width, height)
self.setFixedSize(width, height)
@ -1031,12 +1031,12 @@ class Annotation(QtWidgets.QDialog):
self.oshow()
def initUI(self):
self.setWindowTitle('Annotations')
self.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("Shift+/"), self, self.close, self.close)
class treeEventFilter(QtCore.QObject):
def __init__(self, view, widget):
super(QtCore.QObject, self).__init__()
@ -1046,13 +1046,12 @@ class treeEventFilter(QtCore.QObject):
def eventFilter(self, watched, event):
if event.type() == QtCore.QEvent.KeyPress:
if event.key() == QtCore.Qt.Key_Delete:
# get RVA column from treeView
item = self.widget.currentItem()
offset = item.getOffset()#int(str(item.text(1)),0)
size = item.getSize()#int(str(item.text(2)),0)
offset = item.getOffset() # int(str(item.text(1)),0)
size = item.getSize() # int(str(item.text(2)),0)
u = offset
v = offset + size
@ -1060,8 +1059,8 @@ class treeEventFilter(QtCore.QObject):
# TODO: remove tree!
item.parent().removeChild(item)
#self.widget.takeTopLevelItem(self.widget.indexOfTopLevelItem(item))
#print item
#rva = self.widget.indexFromItem(item, 1).data().toString()
# self.widget.takeTopLevelItem(self.widget.indexOfTopLevelItem(item))
# print item
# rva = self.widget.indexFromItem(item, 1).data().toString()
return False

View File

@ -7,6 +7,7 @@ from . import TextSelection
from PyQt5 import QtGui, QtCore
class SourceViewMode(ViewMode):
def __init__(self, themes, width, height, data, cursor, widget=None):
super(SourceViewMode, self).__init__()
@ -34,7 +35,7 @@ class SourceViewMode(ViewMode):
self.font.setKerning(False)
self.font.setFixedPitch(True)
fm = QtGui.QFontMetrics(self.font)
self._fontWidth = fm.width('a')
self._fontWidth = fm.width('a')
self._fontHeight = fm.height()
self.textPen = QtGui.QPen(self.themes['pen'], 0, QtCore.Qt.SolidLine)
@ -63,15 +64,15 @@ class SourceViewMode(ViewMode):
return QtGui.QPixmap(width, height)
def resize(self, width, height):
self.width = width - width%self.fontWidth
self.height = height - height%self.fontHeight
self.width = width - width % self.fontWidth
self.height = height - height % self.fontHeight
self.computeTextArea()
self.qpix = self._getNewPixmap(self.width, self.height + self.SPACER)
self.refresh = True
def computeTextArea(self):
self.COLUMNS = self.width // self.fontWidth
self.ROWS = self.height // self.fontHeight
self.ROWS = self.height // self.fontHeight
self.notify(self.ROWS, self.COLUMNS)
def getPixmap(self):
@ -83,7 +84,7 @@ class SourceViewMode(ViewMode):
t[0](*t[1:])
self.Ops = []
if not self.newPix:
self.draw()
@ -102,7 +103,7 @@ class SourceViewMode(ViewMode):
if self.dataModel.getOffset() in self.Paints:
self.refresh = False
self.qpix = QtGui.QPixmap(self.Paints[self.dataModel.getOffset()])
#print 'hit'
# print 'hit'
self.drawAdditionals()
return
@ -119,11 +120,11 @@ class SourceViewMode(ViewMode):
self.newPix = self._getNewPixmap(self.width, self.height + self.SPACER)
qp = QtGui.QPainter()
qp.begin(self.newPix)
qp.setWindow(-50, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight)
qp.setWindow(-50, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight)
qp.drawPixmap(0, 0, self.qpix)
#self.transformationEngine.decorateText()
# self.transformationEngine.decorateText()
# highlight selected text
self.selector.highlightText()
@ -138,19 +139,19 @@ class SourceViewMode(ViewMode):
qp.end()
def drawLine(self, qp):
qp.fillRect(-50, 0, 50, self.ROWS * self.fontHeight, self.backgroundBrush)
qp.fillRect(-50, 0, 50, self.ROWS * self.fontHeight, self.backgroundBrush)
def drawTextMode(self, qp):
# draw background
qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
qp.fillRect(0, 0, self.COLUMNS * self.fontWidth, self.ROWS * self.fontHeight, self.backgroundBrush)
# set text pen&font
qp.setFont(self.font)
qp.setPen(self.textPen)
cemu = ConsoleEmulator(qp, self.ROWS, self.COLUMNS)
#ast = self.dataModel.current_class.get_ast()
#print ast
# ast = self.dataModel.current_class.get_ast()
# print ast
for i in range(self.ROWS):
if i < len(self.LINES):
@ -173,7 +174,7 @@ class SourceViewMode(ViewMode):
qp.setBrush(QtGui.QColor(255, 255, 0))
qp.setOpacity(0.5)
qp.drawRect(xstart*self.fontWidth, cursorY*self.fontHeight, width*self.fontWidth, self.fontHeight + 2)
qp.drawRect(xstart * self.fontWidth, cursorY * self.fontHeight, width * self.fontWidth, self.fontHeight + 2)
qp.setOpacity(1)
def handleKeyEvent(self, modifiers, key, event=None):

View File

@ -15,7 +15,7 @@ class CTextDecorator(object):
greenPen = QtGui.QPen(QtGui.QColor(255, 255, 0))
whitePen = QtGui.QPen(QtGui.QColor(255, 255, 255))
normalPen = QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine)
normalPen = QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine)
MZbrush = QtGui.QBrush(QtGui.QColor(128, 0, 0))
grayBrush = QtGui.QBrush(QtGui.QColor(128, 128, 128))
@ -23,6 +23,7 @@ class CTextDecorator(object):
def __init__(self):
pass
class TextDecorator(CTextDecorator):
def __init__(self, viewmode):
self.operations = []
@ -35,27 +36,37 @@ class TextDecorator(CTextDecorator):
self.normalPen = QtGui.QPen(QtGui.QColor(192, 192, 192), 1, QtCore.Qt.SolidLine)
# if we want to generate T/F table
self.Special = string.ascii_letters + string.digits + ' .;\':;=\"?-!()/\\_'
self.Special = [False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, True, True, True, False, False, False, False, True, True,
True, False, False, False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, False, True, False, True,
False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True,
True, True, True, False, True, False, False, True, False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True, True, True, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
self.Special = string.ascii_letters + string.digits + ' .;\':;=\"?-!()/\\_'
self.Special = [False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, True, True,
True, False, False, False, False, True, True,
True, False, False, False, True, True, True, True, True, True, True, True, True, True, True,
True, True, True, True, False, True, False, True,
False, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True,
True, True, True, False, True, False, False, True, False, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True,
True, True, True, True, True, True, True, True, True, True, True, False, False, False, False,
False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False, False, False, False, False,
False, False, False, False]
def reset(self):
self.penMap = {}
self.brushMap = {}
self.PenInterval = []
def getDataModel(self):
return self.dataModel
@ -76,7 +87,7 @@ class TextDecorator(CTextDecorator):
return self.Special[ord(c)]
def getChar(self, idx):
#self.page = self.getDataModel().getDisplayablePage()
# self.page = self.getDataModel().getDisplayablePage()
if idx < len(self.page):
@ -84,24 +95,21 @@ class TextDecorator(CTextDecorator):
return 0
def decorate(self, pageOffset=None):
if pageOffset:
self.page = self.viewmode.getDisplayablePage(pageOffset=pageOffset)
else:
else:
self.page = self.viewmode.getDisplayablePage()
return self.page
def addPenInterval(self, a, b, pen, ignoreHighlights=True):
self.PenInterval.append((a, b, pen, ignoreHighlights))
def choosePen(self, idx):
key = self.dataModel.getOffset() + idx
# if we do have a pen with that index, return it if it's different than default pen
# otherwise, return the pen that was set in that interval
# the priority here is de pen from other transformations, than interval pen
@ -136,7 +144,6 @@ class PageDecorator(TextDecorator):
def __init__(self, decorated):
pass
def reset(self):
self.decorated.reset()
@ -156,6 +163,7 @@ class PageDecorator(TextDecorator):
def getDataModel(self):
return self.dataModel
class HighlightASCII(PageDecorator):
def __init__(self, decorated):
self.dataModel = decorated.getDataModel()
@ -164,8 +172,6 @@ class HighlightASCII(PageDecorator):
super(HighlightASCII, self).__init__(decorated)
self.dataModel = super(HighlightASCII, self).getDataModel()
def decorate(self, pageOffset=None):
page = self.decorated.decorate(pageOffset)
@ -177,16 +183,13 @@ class HighlightASCII(PageDecorator):
Match = [(m.start(), m.end()) for m in re.finditer(b'([a-zA-Z0-9\\-\\\\.%*:/? _<>]){4,}', page)]
for s, e in Match:
for i in range(e-s):
for i in range(e - s):
idx = off + s + i
if idx not in self.penMap:
self.penMap[off + s + i] = self.redPen
self.page = page
return self.page
class HighlightPrefix(PageDecorator):
@ -207,15 +210,11 @@ class HighlightPrefix(PageDecorator):
self.brushMap = self.decorated.brushMap
self.penMap = self.decorated.penMap
self.page = self.highliteWithPrefix(page, self.text, self.additionalLength, self.brush, self.pen)
return self.page
def highliteWithPrefix(self, page, text, additionalLength=0, brush=None, pen=None):
# todo: nu am gasit o metoda mai eleganta pentru a selecta toate aparitiile ale lui text
# regexp nu merg, "bad re expression"
lenText = len(text)
@ -231,17 +230,16 @@ class HighlightPrefix(PageDecorator):
M.append((idx, lenText + additionalLength))
idx += lenText + additionalLength
off = self.dataModel.getOffset()
for start, length in M:
for i in range(length):
self.penMap[off + start + i] = pen
self.brushMap[off + start + i] = brush
return page
class HighlightWideChar(PageDecorator):
def __init__(self, decorated):
super(HighlightWideChar, self).__init__(decorated)
@ -249,7 +247,6 @@ class HighlightWideChar(PageDecorator):
self.dataModel = decorated.getDataModel()
self.decorated = decorated
def decorate(self, pageOffset=None):
self.page = self.decorated.decorate(pageOffset)
@ -257,28 +254,24 @@ class HighlightWideChar(PageDecorator):
self.brushMap = self.decorated.brushMap
self.penMap = self.decorated.penMap
self.page = self.highliteWidechar2(self.page)
return self.page
def highliteWidechar2(self, page):
pageStart = self.dataModel.getOffset()
pageEnd = pageStart + len(page)
pageEnd = pageStart + len(page)
touched = False
#for s, e in self.Intervals:
# for s, e in self.Intervals:
# touched = True
if not touched:
# expand
Match = [(m.start(), m.end()) for m in re.finditer(r'([a-zA-Z0-9\-\\.%*:/? ]\x00){4,}', page)]
for s, e in Match:
for i in range(e-s):
#print i
for i in range(e - s):
# print i
self.penMap[pageStart + s + i] = QtGui.QPen(QtGui.QColor(255, 255, 0))
# get rid of '\x00'
@ -287,12 +280,10 @@ class HighlightWideChar(PageDecorator):
# copy string that has no zeros
page[s:s + l] = string
# fill with zeros the remaining space
page[s + l: s + 2*l] = '\x00'*l
page[s + l: s + 2 * l] = '\x00' * l
return page
### todo: other way to highlight widechar, should test and see which one is faster
"""
def _changeText(self, page, page_start, I):

View File

@ -7,11 +7,13 @@ from __future__ import division
from builtins import object
from PyQt5 import QtGui
class SelectionType(object):
NORMAL = 0
PERMANENT = 1
TEXTHIGHLIGHT = 2
class Selection(object):
def __init__(self, themes, viewMode):
self.themes = themes
@ -48,7 +50,6 @@ class Selection(object):
if type == SelectionType.NORMAL:
if len(self.Selections) >= self.MAX_SELECTIONS:
self.Selections = []
self.Selections.append(t)
@ -99,7 +100,7 @@ class Selection(object):
self.drawSelection(qp, start, end)
self.HighlightSelections = []
#draw current
# draw current
if self.selecting:
self.drawSelection(qp, *self.getCurrentSelection())
@ -129,16 +130,16 @@ class Selection(object):
# but currently, by design we could only have one NORMAL selection
return u, v
#if self.last:
# return self.last
# if self.last:
# return self.last
return None
def stopSelection(self):
if self.selecting == True:
u, v = self.getCurrentSelection()
self.addSelection((u, v, QtGui.QBrush(self.themes['selection']), 0.4) , type=SelectionType.NORMAL)
self.addSelection((u, v, QtGui.QBrush(self.themes['selection']), 0.4), type=SelectionType.NORMAL)
self.last = u, v
self.selecting = False
@ -154,7 +155,7 @@ class Selection(object):
if not t:
# no selection
return
start, end = t
if start == end:
@ -163,7 +164,6 @@ class Selection(object):
text = dataModel.getStream(start, end)
Exclude = [start]
cols, rows = self.viewMode.getGeometry()
# find all occurrence
@ -179,17 +179,17 @@ class Selection(object):
M.append((idx, lenText))
idx += lenText
#Match = [(m.start(), m.end()) for m in re.finditer(bytes(text), bytes(page))]
# Match = [(m.start(), m.end()) for m in re.finditer(bytes(text), bytes(page))]
for start, end in M:
#print start, end
#self._makeSelection(qp, start, end, cols, rows)
# print start, end
# self._makeSelection(qp, start, end, cols, rows)
off = dataModel.getOffset()
if off+start not in Exclude:
#self._makeSelection(off + start, off + start + end, brush=QtGui.QBrush(QtGui.QColor(125, 255, 0)))
#self.viewMode.selector.addSelection((off+start, off + start + end, QtGui.QBrush(QtGui.QColor(125, 255, 0)), 0.4))
self.addSelection((off+start, off + start + end, QtGui.QBrush(self.themes['selection']), 0.4), type=SelectionType.TEXTHIGHLIGHT)
if off + start not in Exclude:
# self._makeSelection(off + start, off + start + end, brush=QtGui.QBrush(QtGui.QColor(125, 255, 0)))
# self.viewMode.selector.addSelection((off+start, off + start + end, QtGui.QBrush(QtGui.QColor(125, 255, 0)), 0.4))
self.addSelection((off + start, off + start + end, QtGui.QBrush(self.themes['selection']), 0.4),
type=SelectionType.TEXTHIGHLIGHT)
class DefaultSelection(Selection):
@ -221,18 +221,18 @@ class DefaultSelection(Selection):
d1 = length
else:
d1 = end - off
mark = True
height = 14
qp.setOpacity(0.4)
while mark:
if d0 // cols == d1 // cols:
qp.fillRect((d0%cols)*8, (d0 // cols) * height, (d1-d0) * 8, 1 * height, brush)
qp.fillRect((d0 % cols) * 8, (d0 // cols) * height, (d1 - d0) * 8, 1 * height, brush)
d0 += (d1 - d0)
else:
qp.fillRect((d0%cols)*8, (d0 // cols)*height, (cols - d0%cols)*8, 1*height, brush)
d0 += (cols - d0%cols)
else:
qp.fillRect((d0 % cols) * 8, (d0 // cols) * height, (cols - d0 % cols) * 8, 1 * height, brush)
d0 += (cols - d0 % cols)
if (d1 - d0 <= 0):
mark = False
@ -263,7 +263,7 @@ class DefaultSelection(Selection):
d1 = length
else:
d1 = end - off
mark = True
height = self.viewMode.fontHeight
width = self.viewMode.fontWidth
@ -274,18 +274,18 @@ class DefaultSelection(Selection):
while mark:
if d0 // cols == d1 // cols:
qp.fillRect((d0%cols)*width, (d0 // cols)*height + offset, (d1-d0)*width, 1*height, brush)
qp.fillRect((d0 % cols) * width, (d0 // cols) * height + offset, (d1 - d0) * width, 1 * height, brush)
d0 += (d1 - d0)
else:
qp.fillRect((d0%cols)*width, (d0 // cols)*height + offset, (cols - d0%cols)*width, 1*height, brush)
d0 += (cols - d0%cols)
else:
qp.fillRect((d0 % cols) * width, (d0 // cols) * height + offset, (cols - d0 % cols) * width, 1 * height,
brush)
d0 += (cols - d0 % cols)
if (d1 - d0 <= 0):
mark = False
qp.setOpacity(1)
class HexSelection(Selection):
def __init__(self, themes, viewMode):
super(HexSelection, self).__init__(themes, viewMode)
@ -316,7 +316,7 @@ class HexSelection(Selection):
d1 = length
else:
d1 = end - off
mark = True
height = self.viewMode.fontHeight
width = self.viewMode.fontWidth
@ -325,15 +325,19 @@ class HexSelection(Selection):
while mark:
if d0 // cols == d1 // cols:
# +2 is an offset for letters
qp.fillRect(3*(d0%cols)*width, (d0 // cols)*height+2, 3*(d1-d0)*width - width, 1*height, brush)
qp.fillRect(3*cols*width + self.viewMode.gap*width + (d0%cols)*width, (d0 // cols)*height+2, (d1-d0)*width, 1*height, brush)
qp.fillRect(3 * (d0 % cols) * width, (d0 // cols) * height + 2, 3 * (d1 - d0) * width - width,
1 * height, brush)
qp.fillRect(3 * cols * width + self.viewMode.gap * width + (d0 % cols) * width,
(d0 // cols) * height + 2, (d1 - d0) * width, 1 * height, brush)
d0 += (d1 - d0)
else:
qp.fillRect(3*(d0%cols)*width, (d0 // cols)*height+2, 3*(cols - d0%cols)*width - width, 1*height, brush)
qp.fillRect(3*cols*width + self.viewMode.gap*width + (d0%cols)*width, (d0 // cols)*height+2, (cols - d0%cols)*width, 1*height, brush)
else:
qp.fillRect(3 * (d0 % cols) * width, (d0 // cols) * height + 2, 3 * (cols - d0 % cols) * width - width,
1 * height, brush)
qp.fillRect(3 * cols * width + self.viewMode.gap * width + (d0 % cols) * width,
(d0 // cols) * height + 2, (cols - d0 % cols) * width, 1 * height, brush)
d0 += (cols - d0%cols)
d0 += (cols - d0 % cols)
if (d1 - d0 <= 0):
mark = False
@ -351,7 +355,7 @@ class DisasmSelection(Selection):
dataModel = self.viewMode.getDataModel()
off = dataModel.getOffset()
length = sum([o.size for o in self.viewMode.OPCODES]) # TODO: not nice!
length = sum([o.size for o in self.viewMode.OPCODES]) # TODO: not nice!
cols, rows = self.viewMode.getGeometry()
# return if out of view
@ -370,7 +374,7 @@ class DisasmSelection(Selection):
d1 = length
else:
d1 = end - off
mark = True
height = self.viewMode.fontHeight
width = self.viewMode.fontWidth
@ -383,17 +387,17 @@ class DisasmSelection(Selection):
for i, asm in enumerate(self.viewMode.OPCODES):
if size + asm.size > d0 and size <= d1:
# compute x offset
x = d0-size
if size > d0:
x = 0
# compute x offset
x = d0 - size
if size > d0:
x = 0
# compute width
w = asm.size
if size + asm.size > d1:
w = d1 - size
# compute width
w = asm.size
if size + asm.size > d1:
w = d1 - size
qp.fillRect(x*3*width, i*height + offset, (w-x)*3*width - width, 1*height, brush)
qp.fillRect(x * 3 * width, i * height + offset, (w - x) * 3 * width - width, 1 * height, brush)
size += asm.size

View File

@ -1,5 +1,7 @@
from builtins import chr
from builtins import object
class Observable(object):
def __init__(self):
self.Callbacks = []
@ -12,8 +14,8 @@ class Observable(object):
for cbk in self.Callbacks:
cbk.update_geometry(rows, cols)
class ViewMode(Observable, object):
class ViewMode(Observable, object):
SPACER = 4
def __init__(self):
@ -26,37 +28,37 @@ class ViewMode(Observable, object):
http://svn.openmoko.org/trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatutils.cpp
"""
cp437ToUnicode = [0x0020, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0018, 0x0019, 0x001c, 0x001b, 0x007f, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x001a,
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x03bc, 0x03c4,
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0]
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0018, 0x0019, 0x001c, 0x001b, 0x007f, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x001a,
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x03bc, 0x03c4,
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0]
def cp437(self, c):
return chr(self.cp437ToUnicode[c])
@ -69,10 +71,10 @@ class ViewMode(Observable, object):
NotImplementedError('method not implemented.')
def startSelection(self):
NotImplementedError('method not implemented.')
NotImplementedError('method not implemented.')
def stopSelection(self):
NotImplementedError('method not implemented.')
NotImplementedError('method not implemented.')
def draw(self, refresh=False):
NotImplementedError('method not implemented.')
@ -80,8 +82,8 @@ class ViewMode(Observable, object):
# returns x,y cursor position in page
def getCursorOffsetInPage(self):
x, y = self.cursor.getPosition()
return y*self.COLUMNS + x
return y * self.COLUMNS + x
def handleKeyPressEvent(self, modifier, key):
raise Exception("not implemented")
@ -97,9 +99,9 @@ class ViewMode(Observable, object):
dataOffset = self.dataModel.getOffset()
cols, rows = self.getGeometry()
if pageOffset:
return bytearray(data[dataOffset:dataOffset + rows*cols*pageOffset])
return bytearray(data[dataOffset:dataOffset + rows * cols * pageOffset])
return bytearray(data[dataOffset:dataOffset + rows*cols])
return bytearray(data[dataOffset:dataOffset + rows * cols])
# moves cursor to offset in page, or moves to page
def goTo(self, offset):
@ -116,8 +118,7 @@ class ViewMode(Observable, object):
self.cursor.moveAbsolute(0, 0)
self.draw(refresh=True)
#self.draw(refresh=False)
# self.draw(refresh=False)
if self.widget:
self.widget.update()

View File

@ -1,85 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>708</width>
<height>513</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QTreeWidget" name="treeWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>691</width>
<height>461</height>
</rect>
</property>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Offset</string>
</property>
</column>
<column>
<property name="text">
<string>Size</string>
</property>
</column>
<column>
<property name="text">
<string>Value</string>
</property>
</column>
<column>
<property name="text">
<string>Description</string>
</property>
</column>
<column>
<property name="text">
<string>Color</string>
</property>
</column>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>610</x>
<y>480</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Load</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>510</x>
<y>480</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Save</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>708</width>
<height>513</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QTreeWidget" name="treeWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>691</width>
<height>461</height>
</rect>
</property>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Offset</string>
</property>
</column>
<column>
<property name="text">
<string>Size</string>
</property>
</column>
<column>
<property name="text">
<string>Value</string>
</property>
</column>
<column>
<property name="text">
<string>Description</string>
</property>
</column>
<column>
<property name="text">
<string>Color</string>
</property>
</column>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>610</x>
<y>480</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Load</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>510</x>
<y>480</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>Save</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -3,7 +3,6 @@ from androguard.gui.xrefwindow import XrefDialogMethod
class APIWindow(QtWidgets.QWidget):
def __init__(self, parent=None, win=None, session=None):
super(APIWindow, self).__init__(parent)
self.mainwin = win
@ -30,7 +29,6 @@ class APIWindow(QtWidgets.QWidget):
class APIValueWindow(QtWidgets.QTreeView):
def __init__(self, parent=None, win=None, session=None):
super(APIValueWindow, self).__init__(parent)
self.mainwin = win
@ -68,7 +66,7 @@ class APIValueWindow(QtWidgets.QTreeView):
self.model.setData(self.model.index(
row, 3, QtCore.QModelIndex()), digest)
self.reverse_methods[method.get_name() + method.get_class_name() + method.get_descriptor()
] = dx.get_method_analysis(method)
] = dx.get_method_analysis(method)
row += 1
self.proxyModel.setSourceModel(self.model)
@ -91,6 +89,6 @@ class APIValueWindow(QtWidgets.QTreeView):
parent=self.mainwin,
win=self.mainwin,
method_analysis=self.reverse_methods[self.model.item(row).text() +
self.model.item(row, 1).text() +
self.model.item(row, 1).text() +
self.model.item(row, 2).text()])
xwin.show()

View File

@ -15,8 +15,8 @@ from .BinViewMode import *
from .DataModel import *
from .Banners import *
class SearchWindow(QtWidgets.QDialog):
def __init__(self, parent, plugin, searchable):
super(SearchWindow, self).__init__(parent)
self.searchable = searchable
@ -35,8 +35,8 @@ class SearchWindow(QtWidgets.QDialog):
def show(self):
# TODO: remember position? resize plugin windows when parent resize?
width = self.ui.size().width()+15
height = self.ui.size().height()+15
width = self.ui.size().width() + 15
height = self.ui.size().height() + 15
self.move((self.parent.width() - width) // 2, (self.parent.height() - height) // 2)
self.ui.lineEdit.setText(self._lastText)
@ -51,12 +51,12 @@ class SearchWindow(QtWidgets.QDialog):
self.ui.pushButton.clicked.connect(self.onClicked)
width = self.ui.size().width()+15
height = self.ui.size().height()+15
width = self.ui.size().width() + 15
height = self.ui.size().height() + 15
self.setFixedSize(width, height)
def onClicked(self):
text = self.ui.lineEdit.text()
text = self.ui.lineEdit.text()
text = str(text)
hexstr = '0123456789abcdefABCDEF'
@ -66,7 +66,8 @@ class SearchWindow(QtWidgets.QDialog):
text = ''
for t in T:
if len(t) != 2:
reply = QtWidgets.QMessageBox.warning(self, 'Qiew', "Hex string with errors.", QtWidgets.QMessageBox.Ok)
reply = QtWidgets.QMessageBox.warning(self, 'Qiew', "Hex string with errors.",
QtWidgets.QMessageBox.Ok)
self.close()
return
@ -74,11 +75,11 @@ class SearchWindow(QtWidgets.QDialog):
o = int(t, 16)
text += chr(o)
else:
reply = QtWidgets.QMessageBox.warning(self, 'Qiew', "Hex string with errors.", QtWidgets.QMessageBox.Ok)
reply = QtWidgets.QMessageBox.warning(self, 'Qiew', "Hex string with errors.",
QtWidgets.QMessageBox.Ok)
self.close()
return
self._lastText = oldtext
else:
@ -94,6 +95,7 @@ class SearchWindow(QtWidgets.QDialog):
self.parent.viewMode.draw(refresh=True)
self.close()
class Observable(object):
def __init__(self):
self.Callbacks = []
@ -111,6 +113,7 @@ class Observer(object):
def changeViewMode(self, viewMode):
self._viewMode = viewMode
class Searchable(Observer):
def __init__(self, dataModel, viewMode):
self._viewMode = viewMode
@ -126,14 +129,14 @@ class Searchable(Observer):
idx = self._lastIdx + 1
else:
idx = start
if idx > -1:
self._search(data, text, idx)
@property
def lastText(self):
return self._lastText
def previous(self, start=None):
data = self._dataModel.getData()
text = self._lastText
@ -183,32 +186,31 @@ class Searchable(Observer):
self._lastIdx = idx
if idx > -1:
self._viewMode.selector.addSelection((idx, idx + len(text), QtGui.QBrush(QtGui.QColor(125, 0, 100)), 0.8) , type=TextSelection.SelectionType.NORMAL)
self._viewMode.selector.addSelection((idx, idx + len(text), QtGui.QBrush(QtGui.QColor(125, 0, 100)), 0.8),
type=TextSelection.SelectionType.NORMAL)
self._viewMode.goTo(idx)
return idx
def search(self, text):
data = self._dataModel.getData()
return self._search(data, text, 0)
class binWidget(QtWidgets.QWidget, Observable):
scrolled = QtCore.pyqtSignal(int, name='scroll')
def __init__(self, parent, source, title):
super(binWidget, self).__init__()
Observable.__init__(self)
self.parent = parent
self.title = title
self.active = False
# offset for text window
#self.data = mapped
# self.data = mapped
self.dataOffset = 0
self.dataModel = source
self.cursor = Cursor(0, 0)
@ -218,7 +220,7 @@ class binWidget(QtWidgets.QWidget, Observable):
'background_cursor': QtGui.QColor(255, 255, 0),
'selection': QtGui.QColor(125, 255, 0),
'pen': QtGui.QColor(0xb5, 0x89, 0x00)
}
}
self.multipleViewModes = []
for view_mode in self.dataModel.GetViews():
@ -231,11 +233,9 @@ class binWidget(QtWidgets.QWidget, Observable):
self.viewMode = self.multipleViewModes[0]
self.Banners = Banners()
self.Banners.add(FileAddrBanner(self.themes, self.dataModel, self.viewMode))
self.Banners.add(FileAddrBanner(self.themes, self.dataModel, self.viewMode))
self.Banners.add(TopBanner(self.themes, self.dataModel, self.viewMode))
self.Banners.add(BottomBanner(self.themes, self.dataModel, self.viewMode))
@ -243,7 +243,6 @@ class binWidget(QtWidgets.QWidget, Observable):
self.offsetWindow_v = 0
self.searchable = Searchable(self.dataModel, self.viewMode)
self.initUI()
self.searchWindow = SearchWindow(self, None, self.searchable)
@ -251,17 +250,17 @@ class binWidget(QtWidgets.QWidget, Observable):
self.addHandler(self.searchable)
self.addHandler(self.Banners)
self.notify(self.viewMode)
self.notify(self.viewMode)
def enable(self):
self.active = True
def disable(self):
self.active = False
def scroll_from_outside(self, i):
#print 'slot-signal ' + str(i)
#self.scroll_pdown = True
# print 'slot-signal ' + str(i)
# self.scroll_pdown = True
self.update()
def initUI(self):
@ -284,8 +283,8 @@ class binWidget(QtWidgets.QWidget, Observable):
# compute space ocupated by banners
offsetLeft = self.offsetWindow_h + self.Banners.getLeftOffset()
offsetBottom = self.offsetWindow_v + self.Banners.getBottomOffset() + self.Banners.getTopOffset()
offsetBottom = self.offsetWindow_v + self.Banners.getBottomOffset() + self.Banners.getTopOffset()
# resize window, substract space ocupated by banners
self.viewMode.resize(self.size().width() - offsetLeft, self.size().height() - offsetBottom)
@ -293,28 +292,26 @@ class binWidget(QtWidgets.QWidget, Observable):
def resizeEvent(self, e):
self._resize()
def paintEvent(self, e):
qp = QtGui.QPainter()
qp.begin(self)
qp.setOpacity(1)
offsetLeft = self.offsetWindow_h + self.Banners.getLeftOffset()
offsetBottom = self.offsetWindow_v + self.Banners.getTopOffset()
offsetBottom = self.offsetWindow_v + self.Banners.getTopOffset()
#self.viewMode.draw2(qp, refresh=True)
#start = time()
# self.viewMode.draw2(qp, refresh=True)
# start = time()
qp.drawPixmap(offsetLeft, offsetBottom, self.viewMode.getPixmap())
#print 'Draw ' + str(time() - start)
# print 'Draw ' + str(time() - start)
self.Banners.draw(qp, self.offsetWindow_h, self.offsetWindow_v, self.size().height())
# qp.drawPixmap(self.offsetWindow_h, self.size().height() - 50, self.banner.getPixmap())
# qp.drawPixmap(self.offsetWindow_h, self.size().height() - 50, self.banner.getPixmap())
# qp.drawPixmap(20, 0, self.filebanner.getPixmap())
# qp.drawPixmap(20, 0, self.filebanner.getPixmap())
qp.end()
def eventFilter(self, watched, event):
if not self.active:
return False
@ -325,9 +322,8 @@ class binWidget(QtWidgets.QWidget, Observable):
if self.viewMode.handleKeyEvent(modifiers, key, event=event):
self.update()
if event.type() == QtCore.QEvent.KeyPress:
#TODO: should we accept only certain keys ?
if event.type() == QtCore.QEvent.KeyPress:
# TODO: should we accept only certain keys ?
key = event.key()
modifiers = event.modifiers()
if key == QtCore.Qt.Key_F2:
@ -358,46 +354,44 @@ class binWidget(QtWidgets.QWidget, Observable):
if self.viewMode.selector.getCurrentSelection():
a, b = self.viewMode.selector.getCurrentSelection()
#print a, b
# print a, b
hx = ''
for s in self.dataModel.getStream(a, b):
hx += '{:02x}'.format(s)
pyperclip.copy(hx)
del pyperclip
#print pyperclip.paste()
# print 'coppied'
# print pyperclip.paste()
# print 'coppied'
if event.modifiers() & QtCore.Qt.ShiftModifier:
if key == QtCore.Qt.Key_Insert:
import re
hx = pyperclip.paste()
#print hx
# print hx
L = re.findall(r'.{1,2}', hx, re.DOTALL)
array = ''
for s in L:
array += chr(int(s, 16))
#print 'write '
#print 'write'
#print array
# print 'write '
# print 'write'
# print array
self.dataModel.write(0, array)
self.viewMode.draw(True)
del pyperclip
#print array
# print array
if key == QtCore.Qt.Key_F4:
self.unp = WUnpack(self, None)
self.unp.show()
if key == QtCore.Qt.Key_F10:
self.dataModel.flush()
self.w = WHeaders(self, None)
self.w.show()
if not self.viewMode.isInEditMode():
if key == QtCore.Qt.Key_Slash:
self.searchWindow.show()
@ -414,7 +408,6 @@ class binWidget(QtWidgets.QWidget, Observable):
self.update()
return True
return False
def setTextViewport(self, qp):

View File

@ -3,11 +3,12 @@ from PyQt5 import QtGui
from androguard.core import androconf
class Cursor(object):
def __init__(self, x, y):
self.x = x
self.y = y
def move(self, dx, dy):
self.x += dx
self.y += dy
@ -19,9 +20,11 @@ class Cursor(object):
def getPosition(self):
return self.x, self.y
def enum(**enums):
return type('Enum', (), enums)
Directions = enum(Left=1, Right=2, Up=3, Down=4, End=5, Home=6, CtrlEnd=7, CtrlHome=8)
@ -34,7 +37,7 @@ class ConsoleEmulator(object):
self._cols = cols
fm = QtGui.QFontMetrics(self.qp.font())
self.fontWidth = fm.width('a')
self.fontWidth = fm.width('a')
self.fontHeight = fm.height()
def incrementPosition(self):
@ -44,7 +47,6 @@ class ConsoleEmulator(object):
self._x = 0
self._y += 1
def newLine(self):
self.LF()
self.CR()
@ -74,7 +76,7 @@ class ConsoleEmulator(object):
self.qp.setBackgroundMode(0)
self.qp.drawText(self._x * self.fontWidth, self.fontHeight + self._y * self.fontHeight, c)
self.incrementPosition()
self.incrementPosition()
self.qp.setBackgroundMode(background)
def write_c(self, c, noBackgroudOnSpaces=False):
@ -84,7 +86,7 @@ class ConsoleEmulator(object):
self.qp.setBackgroundMode(0)
self.qp.drawText(self._x * self.fontWidth, self.fontHeight + self._y * self.fontHeight, c)
self.incrementPosition()
self.incrementPosition()
self.qp.setBackgroundMode(background)
def getXY(self):
@ -99,7 +101,7 @@ class ConsoleEmulator(object):
self.write_c(c, noBackgroudOnSpaces)
def writeLn(self):
if True:#self._validatePosition(self._x, self._y):
if True: # self._validatePosition(self._x, self._y):
self._y += 1
self._x = 0

View File

@ -1,7 +1,8 @@
from __future__ import print_function
from builtins import object
class Signature(object):
class Signature(object):
def __init__(self, cls, method=None, descriptor=None):
self.cls = cls
self.class_components = self.cls.name.strip('L').strip(';').split('/')

View File

@ -49,14 +49,14 @@ class TabsWindow(QtWidgets.QTabWidget):
self.clear()
def actioncloseOtherTabs(self):
for i in range(self.currentIndex()-1, -1, -1):
for i in range(self.currentIndex() - 1, -1, -1):
self.removeTab(i)
for i in range(self.count(), self.currentIndex(), -1):
self.removeTab(i)
def actioncloseLeftTabs(self):
for i in range(self.currentIndex()-1, -1, -1):
for i in range(self.currentIndex() - 1, -1, -1):
self.removeTab(i)
def actioncloseRightTabs(self):
@ -81,7 +81,6 @@ class TabsWindow(QtWidgets.QTabWidget):
androconf.debug("Enable %s" % title)
self.bin_windows[current_title].enable()
def contextMenuEvent(self, event):
menu = QtWidgets.QMenu(self)
menu.addAction(self.closeAllTabs)
@ -90,6 +89,7 @@ class TabsWindow(QtWidgets.QTabWidget):
menu.addAction(self.closeRightTabs)
menu.exec_(event.globalPos())
class MainWindow(QtWidgets.QMainWindow):
'''Main window:
self.central: QTabWidget in center area
@ -139,8 +139,8 @@ class MainWindow(QtWidgets.QMainWindow):
def about(self):
'''User clicked About menu. Display a Message box.'''
QtWidgets.QMessageBox.about(self, "About Androguard GUI",
"<p><b>Androguard GUI</b> is basically a GUI for Androguard :)." \
"<br>Have fun !</p>")
"<p><b>Androguard GUI</b> is basically a GUI for Androguard :)." \
"<br>Have fun !</p>")
def setupSession(self):
androconf.debug("Setup Session")
@ -351,7 +351,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.central.setCurrentWidget(bin_window)
def openSourceWindow(self, current_class, method=None):
'''Main function to open a decompile source window
It checks if it already opened and open that tab,

View File

@ -3,7 +3,6 @@ from androguard.gui.xrefwindow import XrefDialogMethod
class MethodsWindow(QtWidgets.QWidget):
def __init__(self, parent=None, win=None, session=None):
super(MethodsWindow, self).__init__(parent)
self.mainwin = win
@ -30,7 +29,6 @@ class MethodsWindow(QtWidgets.QWidget):
class MethodsValueWindow(QtWidgets.QTreeView):
def __init__(self, parent=None, win=None, session=None):
super(MethodsValueWindow, self).__init__(parent)
self.mainwin = win
@ -70,7 +68,7 @@ class MethodsValueWindow(QtWidgets.QTreeView):
self.model.setData(self.model.index(
row, 4, QtCore.QModelIndex()), digest)
self.reverse_methods[method.get_name() + method.get_class_name() + method.get_descriptor() + digest
] = dx.get_method_analysis(method)
] = dx.get_method_analysis(method)
row += 1
self.proxyModel.setSourceModel(self.model)
@ -93,7 +91,7 @@ class MethodsValueWindow(QtWidgets.QTreeView):
parent=self.mainwin,
win=self.mainwin,
method_analysis=self.reverse_methods[self.model.item(row).text() +
self.model.item(row, 1).text() +
self.model.item(row, 2).text() +
self.model.item(row, 1).text() +
self.model.item(row, 2).text() +
self.model.item(row, 4).text()])
xwin.show()

View File

@ -3,7 +3,6 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class ResourcesWindow(QtWidgets.QWidget):
def __init__(self, parent=None, win=None, session=None):
super(ResourcesWindow, self).__init__(parent)
self.mainwin = win
@ -30,7 +29,6 @@ class ResourcesWindow(QtWidgets.QWidget):
class ResourcesValueWindow(QtWidgets.QTreeView):
def __init__(self, parent=None, win=None, session=None):
super(ResourcesValueWindow, self).__init__(parent)
self.mainwin = win

View File

@ -1,43 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>searchform</class>
<widget class="QWidget" name="searchform">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>430</width>
<height>116</height>
</rect>
</property>
<property name="windowTitle">
<string>Search</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Search</string>
</property>
<class>searchform</class>
<widget class="QWidget" name="searchform">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>430</width>
<height>116</height>
</rect>
</property>
<property name="windowTitle">
<string>Search</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Search</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkHex">
<property name="text">
<string>hex</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkHex">
<property name="text">
<string>hex</string>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>lineEdit</tabstop>
<tabstop>checkHex</tabstop>
<tabstop>pushButton</tabstop>
</tabstops>
<resources/>
<connections/>
<tabstops>
<tabstop>lineEdit</tabstop>
<tabstop>checkHex</tabstop>
<tabstop>pushButton</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -6,10 +6,8 @@ from androguard.gui.helpers import class2func, method2func, classdot2func, class
from androguard.gui.renamewindow import RenameDialog
from androguard.gui.xrefwindow import XrefDialogMethod, XrefDialogField
import pyperclip
from pygments.formatters.html import HtmlFormatter
from pygments.lexers import JavaLexer
from pygments.styles import get_style_by_name
@ -17,7 +15,6 @@ from pygments.styles import get_style_by_name
from pygments.style import Style
from pygments.token import Token, Comment, Name, Keyword, Generic, Number, Operator, String
BINDINGS_NAMES = [
'NAME_PACKAGE', 'NAME_PROTOTYPE', 'NAME_SUPERCLASS', 'NAME_INTERFACE',
'NAME_FIELD', 'NAME_METHOD_PROTOTYPE', 'NAME_ARG', 'NAME_CLASS_ASSIGNMENT',
@ -45,6 +42,7 @@ class SourceDocument(QtGui.QTextDocument):
self.binding[cursor.position()] = t
cursor.insertText(t[1])
class PygmentsBlockUserData(QtGui.QTextBlockUserData):
""" Storage for the user data associated with each line.
"""
@ -58,10 +56,11 @@ class PygmentsBlockUserData(QtGui.QTextBlockUserData):
def __repr__(self):
attrs = ['syntax_stack']
kwds = ', '.join([ '%s=%r' % (attr, getattr(self, attr))
for attr in attrs ])
kwds = ', '.join(['%s=%r' % (attr, getattr(self, attr))
for attr in attrs])
return 'PygmentsBlockUserData(%s)' % kwds
BASE03 = '#002B36'
BASE02 = '#073642'
BASE01 = '#586E75'
@ -79,18 +78,19 @@ BLUE = '#268BD2'
CYAN = '#2AA198'
GREEN = '#859900'
class SolarizedStyle(Style):
background_color = BASE03
styles = {
Keyword: GREEN,
Keyword.Constant: ORANGE,
Keyword.Declaration: BLUE,
#Keyword.Namespace
#Keyword.Pseudo
# Keyword.Namespace
# Keyword.Pseudo
Keyword.Reserved: BLUE,
Keyword.Type: RED,
#Name
# Name
Name.Attribute: BASE1,
Name.Builtin: YELLOW,
Name.Builtin.Pseudo: BLUE,
@ -100,69 +100,70 @@ class SolarizedStyle(Style):
Name.Entity: ORANGE,
Name.Exception: ORANGE,
Name.Function: BLUE,
#Name.Label
#Name.Namespace
#Name.Other
# Name.Label
# Name.Namespace
# Name.Other
Name.Tag: BLUE,
Name.Variable: BLUE,
#Name.Variable.Class
#Name.Variable.Global
#Name.Variable.Instance
# Name.Variable.Class
# Name.Variable.Global
# Name.Variable.Instance
#Literal
#Literal.Date
# Literal
# Literal.Date
String: CYAN,
String.Backtick: BASE01,
String.Char: CYAN,
String.Doc: BASE1,
#String.Double
# String.Double
String.Escape: ORANGE,
String.Heredoc: BASE1,
#String.Interpol
#String.Other
# String.Interpol
# String.Other
String.Regex: RED,
#String.Single
#String.Symbol
# String.Single
# String.Symbol
Number: CYAN,
#Number.Float
#Number.Hex
#Number.Integer
#Number.Integer.Long
#Number.Oct
# Number.Float
# Number.Hex
# Number.Integer
# Number.Integer.Long
# Number.Oct
Operator: GREEN,
#Operator.Word
# Operator.Word
#Punctuation: ORANGE,
# Punctuation: ORANGE,
Comment: BASE01,
#Comment.Multiline
# Comment.Multiline
Comment.Preproc: GREEN,
#Comment.Single
# Comment.Single
Comment.Special: GREEN,
#Generic
# Generic
Generic.Deleted: CYAN,
Generic.Emph: 'italic',
Generic.Error: RED,
Generic.Heading: ORANGE,
Generic.Inserted: GREEN,
#Generic.Output
#Generic.Prompt
# Generic.Output
# Generic.Prompt
Generic.Strong: 'bold',
Generic.Subheading: ORANGE,
#Generic.Traceback
# Generic.Traceback
Token: BASE1,
Token.Other: ORANGE,
}
class MyHighlighter(QtGui.QSyntaxHighlighter):
""" Syntax highlighter that uses Pygments for parsing. """
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# 'QSyntaxHighlighter' interface
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
def __init__(self, parent, lexer=None):
super(MyHighlighter, self).__init__(parent)
@ -195,14 +196,14 @@ class MyHighlighter(QtGui.QSyntaxHighlighter):
# Clean up for the next go-round.
del self._lexer._saved_state_stack
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# 'PygmentsHighlighter' interface
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
def set_style(self, style):
""" Sets the style to the specified Pygments style.
"""
style = SolarizedStyle#get_style_by_name(style)
style = SolarizedStyle # get_style_by_name(style)
self._style = style
self._clear_caches()
@ -217,9 +218,9 @@ class MyHighlighter(QtGui.QSyntaxHighlighter):
self._style = None
self._clear_caches()
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# Protected interface
#---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
def _clear_caches(self):
""" Clear caches for brushes and formats.
@ -282,6 +283,7 @@ class MyHighlighter(QtGui.QSyntaxHighlighter):
int(color[4:6], base=16))
return qcolor
class SourceWindow(QtWidgets.QTextEdit):
'''Each tab is implemented as a Source Window class.
Attributes:
@ -315,7 +317,6 @@ class SourceWindow(QtWidgets.QTextEdit):
self.setReadOnly(True)
self.setStyleSheet("background: rgba(0,43,54,100%)")
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.CustomContextMenuHandler)
@ -327,11 +328,11 @@ class SourceWindow(QtWidgets.QTextEdit):
TODO: implement it, because does not work for now.
'''
#TODO: we need to find a way to scroll to the right place because
# TODO: we need to find a way to scroll to the right place because
# moving the cursor is not enough. Indeed if it is already in the window
# it does not do nothing
#TODO: idea, highlight the method in the screen so we do not have to search for it
# TODO: idea, highlight the method in the screen so we do not have to search for it
androconf.debug("Browsing to %s -> %s" % (self.current_class, method))
@ -366,14 +367,14 @@ class SourceWindow(QtWidgets.QTextEdit):
lines.extend(self.current_class.get_source_ext())
#TODO: delete doc when tab is closed? not deleted by "self" :(
# TODO: delete doc when tab is closed? not deleted by "self" :(
if hasattr(self, "doc"):
del self.doc
self.doc = SourceDocument(parent=self, lines=lines)
self.setDocument(self.doc)
#No need to save hightlighter. highlighBlock will automatically be called
#because we passed the QTextDocument to QSyntaxHighlighter constructor
# No need to save hightlighter. highlighBlock will automatically be called
# because we passed the QTextDocument to QSyntaxHighlighter constructor
MyHighlighter(self.doc, lexer=JavaLexer())
def cursor_position_changed(self):
@ -387,7 +388,7 @@ class SourceWindow(QtWidgets.QTextEdit):
if len(cur.selectedText()) == 0:
cur.select(QtGui.QTextCursor.WordUnderCursor)
self.setTextCursor(cur)
#androconf.debug("cursor: %s" % cur.selectedText())
# androconf.debug("cursor: %s" % cur.selectedText())
def keyPressEvent(self, event):
'''Keyboard shortcuts'''
@ -411,14 +412,14 @@ class SourceWindow(QtWidgets.QTextEdit):
statusTip="List the references where this element is used",
triggered=self.actionXref))
menu.addAction(QtWidgets.QAction("&Goto",
self,
statusTip="Go to element definition",
triggered=self.actionGoto))
self,
statusTip="Go to element definition",
triggered=self.actionGoto))
menu.addAction(
QtWidgets.QAction("Rename...",
self,
statusTip="Rename an element (class, method, ...)",
triggered=self.actionRename))
self,
statusTip="Rename an element (class, method, ...)",
triggered=self.actionRename))
menu.addAction(QtWidgets.QAction(
"&Info",
self,
@ -432,10 +433,10 @@ class SourceWindow(QtWidgets.QTextEdit):
"Reload sources (needed when renaming changed other tabs)",
triggered=self.reload_java_sources))
menu.addAction(QtWidgets.QAction("&Copy",
self,
shortcut=QtGui.QKeySequence.Copy,
statusTip="Copy the current selection's contents to the clipboard",
triggered=self.actionCopy))
self,
shortcut=QtGui.QKeySequence.Copy,
statusTip="Copy the current selection's contents to the clipboard",
triggered=self.actionCopy))
menu.exec_(QtGui.QCursor.pos())
def actionXref(self):
@ -518,17 +519,17 @@ class SourceWindow(QtWidgets.QTextEdit):
self.mainwin.showStatus("No xref returned.")
return
#elif t[0] == 'NAME_METHOD_INVOKE':
# class_, method_ = t[2].split(' -> ')
# if class_ == 'this':
# class_ = self.current_class
# else:
# class_ = classdot2class(class_)
#elif t[0] == 'NAME_PROTOTYPE':
# class_ = classdot2class(t[2] + '.' + t[1])
#else:
# self.mainwin.showStatus("Xref not available. Info ok: '%s' but object not supported." % selection)
# return
# elif t[0] == 'NAME_METHOD_INVOKE':
# class_, method_ = t[2].split(' -> ')
# if class_ == 'this':
# class_ = self.current_class
# else:
# class_ = classdot2class(class_)
# elif t[0] == 'NAME_PROTOTYPE':
# class_ = classdot2class(t[2] + '.' + t[1])
# else:
# self.mainwin.showStatus("Xref not available. Info ok: '%s' but object not supported." % selection)
# return
def actionCopy(self):
print('COPY')
@ -723,12 +724,12 @@ class SourceWindow(QtWidgets.QTextEdit):
self.mainwin.showStatus("Impossible to find the method")
return
method_item.set_name(str(newname)) #unicode to ascii
method_item.set_name(str(newname)) # unicode to ascii
elif type_ == "CLASS":
newname_class = classdot2class(package_ + '.' + newname)
self.mainwin.showStatus("New name: %s" % newname_class)
class_item = self.current_class #getattr(self.mainwin.d, classdot2func(class_))
class_item.set_name(str(newname_class)) #unicode to ascii
class_item = self.current_class # getattr(self.mainwin.d, classdot2func(class_))
class_item.set_name(str(newname_class)) # unicode to ascii
self.mainwin.updateDockWithTree()
elif type_ == 'FIELD':
if self.field_name_exist(newname):

View File

@ -3,7 +3,6 @@ from androguard.gui.xrefwindow import XrefDialogString
class StringsWindow(QtWidgets.QWidget):
def __init__(self, parent=None, win=None, session=None):
super(StringsWindow, self).__init__(parent)
self.mainwin = win
@ -30,7 +29,6 @@ class StringsWindow(QtWidgets.QWidget):
class StringsValueWindow(QtWidgets.QTreeView):
def __init__(self, parent=None, win=None, session=None):
super(StringsValueWindow, self).__init__(parent)
self.mainwin = win
@ -63,7 +61,7 @@ class StringsValueWindow(QtWidgets.QTreeView):
self.model.setData(self.model.index(
row, 3, QtCore.QModelIndex()), digest)
self.reverse_strings[repr(strings_analysis[string_value].get_value()) + digest
] = strings_analysis[string_value]
] = strings_analysis[string_value]
row += 1
self.proxyModel.setSourceModel(self.model)

View File

@ -7,8 +7,8 @@ from androguard.gui.xrefwindow import XrefDialogClass
from androguard.gui.sourcewindow import SourceWindow
from androguard.gui.helpers import classdot2class, Signature
class HashableQTreeWidgetItem(QtWidgets.QTreeWidgetItem):
# TODO this is a pure workaround to have a hash method!
# It seems that for python2 is __hash__ available
# But not on python3
@ -17,7 +17,6 @@ class HashableQTreeWidgetItem(QtWidgets.QTreeWidgetItem):
class TreeWindow(QtWidgets.QTreeWidget):
def __init__(self, parent=None, win=None, session=None):
super(TreeWindow, self).__init__(parent)
self.itemDoubleClicked.connect(self.itemDoubleClickedHandler)
@ -92,13 +91,13 @@ class TreeWindow(QtWidgets.QTreeWidget):
statusTip="List the references where this element is used",
triggered=self.actionXref)
self.expandAct = QtWidgets.QAction("Expand",
self,
statusTip="Expand all the subtrees",
triggered=self.actionExpand)
self,
statusTip="Expand all the subtrees",
triggered=self.actionExpand)
self.collapseAct = QtWidgets.QAction("Collapse",
self,
statusTip="Collapse all the subtrees",
triggered=self.actionCollapse)
self,
statusTip="Collapse all the subtrees",
triggered=self.actionCollapse)
def actionXref(self):
item = self.currentItem()
@ -126,7 +125,6 @@ class TreeWindow(QtWidgets.QTreeWidget):
class_analysis=class_analysis)
xwin.show()
def expand_children(self, item):
self.expandItem(item)
for i in range(item.childCount()):

View File

@ -67,7 +67,6 @@ class XrefDialogClass(QtWidgets.QDialog):
class XrefDialogMethod(QtWidgets.QDialog):
def __init__(self,
parent=None,
win=None,
@ -108,7 +107,6 @@ class XrefDialogMethod(QtWidgets.QDialog):
class XrefDialogField(QtWidgets.QDialog):
def __init__(self,
parent=None,
win=None,
@ -153,7 +151,6 @@ class XrefDialogField(QtWidgets.QDialog):
class XrefDialogString(QtWidgets.QDialog):
def __init__(self, parent=None, win=None, string_analysis=None):
super(XrefDialogString, self).__init__(parent)
self.string_analysis = string_analysis
@ -248,12 +245,11 @@ class XrefDialog(QtWidgets.QDialog):
method_ = xref_item[0].get_name()
descriptor_ = xref_item[0].get_descriptor()
xrefs.append(classmethod2display(class_, method_, descriptor_))
# print xrefs
# print xrefs
return xrefs
class XrefListView(QtWidgets.QWidget):
def __init__(self,
parent=None,
win=None,
@ -290,7 +286,6 @@ class XrefListView(QtWidgets.QWidget):
class XrefValueWindow(QtWidgets.QTreeView):
def __init__(self, parent=None, win=None, xrefs=None, headers=None):
super(XrefValueWindow, self).__init__(parent)
self.parent = parent

View File

@ -1,4 +1,5 @@
from future import standard_library
standard_library.install_aliases()
from androguard.core import *
from androguard.core.bytecode import *
@ -11,6 +12,7 @@ from pickle import dump, load
from androguard.core import androconf
from androguard import session
def init_print_colors():
from IPython.utils import coloransi, io
androconf.default_colors(coloransi.TermColors)
@ -26,6 +28,7 @@ def get_default_session():
CONF["SESSION"] = session.Session()
return CONF["SESSION"]
def save_session(l, filename):
"""
save your session !
@ -138,7 +141,7 @@ def RunDecompiler(d, dx, decompiler, session=None):
if decompiler == "dex2jad":
d.set_decompiler(DecompilerDex2Jad(
d, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"
], androconf.CONF["PATH_JAD"],
], androconf.CONF["PATH_JAD"],
androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"]))
elif decompiler == "dex2fernflower":
d.set_decompiler(DecompilerDex2Fernflower(
@ -147,7 +150,7 @@ def RunDecompiler(d, dx, decompiler, session=None):
], androconf.CONF["PATH_FERNFLOWER"], androconf.CONF[
"BIN_FERNFLOWER"
], androconf.CONF["OPTIONS_FERNFLOWER"
], androconf.CONF["TMP_DIRECTORY"]))
], androconf.CONF["TMP_DIRECTORY"]))
elif decompiler == "ded":
d.set_decompiler(DecompilerDed(d, androconf.CONF["PATH_DED"],
androconf.CONF["BIN_DED"],

View File

@ -3,6 +3,7 @@ Read and write ZIP files.
"""
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import chr
from builtins import map
@ -15,14 +16,16 @@ import io
import re
try:
import zlib # We may need its compression method
import zlib # We may need its compression method
crc32 = zlib.crc32
except ImportError:
zlib = None
crc32 = binascii.crc32
__all__ = ["BadZipfile", "error", "ZIP_STORED", "ZIP_DEFLATED", "is_zipfile",
"ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile" ]
"ZipInfo", "ZipFile", "PyZipFile", "LargeZipFile"]
class BadZipfile(Exception):
pass
@ -34,7 +37,8 @@ class LargeZipFile(Exception):
and those extensions are disabled.
"""
error = BadZipfile # The exception raised by this module
error = BadZipfile # The exception raised by this module
ZIP64_LIMIT = (1 << 31) - 1
ZIP_FILECOUNT_LIMIT = 1 << 16
@ -138,14 +142,16 @@ _CD64_NUMBER_ENTRIES_TOTAL = 7
_CD64_DIRECTORY_SIZE = 8
_CD64_OFFSET_START_CENTDIR = 9
def _check_zipfile(fp):
try:
if _EndRecData(fp):
return True # file has correct magic number
return True # file has correct magic number
except IOError:
pass
return False
def is_zipfile(filename):
"""Quickly see if a file is a ZIP file by checking the magic number.
@ -162,6 +168,7 @@ def is_zipfile(filename):
pass
return result
def _EndRecData64(fpin, offset, endrec):
"""
Read the ZIP64 end-of-archive records and use that to update endrec
@ -185,8 +192,8 @@ def _EndRecData64(fpin, offset, endrec):
fpin.seek(offset - sizeEndCentDir64Locator - sizeEndCentDir64, 2)
data = fpin.read(sizeEndCentDir64)
sig, sz, create_version, read_version, disk_num, disk_dir, \
dircount, dircount2, dirsize, diroffset = \
struct.unpack(structEndArchive64, data)
dircount, dircount2, dirsize, diroffset = \
struct.unpack(structEndArchive64, data)
if sig != stringEndArchive64:
return endrec
@ -222,7 +229,7 @@ def _EndRecData(fpin):
if data[0:4] == stringEndArchive and data[-2:] == "\000\000":
# the signature is correct and there's no comment, unpack structure
endrec = struct.unpack(structEndArchive, data)
endrec=list(endrec)
endrec = list(endrec)
# Append a blank comment and record start offset
endrec.append("")
@ -242,10 +249,10 @@ def _EndRecData(fpin):
start = data.rfind(stringEndArchive)
if start >= 0:
# found the magic number; attempt to unpack and interpret
recData = data[start:start+sizeEndCentDir]
recData = data[start:start + sizeEndCentDir]
endrec = list(struct.unpack(structEndArchive, recData))
commentSize = endrec[_ECD_COMMENT_SIZE] #as claimed by the zip file
comment = data[start+sizeEndCentDir:start+sizeEndCentDir+commentSize]
commentSize = endrec[_ECD_COMMENT_SIZE] # as claimed by the zip file
comment = data[start + sizeEndCentDir:start + sizeEndCentDir + commentSize]
endrec.append(comment)
endrec.append(maxCommentStart + start)
@ -257,33 +264,33 @@ def _EndRecData(fpin):
return
class ZipInfo (object):
class ZipInfo(object):
"""Class with attributes describing each file in the ZIP archive."""
__slots__ = (
'orig_filename',
'filename',
'date_time',
'compress_type',
'comment',
'extra',
'create_system',
'create_version',
'extract_version',
'reserved',
'flag_bits',
'volume',
'internal_attr',
'external_attr',
'header_offset',
'CRC',
'compress_size',
'file_size',
'_raw_time',
)
'orig_filename',
'filename',
'date_time',
'compress_type',
'comment',
'extra',
'create_system',
'create_version',
'extract_version',
'reserved',
'flag_bits',
'volume',
'internal_attr',
'external_attr',
'header_offset',
'CRC',
'compress_size',
'file_size',
'_raw_time',
)
def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)):
self.orig_filename = filename # Original file name in archive
def __init__(self, filename="NoName", date_time=(1980, 1, 1, 0, 0, 0)):
self.orig_filename = filename # Original file name in archive
# Terminate the file name at the first null byte. Null bytes in file
# names are used as tricks by viruses in archives.
@ -296,24 +303,24 @@ class ZipInfo (object):
if os.sep != "/" and os.sep in filename:
filename = filename.replace(os.sep, "/")
self.filename = filename # Normalized file name
self.date_time = date_time # year, month, day, hour, min, sec
self.filename = filename # Normalized file name
self.date_time = date_time # year, month, day, hour, min, sec
# Standard values:
self.compress_type = ZIP_STORED # Type of compression for the file
self.comment = "" # Comment for each file
self.extra = "" # ZIP extra data
self.compress_type = ZIP_STORED # Type of compression for the file
self.comment = "" # Comment for each file
self.extra = "" # ZIP extra data
if sys.platform == 'win32':
self.create_system = 0 # System which created ZIP archive
self.create_system = 0 # System which created ZIP archive
else:
# Assume everything else is unix-y
self.create_system = 3 # System which created ZIP archive
self.create_version = 20 # Version which created ZIP archive
self.extract_version = 20 # Version needed to extract archive
self.reserved = 0 # Must be zero
self.flag_bits = 0 # ZIP flag bits
self.volume = 0 # Volume number of file header
self.internal_attr = 0 # Internal attributes
self.external_attr = 0 # External file attributes
self.create_system = 3 # System which created ZIP archive
self.create_version = 20 # Version which created ZIP archive
self.extract_version = 20 # Version needed to extract archive
self.reserved = 0 # Must be zero
self.flag_bits = 0 # ZIP flag bits
self.volume = 0 # Volume number of file header
self.internal_attr = 0 # Internal attributes
self.external_attr = 0 # External file attributes
# Other attributes are set by class ZipFile(object):
# header_offset Byte offset to the file header
# CRC CRC-32 of the uncompressed file
@ -340,7 +347,7 @@ class ZipInfo (object):
# fall back to the ZIP64 extension
fmt = '<HHQQ'
extra = extra + struct.pack(fmt,
1, struct.calcsize(fmt)-4, file_size, compress_size)
1, struct.calcsize(fmt) - 4, file_size, compress_size)
file_size = 0xffffffff
compress_size = 0xffffffff
self.extract_version = max(45, self.extract_version)
@ -348,10 +355,10 @@ class ZipInfo (object):
filename, flag_bits = self._encodeFilenameFlags()
header = struct.pack(structFileHeader, stringFileHeader,
self.extract_version, self.reserved, flag_bits,
self.compress_type, dostime, dosdate, CRC,
compress_size, file_size,
len(filename), len(extra))
self.extract_version, self.reserved, flag_bits,
self.compress_type, dostime, dosdate, CRC,
compress_size, file_size,
len(filename), len(extra))
return header + filename + extra
def _encodeFilenameFlags(self):
@ -385,7 +392,7 @@ class ZipInfo (object):
elif ln == 0:
counts = ()
else:
raise RuntimeError("Corrupt extra field %s"%(ln,))
raise RuntimeError("Corrupt extra field %s" % (ln,))
idx = 0
@ -401,9 +408,9 @@ class ZipInfo (object):
if self.header_offset == 0xffffffff:
old = self.header_offset
self.header_offset = counts[idx]
idx+=1
idx += 1
extra = extra[ln+4:]
extra = extra[ln + 4:]
class _ZipDecrypter(object):
@ -437,6 +444,7 @@ class _ZipDecrypter(object):
crc = ((crc >> 1) & 0x7FFFFFFF)
table[i] = crc
return table
crctable = _GenerateCRCTable()
def _crc32(self, ch, crc):
@ -460,11 +468,12 @@ class _ZipDecrypter(object):
"""Decrypt a single character."""
c = ord(c)
k = self.key2 | 2
c = c ^ (((k * (k^1)) >> 8) & 255)
c = c ^ (((k * (k ^ 1)) >> 8) & 255)
c = chr(c)
self._UpdateKeys(c)
return c
class ZipExtFile(io.BufferedIOBase):
"""File-like object for reading an archive member.
Is returned by ZipFile.open().
@ -624,7 +633,7 @@ class ZipExtFile(io.BufferedIOBase):
data = ''.join(map(self._decrypter, data))
if self._compress_type == ZIP_STORED:
self._update_crc(data, eof=(self._compress_left==0))
self._update_crc(data, eof=(self._compress_left == 0))
self._readbuffer = self._readbuffer[self._offset:] + data
self._offset = 0
else:
@ -633,7 +642,7 @@ class ZipExtFile(io.BufferedIOBase):
# Handle unconsumed data.
if (len(self._unconsumed) > 0 and n > len_readbuffer and
self._compress_type == ZIP_DEFLATED):
self._compress_type == ZIP_DEFLATED):
data = self._decompressor.decompress(
self._unconsumed,
max(n - len_readbuffer, self.MIN_READ_SIZE)
@ -654,7 +663,6 @@ class ZipExtFile(io.BufferedIOBase):
return data
class ZipFile(object):
""" Class with methods to open, read, write, close, list zip files.
@ -670,7 +678,7 @@ class ZipFile(object):
"""
fp = None # Set here since __del__ checks it
fp = None # Set here since __del__ checks it
def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=False):
"""Open the ZIP file with mode read "r", write "w" or append "a"."""
@ -688,8 +696,8 @@ class ZipFile(object):
self._allowZip64 = allowZip64
self._didModify = False
self.debug = 0 # Level of printing: 0 through 3
self.NameToInfo = {} # Find file info given name
self.filelist = [] # List of ZipInfo instances for archive
self.NameToInfo = {} # Find file info given name
self.filelist = [] # List of ZipInfo instances for archive
self.compression = compression # Method of compression
self.mode = key = mode.replace('b', '')[0]
self.pwd = None
@ -699,7 +707,7 @@ class ZipFile(object):
if isinstance(file, basestring):
self._filePassed = 0
self.filename = file
modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'}
modeDict = {'r': 'rb', 'w': 'wb', 'a': 'r+b'}
try:
self.fp = open(file, modeDict[mode])
except IOError:
@ -766,9 +774,9 @@ class ZipFile(object):
raise BadZipfile("File is not a zip file")
if self.debug > 1:
print(endrec)
size_cd = endrec[_ECD_SIZE] # bytes in central directory
offset_cd = endrec[_ECD_OFFSET] # offset of central directory
self.comment = endrec[_ECD_COMMENT] # archive comment
size_cd = endrec[_ECD_SIZE] # bytes in central directory
offset_cd = endrec[_ECD_OFFSET] # offset of central directory
self.comment = endrec[_ECD_COMMENT] # archive comment
# "concat" is zero, unless zip was concatenated to another file
concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
@ -799,13 +807,13 @@ class ZipFile(object):
x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
(x.create_version, x.create_system, x.extract_version, x.reserved,
x.flag_bits, x.compress_type, t, d,
x.CRC, x.compress_size, x.file_size) = centdir[1:12]
x.flag_bits, x.compress_type, t, d,
x.CRC, x.compress_size, x.file_size) = centdir[1:12]
x.volume, x.internal_attr, x.external_attr = centdir[15:18]
# Convert date/time code to (year, month, day, hour, min, sec)
x._raw_time = t
x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F,
t>>11, (t>>5)&0x3F, (t&0x1F) * 2 )
x.date_time = ((d >> 9) + 1980, (d >> 5) & 0xF, d & 0x1F,
t >> 11, (t >> 5) & 0x3F, (t & 0x1F) * 2)
x._decodeExtra()
x.header_offset = x.header_offset + concat
@ -821,7 +829,6 @@ class ZipFile(object):
if self.debug > 2:
print("total", total)
def namelist(self):
"""Return a list of file names in the archive."""
l = []
@ -849,7 +856,7 @@ class ZipFile(object):
# Read by chunks, to avoid an OverflowError or a
# MemoryError with very large embedded files.
f = self.open(zinfo.filename, "r")
while f.read(chunk_size): # Check CRC-32
while f.read(chunk_size): # Check CRC-32
pass
except BadZipfile:
return zinfo.filename
@ -907,7 +914,7 @@ class ZipFile(object):
if fname != zinfo.orig_filename:
raise BadZipfile('File name in directory "%s" and header "%s" differ.' % (
zinfo.orig_filename, fname))
zinfo.orig_filename, fname))
# check for encrypted flag & handle password
is_encrypted = zinfo.flag_bits & 0x1
@ -917,7 +924,7 @@ class ZipFile(object):
pwd = self.pwd
if not pwd:
raise RuntimeError("File %s is encrypted, " \
"password required for extraction" % name)
"password required for extraction" % name)
zd = _ZipDecrypter(pwd)
# The first 12 bytes in the cypher stream is an encryption header
@ -936,7 +943,7 @@ class ZipFile(object):
if ord(h[11]) != check_byte:
raise RuntimeError("Bad password for file", name)
return ZipExtFile(zef_file, mode, zinfo, zd)
return ZipExtFile(zef_file, mode, zinfo, zd)
def extract(self, member, path=None, pwd=None):
"""Extract a member from the archive to the current working directory,
@ -1004,7 +1011,7 @@ class ZipFile(object):
def _writecheck(self, zinfo):
"""Check for errors before writing a file to the archive."""
if zinfo.filename in self.NameToInfo:
if self.debug: # Warning for duplicate names
if self.debug: # Warning for duplicate names
print("Duplicate name:", zinfo.filename)
if self.mode not in ("w", "a"):
raise RuntimeError('write() requires mode "w" or "a"')
@ -1026,7 +1033,7 @@ class ZipFile(object):
arcname."""
if not self.fp:
raise RuntimeError(
"Attempt to write to ZIP archive that was already closed")
"Attempt to write to ZIP archive that was already closed")
st = os.stat(filename)
isdir = stat.S_ISDIR(st.st_mode)
@ -1041,7 +1048,7 @@ class ZipFile(object):
if isdir:
arcname += '/'
zinfo = ZipInfo(arcname, date_time)
zinfo.external_attr = (st[0] & 0xFFFF) << 16 # Unix attributes
zinfo.external_attr = (st[0] & 0xFFFF) << 16 # Unix attributes
if compress_type is None:
zinfo.compress_type = self.compression
else:
@ -1049,7 +1056,7 @@ class ZipFile(object):
zinfo.file_size = st.st_size
zinfo.flag_bits = 0x00
zinfo.header_offset = self.fp.tell() # Start of header bytes
zinfo.header_offset = self.fp.tell() # Start of header bytes
self._writecheck(zinfo)
self._didModify = True
@ -1071,7 +1078,7 @@ class ZipFile(object):
self.fp.write(zinfo.FileHeader())
if zinfo.compress_type == ZIP_DEFLATED:
cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
zlib.DEFLATED, -15)
zlib.DEFLATED, -15)
else:
cmpr = None
while 1:
@ -1094,10 +1101,10 @@ class ZipFile(object):
zinfo.CRC = CRC
zinfo.file_size = file_size
# Seek backwards and write CRC and file sizes
position = self.fp.tell() # Preserve current position in file
position = self.fp.tell() # Preserve current position in file
self.fp.seek(zinfo.header_offset + 14, 0)
self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
zinfo.file_size))
zinfo.file_size))
self.fp.seek(position, 0)
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
@ -1117,31 +1124,31 @@ class ZipFile(object):
if not self.fp:
raise RuntimeError(
"Attempt to write to ZIP archive that was already closed")
"Attempt to write to ZIP archive that was already closed")
if compress_type is not None:
zinfo.compress_type = compress_type
zinfo.file_size = len(bytes) # Uncompressed size
zinfo.header_offset = self.fp.tell() # Start of header bytes
zinfo.file_size = len(bytes) # Uncompressed size
zinfo.header_offset = self.fp.tell() # Start of header bytes
self._writecheck(zinfo)
self._didModify = True
zinfo.CRC = crc32(bytes) & 0xffffffff # CRC-32 checksum
zinfo.CRC = crc32(bytes) & 0xffffffff # CRC-32 checksum
if zinfo.compress_type == ZIP_DEFLATED:
co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
zlib.DEFLATED, -15)
zlib.DEFLATED, -15)
bytes = co.compress(bytes) + co.flush()
zinfo.compress_size = len(bytes) # Compressed size
zinfo.compress_size = len(bytes) # Compressed size
else:
zinfo.compress_size = zinfo.file_size
zinfo.header_offset = self.fp.tell() # Start of header bytes
zinfo.header_offset = self.fp.tell() # Start of header bytes
self.fp.write(zinfo.FileHeader())
self.fp.write(bytes)
self.fp.flush()
if zinfo.flag_bits & 0x08:
# Write CRC and file sizes after the file data
self.fp.write(struct.pack("<LLL", zinfo.CRC, zinfo.compress_size,
zinfo.file_size))
zinfo.file_size))
self.filelist.append(zinfo)
self.NameToInfo[zinfo.filename] = zinfo
@ -1155,10 +1162,10 @@ class ZipFile(object):
if self.fp is None:
return
if self.mode in ("w", "a") and self._didModify: # write ending records
if self.mode in ("w", "a") and self._didModify: # write ending records
count = 0
pos1 = self.fp.tell()
for zinfo in self.filelist: # write central directory
for zinfo in self.filelist: # write central directory
count = count + 1
dt = zinfo.date_time
dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
@ -1184,8 +1191,8 @@ class ZipFile(object):
if extra:
# Append a ZIP64 field to the extra's
extra_data = struct.pack(
'<HH' + 'Q'*len(extra),
1, 8*len(extra), *extra) + extra_data
'<HH' + 'Q' * len(extra),
1, 8 * len(extra), *extra) + extra_data
extract_version = max(45, zinfo.extract_version)
create_version = max(45, zinfo.create_version)
@ -1196,22 +1203,22 @@ class ZipFile(object):
try:
filename, flag_bits = zinfo._encodeFilenameFlags()
centdir = struct.pack(structCentralDir,
stringCentralDir, create_version,
zinfo.create_system, extract_version, zinfo.reserved,
flag_bits, zinfo.compress_type, dostime, dosdate,
zinfo.CRC, compress_size, file_size,
len(filename), len(extra_data), len(zinfo.comment),
0, zinfo.internal_attr, zinfo.external_attr,
header_offset)
stringCentralDir, create_version,
zinfo.create_system, extract_version, zinfo.reserved,
flag_bits, zinfo.compress_type, dostime, dosdate,
zinfo.CRC, compress_size, file_size,
len(filename), len(extra_data), len(zinfo.comment),
0, zinfo.internal_attr, zinfo.external_attr,
header_offset)
except DeprecationWarning:
print((structCentralDir,
stringCentralDir, create_version,
zinfo.create_system, extract_version, zinfo.reserved,
zinfo.flag_bits, zinfo.compress_type, dostime, dosdate,
zinfo.CRC, compress_size, file_size,
len(zinfo.filename), len(extra_data), len(zinfo.comment),
0, zinfo.internal_attr, zinfo.external_attr,
header_offset), file=sys.stderr)
stringCentralDir, create_version,
zinfo.create_system, extract_version, zinfo.reserved,
zinfo.flag_bits, zinfo.compress_type, dostime, dosdate,
zinfo.CRC, compress_size, file_size,
len(zinfo.filename), len(extra_data), len(zinfo.comment),
0, zinfo.internal_attr, zinfo.external_attr,
header_offset), file=sys.stderr)
raise
self.fp.write(centdir)
self.fp.write(filename)
@ -1224,18 +1231,18 @@ class ZipFile(object):
centDirSize = pos2 - pos1
centDirOffset = pos1
if (centDirCount >= ZIP_FILECOUNT_LIMIT or
centDirOffset > ZIP64_LIMIT or
centDirSize > ZIP64_LIMIT):
centDirOffset > ZIP64_LIMIT or
centDirSize > ZIP64_LIMIT):
# Need to write the ZIP64 end-of-archive records
zip64endrec = struct.pack(
structEndArchive64, stringEndArchive64,
44, 45, 45, 0, 0, centDirCount, centDirCount,
centDirSize, centDirOffset)
structEndArchive64, stringEndArchive64,
44, 45, 45, 0, 0, centDirCount, centDirCount,
centDirSize, centDirOffset)
self.fp.write(zip64endrec)
zip64locrec = struct.pack(
structEndArchive64Locator,
stringEndArchive64Locator, 0, pos2, 1)
structEndArchive64Locator,
stringEndArchive64Locator, 0, pos2, 1)
self.fp.write(zip64locrec)
centDirCount = min(centDirCount, 0xFFFF)
centDirSize = min(centDirSize, 0xFFFFFFFF)
@ -1263,7 +1270,7 @@ class ZipFile(object):
class PyZipFile(ZipFile):
"""Class to create ZIP archives with Python library files and packages."""
def writepy(self, pathname, basename = ""):
def writepy(self, pathname, basename=""):
"""Add all files from "pathname" to the ZIP archive.
If pathname is a package directory, search the directory and
@ -1302,7 +1309,7 @@ class PyZipFile(ZipFile):
self.writepy(path, basename) # Recursive call
elif ext == ".py":
fname, arcname = self._get_codename(path[0:-3],
basename)
basename)
if self.debug:
print("Adding", arcname)
self.write(fname, arcname)
@ -1315,7 +1322,7 @@ class PyZipFile(ZipFile):
root, ext = os.path.splitext(filename)
if ext == ".py":
fname, arcname = self._get_codename(path[0:-3],
basename)
basename)
if self.debug:
print("Adding", arcname)
self.write(fname, arcname)
@ -1334,14 +1341,14 @@ class PyZipFile(ZipFile):
archive name, compiling if necessary. For example, given
/python/lib/string, return (/python/lib/string.pyc, string).
"""
file_py = pathname + ".py"
file_py = pathname + ".py"
file_pyc = pathname + ".pyc"
file_pyo = pathname + ".pyo"
if os.path.isfile(file_pyo) and \
os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime:
fname = file_pyo # Use .pyo file
os.stat(file_pyo).st_mtime >= os.stat(file_py).st_mtime:
fname = file_pyo # Use .pyo file
elif not os.path.isfile(file_pyc) or \
os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime:
os.stat(file_pyc).st_mtime < os.stat(file_py).st_mtime:
import py_compile
if self.debug:
print("Compiling", file_py)
@ -1358,9 +1365,9 @@ class PyZipFile(ZipFile):
return (fname, archivename)
def main(args = None):
def main(args=None):
import textwrap
USAGE=textwrap.dedent("""\
USAGE = textwrap.dedent("""\
Usage:
zipfile.py -l zipfile.zip # Show listing of a zipfile
zipfile.py -t zipfile.zip # Test if a zipfile is valid
@ -1423,8 +1430,8 @@ def main(args = None):
elif os.path.isdir(path):
for nm in os.listdir(path):
addToZip(zf,
os.path.join(path, nm), os.path.join(zippath, nm))
# else: ignore
os.path.join(path, nm), os.path.join(zippath, nm))
# else: ignore
zf = ZipFile(args[1], 'w', allowZip64=True)
for src in args[2:]:
@ -1432,5 +1439,6 @@ def main(args = None):
zf.close()
if __name__ == "__main__":
main()

View File

@ -10,12 +10,15 @@ from androguard.core.analysis.analysis import *
from androguard.decompiler.decompiler import *
from androguard import misc
def Save(session, filename):
misc.save_session(session, filename)
def Load(filename):
return misc.load_session(filename)
class Session(object):
def __init__(self, export_ipython=False):
self.setupObjects()

View File

@ -10,7 +10,6 @@ from androguard.gui.mainwindow import MainWindow
from PyQt5 import QtWidgets, QtGui
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Androguard GUI")
parser.add_argument("-d", "--debug", action="store_true", default=False)

View File

@ -1,6 +1,7 @@
import unittest
import sys
PATH_INSTALL = "./"
sys.path.append(PATH_INSTALL)
@ -9,7 +10,6 @@ from androguard.core.analysis import analysis
class AnalysisTest(unittest.TestCase):
def testDex(self):
with open("examples/android/TestsAndroguard/bin/classes.dex",
"rb") as fd:

View File

@ -1,6 +1,7 @@
import unittest
import sys
PATH_INSTALL = "./"
sys.path.append(PATH_INSTALL)
@ -8,7 +9,6 @@ from androguard.core.bytecodes import apk
class APKTest(unittest.TestCase):
def testAPK(self):
with open("examples/android/TestsAndroguard/bin/TestActivity.apk",
"rb") as fd:

View File

@ -1,13 +1,13 @@
import unittest
import sys
PATH_INSTALL = "./"
sys.path.append(PATH_INSTALL)
from androguard.core.bytecodes import apk
import collections
TEST_APP_NAME = "TestsAndroguardApplication"
TEST_ICONS = {
120: "res/drawable-ldpi/icon.png",

View File

@ -1,6 +1,7 @@
import unittest
import sys
PATH_INSTALL = "./"
sys.path.append(PATH_INSTALL)
@ -8,7 +9,6 @@ from androguard.core.bytecodes import apk
class AXMLTest(unittest.TestCase):
def testAXML(self):
filenames = [
"examples/axml/AndroidManifest-Chinese.xml",

View File

@ -1,6 +1,7 @@
import unittest
import sys
PATH_INSTALL = "./"
sys.path.append(PATH_INSTALL)
@ -8,7 +9,6 @@ from androguard.core.bytecodes import dvm
class DexTest(unittest.TestCase):
def testDex(self):
with open("examples/android/TestsAndroguard/bin/classes.dex",
"rb") as fd:
@ -32,7 +32,6 @@ class DexTest(unittest.TestCase):
class InstructionTest(unittest.TestCase):
def testNOP(self):
instruction = dvm.Instruction10x(None, bytearray(b"\x00\x00"))
self.assertEqual(instruction.get_name(), "nop")

View File

@ -1,6 +1,7 @@
import unittest
import sys
PATH_INSTALL = "./"
sys.path.append(PATH_INSTALL)
@ -8,7 +9,6 @@ from androguard import session
class SessionTest(unittest.TestCase):
def testSessionDex(self):
s = session.Session()
with open("examples/android/TestsAndroguard/bin/classes.dex",