Clean up
Started to clean up the code: - remove BuffHandle/Buff classes - use logger - remove all non necessary stuff See ya !
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
||||
[submodule "libraries/axplorer"]
|
||||
path = libraries/axplorer
|
||||
url = https://github.com/reddr/axplorer.git
|
@ -21,7 +21,7 @@ Androguard is a full python tool to play with Android files.
|
||||
* Android's binary xml
|
||||
* Android resources
|
||||
* Disassemble DEX/ODEX bytecodes
|
||||
* Decompiler for DEX/ODEX files
|
||||
* Basic Decompiler for DEX/ODEX files
|
||||
|
||||
## Authors: Androguard Team
|
||||
|
||||
@ -60,7 +60,7 @@ You are using Androguard and are not listed here? Just create a [ticket](https:/
|
||||
|
||||
### Androguard
|
||||
|
||||
Copyright (C) 2012 - 2016, Anthony Desnos (desnos at t0t0.fr)
|
||||
Copyright (C) 2012 - 2022, Anthony Desnos (desnos at t0t0.fr)
|
||||
All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -1,4 +1,4 @@
|
||||
# The current version of Androguard
|
||||
# Please use only this variable in any scripts,
|
||||
# to keep the version number the same everywhere.
|
||||
__version__ = "3.4.0a1"
|
||||
__version__ = "4.0"
|
||||
|
@ -1 +0,0 @@
|
||||
|
@ -1,8 +1,10 @@
|
||||
# Androguard
|
||||
from androguard.core import androconf
|
||||
from androguard.util import read, get_certificate_name_string
|
||||
|
||||
from androguard.core.bytecodes.axml import ARSCParser, AXMLPrinter, ARSCResTableConfig, AXMLParser, format_value, START_TAG, END_TAG, TEXT, END_DOCUMENT
|
||||
from androguard.core.axml import ARSCParser, AXMLPrinter, ARSCResTableConfig, AXMLParser, format_value, START_TAG, END_TAG, TEXT, END_DOCUMENT
|
||||
|
||||
# Python core
|
||||
import io
|
||||
from zlib import crc32
|
||||
import os
|
||||
@ -13,13 +15,17 @@ import logging
|
||||
from struct import unpack
|
||||
import hashlib
|
||||
import warnings
|
||||
import sys
|
||||
|
||||
# External dependecies
|
||||
from loguru import logger
|
||||
import lxml.sax
|
||||
from xml.dom.pulldom import SAX2DOM
|
||||
|
||||
# Used for reading Certificates
|
||||
from asn1crypto import cms, x509, keys
|
||||
|
||||
logger.add(sys.stderr, format="{time} {level} {message}", filter="apk", level="INFO")
|
||||
|
||||
NS_ANDROID_URI = 'http://schemas.android.com/apk/res/android'
|
||||
NS_ANDROID = '{{{}}}'.format(NS_ANDROID_URI) # Namespace as used by etree
|
||||
|
||||
@ -236,7 +242,7 @@ class APK:
|
||||
|
||||
"""
|
||||
if magic_file:
|
||||
log.warning("You set magic_file but this parameter is actually unused. You should remove it.")
|
||||
logger.warning("You set magic_file but this parameter is actually unused. You should remove it.")
|
||||
|
||||
self.filename = filename
|
||||
|
||||
@ -272,7 +278,7 @@ class APK:
|
||||
self.zip = zipfile.ZipFile(filename, mode="r")
|
||||
|
||||
if testzip:
|
||||
log.info("Testing zip file integrity, this might take a while...")
|
||||
logger.info("Testing zip file integrity, this might take a while...")
|
||||
# Test the zipfile for integrity before continuing.
|
||||
# This process might be slow, as the whole file is read.
|
||||
# Therefore it is possible to enable it as a separate feature.
|
||||
@ -306,27 +312,27 @@ class APK:
|
||||
extracted from the Manifest.
|
||||
"""
|
||||
i = "AndroidManifest.xml"
|
||||
log.info("Starting analysis on {}".format(i))
|
||||
logger.info("Starting analysis on {}".format(i))
|
||||
try:
|
||||
manifest_data = self.zip.read(i)
|
||||
except KeyError:
|
||||
log.warning("Missing AndroidManifest.xml. Is this an APK file?")
|
||||
logger.warning("Missing AndroidManifest.xml. Is this an APK file?")
|
||||
else:
|
||||
ap = AXMLPrinter(manifest_data)
|
||||
|
||||
if not ap.is_valid():
|
||||
log.error("Error while parsing AndroidManifest.xml - is the file valid?")
|
||||
logger.error("Error while parsing AndroidManifest.xml - is the file valid?")
|
||||
return
|
||||
|
||||
self.axml[i] = ap
|
||||
self.xml[i] = self.axml[i].get_xml_obj()
|
||||
|
||||
if self.axml[i].is_packed():
|
||||
log.warning("XML Seems to be packed, operations on the AndroidManifest.xml might fail.")
|
||||
logger.warning("XML Seems to be packed, operations on the AndroidManifest.xml might fail.")
|
||||
|
||||
if self.xml[i] is not None:
|
||||
if self.xml[i].tag != "manifest":
|
||||
log.error("AndroidManifest.xml does not start with a <manifest> tag! Is this a valid APK?")
|
||||
logger.error("AndroidManifest.xml does not start with a <manifest> tag! Is this a valid APK?")
|
||||
return
|
||||
|
||||
self.package = self.get_attribute_value("manifest", "package")
|
||||
@ -363,7 +369,7 @@ class APK:
|
||||
self.declared_permissions[d_perm_name] = d_perm_details
|
||||
|
||||
self.valid_apk = True
|
||||
log.info("APK file was successfully validated!")
|
||||
logger.info("APK file was successfully validated!")
|
||||
|
||||
self.permission_module = androconf.load_api_specific_resource_module(
|
||||
"aosp_permissions", self.get_target_sdk_version())
|
||||
@ -418,7 +424,7 @@ class APK:
|
||||
try:
|
||||
maxSdkVersion = int(self.get_value_from_tag(item, "maxSdkVersion"))
|
||||
except ValueError:
|
||||
log.warning(self.get_max_sdk_version() + 'is not a valid value for <uses-permission> maxSdkVersion')
|
||||
logger.warning(self.get_max_sdk_version() + 'is not a valid value for <uses-permission> maxSdkVersion')
|
||||
except TypeError:
|
||||
pass
|
||||
return maxSdkVersion
|
||||
@ -469,7 +475,7 @@ class APK:
|
||||
if app_name is None:
|
||||
# No App name set
|
||||
# TODO return packagename instead?
|
||||
log.warning("It looks like that no app name is set for the main activity!")
|
||||
logger.warning("It looks like that no app name is set for the main activity!")
|
||||
return ""
|
||||
|
||||
if app_name.startswith("@"):
|
||||
@ -486,12 +492,12 @@ class APK:
|
||||
if package == 'android':
|
||||
# TODO: we can not resolve this, as we lack framework-res.apk
|
||||
# one exception would be when parsing framework-res.apk directly.
|
||||
log.warning("Resource ID with android package name encountered! "
|
||||
logger.warning("Resource ID with android package name encountered! "
|
||||
"Will not resolve, framework-res.apk would be required.")
|
||||
return app_name
|
||||
else:
|
||||
# TODO should look this up, might be in the resources
|
||||
log.warning("Resource ID with Package name '{}' encountered! Will not resolve".format(package))
|
||||
logger.warning("Resource ID with Package name '{}' encountered! Will not resolve".format(package))
|
||||
return app_name
|
||||
|
||||
try:
|
||||
@ -586,7 +592,7 @@ class APK:
|
||||
app_icon = file_name
|
||||
current_dpi = dpi
|
||||
except Exception as e:
|
||||
log.warning("Exception selecting app icon: %s" % e)
|
||||
logger.warning("Exception selecting app icon: %s" % e)
|
||||
|
||||
return app_icon
|
||||
|
||||
@ -2167,8 +2173,10 @@ def get_apkid(apkfile):
|
||||
hex value that starts with @).
|
||||
|
||||
"""
|
||||
logger.debug("GET_APKID")
|
||||
|
||||
if not os.path.exists(apkfile):
|
||||
log.error("'{apkfile}' does not exist!".format(apkfile=apkfile))
|
||||
logger.error("'{apkfile}' does not exist!".format(apkfile=apkfile))
|
||||
|
||||
appid = None
|
||||
versionCode = None
|
@ -1,7 +1,5 @@
|
||||
from androguard.core import bytecode
|
||||
|
||||
from androguard.core.resources import public
|
||||
from androguard.core.bytecodes.axml.types import *
|
||||
from .types import *
|
||||
|
||||
from struct import pack, unpack
|
||||
from xml.sax.saxutils import escape
|
||||
@ -9,13 +7,14 @@ import collections
|
||||
from collections import defaultdict
|
||||
|
||||
from lxml import etree
|
||||
from loguru import logger
|
||||
import logging
|
||||
import re
|
||||
import sys
|
||||
import binascii
|
||||
import io
|
||||
import sys
|
||||
|
||||
log = logging.getLogger("androguard.axml")
|
||||
|
||||
logger.add(sys.stderr, format="{time} {level} {message}", filter="axml", level="INFO")
|
||||
|
||||
# Constants for ARSC Files
|
||||
# see http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#215
|
||||
@ -128,7 +127,7 @@ class StringBlock:
|
||||
|
||||
# Check if they supplied a stylesOffset even if the count is 0:
|
||||
if self.styleCount == 0 and self.stylesOffset > 0:
|
||||
log.info("Styles Offset given, but styleCount is zero. "
|
||||
logger.info("Styles Offset given, but styleCount is zero. "
|
||||
"This is not a problem but could indicate packers.")
|
||||
|
||||
self.m_stringOffsets = []
|
||||
@ -155,7 +154,7 @@ class StringBlock:
|
||||
size = self.stylesOffset - self.stringsOffset
|
||||
|
||||
if (size % 4) != 0:
|
||||
log.warning("Size of strings is not aligned by four bytes.")
|
||||
logger.warning("Size of strings is not aligned by four bytes.")
|
||||
|
||||
self.m_charbuff = buff.read(size)
|
||||
|
||||
@ -163,7 +162,7 @@ class StringBlock:
|
||||
size = self.header.size - self.stylesOffset
|
||||
|
||||
if (size % 4) != 0:
|
||||
log.warning("Size of styles is not aligned by four bytes.")
|
||||
logger.warning("Size of styles is not aligned by four bytes.")
|
||||
|
||||
for i in range(0, size // 4):
|
||||
self.m_styles.append(unpack('<I', buff.read(4))[0])
|
||||
@ -279,7 +278,7 @@ class StringBlock:
|
||||
"""
|
||||
string = data.decode(encoding, 'replace')
|
||||
if len(string) != str_len:
|
||||
log.warning("invalid decoded string length")
|
||||
logger.warning("invalid decoded string length")
|
||||
return string
|
||||
|
||||
def _decode_length(self, offset, sizeof_char):
|
||||
@ -371,29 +370,32 @@ class AXMLParser:
|
||||
See http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#563
|
||||
"""
|
||||
def __init__(self, raw_buff):
|
||||
logger.info("AXMLParser")
|
||||
|
||||
self._reset()
|
||||
|
||||
self._valid = True
|
||||
self.axml_tampered = False
|
||||
self.buff = bytecode.BuffHandle(raw_buff)
|
||||
self.buff = io.BufferedReader(io.BytesIO(raw_buff))
|
||||
self.buff_size = self.buff.raw.getbuffer().nbytes
|
||||
|
||||
# Minimum is a single ARSCHeader, which would be a strange edge case...
|
||||
if self.buff.size() < 8:
|
||||
log.error("Filesize is too small to be a valid AXML file! Filesize: {}".format(self.buff.size()))
|
||||
if self.buff_size < 8:
|
||||
logger.error("Filesize is too small to be a valid AXML file! Filesize: {}".format(self.buff.size()))
|
||||
self._valid = False
|
||||
return
|
||||
|
||||
# This would be even stranger, if an AXML file is larger than 4GB...
|
||||
# But this is not possible as the maximum chunk size is a unsigned 4 byte int.
|
||||
if self.buff.size() > 0xFFFFFFFF:
|
||||
log.error("Filesize is too large to be a valid AXML file! Filesize: {}".format(self.buff.size()))
|
||||
if self.buff_size > 0xFFFFFFFF:
|
||||
logger.error("Filesize is too large to be a valid AXML file! Filesize: {}".format(self.buff.size()))
|
||||
self._valid = False
|
||||
return
|
||||
|
||||
try:
|
||||
axml_header = ARSCHeader(self.buff)
|
||||
except ResParserError as e:
|
||||
log.error("Error parsing first resource header: %s", e)
|
||||
logger.error("Error parsing first resource header: %s", e)
|
||||
self._valid = False
|
||||
return
|
||||
|
||||
@ -402,29 +404,29 @@ class AXMLParser:
|
||||
if axml_header.header_size == 28024:
|
||||
# Can be a common error: the file is not an AXML but a plain XML
|
||||
# The file will then usually start with '<?xm' / '3C 3F 78 6D'
|
||||
log.warning("Header size is 28024! Are you trying to parse a plain XML file?")
|
||||
logger.warning("Header size is 28024! Are you trying to parse a plain XML file?")
|
||||
|
||||
if axml_header.header_size != 8:
|
||||
log.error("This does not look like an AXML file. header size does not equal 8! header size = {}".format(axml_header.header_size))
|
||||
logger.error("This does not look like an AXML file. header size does not equal 8! header size = {}".format(axml_header.header_size))
|
||||
self._valid = False
|
||||
return
|
||||
|
||||
if self.filesize > self.buff.size():
|
||||
log.error("This does not look like an AXML file. Declared filesize does not match real size: {} vs {}".format(self.filesize, self.buff.size()))
|
||||
if self.filesize > self.buff_size:
|
||||
logger.error("This does not look like an AXML file. Declared filesize does not match real size: {} vs {}".format(self.filesize, self.buff.size()))
|
||||
self._valid = False
|
||||
return
|
||||
|
||||
if self.filesize < self.buff.size():
|
||||
if self.filesize < self.buff_size:
|
||||
# The file can still be parsed up to the point where the chunk should end.
|
||||
self.axml_tampered = True
|
||||
log.warning("Declared filesize ({}) is smaller than total file size ({}). "
|
||||
logger.warning("Declared filesize ({}) is smaller than total file size ({}). "
|
||||
"Was something appended to the file? Trying to parse it anyways.".format(self.filesize, self.buff.size()))
|
||||
|
||||
# Not that severe of an error, we have plenty files where this is not
|
||||
# set correctly
|
||||
if axml_header.type != RES_XML_TYPE:
|
||||
self.axml_tampered = True
|
||||
log.warning("AXML file has an unusual resource type! "
|
||||
logger.warning("AXML file has an unusual resource type! "
|
||||
"Malware likes to to such stuff to anti androguard! "
|
||||
"But we try to parse it anyways. Resource Type: 0x{:04x}".format(axml_header.type))
|
||||
|
||||
@ -432,12 +434,12 @@ class AXMLParser:
|
||||
try:
|
||||
header = ARSCHeader(self.buff, expected_type=RES_STRING_POOL_TYPE)
|
||||
except ResParserError as e:
|
||||
log.error("Error parsing resource header of string pool: %s", e)
|
||||
logger.error("Error parsing resource header of string pool: %s", e)
|
||||
self._valid = False
|
||||
return
|
||||
|
||||
if header.header_size != 0x1C:
|
||||
log.error("This does not look like an AXML file. String chunk header size does not equal 28! header size = {}".format(header.header_size))
|
||||
logger.error("This does not look like an AXML file. String chunk header size does not equal 28! header size = {}".format(header.header_size))
|
||||
self._valid = False
|
||||
return
|
||||
|
||||
@ -455,6 +457,7 @@ class AXMLParser:
|
||||
if an error happend somewhere in the process of parsing the file,
|
||||
this flag is set to False.
|
||||
"""
|
||||
logger.debug(self._valid)
|
||||
return self._valid
|
||||
|
||||
def _reset(self):
|
||||
@ -478,7 +481,7 @@ class AXMLParser:
|
||||
self._reset()
|
||||
while self._valid:
|
||||
# Stop at the declared filesize or at the end of the file
|
||||
if self.buff.end() or self.buff.get_idx() == self.filesize:
|
||||
if self.buff.tell() == self.filesize:
|
||||
self.m_event = END_DOCUMENT
|
||||
break
|
||||
|
||||
@ -486,18 +489,18 @@ class AXMLParser:
|
||||
try:
|
||||
h = ARSCHeader(self.buff)
|
||||
except ResParserError as e:
|
||||
log.error("Error parsing resource header: %s", e)
|
||||
logger.error("Error parsing resource header: %s", e)
|
||||
self._valid = False
|
||||
return
|
||||
|
||||
# Special chunk: Resource Map. This chunk might be contained inside
|
||||
# the file, after the string pool.
|
||||
if h.type == RES_XML_RESOURCE_MAP_TYPE:
|
||||
log.debug("AXML contains a RESOURCE MAP")
|
||||
logger.debug("AXML contains a RESOURCE MAP")
|
||||
# Check size: < 8 bytes mean that the chunk is not complete
|
||||
# Should be aligned to 4 bytes.
|
||||
if h.size < 8 or (h.size % 4) != 0:
|
||||
log.error("Invalid chunk size in chunk XML_RESOURCE_MAP")
|
||||
logger.error("Invalid chunk size in chunk XML_RESOURCE_MAP")
|
||||
self._valid = False
|
||||
return
|
||||
|
||||
@ -512,13 +515,13 @@ class AXMLParser:
|
||||
# h.size is the size of the whole chunk including the header.
|
||||
# We read already 8 bytes of the header, thus we need to
|
||||
# subtract them.
|
||||
log.error("Not a XML resource chunk type: 0x{:04x}. Skipping {} bytes".format(h.type, h.size))
|
||||
self.buff.set_idx(h.end)
|
||||
logger.error("Not a XML resource chunk type: 0x{:04x}. Skipping {} bytes".format(h.type, h.size))
|
||||
self.buff.seek(h.end)
|
||||
continue
|
||||
|
||||
# Check that we read a correct header
|
||||
if h.header_size != 0x10:
|
||||
log.error("XML Resource Type Chunk header size does not match 16! " \
|
||||
logger.error("XML Resource Type Chunk header size does not match 16! " \
|
||||
"At chunk type 0x{:04x}, declared header size={}, chunk size={}".format(h.type, h.header_size, h.size))
|
||||
self._valid = False
|
||||
return
|
||||
@ -530,7 +533,7 @@ class AXMLParser:
|
||||
self.m_comment_index, = unpack('<L', self.buff.read(4))
|
||||
|
||||
if self.m_comment_index != 0xFFFFFFFF and h.type in [RES_XML_START_NAMESPACE_TYPE, RES_XML_END_NAMESPACE_TYPE]:
|
||||
log.warning("Unhandled Comment at namespace chunk: '{}'".format(self.sb[self.m_comment_index]))
|
||||
logger.warning("Unhandled Comment at namespace chunk: '{}'".format(self.sb[self.m_comment_index]))
|
||||
|
||||
if h.type == RES_XML_START_NAMESPACE_TYPE:
|
||||
prefix, = unpack('<L', self.buff.read(4))
|
||||
@ -539,14 +542,14 @@ class AXMLParser:
|
||||
s_prefix = self.sb[prefix]
|
||||
s_uri = self.sb[uri]
|
||||
|
||||
log.debug("Start of Namespace mapping: prefix {}: '{}' --> uri {}: '{}'".format(prefix, s_prefix, uri, s_uri))
|
||||
logger.debug("Start of Namespace mapping: prefix {}: '{}' --> uri {}: '{}'".format(prefix, s_prefix, uri, s_uri))
|
||||
|
||||
if s_uri == '':
|
||||
log.warning("Namespace prefix '{}' resolves to empty URI. "
|
||||
logger.warning("Namespace prefix '{}' resolves to empty URI. "
|
||||
"This might be a packer.".format(s_prefix))
|
||||
|
||||
if (prefix, uri) in self.namespaces:
|
||||
log.info("Namespace mapping ({}, {}) already seen! "
|
||||
logger.info("Namespace mapping ({}, {}) already seen! "
|
||||
"This is usually not a problem but could indicate packers or broken AXML compilers.".format(prefix, uri))
|
||||
self.namespaces.append((prefix, uri))
|
||||
|
||||
@ -563,7 +566,7 @@ class AXMLParser:
|
||||
if (prefix, uri) in self.namespaces:
|
||||
self.namespaces.remove((prefix, uri))
|
||||
else:
|
||||
log.warning("Reached a NAMESPACE_END without having the namespace stored before? "
|
||||
logger.warning("Reached a NAMESPACE_END without having the namespace stored before? "
|
||||
"Prefix ID: {}, URI ID: {}".format(prefix, uri))
|
||||
|
||||
# We can continue with the next chunk, as we store the namespace
|
||||
@ -640,7 +643,7 @@ class AXMLParser:
|
||||
# For now, we ingore these values
|
||||
size, res0, dataType, data = unpack("<HBBL", self.buff.read(8))
|
||||
|
||||
log.debug("found a CDATA Chunk: "
|
||||
logger.debug("found a CDATA Chunk: "
|
||||
"index={: 6d}, size={: 4d}, res0={: 4d}, dataType={: 4d}, data={: 4d}".format(self.m_name,
|
||||
size,
|
||||
res0,
|
||||
@ -651,8 +654,8 @@ class AXMLParser:
|
||||
break
|
||||
|
||||
# Still here? Looks like we read an unknown XML header, try to skip it...
|
||||
log.warning("Unknown XML Chunk: 0x{:04x}, skipping {} bytes.".format(h.type, h.size))
|
||||
self.buff.set_idx(h.end)
|
||||
logger.warning("Unknown XML Chunk: 0x{:04x}, skipping {} bytes.".format(h.type, h.size))
|
||||
self.buff.seek(h.end)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@ -753,11 +756,11 @@ class AXMLParser:
|
||||
Return the start inside the m_attributes array for a given attribute
|
||||
"""
|
||||
if self.m_event != START_TAG:
|
||||
log.warning("Current event is not START_TAG.")
|
||||
logger.warning("Current event is not START_TAG.")
|
||||
|
||||
offset = index * ATTRIBUTE_LENGHT
|
||||
if offset >= len(self.m_attributes):
|
||||
log.warning("Invalid attribute index")
|
||||
logger.warning("Invalid attribute index")
|
||||
|
||||
return offset
|
||||
|
||||
@ -775,6 +778,8 @@ class AXMLParser:
|
||||
"""
|
||||
Returns the numeric ID for the namespace URI of an attribute
|
||||
"""
|
||||
logger.debug(index)
|
||||
|
||||
offset = self._get_attribute_offset(index)
|
||||
uri = self.m_attributes[offset + ATTRIBUTE_IX_NAMESPACE_URI]
|
||||
|
||||
@ -784,6 +789,8 @@ class AXMLParser:
|
||||
"""
|
||||
Return the Namespace URI (if any) for the attribute
|
||||
"""
|
||||
logger.debug(index)
|
||||
|
||||
uri = self.getAttributeUri(index)
|
||||
|
||||
# No Namespace
|
||||
@ -796,6 +803,7 @@ class AXMLParser:
|
||||
"""
|
||||
Returns the String which represents the attribute name
|
||||
"""
|
||||
logger.debug(index)
|
||||
offset = self._get_attribute_offset(index)
|
||||
name = self.m_attributes[offset + ATTRIBUTE_IX_NAME]
|
||||
|
||||
@ -818,6 +826,8 @@ class AXMLParser:
|
||||
|
||||
:param index: index of the attribute
|
||||
"""
|
||||
logger.debug(index)
|
||||
|
||||
offset = self._get_attribute_offset(index)
|
||||
return self.m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE]
|
||||
|
||||
@ -827,6 +837,8 @@ class AXMLParser:
|
||||
|
||||
:param index: index of the attribute
|
||||
"""
|
||||
logger.debug(index)
|
||||
|
||||
offset = self._get_attribute_offset(index)
|
||||
return self.m_attributes[offset + ATTRIBUTE_IX_VALUE_DATA]
|
||||
|
||||
@ -839,6 +851,8 @@ class AXMLParser:
|
||||
:param index: index of the attribute
|
||||
:return:
|
||||
"""
|
||||
logger.debug(index)
|
||||
|
||||
offset = self._get_attribute_offset(index)
|
||||
valueType = self.m_attributes[offset + ATTRIBUTE_IX_VALUE_TYPE]
|
||||
if valueType == TYPE_STRING:
|
||||
@ -929,11 +943,11 @@ class AXMLPrinter:
|
||||
comment = self.axml.comment
|
||||
if comment:
|
||||
if self.root is None:
|
||||
log.warning("Can not attach comment with content '{}' without root!".format(comment))
|
||||
logger.warning("Can not attach comment with content '{}' without root!".format(comment))
|
||||
else:
|
||||
cur[-1].append(etree.Comment(comment))
|
||||
|
||||
log.debug("START_TAG: {} (line={})".format(tag, self.axml.m_lineNumber))
|
||||
logger.debug("START_TAG: {} (line={})".format(tag, self.axml.m_lineNumber))
|
||||
elem = etree.Element(tag, nsmap=self.axml.nsmap)
|
||||
|
||||
for i in range(self.axml.getAttributeCount()):
|
||||
@ -941,9 +955,9 @@ class AXMLPrinter:
|
||||
uri, name = self._fix_name(uri, self.axml.getAttributeName(i))
|
||||
value = self._fix_value(self._get_attribute_value(i))
|
||||
|
||||
log.debug("found an attribute: {}{}='{}'".format(uri, name, value.encode("utf-8")))
|
||||
logger.debug("found an attribute: {}{}='{}'".format(uri, name, value.encode("utf-8")))
|
||||
if "{}{}".format(uri, name) in elem.attrib:
|
||||
log.warning("Duplicate attribute '{}{}'! Will overwrite!".format(uri, name))
|
||||
logger.warning("Duplicate attribute '{}{}'! Will overwrite!".format(uri, name))
|
||||
elem.set("{}{}".format(uri, name), value)
|
||||
|
||||
if self.root is None:
|
||||
@ -951,28 +965,28 @@ class AXMLPrinter:
|
||||
else:
|
||||
if not cur:
|
||||
# looks like we lost the root?
|
||||
log.error("No more elements available to attach to! Is the XML malformed?")
|
||||
logger.error("No more elements available to attach to! Is the XML malformed?")
|
||||
break
|
||||
cur[-1].append(elem)
|
||||
cur.append(elem)
|
||||
|
||||
if _type == END_TAG:
|
||||
if not cur:
|
||||
log.warning("Too many END_TAG! No more elements available to attach to!")
|
||||
logger.warning("Too many END_TAG! No more elements available to attach to!")
|
||||
|
||||
name = self.axml.name
|
||||
uri = self._print_namespace(self.axml.namespace)
|
||||
tag = "{}{}".format(uri, name)
|
||||
if cur[-1].tag != tag:
|
||||
log.warning("Closing tag '{}' does not match current stack! At line number: {}. Is the XML malformed?".format(self.axml.name, self.axml.m_lineNumber))
|
||||
logger.warning("Closing tag '{}' does not match current stack! At line number: {}. Is the XML malformed?".format(self.axml.name, self.axml.m_lineNumber))
|
||||
cur.pop()
|
||||
if _type == TEXT:
|
||||
log.debug("TEXT for {}".format(cur[-1]))
|
||||
logger.debug("TEXT for {}".format(cur[-1]))
|
||||
cur[-1].text = self.axml.text
|
||||
if _type == END_DOCUMENT:
|
||||
# Check if all namespace mappings are closed
|
||||
if len(self.axml.namespaces) > 0:
|
||||
log.warning("Not all namespace mappings were closed! Malformed AXML?")
|
||||
logger.warning("Not all namespace mappings were closed! Malformed AXML?")
|
||||
break
|
||||
|
||||
def get_buff(self):
|
||||
@ -1055,13 +1069,13 @@ class AXMLPrinter:
|
||||
:rtype: tuple
|
||||
"""
|
||||
if not name[0].isalpha() and name[0] != "_":
|
||||
log.warning("Invalid start for name '{}'. "
|
||||
logger.warning("Invalid start for name '{}'. "
|
||||
"XML name must start with a letter.".format(name))
|
||||
self.packerwarning = True
|
||||
name = "_{}".format(name)
|
||||
if name.startswith("android:") and prefix == '' and 'android' in self.axml.nsmap:
|
||||
# Seems be a common thing...
|
||||
log.info("Name '{}' starts with 'android:' prefix but 'android' is a known prefix. Replacing prefix.".format(name))
|
||||
logger.info("Name '{}' starts with 'android:' prefix but 'android' is a known prefix. Replacing prefix.".format(name))
|
||||
prefix = self._print_namespace(self.axml.nsmap['android'])
|
||||
name = name[len("android:"):]
|
||||
# It looks like this is some kind of packer... Not sure though.
|
||||
@ -1070,15 +1084,15 @@ class AXMLPrinter:
|
||||
self.packerwarning = True
|
||||
embedded_prefix, new_name = name.split(":", 1)
|
||||
if embedded_prefix in self.axml.nsmap:
|
||||
log.info("Prefix '{}' is in namespace mapping, assume that it is a prefix.")
|
||||
logger.info("Prefix '{}' is in namespace mapping, assume that it is a prefix.")
|
||||
prefix = self._print_namespace(self.axml.nsmap[embedded_prefix])
|
||||
name = new_name
|
||||
else:
|
||||
# Print out an extra warning
|
||||
log.warning("Confused: name contains a unknown namespace prefix: '{}'. "
|
||||
logger.warning("Confused: name contains a unknown namespace prefix: '{}'. "
|
||||
"This is either a broken AXML file or some attempt to break stuff.".format(name))
|
||||
if not re.match(r"^[a-zA-Z0-9._-]*$", name):
|
||||
log.warning("Name '{}' contains invalid characters!".format(name))
|
||||
logger.warning("Name '{}' contains invalid characters!".format(name))
|
||||
self.packerwarning = True
|
||||
name = re.sub(r"[^a-zA-Z0-9._-]", "_", name)
|
||||
|
||||
@ -1102,14 +1116,14 @@ class AXMLPrinter:
|
||||
# Reading string until \x00. This is the same as aapt does.
|
||||
if "\x00" in value:
|
||||
self.packerwarning = True
|
||||
log.warning("Null byte found in attribute value at position {}: "
|
||||
logger.warning("Null byte found in attribute value at position {}: "
|
||||
"Value(hex): '{}'".format(
|
||||
value.find("\x00"),
|
||||
binascii.hexlify(value.encode("utf-8"))))
|
||||
value = value[:value.find("\x00")]
|
||||
|
||||
if not self.__charrange.match(value):
|
||||
log.warning("Invalid character in value found. Replacing with '_'.")
|
||||
logger.warning("Invalid character in value found. Replacing with '_'.")
|
||||
self.packerwarning = True
|
||||
value = self.__replacement.sub('_', value)
|
||||
return value
|
||||
@ -1207,9 +1221,10 @@ class ARSCParser:
|
||||
"""
|
||||
:param bytes raw_buff: the raw bytes of the file
|
||||
"""
|
||||
self.buff = bytecode.BuffHandle(raw_buff)
|
||||
self.buff = io.BufferedReader(io.BytesIO(raw_buff))
|
||||
self.buff_size = self.buff.raw.getbuffer().nbytes
|
||||
|
||||
if self.buff.size() < 8 or self.buff.size() > 0xFFFFFFFF:
|
||||
if self.buff_size < 8 or self.buff_size > 0xFFFFFFFF:
|
||||
raise ResParserError("Invalid file size {} for a resources.arsc file!".format(self.buff.size()))
|
||||
|
||||
self.analyzed = False
|
||||
@ -1226,43 +1241,43 @@ class ARSCParser:
|
||||
|
||||
# More sanity checks...
|
||||
if self.header.header_size != 12:
|
||||
log.warning("The ResTable_header has an unexpected header size! Expected 12 bytes, got {}.".format(self.header.header_size))
|
||||
logger.warning("The ResTable_header has an unexpected header size! Expected 12 bytes, got {}.".format(self.header.header_size))
|
||||
|
||||
if self.header.size > self.buff.size():
|
||||
raise ResParserError("The file seems to be truncated. Refuse to parse the file! Filesize: {}, declared size: {}".format(self.buff.size(), self.header.size))
|
||||
if self.header.size > self.buff_size:
|
||||
raise ResParserError("The file seems to be truncated. Refuse to parse the file! Filesize: {}, declared size: {}".format(self.buff_size, self.header.size))
|
||||
|
||||
if self.header.size < self.buff.size():
|
||||
log.warning("The Resource file seems to have data appended to it. Filesize: {}, declared size: {}".format(self.buff.size(), self.header.size))
|
||||
if self.header.size < self.buff_size:
|
||||
logger.warning("The Resource file seems to have data appended to it. Filesize: {}, declared size: {}".format(self.buff_size, self.header.size))
|
||||
|
||||
# The ResTable_header contains the packageCount, i.e. the number of ResTable_package
|
||||
self.packageCount = unpack('<I', self.buff.read(4))[0]
|
||||
|
||||
# Even more sanity checks...
|
||||
if self.packageCount < 1:
|
||||
log.warning("The number of packages is smaller than one. There should be at least one package!")
|
||||
logger.warning("The number of packages is smaller than one. There should be at least one package!")
|
||||
|
||||
log.debug("Parsed ResTable_header with {} package(s) inside.".format(self.packageCount))
|
||||
logger.debug("Parsed ResTable_header with {} package(s) inside.".format(self.packageCount))
|
||||
|
||||
# skip to the start of the first chunk's data, skipping trailing header bytes (there should be none)
|
||||
self.buff.set_idx(self.header.start + self.header.header_size)
|
||||
self.buff.seek(self.header.start + self.header.header_size)
|
||||
|
||||
# Now parse the data:
|
||||
# We should find one ResStringPool_header and one or more ResTable_package chunks inside
|
||||
while self.buff.get_idx() <= self.header.end - ARSCHeader.SIZE:
|
||||
while self.buff.tell() <= self.header.end - ARSCHeader.SIZE:
|
||||
res_header = ARSCHeader(self.buff)
|
||||
|
||||
if res_header.end > self.header.end:
|
||||
# this inner chunk crosses the boundary of the table chunk
|
||||
log.warning("Invalid chunk found! It is larger than the outer chunk: %s", res_header)
|
||||
logger.warning("Invalid chunk found! It is larger than the outer chunk: %s", res_header)
|
||||
break
|
||||
|
||||
if res_header.type == RES_STRING_POOL_TYPE:
|
||||
# There should be only one StringPool per resource table.
|
||||
if self.stringpool_main:
|
||||
log.warning("Already found a ResStringPool_header, but there should be only one! Will not parse the Pool again.")
|
||||
logger.warning("Already found a ResStringPool_header, but there should be only one! Will not parse the Pool again.")
|
||||
else:
|
||||
self.stringpool_main = StringBlock(self.buff, res_header)
|
||||
log.debug("Found the main string pool: %s", self.stringpool_main)
|
||||
logger.debug("Found the main string pool: %s", self.stringpool_main)
|
||||
|
||||
elif res_header.type == RES_TABLE_PACKAGE_TYPE:
|
||||
if len(self.packages) > self.packageCount:
|
||||
@ -1272,12 +1287,12 @@ class ARSCParser:
|
||||
package_name = current_package.get_name()
|
||||
|
||||
# After the Header, we have the resource type symbol table
|
||||
self.buff.set_idx(current_package.header.start + current_package.typeStrings)
|
||||
self.buff.seek(current_package.header.start + current_package.typeStrings)
|
||||
type_sp_header = ARSCHeader(self.buff, expected_type=RES_STRING_POOL_TYPE)
|
||||
mTableStrings = StringBlock(self.buff, type_sp_header)
|
||||
|
||||
# Next, we should have the resource key symbol table
|
||||
self.buff.set_idx(current_package.header.start + current_package.keyStrings)
|
||||
self.buff.seek(current_package.header.start + current_package.keyStrings)
|
||||
key_sp_header = ARSCHeader(self.buff, expected_type=RES_STRING_POOL_TYPE)
|
||||
mKeyStrings = StringBlock(self.buff, key_sp_header)
|
||||
|
||||
@ -1287,7 +1302,7 @@ class ARSCParser:
|
||||
self.packages[package_name].append(mKeyStrings)
|
||||
|
||||
pc = PackageContext(current_package, self.stringpool_main, mTableStrings, mKeyStrings)
|
||||
log.debug("Constructed a PackageContext: %s", pc)
|
||||
logger.debug("Constructed a PackageContext: %s", pc)
|
||||
|
||||
# skip to the first header in this table package chunk
|
||||
# FIXME is this correct? We have already read the first two sections!
|
||||
@ -1299,18 +1314,18 @@ class ARSCParser:
|
||||
|
||||
if next_idx != self.buff.tell():
|
||||
# If this happens, we have a testfile ;)
|
||||
log.error("This looks like an odd resources.arsc file!")
|
||||
log.error("Please report this error including the file you have parsed!")
|
||||
log.error("next_idx = {}, current buffer position = {}".format(next_idx, self.buff.tell()))
|
||||
log.error("Please open a issue at https://github.com/androguard/androguard/issues")
|
||||
log.error("Thank you!")
|
||||
logger.error("This looks like an odd resources.arsc file!")
|
||||
logger.error("Please report this error including the file you have parsed!")
|
||||
logger.error("next_idx = {}, current buffer position = {}".format(next_idx, self.buff.tell()))
|
||||
logger.error("Please open a issue at https://github.com/androguard/androguard/issues")
|
||||
logger.error("Thank you!")
|
||||
|
||||
self.buff.set_idx(next_idx)
|
||||
self.buff.seek(next_idx)
|
||||
|
||||
# Read all other headers
|
||||
while self.buff.get_idx() <= res_header.end - ARSCHeader.SIZE:
|
||||
while self.buff.tell() <= res_header.end - ARSCHeader.SIZE:
|
||||
pkg_chunk_header = ARSCHeader(self.buff)
|
||||
log.debug("Found a header: {}".format(pkg_chunk_header))
|
||||
logger.debug("Found a header: {}".format(pkg_chunk_header))
|
||||
if pkg_chunk_header.start + pkg_chunk_header.size > res_header.end:
|
||||
# we are way off the package chunk; bail out
|
||||
break
|
||||
@ -1327,7 +1342,7 @@ class ARSCParser:
|
||||
self.packages[package_name].append(a_res_type)
|
||||
self.resource_configs[package_name][a_res_type].add(a_res_type.config)
|
||||
|
||||
log.debug("Config: {}".format(a_res_type.config))
|
||||
logger.debug("Config: {}".format(a_res_type.config))
|
||||
|
||||
entries = []
|
||||
for i in range(0, a_res_type.entryCount):
|
||||
@ -1337,9 +1352,6 @@ class ARSCParser:
|
||||
self.packages[package_name].append(entries)
|
||||
|
||||
for entry, res_id in entries:
|
||||
if self.buff.end():
|
||||
break
|
||||
|
||||
if entry != -1:
|
||||
ate = ARSCResTableEntry(self.buff, res_id, pc)
|
||||
self.packages[package_name].append(ate)
|
||||
@ -1351,21 +1363,21 @@ class ARSCParser:
|
||||
# So we do some kind of hack here. We set the idx to the entry again...
|
||||
# Now we will read all entries!
|
||||
# Not sure if this is a good solution though
|
||||
self.buff.set_idx(ate.start)
|
||||
self.buff.seek(ate.start)
|
||||
elif pkg_chunk_header.type == RES_TABLE_LIBRARY_TYPE:
|
||||
log.warning("RES_TABLE_LIBRARY_TYPE chunk is not supported")
|
||||
logger.warning("RES_TABLE_LIBRARY_TYPE chunk is not supported")
|
||||
else:
|
||||
# Unknown / not-handled chunk type
|
||||
log.warning("Unknown chunk type encountered inside RES_TABLE_PACKAGE: %s", pkg_chunk_header)
|
||||
logger.warning("Unknown chunk type encountered inside RES_TABLE_PACKAGE: %s", pkg_chunk_header)
|
||||
|
||||
# skip to the next chunk
|
||||
self.buff.set_idx(pkg_chunk_header.end)
|
||||
self.buff.seek(pkg_chunk_header.end)
|
||||
else:
|
||||
# Unknown / not-handled chunk type
|
||||
log.warning("Unknown chunk type encountered: %s", res_header)
|
||||
logger.warning("Unknown chunk type encountered: %s", res_header)
|
||||
|
||||
# move to the next resource chunk
|
||||
self.buff.set_idx(res_header.end)
|
||||
self.buff.seek(res_header.end)
|
||||
|
||||
def _analyse(self):
|
||||
if self.analyzed:
|
||||
@ -1475,7 +1487,7 @@ class ARSCParser:
|
||||
DIMENSION_UNITS[ate.key.get_data() & COMPLEX_UNIT_MASK])
|
||||
]
|
||||
except IndexError:
|
||||
log.debug("Out of range dimension unit index for {}: {}".format(
|
||||
logger.debug("Out of range dimension unit index for {}: {}".format(
|
||||
complexToFloat(ate.key.get_data()),
|
||||
ate.key.get_data() & COMPLEX_UNIT_MASK))
|
||||
return [ate.get_value(), ate.key.get_data()]
|
||||
@ -1813,7 +1825,7 @@ class ARSCParser:
|
||||
# Infinite loop detection:
|
||||
# TODO should this stay here or should be detect the loop much earlier?
|
||||
if res_id == parent.mResId:
|
||||
log.warning("Infinite loop detected at resource item {}. It references itself!".format(parent))
|
||||
logger.warning("Infinite loop detected at resource item {}. It references itself!".format(parent))
|
||||
return
|
||||
|
||||
self._resolve_into_result(result, item.get_data(), self.wanted_config)
|
||||
@ -1902,7 +1914,7 @@ class ARSCParser:
|
||||
raise ValueError("'rid' must be an int")
|
||||
|
||||
if rid not in self.resource_values:
|
||||
log.warning("The requested rid '0x{:08x}' could not be found in the list of resources.".format(rid))
|
||||
logger.warning("The requested rid '0x{:08x}' could not be found in the list of resources.".format(rid))
|
||||
return []
|
||||
|
||||
res_options = self.resource_values[rid]
|
||||
@ -1910,7 +1922,7 @@ class ARSCParser:
|
||||
if config in res_options:
|
||||
return [(config, res_options[config])]
|
||||
elif fallback and config == ARSCResTableConfig.default_config():
|
||||
log.warning("No default resource config could be found for the given rid '0x{:08x}', using fallback!".format(rid))
|
||||
logger.warning("No default resource config could be found for the given rid '0x{:08x}', using fallback!".format(rid))
|
||||
return [list(self.resource_values[rid].items())[0]]
|
||||
else:
|
||||
return []
|
||||
@ -2074,9 +2086,9 @@ class ARSCHeader:
|
||||
:param androguard.core.bytecode.BuffHandle buff: the buffer set to the position where the header starts.
|
||||
:param int expected_type: the type of the header which is expected.
|
||||
"""
|
||||
self.start = buff.get_idx()
|
||||
self.start = buff.tell()
|
||||
# Make sure we do not read over the buffer:
|
||||
if buff.size() < self.start + self.SIZE:
|
||||
if buff.raw.getbuffer().nbytes < self.start + self.SIZE:
|
||||
raise ResParserError("Can not read over the buffer size! Offset={}".format(self.start))
|
||||
|
||||
self._type, self._header_size, self._size = unpack('<HHL', buff.read(self.SIZE))
|
||||
@ -2148,11 +2160,9 @@ class ARSCResTablePackage:
|
||||
"""
|
||||
def __init__(self, buff, header):
|
||||
self.header = header
|
||||
self.start = buff.get_idx()
|
||||
self.start = buff.tell()
|
||||
self.id = unpack('<I', buff.read(4))[0]
|
||||
# 128 times 16bit -> read 256 bytes
|
||||
# TODO why not read a null terminated string in buffer (like the meth name suggests) instead of parsing it later in get_name()?
|
||||
self.name = buff.readNullString(256)
|
||||
self.name = buff.read(256)
|
||||
self.typeStrings = unpack('<I', buff.read(4))[0]
|
||||
self.lastPublicType = unpack('<I', buff.read(4))[0]
|
||||
self.keyStrings = unpack('<I', buff.read(4))[0]
|
||||
@ -2170,7 +2180,7 @@ class ARSCResTypeSpec:
|
||||
See http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#1327
|
||||
"""
|
||||
def __init__(self, buff, parent=None):
|
||||
self.start = buff.get_idx()
|
||||
self.start = buff.tell()
|
||||
self.parent = parent
|
||||
self.id = unpack('<B', buff.read(1))[0]
|
||||
self.res0 = unpack('<B', buff.read(1))[0]
|
||||
@ -2194,7 +2204,7 @@ class ARSCResType:
|
||||
See http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#1364
|
||||
"""
|
||||
def __init__(self, buff, parent=None):
|
||||
self.start = buff.get_idx()
|
||||
self.start = buff.tell()
|
||||
self.parent = parent
|
||||
|
||||
self.id = unpack('<B', buff.read(1))[0]
|
||||
@ -2211,7 +2221,7 @@ class ARSCResType:
|
||||
|
||||
self.config = ARSCResTableConfig(buff)
|
||||
|
||||
log.debug("Parsed %s", self)
|
||||
logger.debug("Parsed {}".format(self))
|
||||
|
||||
def get_type(self):
|
||||
return self.parent.mTableStrings.getString(self.id - 1)
|
||||
@ -2248,7 +2258,7 @@ class ARSCResTableConfig:
|
||||
|
||||
def __init__(self, buff=None, **kwargs):
|
||||
if buff is not None:
|
||||
self.start = buff.get_idx()
|
||||
self.start = buff.tell()
|
||||
|
||||
# uint32_t
|
||||
self.size = unpack('<I', buff.read(4))[0]
|
||||
@ -2293,7 +2303,7 @@ class ARSCResTableConfig:
|
||||
# uint16_t smallestScreenWidthDp
|
||||
self.screenConfig, = unpack('<I', buff.read(4))
|
||||
else:
|
||||
log.debug("This file does not have a screenConfig! size={}".format(self.size))
|
||||
logger.debug("This file does not have a screenConfig! size={}".format(self.size))
|
||||
self.screenConfig = 0
|
||||
|
||||
if self.size >= 36:
|
||||
@ -2302,7 +2312,7 @@ class ARSCResTableConfig:
|
||||
# uint16_t screenHeightDp
|
||||
self.screenSizeDp, = unpack('<I', buff.read(4))
|
||||
else:
|
||||
log.debug("This file does not have a screenSizeDp! size={}".format(self.size))
|
||||
logger.debug("This file does not have a screenSizeDp! size={}".format(self.size))
|
||||
self.screenSizeDp = 0
|
||||
|
||||
if self.size >= 40:
|
||||
@ -2312,12 +2322,12 @@ class ARSCResTableConfig:
|
||||
# uint16_t screenConfigPad2
|
||||
self.screenConfig2, = unpack("<I", buff.read(4))
|
||||
else:
|
||||
log.debug("This file does not have a screenConfig2! size={}".format(self.size))
|
||||
logger.debug("This file does not have a screenConfig2! size={}".format(self.size))
|
||||
self.screenConfig2 = 0
|
||||
|
||||
self.exceedingSize = self.size - (buff.tell() - self.start)
|
||||
if self.exceedingSize > 0:
|
||||
log.debug("Skipping padding bytes!")
|
||||
logger.debug("Skipping padding bytes!")
|
||||
self.padding = buff.read(self.exceedingSize)
|
||||
|
||||
else:
|
||||
@ -2576,7 +2586,7 @@ class ARSCResTableEntry:
|
||||
FLAG_WEAK = 4
|
||||
|
||||
def __init__(self, buff, mResId, parent=None):
|
||||
self.start = buff.get_idx()
|
||||
self.start = buff.tell()
|
||||
self.mResId = mResId
|
||||
self.parent = parent
|
||||
|
||||
@ -2592,7 +2602,7 @@ class ARSCResTableEntry:
|
||||
self.key = ARSCResStringPoolRef(buff, self.parent)
|
||||
|
||||
if self.is_weak():
|
||||
log.debug("Parsed %s", self)
|
||||
logger.debug("Parsed {}".format(self))
|
||||
|
||||
def get_index(self):
|
||||
return self.index
|
||||
@ -2633,7 +2643,7 @@ class ARSCComplex:
|
||||
and http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#1498 for `ResTable_map`
|
||||
"""
|
||||
def __init__(self, buff, parent=None):
|
||||
self.start = buff.get_idx()
|
||||
self.start = buff.tell()
|
||||
self.parent = parent
|
||||
|
||||
self.id_parent = unpack('<I', buff.read(4))[0]
|
||||
@ -2658,7 +2668,7 @@ class ARSCResStringPoolRef:
|
||||
See: http://androidxref.com/9.0.0_r3/xref/frameworks/base/libs/androidfw/include/androidfw/ResourceTypes.h#262
|
||||
"""
|
||||
def __init__(self, buff, parent=None):
|
||||
self.start = buff.get_idx()
|
||||
self.start = buff.tell()
|
||||
self.parent = parent
|
||||
|
||||
self.size, = unpack("<H", buff.read(2))
|
@ -6,7 +6,7 @@ import json
|
||||
import logging
|
||||
|
||||
from androguard.core.androconf import CONF, color_range
|
||||
from androguard.core.bytecodes.dvm_types import Kind, Operand
|
||||
from androguard.core.dex.dvm_types import Kind, Operand
|
||||
|
||||
log = logging.getLogger("androguard.bytecode")
|
||||
|
||||
@ -696,184 +696,6 @@ def object_to_bytes(obj):
|
||||
return obj.get_raw()
|
||||
|
||||
|
||||
class BuffHandle:
|
||||
"""
|
||||
BuffHandle is a wrapper around bytes.
|
||||
It gives the ability to jump in the byte stream, just like with BytesIO.
|
||||
"""
|
||||
|
||||
def __init__(self, buff):
|
||||
self.__buff = bytearray(buff)
|
||||
self.__idx = 0
|
||||
|
||||
def __getitem__(self, item):
|
||||
"""
|
||||
Get the byte at the position `item`
|
||||
|
||||
:param int item: offset in the buffer
|
||||
:returns: byte at the position
|
||||
:rtype: int
|
||||
"""
|
||||
return self.__buff[item]
|
||||
|
||||
def __len__(self):
|
||||
return self.size()
|
||||
|
||||
def size(self):
|
||||
"""
|
||||
Get the total size of the buffer
|
||||
|
||||
:rtype: int
|
||||
"""
|
||||
return len(self.__buff)
|
||||
|
||||
def length_buff(self):
|
||||
"""
|
||||
Alias for :meth:`size`
|
||||
"""
|
||||
return self.size()
|
||||
|
||||
def set_idx(self, idx):
|
||||
"""
|
||||
Set the current offset in the buffer
|
||||
|
||||
:param int idx: offset to set
|
||||
"""
|
||||
self.__idx = idx
|
||||
|
||||
def get_idx(self):
|
||||
"""
|
||||
Get the current offset in the buffer
|
||||
|
||||
:rtype: int
|
||||
"""
|
||||
return self.__idx
|
||||
|
||||
def add_idx(self, idx):
|
||||
"""
|
||||
Advance the current offset by `idx`
|
||||
|
||||
:param int idx: number of bytes to advance
|
||||
"""
|
||||
self.__idx += idx
|
||||
|
||||
def tell(self):
|
||||
"""
|
||||
Alias for :meth:`get_idx`.
|
||||
|
||||
:rtype: int
|
||||
"""
|
||||
return self.__idx
|
||||
|
||||
def readNullString(self, size):
|
||||
"""
|
||||
Read a String with length `size` at the current offset
|
||||
|
||||
:param int size: length of the string
|
||||
:rtype: bytearray
|
||||
"""
|
||||
data = self.read(size)
|
||||
return data
|
||||
|
||||
def read_b(self, size):
|
||||
"""
|
||||
Read bytes with length `size` without incrementing the current offset
|
||||
|
||||
:param int size: length to read in bytes
|
||||
:rtype: bytearray
|
||||
"""
|
||||
return self.__buff[self.__idx:self.__idx + size]
|
||||
|
||||
def peek(self, size):
|
||||
"""
|
||||
Alias for :meth:`read_b`
|
||||
"""
|
||||
return self.read_b(size)
|
||||
|
||||
def read_at(self, offset, size):
|
||||
"""
|
||||
Read bytes from the given offset with length `size` without incrementing
|
||||
the current offset
|
||||
|
||||
:param int offset: offset to start reading
|
||||
:param int size: length of bytes to read
|
||||
:rtype: bytearray
|
||||
"""
|
||||
return self.__buff[offset:offset + size]
|
||||
|
||||
def readat(self, off):
|
||||
"""
|
||||
Read all bytes from the start of `off` until the end of the buffer
|
||||
|
||||
This method can be used to determine a checksum of a buffer from a given
|
||||
point on.
|
||||
|
||||
:param int off: starting offset
|
||||
:rtype: bytearray
|
||||
"""
|
||||
return self.__buff[off:]
|
||||
|
||||
def read(self, size):
|
||||
"""
|
||||
Read from the current offset a total number of `size` bytes
|
||||
and increment the offset by `size`
|
||||
|
||||
:param int size: length of bytes to read
|
||||
:rtype: bytearray
|
||||
"""
|
||||
buff = self.__buff[self.__idx:self.__idx + size]
|
||||
self.__idx += size
|
||||
|
||||
return buff
|
||||
|
||||
def end(self):
|
||||
"""
|
||||
Test if the current offset is at the end or over the buffer boundary
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return self.__idx >= len(self.__buff)
|
||||
|
||||
def get_buff(self):
|
||||
"""
|
||||
Return the whole buffer
|
||||
|
||||
:rtype: bytearray
|
||||
"""
|
||||
return self.__buff
|
||||
|
||||
def set_buff(self, buff):
|
||||
"""
|
||||
Overwrite the current buffer with the content of `buff`
|
||||
|
||||
:param bytearray buff: the new buffer
|
||||
"""
|
||||
self.__buff = buff
|
||||
|
||||
def save(self, filename):
|
||||
"""
|
||||
Save the current buffer to `filename`
|
||||
|
||||
Exisiting files with the same name will be overwritten.
|
||||
|
||||
:param str filename: the name of the file to save to
|
||||
"""
|
||||
with open(filename, "wb") as fd:
|
||||
fd.write(self.__buff)
|
||||
|
||||
|
||||
class Buff:
|
||||
def __init__(self, offset, buff):
|
||||
self.offset = offset
|
||||
self.buff = buff
|
||||
|
||||
self.size = len(buff)
|
||||
|
||||
|
||||
# Here for legacy reasons. Might get removed some day...
|
||||
_Bytecode = BuffHandle
|
||||
|
||||
|
||||
def FormatClassToJava(i):
|
||||
"""
|
||||
Transform a java class name into the typed variant found in DEX files.
|
||||
|
@ -1,4 +1,5 @@
|
||||
import sys
|
||||
import io
|
||||
import re
|
||||
import struct
|
||||
import binascii
|
||||
@ -9,13 +10,15 @@ import warnings
|
||||
import zlib
|
||||
import hashlib
|
||||
from enum import IntEnum
|
||||
from loguru import logger
|
||||
|
||||
from androguard.core import bytecode
|
||||
from androguard.core.bytecodes.apk import APK
|
||||
from androguard.core.apk import APK
|
||||
from androguard.core.androconf import CONF
|
||||
from androguard.util import read_at
|
||||
|
||||
from androguard.core import mutf8
|
||||
from androguard.core.bytecodes.dvm_types import (
|
||||
from .dvm_types import (
|
||||
TypeMapItem,
|
||||
ACCESS_FLAGS,
|
||||
TYPE_DESCRIPTOR,
|
||||
@ -23,10 +26,9 @@ from androguard.core.bytecodes.dvm_types import (
|
||||
Operand,
|
||||
)
|
||||
|
||||
logger.add(sys.stderr, format="{time} {level} {message}", filter="dex", level="INFO")
|
||||
|
||||
|
||||
log = logging.getLogger("androguard.dvm")
|
||||
|
||||
# TODO: have some more generic magic...
|
||||
DEX_FILE_MAGIC_35 = b'dex\n035\x00'
|
||||
DEX_FILE_MAGIC_36 = b'dex\n036\x00'
|
||||
@ -109,8 +111,8 @@ def read_null_terminated_string(f):
|
||||
if 0 in z:
|
||||
s = z.split(b'\x00',1)
|
||||
x.append(s[0])
|
||||
idx = f.get_idx()
|
||||
f.set_idx(idx - len(s[1]))
|
||||
idx = f.tell()
|
||||
f.seek(idx - len(s[1]))
|
||||
break
|
||||
else:
|
||||
x.append(z)
|
||||
@ -230,7 +232,7 @@ def readuleb128(cm, buff):
|
||||
if cur > 0x7f:
|
||||
cur = get_byte(cm, buff)
|
||||
if cur > 0x0f:
|
||||
log.warning("possible error while decoding number")
|
||||
logger.warning("possible error while decoding number")
|
||||
result |= cur << 28
|
||||
|
||||
return result
|
||||
@ -377,7 +379,7 @@ def determineNext(i, cur_idx, m):
|
||||
# emit an extra nop instruction as a spacer if such an instruction would otherwise be unaligned."
|
||||
padding = (off + cur_idx) % 4
|
||||
if padding != 0:
|
||||
log.warning("Switch payload not aligned, assume stuff and add {} bytes...".format(padding))
|
||||
logger.warning("Switch payload not aligned, assume stuff and add {} bytes...".format(padding))
|
||||
data = code.get_ins_off(off + cur_idx + padding)
|
||||
|
||||
# TODO: some malware points to invalid code
|
||||
@ -387,7 +389,7 @@ def determineNext(i, cur_idx, m):
|
||||
for target in data.get_targets():
|
||||
x.append(target * 2 + cur_idx)
|
||||
else:
|
||||
log.warning("Could not determine payload of switch command at offset {} inside {}! "
|
||||
logger.warning("Could not determine payload of switch command at offset {} inside {}! "
|
||||
"Possibly broken bytecode?".format(cur_idx, m))
|
||||
|
||||
return x
|
||||
@ -460,23 +462,25 @@ class HeaderItem:
|
||||
Also the Adler32 checksum of the file is calculated in order to detect file
|
||||
corruption.
|
||||
:param buff: a string which represents a Buff object of the header_item
|
||||
:type androguard.core.bytecode.BuffHandle buff: Buff object
|
||||
:type io.BufferedReader buff: Buff object
|
||||
:param cm: a ClassManager object
|
||||
:type cm: :class:`ClassManager`
|
||||
"""
|
||||
|
||||
def __init__(self, size, buff, cm):
|
||||
logger.debug("HeaderItem")
|
||||
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
if self.offset != 0:
|
||||
log.warning("Unusual DEX file, does not have the header at offset 0")
|
||||
logger.warning("Unusual DEX file, does not have the header at offset 0")
|
||||
|
||||
if len(buff) < self.get_length():
|
||||
if buff.raw.getbuffer().nbytes < self.get_length():
|
||||
raise ValueError("Not a DEX file, Header too small.")
|
||||
|
||||
self.endian_tag, = unpack('<I', buff.read_at(40, 4))
|
||||
self.endian_tag, = unpack('<I', read_at(buff, 40, 4))
|
||||
cm.packer = DalvikPacker(self.endian_tag)
|
||||
|
||||
# Q is actually wrong, but we do not change it here and unpack our own
|
||||
@ -512,15 +516,15 @@ class HeaderItem:
|
||||
try:
|
||||
self.dex_version = int(self.magic[4:7].decode('ascii'), 10)
|
||||
except (UnicodeDecodeError, ValueError):
|
||||
log.warning("Wrong DEX version: {}, trying to parse anyways".format(repr(self.magic)))
|
||||
logger.warning("Wrong DEX version: {}, trying to parse anyways".format(repr(self.magic)))
|
||||
self.dex_version = 35 # assume a common version...
|
||||
|
||||
if zlib.adler32(buff.readat(self.offset + 12)) != self.checksum:
|
||||
if zlib.adler32(read_at(buff, self.offset + 12)) != self.checksum:
|
||||
raise ValueError("Wrong Adler32 checksum for DEX file!")
|
||||
|
||||
if self.file_size != buff.size():
|
||||
if self.file_size != buff.raw.getbuffer().nbytes:
|
||||
# Maybe raise an error here too...
|
||||
log.warning("DEX file size is different to the buffer. Trying to parse anyways.")
|
||||
logger.warning("DEX file size is different to the buffer. Trying to parse anyways.")
|
||||
|
||||
if self.header_size != 0x70:
|
||||
raise ValueError("This is not a DEX file! Wrong header size: '{}'".format(self.header_size))
|
||||
@ -532,7 +536,7 @@ class HeaderItem:
|
||||
raise ValueError("DEX file contains too many ({}) PROTO_IDs to be valid!".format(self.proto_ids_size))
|
||||
|
||||
if self.data_size % 4 != 0:
|
||||
log.warning("data_size is not a multiple of sizeof(uint32_t), but try to parse anyways.")
|
||||
logger.warning("data_size is not a multiple of sizeof(uint32_t), but try to parse anyways.")
|
||||
|
||||
self.map_off_obj = None
|
||||
self.string_off_obj = None
|
||||
@ -700,14 +704,14 @@ class AnnotationSetItem:
|
||||
This class can parse an annotation_set_item of a dex file
|
||||
|
||||
:param buff: a string which represents a Buff object of the annotation_set_item
|
||||
:type androguard.core.bytecode.BuffHandle buff: Buff object
|
||||
:type io.BufferedReader buff: Buff object
|
||||
:param cm: a ClassManager object
|
||||
:type cm: :class:`ClassManager`
|
||||
"""
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.size, = cm.packer["I"].unpack(buff.read(4))
|
||||
self.annotation_off_item = [AnnotationOffItem(buff, cm) for _ in range(self.size)]
|
||||
@ -796,7 +800,7 @@ class AnnotationSetRefList:
|
||||
"""
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.CM = cm
|
||||
self.size, = cm.packer["I"].unpack(buff.read(4))
|
||||
@ -843,7 +847,7 @@ class FieldAnnotation:
|
||||
"""
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.CM = cm
|
||||
self.field_idx, self.annotations_off = cm.packer["2I"].unpack(buff.read(8))
|
||||
@ -900,7 +904,7 @@ class MethodAnnotation:
|
||||
"""
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.CM = cm
|
||||
self.method_idx, \
|
||||
@ -958,7 +962,7 @@ class ParameterAnnotation:
|
||||
"""
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.CM = cm
|
||||
self.method_idx, \
|
||||
@ -1018,7 +1022,7 @@ class AnnotationsDirectoryItem:
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.class_annotations_off, \
|
||||
self.annotated_fields_size, \
|
||||
@ -1170,14 +1174,14 @@ class HiddenApiClassDataItem:
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.section_size, = cm.packer["I"].unpack(buff.read(4))
|
||||
|
||||
# Find the end of the offsets array (first non-zero offset entry is the start of `flags`)
|
||||
offsets_size = 0
|
||||
i = 0
|
||||
while buff.get_idx() - self.offset < self.section_size:
|
||||
while buff.tell() - self.offset < self.section_size:
|
||||
if offsets_size != 0 and i >= offsets_size:
|
||||
break
|
||||
offset, = cm.packer["I"].unpack(buff.read(4))
|
||||
@ -1302,7 +1306,7 @@ class TypeList:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
self.size, = cm.packer["I"].unpack(buff.read(4))
|
||||
|
||||
self.list = [TypeItem(buff, cm) for _ in range(self.size)]
|
||||
@ -1423,7 +1427,7 @@ class DebugInfoItem:
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.line_start = readuleb128(cm, buff)
|
||||
self.parameters_size = readuleb128(cm, buff)
|
||||
@ -1505,10 +1509,11 @@ class DebugInfoItem:
|
||||
i.show()
|
||||
|
||||
def get_raw(self):
|
||||
return [bytecode.Buff(self.__offset, writeuleb128(self.CM, self.line_start) + \
|
||||
writeuleb128(self.CM, self.parameters_size) + \
|
||||
b''.join(writeuleb128(self.CM, i) for i in self.parameter_names) + \
|
||||
b''.join(i.get_raw() for i in self.bytecodes))]
|
||||
pass
|
||||
#return [bytecode.Buff(self.__offset, writeuleb128(self.CM, self.line_start) + \
|
||||
# writeuleb128(self.CM, self.parameters_size) + \
|
||||
# b''.join(writeuleb128(self.CM, i) for i in self.parameter_names) + \
|
||||
# b''.join(i.get_raw() for i in self.bytecodes))]
|
||||
|
||||
def get_off(self):
|
||||
return self.offset
|
||||
@ -1518,7 +1523,7 @@ class DebugInfoItemEmpty:
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
self.__buff = buff
|
||||
self.__raw = ""
|
||||
|
||||
@ -1535,10 +1540,10 @@ class DebugInfoItemEmpty:
|
||||
|
||||
n = self.CM.get_next_offset_item(offset)
|
||||
|
||||
s_idx = self.__buff.get_idx()
|
||||
self.__buff.set_idx(offset)
|
||||
s_idx = self.__buff.tell()
|
||||
self.__buff.seek(offset)
|
||||
self.__raw = self.__buff.read(n - offset)
|
||||
self.__buff.set_idx(s_idx)
|
||||
self.__buff.seek(s_idx)
|
||||
|
||||
def show(self):
|
||||
pass
|
||||
@ -1565,7 +1570,7 @@ class EncodedArray:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.size = readuleb128(cm, buff)
|
||||
|
||||
@ -1667,7 +1672,7 @@ class EncodedValue:
|
||||
else:
|
||||
self.value = False
|
||||
else:
|
||||
log.warning("Unknown value 0x%x" % self.value_type)
|
||||
logger.warning("Unknown value 0x%x" % self.value_type)
|
||||
|
||||
def get_value(self):
|
||||
"""
|
||||
@ -1725,7 +1730,7 @@ class AnnotationElement:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.name_idx = readuleb128(cm, buff)
|
||||
self.value = EncodedValue(buff, cm)
|
||||
@ -1773,7 +1778,7 @@ class EncodedAnnotation:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.type_idx = readuleb128(cm, buff)
|
||||
self.size = readuleb128(cm, buff)
|
||||
@ -1841,7 +1846,7 @@ class AnnotationItem:
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.visibility = get_byte(cm, buff)
|
||||
self.annotation = EncodedAnnotation(buff, cm)
|
||||
@ -1896,7 +1901,7 @@ class EncodedArrayItem:
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
self.value = EncodedArray(buff, cm)
|
||||
|
||||
def get_value(self):
|
||||
@ -1950,7 +1955,7 @@ class StringDataItem:
|
||||
python you ca use :meth:`get` which escapes invalid characters.
|
||||
|
||||
:param buff: a string which represents a Buff object of the string_data_item
|
||||
:type buff: BuffHandle
|
||||
:type buff: io.io.BufferedReader
|
||||
:param cm: a ClassManager object
|
||||
:type cm: :class:`ClassManager`
|
||||
"""
|
||||
@ -1958,7 +1963,7 @@ class StringDataItem:
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
# Content of string_data_item
|
||||
self.utf16_size = readuleb128(cm, buff)
|
||||
@ -2031,7 +2036,7 @@ class StringIdItem:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.string_data_off, = cm.packer["I"].unpack(buff.read(4))
|
||||
|
||||
@ -2079,7 +2084,7 @@ class TypeIdItem:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.descriptor_idx, = cm.packer["I"].unpack(buff.read(4))
|
||||
self.descriptor_idx_value = self.CM.get_string(self.descriptor_idx)
|
||||
@ -2128,7 +2133,7 @@ class TypeHIdItem:
|
||||
def __init__(self, size, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.type = [TypeIdItem(buff, cm) for i in range(0,size)]
|
||||
|
||||
@ -2182,7 +2187,7 @@ class ProtoIdItem:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.shorty_idx, \
|
||||
self.return_type_idx, \
|
||||
@ -2287,7 +2292,7 @@ class ProtoHIdItem:
|
||||
def __init__(self, size, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.proto = [ProtoIdItem(buff, cm) for i in range(0, size)]
|
||||
|
||||
@ -2333,7 +2338,7 @@ class FieldIdItem:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.class_idx, \
|
||||
self.type_idx, \
|
||||
@ -2448,7 +2453,7 @@ class FieldHIdItem:
|
||||
"""
|
||||
|
||||
def __init__(self, size, buff, cm):
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.elem = [FieldIdItem(buff, cm) for i in range(0, size)]
|
||||
|
||||
@ -2499,7 +2504,7 @@ class MethodIdItem:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.class_idx, \
|
||||
self.proto_idx, \
|
||||
@ -2627,7 +2632,7 @@ class MethodHIdItem:
|
||||
def __init__(self, size, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.methods = [MethodIdItem(buff, cm) for i in range(0, size)]
|
||||
|
||||
@ -2735,7 +2740,7 @@ class EncodedField:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.field_idx_diff = readuleb128(cm, buff)
|
||||
self.access_flags = readuleb128(cm, buff)
|
||||
@ -2905,7 +2910,7 @@ class EncodedMethod:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.method_idx_diff = readuleb128(cm, buff) #: method index diff in the corresponding section
|
||||
self.access_flags = readuleb128(cm, buff) #: access flags of the method
|
||||
@ -3361,7 +3366,7 @@ class EncodedMethod:
|
||||
:type idx: int
|
||||
"""
|
||||
if self.code is not None:
|
||||
self.code.set_idx(idx)
|
||||
self.code.seek(idx)
|
||||
|
||||
def set_name(self, value):
|
||||
self.CM.set_hook_method_name(self, value)
|
||||
@ -3391,7 +3396,7 @@ class ClassDataItem:
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.static_fields_size = readuleb128(cm, buff)
|
||||
self.instance_fields_size = readuleb128(cm, buff)
|
||||
@ -3596,7 +3601,7 @@ class ClassDefItem:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.class_idx, \
|
||||
self.access_flags, \
|
||||
@ -3886,17 +3891,17 @@ class ClassHDefItem:
|
||||
def __init__(self, size, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.class_def = []
|
||||
|
||||
for i in range(0, size):
|
||||
idx = buff.get_idx()
|
||||
idx = buff.tell()
|
||||
|
||||
class_def = ClassDefItem(buff, cm)
|
||||
self.class_def.append(class_def)
|
||||
|
||||
buff.set_idx(idx + calcsize("8I"))
|
||||
buff.seek(idx + calcsize("8I"))
|
||||
|
||||
def set_off(self, off):
|
||||
self.offset = off
|
||||
@ -3999,7 +4004,7 @@ class EncodedCatchHandler:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.size = readsleb128(cm, buff)
|
||||
|
||||
@ -4089,7 +4094,7 @@ class EncodedCatchHandlerList:
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.size = readuleb128(cm, buff)
|
||||
self.list = [EncodedCatchHandler(buff, cm) for _ in range(self.size)]
|
||||
@ -6414,7 +6419,7 @@ class LinearSweepAlgorithm:
|
||||
"""
|
||||
Yields all instructions for the given bytecode sequence.
|
||||
If unknown/corrupt/unused instructions are encountered,
|
||||
the loop will stop and an error is written to the log.
|
||||
the loop will stop and an error is written to the logger.
|
||||
|
||||
That means that the bytecode read might be corrupt
|
||||
or was crafted in this way, to break parsers.
|
||||
@ -6431,7 +6436,7 @@ class LinearSweepAlgorithm:
|
||||
|
||||
max_idx = size * calcsize('H')
|
||||
if max_idx > len(insn):
|
||||
log.warning("Declared size of instructions is larger than the bytecode!")
|
||||
logger.warning("Declared size of instructions is larger than the bytecode!")
|
||||
max_idx = len(insn)
|
||||
|
||||
# Get instructions
|
||||
@ -6457,7 +6462,7 @@ class LinearSweepAlgorithm:
|
||||
obj = get_instruction(cm, op_value & 0xff, insn[idx:])
|
||||
except InvalidInstruction as e:
|
||||
# TODO somehow it would be nice to know that the parsing failed at the level of EncodedMethod or for the decompiler
|
||||
log.error("Invalid instruction encountered! Stop parsing bytecode at idx %s. Message: %s", idx, e)
|
||||
logger.error("Invalid instruction encountered! Stop parsing bytecode at idx %s. Message: %s", idx, e)
|
||||
return
|
||||
# emit instruction
|
||||
yield obj
|
||||
@ -6507,7 +6512,7 @@ class DCode:
|
||||
self.insn = insn
|
||||
self.size = len(self.insn)
|
||||
|
||||
def set_idx(self, idx):
|
||||
def seek(self, idx):
|
||||
"""
|
||||
Set the start address of the buffer
|
||||
|
||||
@ -6648,13 +6653,13 @@ class TryItem:
|
||||
This class represents the try_item format
|
||||
|
||||
:param buff: a raw buffer where are the try_item format
|
||||
:type buff: BuffHandle
|
||||
:type buff: io.BufferedReader
|
||||
:param cm: the ClassManager
|
||||
:type cm: ClassManager
|
||||
"""
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.CM = cm
|
||||
|
||||
@ -6706,14 +6711,14 @@ class DalvikCode:
|
||||
This class represents the instructions of a method
|
||||
|
||||
:param buff: a raw buffer where are the instructions
|
||||
:type buff: BuffHandle
|
||||
:type buff: io.BufferedReader
|
||||
:param cm: the ClassManager
|
||||
:type cm: :class:`ClassManager` object
|
||||
"""
|
||||
|
||||
def __init__(self, buff, cm):
|
||||
self.CM = cm
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.registers_size, \
|
||||
self.ins_size, \
|
||||
@ -6724,7 +6729,7 @@ class DalvikCode:
|
||||
|
||||
ushort = calcsize('H')
|
||||
|
||||
self.code = DCode(self.CM, buff.get_idx(), self.insns_size, buff.read(self.insns_size * ushort))
|
||||
self.code = DCode(self.CM, buff.tell(), self.insns_size, buff.read(self.insns_size * ushort))
|
||||
|
||||
if self.insns_size % 2 == 1 and self.tries_size > 0:
|
||||
self.padding, = cm.packer["H"].unpack(buff.read(2))
|
||||
@ -6817,19 +6822,19 @@ class DalvikCode:
|
||||
"""
|
||||
return self.code
|
||||
|
||||
def set_idx(self, idx):
|
||||
self.code.set_idx(idx)
|
||||
def seek(self, idx):
|
||||
self.code.seek(idx)
|
||||
|
||||
def get_length(self):
|
||||
return self.insns_size
|
||||
|
||||
def _begin_show(self):
|
||||
log.debug("registers_size: %d" % self.registers_size)
|
||||
log.debug("ins_size: %d" % self.ins_size)
|
||||
log.debug("outs_size: %d" % self.outs_size)
|
||||
log.debug("tries_size: %d" % self.tries_size)
|
||||
log.debug("debug_info_off: %d" % self.debug_info_off)
|
||||
log.debug("insns_size: %d" % self.insns_size)
|
||||
logger.debug("registers_size: %d" % self.registers_size)
|
||||
logger.debug("ins_size: %d" % self.ins_size)
|
||||
logger.debug("outs_size: %d" % self.outs_size)
|
||||
logger.debug("tries_size: %d" % self.tries_size)
|
||||
logger.debug("debug_info_off: %d" % self.debug_info_off)
|
||||
logger.debug("insns_size: %d" % self.insns_size)
|
||||
|
||||
bytecode._PrintBanner()
|
||||
|
||||
@ -6903,7 +6908,7 @@ class CodeItem:
|
||||
def __init__(self, size, buff, cm):
|
||||
self.CM = cm
|
||||
|
||||
self.offset = buff.get_idx()
|
||||
self.offset = buff.tell()
|
||||
|
||||
self.code = []
|
||||
self.__code_off = {}
|
||||
@ -6912,9 +6917,9 @@ class CodeItem:
|
||||
# As we read the DalvikCode items from the map, there might be
|
||||
# padding bytes in between.
|
||||
# We know, that the alignment is 4 bytes.
|
||||
off = buff.get_idx()
|
||||
off = buff.tell()
|
||||
if off % 4 != 0:
|
||||
buff.set_idx(off + (4 - (off % 4)))
|
||||
buff.seek(off + (4 - (off % 4)))
|
||||
|
||||
x = DalvikCode(buff, cm)
|
||||
self.code.append(x)
|
||||
@ -6966,7 +6971,7 @@ class MapItem:
|
||||
self.CM = cm
|
||||
self.buff = buff
|
||||
|
||||
self.off = buff.get_idx()
|
||||
self.off = buff.tell()
|
||||
|
||||
self.type = TypeMapItem(cm.packer["H"].unpack(buff.read(2))[0])
|
||||
self.unused, \
|
||||
@ -6994,7 +6999,7 @@ class MapItem:
|
||||
return self.size
|
||||
|
||||
def parse(self):
|
||||
log.debug("Starting parsing map_item '{}'".format(self.type.name))
|
||||
logger.debug("Starting parsing map_item '{}'".format(self.type.name))
|
||||
started_at = time.time()
|
||||
|
||||
# Not all items are aligned in the same way. Most are aligned by four bytes,
|
||||
@ -7006,108 +7011,108 @@ class MapItem:
|
||||
|
||||
if TypeMapItem.STRING_ID_ITEM == self.type:
|
||||
# Byte aligned
|
||||
buff.set_idx(self.offset)
|
||||
buff.seek(self.offset)
|
||||
self.item = [StringIdItem(buff, cm) for _ in range(self.size)]
|
||||
|
||||
elif TypeMapItem.CODE_ITEM == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = CodeItem(self.size, buff, cm)
|
||||
|
||||
elif TypeMapItem.TYPE_ID_ITEM == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = TypeHIdItem(self.size, buff, cm)
|
||||
|
||||
elif TypeMapItem.PROTO_ID_ITEM == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = ProtoHIdItem(self.size, buff, cm)
|
||||
|
||||
elif TypeMapItem.FIELD_ID_ITEM == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = FieldHIdItem(self.size, buff, cm)
|
||||
|
||||
elif TypeMapItem.METHOD_ID_ITEM == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = MethodHIdItem(self.size, buff, cm)
|
||||
|
||||
elif TypeMapItem.CLASS_DEF_ITEM == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = ClassHDefItem(self.size, buff, cm)
|
||||
|
||||
elif TypeMapItem.HEADER_ITEM == self.type:
|
||||
# FIXME probably not necessary to parse again here...
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = HeaderItem(self.size, buff, cm)
|
||||
|
||||
elif TypeMapItem.ANNOTATION_ITEM == self.type:
|
||||
# Byte aligned
|
||||
buff.set_idx(self.offset)
|
||||
buff.seek(self.offset)
|
||||
self.item = [AnnotationItem(buff, cm) for _ in range(self.size)]
|
||||
|
||||
elif TypeMapItem.ANNOTATION_SET_ITEM == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = [AnnotationSetItem(buff, cm) for _ in range(self.size)]
|
||||
|
||||
elif TypeMapItem.ANNOTATIONS_DIRECTORY_ITEM == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = [AnnotationsDirectoryItem(buff, cm) for _ in range(self.size)]
|
||||
|
||||
elif TypeMapItem.HIDDENAPI_CLASS_DATA_ITEM == self.type:
|
||||
# Byte aligned
|
||||
buff.set_idx(self.offset)
|
||||
buff.seek(self.offset)
|
||||
self.item = HiddenApiClassDataItem(buff, cm)
|
||||
|
||||
elif TypeMapItem.ANNOTATION_SET_REF_LIST == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = [AnnotationSetRefList(buff, cm) for _ in range(self.size)]
|
||||
|
||||
elif TypeMapItem.TYPE_LIST == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
self.item = [TypeList(buff, cm) for _ in range(self.size)]
|
||||
|
||||
elif TypeMapItem.STRING_DATA_ITEM == self.type:
|
||||
# Byte aligned
|
||||
buff.set_idx(self.offset)
|
||||
buff.seek(self.offset)
|
||||
self.item = [StringDataItem(buff, cm) for _ in range(self.size)]
|
||||
|
||||
elif TypeMapItem.DEBUG_INFO_ITEM == self.type:
|
||||
# Byte aligned
|
||||
buff.set_idx(self.offset)
|
||||
buff.seek(self.offset)
|
||||
self.item = DebugInfoItemEmpty(buff, cm)
|
||||
|
||||
elif TypeMapItem.ENCODED_ARRAY_ITEM == self.type:
|
||||
# Byte aligned
|
||||
buff.set_idx(self.offset)
|
||||
buff.seek(self.offset)
|
||||
self.item = [EncodedArrayItem(buff, cm) for _ in range(self.size)]
|
||||
|
||||
elif TypeMapItem.CLASS_DATA_ITEM == self.type:
|
||||
# Byte aligned
|
||||
buff.set_idx(self.offset)
|
||||
buff.seek(self.offset)
|
||||
self.item = [ClassDataItem(buff, cm) for _ in range(self.size)]
|
||||
|
||||
elif TypeMapItem.MAP_LIST == self.type:
|
||||
# 4-byte aligned
|
||||
buff.set_idx(self.offset + (self.offset % 4))
|
||||
buff.seek(self.offset + (self.offset % 4))
|
||||
pass # It's me I think !!! No need to parse again
|
||||
|
||||
else:
|
||||
log.warning("Map item with id '{type}' offset: 0x{off:x} ({off}) "
|
||||
logger.warning("Map item with id '{type}' offset: 0x{off:x} ({off}) "
|
||||
"size: {size} is unknown. "
|
||||
"Is this a newer DEX format?".format(type=self.type, off=buff.get_idx(), size=self.size))
|
||||
"Is this a newer DEX format?".format(type=self.type, off=buff.tell(), size=self.size))
|
||||
|
||||
diff = time.time() - started_at
|
||||
minutes, seconds = diff // 60, diff % 60
|
||||
log.debug("End of parsing map_item '{}'. Required time {:.0f}:{:07.4f}".format(self.type.name, minutes, seconds))
|
||||
logger.debug("End of parsing map_item '{}'. Required time {:.0f}:{:07.4f}".format(self.type.name, minutes, seconds))
|
||||
|
||||
def show(self):
|
||||
bytecode._Print("\tMAP_TYPE_ITEM", self.type.name)
|
||||
@ -7294,7 +7299,7 @@ class ClassManager:
|
||||
def get_class_data_item(self, off):
|
||||
i = self.__classdata_off.get(off)
|
||||
if i is None:
|
||||
log.warning("unknown class data item @ 0x%x" % off)
|
||||
logger.warning("unknown class data item @ 0x%x" % off)
|
||||
|
||||
return i
|
||||
|
||||
@ -7350,13 +7355,13 @@ class ClassManager:
|
||||
try:
|
||||
off = self.__manage_item[TypeMapItem.STRING_ID_ITEM][idx].get_string_data_off()
|
||||
except IndexError:
|
||||
log.warning("unknown string item @ %d" % idx)
|
||||
logger.warning("unknown string item @ %d" % idx)
|
||||
return "AG:IS: invalid string"
|
||||
|
||||
try:
|
||||
return self.__strings_off[off].get()
|
||||
except KeyError:
|
||||
log.warning("unknown string item @ 0x%x(%d)" % (off, idx))
|
||||
logger.warning("unknown string item @ 0x%x(%d)" % (off, idx))
|
||||
return "AG:IS: invalid string"
|
||||
|
||||
def get_type_list(self, off):
|
||||
@ -7455,12 +7460,12 @@ class ClassManager:
|
||||
name += "_" + bytecode.FormatDescriptorToPython(
|
||||
encoded_method.get_descriptor())
|
||||
|
||||
log.debug("try deleting old name in python...")
|
||||
logger.debug("try deleting old name in python...")
|
||||
try:
|
||||
delattr(class_def.M, name)
|
||||
log.debug("success with regular name")
|
||||
logger.debug("success with regular name")
|
||||
except AttributeError:
|
||||
log.debug("WARNING: fail with regular name")
|
||||
logger.debug("WARNING: fail with regular name")
|
||||
# python_export = False
|
||||
|
||||
try:
|
||||
@ -7474,17 +7479,17 @@ class ClassManager:
|
||||
|
||||
try:
|
||||
delattr(class_def.M, name)
|
||||
log.debug("success with name containing prototype")
|
||||
logger.debug("success with name containing prototype")
|
||||
except AttributeError:
|
||||
log.debug("WARNING: fail with name containing prototype")
|
||||
logger.debug("WARNING: fail with name containing prototype")
|
||||
python_export = False
|
||||
|
||||
if python_export:
|
||||
name = bytecode.FormatNameToPython(value)
|
||||
setattr(class_def.M, name, encoded_method)
|
||||
log.debug("new name in python: created: %s." % name)
|
||||
logger.debug("new name in python: created: %s." % name)
|
||||
else:
|
||||
log.debug("skipping creating new name in python")
|
||||
logger.debug("skipping creating new name in python")
|
||||
|
||||
method.reload()
|
||||
|
||||
@ -7525,7 +7530,7 @@ class ClassManager:
|
||||
return idx
|
||||
|
||||
def get_debug_off(self, off):
|
||||
self.buff.set_idx(off)
|
||||
self.buff.seek(off)
|
||||
|
||||
return DebugInfoItem(self.buff, self)
|
||||
|
||||
@ -7540,7 +7545,7 @@ class MapList:
|
||||
def __init__(self, cm, off, buff):
|
||||
self.CM = cm
|
||||
|
||||
buff.set_idx(off)
|
||||
buff.seek(off)
|
||||
|
||||
self.offset = off
|
||||
|
||||
@ -7548,12 +7553,12 @@ class MapList:
|
||||
|
||||
self.map_item = []
|
||||
for _ in range(0, self.size):
|
||||
idx = buff.get_idx()
|
||||
idx = buff.tell()
|
||||
|
||||
mi = MapItem(buff, self.CM)
|
||||
self.map_item.append(mi)
|
||||
|
||||
buff.set_idx(idx + mi.get_length())
|
||||
buff.seek(idx + mi.get_length())
|
||||
|
||||
load_order = TypeMapItem.determine_load_order()
|
||||
ordered = sorted(self.map_item, key=lambda mi: load_order[mi.get_type()])
|
||||
@ -7617,7 +7622,7 @@ class DalvikPacker:
|
||||
"""
|
||||
def __init__(self, endian_tag):
|
||||
if endian_tag == 0x78563412:
|
||||
log.error("DEX file with byte swapped endian tag is not supported!")
|
||||
logger.error("DEX file with byte swapped endian tag is not supported!")
|
||||
raise NotImplementedError("Byte swapped endian tag encountered!")
|
||||
elif endian_tag == 0x12345678:
|
||||
self.endian_tag = '<'
|
||||
@ -7640,7 +7645,7 @@ class DalvikPacker:
|
||||
self.__structs = {}
|
||||
|
||||
|
||||
class DalvikVMFormat(bytecode.BuffHandle):
|
||||
class DEX:
|
||||
"""
|
||||
This class can parse a classes.dex file of an Android application (APK).
|
||||
|
||||
@ -7651,10 +7656,12 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
|
||||
example::
|
||||
|
||||
d = DalvikVMFormat( read("classes.dex") )
|
||||
d = DEX( read("classes.dex") )
|
||||
"""
|
||||
|
||||
def __init__(self, buff, decompiler=None, config=None, using_api=None):
|
||||
logger.debug("DEX {} {} {}".format(decompiler, config, using_api))
|
||||
|
||||
# to allow to pass apk object ==> we do not need to pass additionally target version
|
||||
if isinstance(buff, APK):
|
||||
self.api_version = buff.get_target_sdk_version()
|
||||
@ -7664,7 +7671,8 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
else:
|
||||
self.api_version = CONF["DEFAULT_API"]
|
||||
|
||||
super().__init__(buff)
|
||||
self.raw = io.BufferedReader(io.BytesIO(buff))
|
||||
|
||||
self._flush()
|
||||
|
||||
self.CM = ClassManager(self)
|
||||
@ -7677,13 +7685,13 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
pass
|
||||
|
||||
def _load(self, buff):
|
||||
self.header = HeaderItem(0, self, self.CM)
|
||||
self.header = HeaderItem(0, self.raw, self.CM)
|
||||
|
||||
if self.header.map_off == 0:
|
||||
# TODO check if the header specifies items but does not have a map
|
||||
log.warning("no map list! This DEX file is probably empty.")
|
||||
logger.warning("no map list! This DEX file is probably empty.")
|
||||
else:
|
||||
self.map_list = MapList(self.CM, self.header.map_off, self)
|
||||
self.map_list = MapList(self.CM, self.header.map_off, self.raw)
|
||||
|
||||
self.classes = self.map_list.get_item_type(TypeMapItem.CLASS_DEF_ITEM)
|
||||
self.methods = self.map_list.get_item_type(TypeMapItem.METHOD_ID_ITEM)
|
||||
@ -7720,14 +7728,14 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
"""
|
||||
.. deprecated:: 3.1.0
|
||||
The :class:`~androguard.core.analysis.analysis.Analysis` is not
|
||||
loaded anymore into :class:`DalvikVMFormat` in order to avoid
|
||||
loaded anymore into :class:`DEX` in order to avoid
|
||||
cyclic dependencies.
|
||||
:class:`~androguard.core.analysis.analysis.Analysis` extends now
|
||||
:class:`DalvikVMFormat`.
|
||||
:class:`DEX`.
|
||||
This Method does nothing anymore!
|
||||
|
||||
The Analysis Object should contain all the information required,
|
||||
inclduing the DalvikVMFormats.
|
||||
inclduing the DEX.
|
||||
"""
|
||||
warnings.warn("deprecated, this method does nothing!", DeprecationWarning)
|
||||
|
||||
@ -7735,14 +7743,14 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
"""
|
||||
.. deprecated:: 3.1.0
|
||||
The :class:`~androguard.core.analysis.analysis.Analysis` is not
|
||||
loaded anymore into :class:`DalvikVMFormat` in order to avoid
|
||||
loaded anymore into :class:`DEX` in order to avoid
|
||||
cyclic dependencies.
|
||||
:class:`~androguard.core.analysis.analysis.Analysis` extends now
|
||||
:class:`DalvikVMFormat`.
|
||||
:class:`DEX`.
|
||||
This Method does nothing anymore!
|
||||
|
||||
The Analysis Object should contain all the information required,
|
||||
inclduing the DalvikVMFormats.
|
||||
inclduing the DEX.
|
||||
"""
|
||||
warnings.warn("deprecated, this method does nothing!", DeprecationWarning)
|
||||
|
||||
@ -7866,9 +7874,9 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
s[idx + length] = c_length
|
||||
|
||||
length += c_length
|
||||
# log.debug("SAVE" + str(j) + " @ 0x%x" % (idx+length))
|
||||
# logger.debug("SAVE" + str(j) + " @ 0x%x" % (idx+length))
|
||||
|
||||
log.debug("SAVE " + str(i[0]) + " @0x{:x} ({:x})".format(idx, length))
|
||||
logger.debug("SAVE " + str(i[0]) + " @0x{:x} ({:x})".format(idx, length))
|
||||
|
||||
else:
|
||||
if isinstance(i, MapList):
|
||||
@ -7883,7 +7891,7 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
|
||||
s[idx] = length
|
||||
|
||||
log.debug("SAVE " + str(i) + " @0x{:x} ({:x})".format(idx, length))
|
||||
logger.debug("SAVE " + str(i) + " @0x{:x} ({:x})".format(idx, length))
|
||||
|
||||
idx += length
|
||||
|
||||
@ -7905,7 +7913,7 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
idx = h[i]
|
||||
|
||||
if idx != last_idx:
|
||||
log.debug("Adjust alignment @{:x} with 00 {:x}".format(idx, idx - last_idx))
|
||||
logger.debug("Adjust alignment @{:x} with 00 {:x}".format(idx, idx - last_idx))
|
||||
buff += bytearray([0] * (idx - last_idx))
|
||||
|
||||
buff += i.get_raw()
|
||||
@ -7913,7 +7921,7 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
buff += b"\x00"
|
||||
last_idx = idx + s[idx]
|
||||
|
||||
log.debug("GLOBAL SIZE %d" % len(buff))
|
||||
logger.debug("GLOBAL SIZE %d" % len(buff))
|
||||
|
||||
return self.fix_checksums(buff)
|
||||
|
||||
@ -7930,8 +7938,8 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
checksum = zlib.adler32(buff[12:])
|
||||
buff = buff[:8] + self.CM.packer["I"].pack(checksum) + buff[12:]
|
||||
|
||||
log.debug("NEW SIGNATURE %s" % repr(signature))
|
||||
log.debug("NEW CHECKSUM %x" % checksum)
|
||||
logger.debug("NEW SIGNATURE %s" % repr(signature))
|
||||
logger.debug("NEW CHECKSUM %x" % checksum)
|
||||
|
||||
return buff
|
||||
|
||||
@ -8354,7 +8362,7 @@ class DalvikVMFormat(bytecode.BuffHandle):
|
||||
"""
|
||||
for i in DCode(
|
||||
self.CM, offset, size,
|
||||
self.get_buff()[offset:offset + size]).get_instructions():
|
||||
read_at(self.raw, offset, size)).get_instructions():
|
||||
yield i
|
||||
|
||||
def _get_class_hierarchy(self):
|
||||
@ -8508,7 +8516,7 @@ class OdexHeaderItem:
|
||||
"""
|
||||
|
||||
def __init__(self, buff):
|
||||
buff.set_idx(8)
|
||||
buff.seek(8)
|
||||
|
||||
self.dex_offset = unpack("=I", buff.read(4))[0]
|
||||
self.dex_length = unpack("=I", buff.read(4))[0]
|
||||
@ -8579,7 +8587,7 @@ class OdexDependencies:
|
||||
dependencies
|
||||
|
||||
|
||||
class DalvikOdexVMFormat(DalvikVMFormat):
|
||||
class ODEX(DEX):
|
||||
"""
|
||||
This class can parse an odex file
|
||||
|
||||
@ -8589,7 +8597,7 @@ class DalvikOdexVMFormat(DalvikVMFormat):
|
||||
:type decompiler: object
|
||||
|
||||
:Example:
|
||||
DalvikOdexVMFormat( read("classes.odex") )
|
||||
ODEX( read("classes.odex") )
|
||||
"""
|
||||
|
||||
def _preload(self, buff):
|
||||
@ -8598,15 +8606,15 @@ class DalvikOdexVMFormat(DalvikVMFormat):
|
||||
if self.magic in (ODEX_FILE_MAGIC_35, ODEX_FILE_MAGIC_36, ODEX_FILE_MAGIC_37):
|
||||
self.odex_header = OdexHeaderItem(self)
|
||||
|
||||
self.set_idx(self.odex_header.deps_offset)
|
||||
self.seek(self.odex_header.deps_offset)
|
||||
self.dependencies = OdexDependencies(self)
|
||||
|
||||
self.padding = buff[self.odex_header.deps_offset +
|
||||
self.odex_header.deps_length:]
|
||||
|
||||
self.set_idx(self.odex_header.dex_offset)
|
||||
self.seek(self.odex_header.dex_offset)
|
||||
self.set_buff(self.read(self.odex_header.dex_length))
|
||||
self.set_idx(0)
|
||||
self.seek(0)
|
||||
|
||||
def save(self):
|
||||
"""
|
@ -1,18 +1,15 @@
|
||||
# External dependecies
|
||||
from loguru import logger
|
||||
import asn1crypto
|
||||
# Functions that might be useful
|
||||
|
||||
# Stuff that might be useful
|
||||
|
||||
def read(filename, binary=True):
|
||||
"""
|
||||
Open and read a file
|
||||
|
||||
:param filename: filename to open and read
|
||||
:param binary: True if the file should be read as binary
|
||||
:return: bytes if binary is True, str otherwise
|
||||
"""
|
||||
with open(filename, 'rb' if binary else 'r') as f:
|
||||
return f.read()
|
||||
|
||||
def read_at(buff, offset, size=-1):
|
||||
idx = buff.tell()
|
||||
buff.seek(offset)
|
||||
d = buff.read(size)
|
||||
buff.seek(idx)
|
||||
return d
|
||||
|
||||
def get_certificate_name_string(name, short=False, delimiter=', '):
|
||||
"""
|
||||
|
@ -3,17 +3,22 @@
|
||||
|
||||
"""Androguard is a full Python tool to play with Android files."""
|
||||
|
||||
|
||||
# core modules
|
||||
import sys
|
||||
import logging
|
||||
import sys, json
|
||||
from loguru import logger
|
||||
|
||||
|
||||
# 3rd party modules
|
||||
import click
|
||||
|
||||
import androguard.core.apk
|
||||
|
||||
# local modules
|
||||
import androguard
|
||||
|
||||
from androguard.core.androconf import show_logging
|
||||
from androguard.cli import (androarsc_main,
|
||||
from main import (androarsc_main,
|
||||
androaxml_main,
|
||||
androcg_main,
|
||||
export_apps_to_format,
|
||||
@ -23,6 +28,7 @@ from androguard.cli import (androarsc_main,
|
||||
androdis_main
|
||||
)
|
||||
|
||||
logger.add(sys.stderr, format="{time} {level} {message}", filter="cli", level="INFO")
|
||||
|
||||
@click.group(help=__doc__)
|
||||
@click.version_option(version=androguard.__version__)
|
||||
@ -30,16 +36,7 @@ from androguard.cli import (androarsc_main,
|
||||
@click.option("--quiet", 'verbosity', flag_value='quiet', help="Print less (only warnings and above)")
|
||||
@click.option("--silent", 'verbosity', flag_value='silent', help="Print no log messages")
|
||||
def entry_point(verbosity):
|
||||
level = logging.INFO
|
||||
|
||||
if verbosity == 'verbose':
|
||||
level = logging.DEBUG
|
||||
if verbosity == 'quiet':
|
||||
level = logging.WARNING
|
||||
|
||||
# If something out of this module is imported, activate console logging
|
||||
if verbosity != 'silent':
|
||||
show_logging(level=level)
|
||||
pass
|
||||
|
||||
|
||||
@entry_point.command()
|
||||
@ -155,17 +152,17 @@ def arsc(input_,
|
||||
\b
|
||||
$ androguard arsc app.apk
|
||||
"""
|
||||
logger.debug("ARSC")
|
||||
|
||||
from androguard.core import androconf
|
||||
from androguard.core.bytecodes import apk
|
||||
from androguard.core import axml, apk
|
||||
|
||||
if file_ and input_:
|
||||
print("Can not give --input and positional argument! "
|
||||
"Please use only one of them!",
|
||||
file=sys.stderr)
|
||||
logger.info("Can not give --input and positional argument! Please use only one of them!")
|
||||
sys.exit(1)
|
||||
|
||||
if not input_ and not file_:
|
||||
print("Give one file to decode!", file=sys.stderr)
|
||||
logger.info("Give one file to decode!")
|
||||
sys.exit(1)
|
||||
|
||||
if input_:
|
||||
@ -178,16 +175,16 @@ def arsc(input_,
|
||||
a = apk.APK(fname)
|
||||
arscobj = a.get_android_resources()
|
||||
if not arscobj:
|
||||
print("The APK does not contain a resources file!", file=sys.stderr)
|
||||
logger.error("The APK does not contain a resources file!")
|
||||
sys.exit(0)
|
||||
elif ret_type == "ARSC":
|
||||
with open(fname, 'rb') as fp:
|
||||
arscobj = apk.ARSCParser(fp.read())
|
||||
arscobj = axml.ARSCParser(fp.read())
|
||||
if not arscobj:
|
||||
print("The resources file seems to be invalid!", file=sys.stderr)
|
||||
logger.error("The resources file seems to be invalid!")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("Unknown file type!", file=sys.stderr)
|
||||
logger.error("Unknown file type!")
|
||||
sys.exit(1)
|
||||
|
||||
if id_:
|
||||
@ -435,12 +432,13 @@ def sign(hash_, print_all_hashes, show, apk):
|
||||
)
|
||||
def apkid(apks):
|
||||
"""Return the packageName/versionCode/versionName per APK as JSON."""
|
||||
import json
|
||||
import logging
|
||||
logging.getLogger("androguard.axml").setLevel(logging.ERROR)
|
||||
from androguard.core.apk import get_apkid
|
||||
|
||||
logger.debug("APKID")
|
||||
|
||||
results = dict()
|
||||
for apk in apks:
|
||||
results[apk] = androguard.core.bytecodes.apk.get_apkid(apk)
|
||||
results[apk] = get_apkid(apk)
|
||||
print(json.dumps(results, indent=2))
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.t0t0.androguard.TC"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon">
|
||||
<activity android:name="TCActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
@ -1,30 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<parent id="androguard Test">
|
||||
|
||||
<main_path>./examples/android/TC/</main_path>
|
||||
<libs_path>./libs/</libs_path>
|
||||
|
||||
<watermark>
|
||||
<type>BM_A0</type>
|
||||
<type>BM_A1</type>
|
||||
<output>wm.xml</output>
|
||||
</watermark>
|
||||
|
||||
<protect_code>
|
||||
</protect_code>
|
||||
|
||||
<protect_names type="class">
|
||||
|
||||
<except_class>
|
||||
<name>org/t0t0/androguard/TC/TCActivity</name>
|
||||
</except_class>
|
||||
|
||||
<except_fields>
|
||||
<class>org/t0t0/androguard/TC/TCMod1</class>
|
||||
<name>TC1</name>
|
||||
<descriptor>I</descriptor>
|
||||
</except_fields>
|
||||
|
||||
</protect_names>
|
||||
|
||||
</parent>
|
@ -1,17 +0,0 @@
|
||||
# This file is used to override default values used by the Ant build system.
|
||||
#
|
||||
# This file must be checked in Version Control Systems, as it is
|
||||
# integral to the build system of your project.
|
||||
|
||||
# This file is only used by the Ant script.
|
||||
|
||||
# You can use this to override default values such as
|
||||
# 'source.dir' for the location of your java source folder and
|
||||
# 'out.dir' for the location of your output folder.
|
||||
|
||||
# You can also use it define how the release builds are signed by declaring
|
||||
# the following properties:
|
||||
# 'key.store' for the location of your keystore and
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
|
@ -1,84 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="TC" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android'
|
||||
tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The build.properties file can be created by you and is never touched
|
||||
by the 'android' tool. This is the place to change some of the
|
||||
default property values used by the Ant rules.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="build.properties" />
|
||||
|
||||
<!-- The default.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<property file="default.properties" />
|
||||
|
||||
<!-- Custom Android task to deal with the project target, and import the
|
||||
proper rules.
|
||||
This requires ant 1.6.0 or above. -->
|
||||
<path id="android.antlibs">
|
||||
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
|
||||
</path>
|
||||
|
||||
<taskdef name="setup"
|
||||
classname="com.android.ant.SetupTask"
|
||||
classpathref="android.antlibs" />
|
||||
|
||||
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||
in between standard targets -->
|
||||
<!--
|
||||
<target name="-pre-build">
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
</target>
|
||||
|
||||
[This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir}]
|
||||
<target name="-post-compile">
|
||||
</target>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Execute the Android Setup task that will setup some properties
|
||||
specific to the target, and import the build rules files.
|
||||
|
||||
The rules file is imported from
|
||||
<SDK>/platforms/<target_platform>/ant/ant_rules_r#.xml
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<setup> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole script.
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, *after* the <setup> task
|
||||
- disable the import of the rules by changing the setup task
|
||||
below to <setup import="false" />.
|
||||
- customize to your needs.
|
||||
-->
|
||||
<setup />
|
||||
|
||||
</project>
|
@ -1,11 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "build.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-8
|
@ -1,10 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must *NOT* be checked in Version Control Systems,
|
||||
# as it contains information specific to your local configuration.
|
||||
|
||||
# location of the SDK. This is only used by Ant
|
||||
# For customization when using a Version Control System, please read the
|
||||
# header note.
|
||||
sdk.dir=/home/desnos/android/android-sdk-linux_x86
|
@ -1,34 +0,0 @@
|
||||
-optimizationpasses 5
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-dontpreverify
|
||||
-verbose
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.5 KiB |
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World, TCActivity"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">TCActivity</string>
|
||||
</resources>
|
@ -1,33 +0,0 @@
|
||||
package org.t0t0.androguard.TC;
|
||||
|
||||
public class TCA {
|
||||
public int TC1 = 30;
|
||||
private int TC2 = -6;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCA()
|
||||
{
|
||||
System.out.println("TCA TC1 == 30 : " + this.equal( this.TC1, "30" ));
|
||||
System.out.println("TCA TC2 == -6 : " + this.equal( this.TC2, "-6" ));
|
||||
TC1 = 20;
|
||||
System.out.println("TCA TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
TCC c = new TCC();
|
||||
|
||||
c.T1();
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package org.t0t0.androguard.TC;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class TCActivity extends Activity
|
||||
{
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package org.t0t0.androguard.TC;
|
||||
|
||||
public class TCB {
|
||||
public int TC1 = 1337;
|
||||
private int TC2 = -90000;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCB(TCA a)
|
||||
{
|
||||
System.out.println("TCB TC1 == 1337 : " + this.equal( this.TC1, "1337" ));
|
||||
System.out.println("TCB TC2 == -90000 : " + this.equal( this.TC2, "-90000" ));
|
||||
TC1 = 20;
|
||||
System.out.println("TCB TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
|
||||
a.T1();
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package org.t0t0.androguard.TC;
|
||||
|
||||
public class TCC {
|
||||
public int TC1 = 30;
|
||||
private int TC2 = -6;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCC()
|
||||
{
|
||||
System.out.println("TCC TC1 == 30 : " + this.equal( this.TC1, "30" ));
|
||||
System.out.println("TCC TC2 == -6 : " + this.equal( this.TC2, "-6" ));
|
||||
TC1 = 20;
|
||||
System.out.println("TCC TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package org.t0t0.androguard.TC;
|
||||
|
||||
public class TCD {
|
||||
public int TC1 = 1337;
|
||||
private int TC2 = -90000;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCD()
|
||||
{
|
||||
System.out.println("TCD TC1 == 1337 : " + this.equal( this.TC1, "1337" ));
|
||||
System.out.println("TCD TC2 == -90000 : " + this.equal( this.TC2, "-90000" ));
|
||||
TC1 = 20;
|
||||
System.out.println("TCD TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
|
||||
TCE e = new TCE();
|
||||
e.T1();
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
package org.t0t0.androguard.TC;
|
||||
|
||||
public class TCE {
|
||||
public int TC1 = 1337;
|
||||
private int TC2 = -90000;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCE()
|
||||
{
|
||||
System.out.println("TCE TC1 == 1337 : " + this.equal( this.TC1, "1337" ));
|
||||
System.out.println("TCE TC2 == -90000 : " + this.equal( this.TC2, "-90000" ));
|
||||
|
||||
this.TC1 = 20;
|
||||
System.out.println("TCE TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
|
||||
this.TC2 = -30;
|
||||
System.out.println("TCE TC2 == -30 : " + this.equal( this.TC2, "-30" ));
|
||||
|
||||
int y = 0;
|
||||
for(int i = 0; i < (this.TC1 - this.TC2); i++) {
|
||||
for(int j=0; j < i; j++) {
|
||||
y = y + this.TCE_t1( 400 );
|
||||
}
|
||||
|
||||
switch( this.TC1 ) {
|
||||
case 0 : y += 1;
|
||||
default : y = y + this.TCE_t2();
|
||||
}
|
||||
|
||||
switch( this.TC2 ) {
|
||||
case 0 : y += 30;
|
||||
case 45 : y += 2;
|
||||
case -6 : y = y + this.TCE_t3();
|
||||
}
|
||||
}
|
||||
|
||||
this.TC1 = y;
|
||||
|
||||
System.out.println("TCE TC1 == 3433300 : " + this.equal( this.TC1, "3433300" ));
|
||||
|
||||
TCC c = new TCC();
|
||||
c.T1();
|
||||
}
|
||||
|
||||
public int TCE_t1(int a)
|
||||
{
|
||||
return a * 7;
|
||||
}
|
||||
|
||||
public int TCE_t2()
|
||||
{
|
||||
return 0x42;
|
||||
}
|
||||
|
||||
public int TCE_t3()
|
||||
{
|
||||
return 0x45;
|
||||
}
|
||||
|
||||
|
||||
public void T1()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package org.t0t0.androguard.TC;
|
||||
|
||||
public class TCMod1 {
|
||||
public int TC1 = 0;
|
||||
private int TC2 = 3;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCMod1()
|
||||
{
|
||||
System.out.println("TC1 == 0 : " + this.equal( this.TC1, "0" ));
|
||||
System.out.println("TC2 == 3 : " + this.equal( this.TC2, "3" ));
|
||||
TC1 = 20;
|
||||
System.out.println("TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 30; i++)
|
||||
{
|
||||
this.TC1 += i;
|
||||
}
|
||||
System.out.println("TC1 == 455 : " + this.equal( this.TC1, "455" ));
|
||||
|
||||
int j = 40;
|
||||
System.out.println("J == 40 : " + this.equal( j, "40" ));
|
||||
|
||||
for(; j < 40000; j++);
|
||||
System.out.println("J == 40000 : " + this.equal( j, "40000" ));
|
||||
|
||||
this.TC1 += j;
|
||||
System.out.println("TC1 == 40455 : " + this.equal( this.TC1, "40455" ));
|
||||
|
||||
int k[][] = { { 40, 30 }, { 60000, -788 }, { -2344556, 10000 } };
|
||||
|
||||
for(i = 0; i < k.length; i++) {
|
||||
for(j=0; j < k[i].length; j++) {
|
||||
this.TC1 += k[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
TCA a = new TCA() ;
|
||||
a.T1();
|
||||
|
||||
System.out.println("TC1 == -2234819 : " + this.equal( this.TC1, "-2234819" ));
|
||||
|
||||
i = 300; j =-188;
|
||||
System.out.println("I == 300 : " + this.equal( i, "300" ));
|
||||
System.out.println("J == -188 : " + this.equal( j, "-188" ));
|
||||
|
||||
TCD d = new TCD();
|
||||
d.T1();
|
||||
|
||||
do {
|
||||
this.TC2 += ( j - i );
|
||||
j += 3;
|
||||
i -= 2;
|
||||
} while ( j < i );
|
||||
System.out.println("TC2 == -24056 : " + this.equal( this.TC2, "-24056" ));
|
||||
TCA a1 = new TCA() ;
|
||||
a1.T1();
|
||||
|
||||
TCB b = new TCB( a );
|
||||
b.T1();
|
||||
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package org.t0t0.androguard.TC;
|
||||
|
||||
public class TestType1
|
||||
{
|
||||
public TestType1()
|
||||
{
|
||||
long long_tc1 = 42;
|
||||
long long_tc2 = -42;
|
||||
long long_tc3 = 0;
|
||||
|
||||
int int_tc1 = 42;
|
||||
int int_tc2 = -42;
|
||||
int int_tc3 = 0;
|
||||
|
||||
double double_tc1 = 42.0;
|
||||
double double_tc2 = -42.0;
|
||||
double double_tc3 = 0.0;
|
||||
|
||||
float float_tc1 = 42.0f;
|
||||
float float_tc2 = -42.0f;
|
||||
float float_tc3 = 0.0f;
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.t0t0.androguard.TCDiff"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<application android:label="@string/app_name" android:icon="@drawable/icon">
|
||||
<activity android:name="TCActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
@ -1,30 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<parent id="androguard Test">
|
||||
|
||||
<main_path>./examples/android/TCDiff/</main_path>
|
||||
<libs_path>./libs/</libs_path>
|
||||
|
||||
<watermark>
|
||||
<type>BM_A0</type>
|
||||
<type>BM_A1</type>
|
||||
<output>wm.xml</output>
|
||||
</watermark>
|
||||
|
||||
<protect_code>
|
||||
</protect_code>
|
||||
|
||||
<protect_names type="class">
|
||||
|
||||
<except_class>
|
||||
<name>org/t0t0/androguard/TCDiff/TCActivity</name>
|
||||
</except_class>
|
||||
|
||||
<except_fields>
|
||||
<class>org/t0t0/androguard/TCDiff/TCMod1</class>
|
||||
<name>TC1</name>
|
||||
<descriptor>I</descriptor>
|
||||
</except_fields>
|
||||
|
||||
</protect_names>
|
||||
|
||||
</parent>
|
@ -1,17 +0,0 @@
|
||||
# This file is used to override default values used by the Ant build system.
|
||||
#
|
||||
# This file must be checked in Version Control Systems, as it is
|
||||
# integral to the build system of your project.
|
||||
|
||||
# This file is only used by the Ant script.
|
||||
|
||||
# You can use this to override default values such as
|
||||
# 'source.dir' for the location of your java source folder and
|
||||
# 'out.dir' for the location of your output folder.
|
||||
|
||||
# You can also use it define how the release builds are signed by declaring
|
||||
# the following properties:
|
||||
# 'key.store' for the location of your keystore and
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
|
@ -1,84 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="TCDiff" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android'
|
||||
tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The build.properties file can be created by you and is never touched
|
||||
by the 'android' tool. This is the place to change some of the
|
||||
default property values used by the Ant rules.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="build.properties" />
|
||||
|
||||
<!-- The default.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<property file="default.properties" />
|
||||
|
||||
<!-- Custom Android task to deal with the project target, and import the
|
||||
proper rules.
|
||||
This requires ant 1.6.0 or above. -->
|
||||
<path id="android.antlibs">
|
||||
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
|
||||
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
|
||||
</path>
|
||||
|
||||
<taskdef name="setup"
|
||||
classname="com.android.ant.SetupTask"
|
||||
classpathref="android.antlibs" />
|
||||
|
||||
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||
in between standard targets -->
|
||||
<!--
|
||||
<target name="-pre-build">
|
||||
</target>
|
||||
<target name="-pre-compile">
|
||||
</target>
|
||||
|
||||
[This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir}]
|
||||
<target name="-post-compile">
|
||||
</target>
|
||||
-->
|
||||
|
||||
|
||||
<!-- Execute the Android Setup task that will setup some properties
|
||||
specific to the target, and import the build rules files.
|
||||
|
||||
The rules file is imported from
|
||||
<SDK>/platforms/<target_platform>/ant/ant_rules_r#.xml
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<setup> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole script.
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, *after* the <setup> task
|
||||
- disable the import of the rules by changing the setup task
|
||||
below to <setup import="false" />.
|
||||
- customize to your needs.
|
||||
-->
|
||||
<setup />
|
||||
|
||||
</project>
|
@ -1,11 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "build.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-8
|
@ -1,10 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must *NOT* be checked in Version Control Systems,
|
||||
# as it contains information specific to your local configuration.
|
||||
|
||||
# location of the SDK. This is only used by Ant
|
||||
# For customization when using a Version Control System, please read the
|
||||
# header note.
|
||||
sdk.dir=/home/desnos/android/android-sdk-linux_x86
|
@ -1,34 +0,0 @@
|
||||
-optimizationpasses 5
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-dontpreverify
|
||||
-verbose
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.5 KiB |
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World, TCActivity"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">TCActivity</string>
|
||||
</resources>
|
@ -1,39 +0,0 @@
|
||||
package org.t0t0.androguard.TCDiff;
|
||||
|
||||
public class TCA {
|
||||
public int TC1 = 30;
|
||||
private int TC2 = -6;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCA()
|
||||
{
|
||||
System.out.println("TCA TC1 == 30 : " + this.equal( this.TC1, "30" ));
|
||||
System.out.println("TCA TC2 == -6 : " + this.equal( this.TC2, "-6" ));
|
||||
TC1 = 20;
|
||||
System.out.println("TCA TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
TCC c = new TCC();
|
||||
|
||||
// PATCH
|
||||
if ((TC2 % 2) == 1) {
|
||||
TC1 = 3;
|
||||
}
|
||||
// END PATCH
|
||||
|
||||
c.T1();
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package org.t0t0.androguard.TCDiff;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class TCActivity extends Activity
|
||||
{
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package org.t0t0.androguard.TCDiff;
|
||||
|
||||
public class TCB {
|
||||
public int TC1 = 1337;
|
||||
private int TC2 = -90000;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCB(TCA a)
|
||||
{
|
||||
System.out.println("TCB TC1 == 1337 : " + this.equal( this.TC1, "1337" ));
|
||||
System.out.println("TCB TC2 == -90000 : " + this.equal( this.TC2, "-90000" ));
|
||||
TC1 = 20;
|
||||
System.out.println("TCB TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
|
||||
a.T1();
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package org.t0t0.androguard.TCDiff;
|
||||
|
||||
public class TCC {
|
||||
public int TC1 = 30;
|
||||
private int TC2 = -6;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCC()
|
||||
{
|
||||
System.out.println("TCC TC1 == 30 : " + this.equal( this.TC1, "30" ));
|
||||
System.out.println("TCC TC2 == -6 : " + this.equal( this.TC2, "-6" ));
|
||||
TC1 = 20;
|
||||
System.out.println("TCC TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package org.t0t0.androguard.TCDiff;
|
||||
|
||||
public class TCD {
|
||||
public int TC1 = 1337;
|
||||
private int TC2 = -90000;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCD()
|
||||
{
|
||||
System.out.println("TCD TC1 == 1337 : " + this.equal( this.TC1, "1337" ));
|
||||
System.out.println("TCD TC2 == -90000 : " + this.equal( this.TC2, "-90000" ));
|
||||
TC1 = 20;
|
||||
System.out.println("TCD TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
|
||||
TCE e = new TCE();
|
||||
e.T1();
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
package org.t0t0.androguard.TCDiff;
|
||||
|
||||
public class TCE {
|
||||
public int TC1 = 1337;
|
||||
private int TC2 = -90000;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCE()
|
||||
{
|
||||
System.out.println("TCE TC1 == 1337 : " + this.equal( this.TC1, "1337" ));
|
||||
System.out.println("TCE TC2 == -90000 : " + this.equal( this.TC2, "-90000" ));
|
||||
|
||||
this.TC1 = 20;
|
||||
System.out.println("TCE TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
|
||||
this.TC2 = -30;
|
||||
System.out.println("TCE TC2 == -30 : " + this.equal( this.TC2, "-30" ));
|
||||
|
||||
int y = 0;
|
||||
for(int i = 0; i < (this.TC1 - this.TC2); i++) {
|
||||
for(int j=0; j < i; j++) {
|
||||
y = y + this.TCE_t1( 400 );
|
||||
}
|
||||
|
||||
switch( this.TC1 ) {
|
||||
case 0 : y += 1;
|
||||
default : y = y + this.TCE_t2();
|
||||
}
|
||||
|
||||
switch( this.TC2 ) {
|
||||
case 0 : y += 30;
|
||||
case 45 : y += 2;
|
||||
case -6 : y = y + this.TCE_t3();
|
||||
}
|
||||
}
|
||||
|
||||
this.TC1 = y;
|
||||
|
||||
System.out.println("TCE TC1 == 3433300 : " + this.equal( this.TC1, "3433300" ));
|
||||
|
||||
TCC c = new TCC();
|
||||
c.T1();
|
||||
}
|
||||
|
||||
public int TCE_t1(int a)
|
||||
{
|
||||
return a * 7;
|
||||
}
|
||||
|
||||
public int TCE_t2()
|
||||
{
|
||||
return 0x42;
|
||||
}
|
||||
|
||||
public int TCE_t3()
|
||||
{
|
||||
return 0x45;
|
||||
}
|
||||
|
||||
// NEW METHOD
|
||||
public int TCE_t4()
|
||||
{
|
||||
return 0x90;
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
package org.t0t0.androguard.TCDiff;
|
||||
|
||||
public class TCMod1 {
|
||||
public int TC1 = 0;
|
||||
private int TC2 = 3;
|
||||
|
||||
public String equal(int a, String b)
|
||||
{
|
||||
String c = Integer.toString( a );
|
||||
|
||||
System.out.print(c + " " + b + " ---- ");
|
||||
if (c.equals(b)) {
|
||||
return " OK ";
|
||||
}
|
||||
|
||||
return " X ";
|
||||
}
|
||||
|
||||
public TCMod1()
|
||||
{
|
||||
System.out.println("TC1 == 0 : " + this.equal( this.TC1, "0" ));
|
||||
System.out.println("TC2 == 3 : " + this.equal( this.TC2, "3" ));
|
||||
TC1 = 20;
|
||||
System.out.println("TC1 == 20 : " + this.equal( this.TC1, "20" ));
|
||||
}
|
||||
|
||||
public void T1()
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 30; i++)
|
||||
{
|
||||
this.TC1 += i;
|
||||
}
|
||||
System.out.println("TC1 == 455 : " + this.equal( this.TC1, "455" ));
|
||||
|
||||
int j = 40;
|
||||
System.out.println("J == 40 : " + this.equal( j, "40" ));
|
||||
|
||||
for(; j < 40000; j++);
|
||||
System.out.println("J == 40000 : " + this.equal( j, "40000" ));
|
||||
|
||||
this.TC1 += j;
|
||||
System.out.println("TC1 == 40455 : " + this.equal( this.TC1, "40455" ));
|
||||
|
||||
int k[][] = { { 40, 30 }, { 60000, -788 }, { -2344556, 10000 } };
|
||||
|
||||
for(i = 0; i < k.length; i++) {
|
||||
for(j=0; j < k[i].length; j++) {
|
||||
// PATCH
|
||||
this.TC1 += k[i][j] + 1;
|
||||
// END PATCH
|
||||
}
|
||||
}
|
||||
|
||||
TCA a = new TCA() ;
|
||||
a.T1();
|
||||
|
||||
System.out.println("TC1 == -2234819 : " + this.equal( this.TC1, "-2234819" ));
|
||||
|
||||
i = 300; j =-188;
|
||||
System.out.println("I == 300 : " + this.equal( i, "300" ));
|
||||
System.out.println("J == -188 : " + this.equal( j, "-188" ));
|
||||
|
||||
TCD d = new TCD();
|
||||
d.T1();
|
||||
|
||||
do {
|
||||
this.TC2 += ( j - i );
|
||||
j += 3;
|
||||
// PATCH
|
||||
if (j == 4) {
|
||||
break;
|
||||
}
|
||||
// END PATCH
|
||||
|
||||
i -= 2;
|
||||
} while ( j < i );
|
||||
System.out.println("TC2 == -24056 : " + this.equal( this.TC2, "-24056" ));
|
||||
TCA a1 = new TCA() ;
|
||||
a1.T1();
|
||||
|
||||
TCB b = new TCB( a );
|
||||
b.T1();
|
||||
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package org.t0t0.androguard.TCDiff;
|
||||
|
||||
public class TestType1
|
||||
{
|
||||
public TestType1()
|
||||
{
|
||||
long long_tc1 = 42;
|
||||
long long_tc2 = -42;
|
||||
long long_tc3 = 0;
|
||||
|
||||
int int_tc1 = 42;
|
||||
int int_tc2 = -42;
|
||||
int int_tc3 = 0;
|
||||
|
||||
double double_tc1 = 42.0;
|
||||
double double_tc2 = -42.0;
|
||||
double double_tc3 = 0.0;
|
||||
|
||||
float float_tc1 = 42.0f;
|
||||
float float_tc2 = -42.0f;
|
||||
float float_tc3 = 0.0f;
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="lib" path="libs/android-support-v4.jar"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>TestsAndroguard</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="tests.androguard"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="9"
|
||||
android:targetSdkVersion="16" />
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@drawable/icon"
|
||||
android:label="@string/app_name" >
|
||||
<activity
|
||||
android:name="TestActivity"
|
||||
android:label="@string/app_name" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -1,23 +0,0 @@
|
||||
/* AUTO-GENERATED FILE. DO NOT MODIFY.
|
||||
*
|
||||
* This class was automatically generated by the
|
||||
* aapt tool from the resource data it found. It
|
||||
* should not be modified by hand.
|
||||
*/
|
||||
|
||||
package tests.androguard;
|
||||
|
||||
public final class R {
|
||||
public static final class attr {
|
||||
}
|
||||
public static final class drawable {
|
||||
public static final int icon=0x7f020000;
|
||||
}
|
||||
public static final class layout {
|
||||
public static final int main=0x7f030000;
|
||||
}
|
||||
public static final class string {
|
||||
public static final int app_name=0x7f040001;
|
||||
public static final int hello=0x7f040000;
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-10
|
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.5 KiB |
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/hello"
|
||||
/>
|
||||
</LinearLayout>
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="hello">Hello World, TestActivity! kikoololmodif</string>
|
||||
<string name="app_name">TestsAndroguardApplication</string>
|
||||
</resources>
|
@ -1,82 +0,0 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class TestDefaultPackage {
|
||||
|
||||
static long [] test_;
|
||||
private class TestInnerClass {
|
||||
private int a, b;
|
||||
|
||||
private TestInnerClass(int a, int b)
|
||||
{
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public void Test(int d)
|
||||
{
|
||||
System.out.println("Test2: " + this.a + d + this.b);
|
||||
}
|
||||
|
||||
private class TestInnerInnerClass {
|
||||
private int a, c;
|
||||
|
||||
private TestInnerInnerClass(int a, int c)
|
||||
{
|
||||
this.a = a;
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public void Test(int b)
|
||||
{
|
||||
System.out.println("Test: " + this.a * b + this.c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void const4()
|
||||
{
|
||||
byte _ = -8;
|
||||
byte a = -7;
|
||||
byte b = -6;
|
||||
byte c = -5;
|
||||
byte d = -4;
|
||||
byte e = -3;
|
||||
byte f = -2;
|
||||
byte g = -1;
|
||||
byte h = 0;
|
||||
byte i = 1;
|
||||
byte j = 2;
|
||||
byte k = 3;
|
||||
byte l = 4;
|
||||
byte m = 5;
|
||||
byte n = 6;
|
||||
byte o = 7;
|
||||
System.out.println("" + _ + a + b + c + d + e + f + g + h + i + j + k + l + m + n + o);
|
||||
}
|
||||
|
||||
public static void main(String [] z)
|
||||
{
|
||||
int a = 5;
|
||||
switch(a)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
System.out.println("1 || 2");
|
||||
break;
|
||||
case 3:
|
||||
System.out.print("3 || ");
|
||||
case 4:
|
||||
default:
|
||||
System.out.println("4");
|
||||
break;
|
||||
case 5:
|
||||
System.out.println("5");
|
||||
}
|
||||
TestDefaultPackage p = new TestDefaultPackage();
|
||||
TestInnerClass t = p.new TestInnerClass(3, 4);
|
||||
TestInnerClass.TestInnerInnerClass t2 = t.new TestInnerInnerClass(3, 4);
|
||||
System.out.println("t.a = " + t.a);
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
public class Eratosthene {
|
||||
public static int[] eratosthenes(int n) {
|
||||
boolean a[] = new boolean[n+1];
|
||||
a[0] = true;
|
||||
a[1] = true;
|
||||
|
||||
int sqn = (int)Math.sqrt(n);
|
||||
for(int i = 2; i <= sqn; i++) {
|
||||
if(!a[i]) {
|
||||
int j = i*i;
|
||||
while(j <= n) {
|
||||
a[j] = true;
|
||||
j += i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
for(boolean b: a) {
|
||||
if(!b) {
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
int[] primes = new int[cnt];
|
||||
for(int i = 0; i < a.length; i++) {
|
||||
if(!a[i]) {
|
||||
primes[j++] = i;
|
||||
}
|
||||
}
|
||||
return primes;
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
public class Lzss {
|
||||
public static int lzss_decompress(byte[] in, byte[] out) {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int flags = 0;
|
||||
int cnt = 7;
|
||||
|
||||
while(j < out.length) {
|
||||
|
||||
if(++cnt == 8) {
|
||||
if(i >= in.length) {
|
||||
break;
|
||||
}
|
||||
flags = in[i++] & 0xFF;
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
if((flags & 1) == 0) {
|
||||
if(i >= in.length) {
|
||||
break;
|
||||
}
|
||||
out[j] = in[i];
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
if((i + 1) >= in.length) {
|
||||
return -1;
|
||||
}
|
||||
int v = (in[i] & 0xFF) | (in[i+1] & 0xFF) << 8;
|
||||
i += 2;
|
||||
|
||||
int offset = (v >> 4) + 1;
|
||||
int length = (v & 0xF) + 3;
|
||||
|
||||
// not enough data decoded
|
||||
if(offset > j) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// output buffer is too small
|
||||
if((out.length - j) < length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(int k = 0; k < length; k++) {
|
||||
out[j+k] = out[j+k-offset];
|
||||
}
|
||||
j += length;
|
||||
}
|
||||
|
||||
flags >>= 1;
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
public class RC4 {
|
||||
|
||||
public static void rc4_crypt(byte[] key, byte[] data) {
|
||||
int keylen = key.length;
|
||||
int datalen = data.length;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
// key scheduling
|
||||
byte[] sbox = new byte[256];
|
||||
for(i = 0; i < 256; i++) {
|
||||
sbox[i] = (byte)i;
|
||||
}
|
||||
j = 0;
|
||||
for(i = 0; i < 256; i++) {
|
||||
j = ((j + sbox[i] + key[i % keylen]) % 256) & 0xFF;
|
||||
byte tmp = sbox[i];
|
||||
sbox[i] = sbox[j];
|
||||
sbox[j] = tmp;
|
||||
}
|
||||
|
||||
// generate output
|
||||
i = 0;
|
||||
j = 0;
|
||||
int index = 0;
|
||||
while(index < datalen) {
|
||||
i = ((i + 1) % 256) & 0xFF;
|
||||
j = ((j + sbox[i]) % 256) & 0xFF;
|
||||
|
||||
byte tmp = sbox[i];
|
||||
sbox[i] = sbox[j];
|
||||
sbox[j] = tmp;
|
||||
|
||||
byte k = (byte)(sbox[((sbox[i] + sbox[j]) % 256) & 0xFF]);
|
||||
data[index] ^= k;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,373 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class TestActivity<T> extends Activity {
|
||||
public int value;
|
||||
public int value2;
|
||||
private int test = 10;
|
||||
private static final int test2 = 20;
|
||||
public int test3 = 30;
|
||||
public int tab[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
|
||||
static {
|
||||
int t = 5;
|
||||
System.out.println("foobar");
|
||||
}
|
||||
|
||||
public TestActivity() {
|
||||
value = 100;
|
||||
value2 = 200;
|
||||
}
|
||||
|
||||
public TestActivity(int value, int value2) {
|
||||
this.value = value;
|
||||
this.value2 = value2;
|
||||
}
|
||||
|
||||
public TestActivity(double value, double value2) {
|
||||
this.test = 5;
|
||||
this.value = (int) value;
|
||||
this.value2 = (int) value2;
|
||||
}
|
||||
|
||||
public int test_base(int _value, int _value2) {
|
||||
int y = 0;
|
||||
double sd = -6;
|
||||
double zz = -5;
|
||||
double yy = -4;
|
||||
double xx = -3;
|
||||
double w = -2;
|
||||
double x = -1;
|
||||
double k = 0.0;
|
||||
double d = 1;
|
||||
double b = 2;
|
||||
double c = 3;
|
||||
double f = 4;
|
||||
double z = 5;
|
||||
double cd = 6;
|
||||
float g = 4.20f;
|
||||
|
||||
double useless = g * c + b - y + d;
|
||||
|
||||
System.out.println("VALUE = " + this.value + " VALUE 2 = "
|
||||
+ this.value2);
|
||||
|
||||
for (int i = 0; i < (_value + _value2); i++) {
|
||||
y = this.value + y - this.value2;
|
||||
y = y & 200 * test1(20);
|
||||
|
||||
y = this.value2 - y;
|
||||
}
|
||||
|
||||
try {
|
||||
int[] t = new int[5];
|
||||
t[6] = 1;
|
||||
} catch (java.lang.ArrayIndexOutOfBoundsException e) {
|
||||
System.out.println("boom");
|
||||
}
|
||||
|
||||
if (this.value > 0) {
|
||||
this.value2 = y;
|
||||
}
|
||||
|
||||
switch (this.value) {
|
||||
case 0:
|
||||
this.value2 = this.pouet();
|
||||
break;
|
||||
default:
|
||||
this.value2 = this.pouet2();
|
||||
}
|
||||
|
||||
switch (this.value) {
|
||||
case 1:
|
||||
this.value2 = this.pouet();
|
||||
break;
|
||||
case 2:
|
||||
this.value2 = this.pouet2();
|
||||
break;
|
||||
case 3:
|
||||
this.value2 = this.pouet3();
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
public int foo(int i, int j) {
|
||||
while (true) {
|
||||
try {
|
||||
while (i < j)
|
||||
i = j++ / i;
|
||||
} catch (RuntimeException re) {
|
||||
i = 10;
|
||||
continue;
|
||||
}
|
||||
if (i == 0)
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
public int foobis(int i, int j) {
|
||||
while (i < j && i != 10) {
|
||||
try {
|
||||
i = j++ / i;
|
||||
} catch (RuntimeException re) {
|
||||
i = 10;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
|
||||
}
|
||||
|
||||
public int foo2(int i, int j) {
|
||||
while (true) {
|
||||
if (i < j) {
|
||||
try {
|
||||
i = j++ / i;
|
||||
} catch (RuntimeException re) {
|
||||
i = 10;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (i == 0)
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
public int foo4(int i, int j) {
|
||||
while (i < j) {
|
||||
try {
|
||||
i = j++ / i;
|
||||
} catch (RuntimeException re) {
|
||||
i = 10;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
public int test1(int val) {
|
||||
int a = 0x10;
|
||||
|
||||
return val + a - 60 * this.value;
|
||||
}
|
||||
|
||||
public int pouet() {
|
||||
int v = this.value;
|
||||
return v;
|
||||
}
|
||||
|
||||
public void testVars(int z, char y) {
|
||||
int a = this.value * 2;
|
||||
int b = 3;
|
||||
int c = 4;
|
||||
int d = c + b * a - 1 / 3 * this.value;
|
||||
int e = c + b - a;
|
||||
int f = e + 2;
|
||||
int g = 3 * d - c + f - 8;
|
||||
int h = 10 + this.value + a + b + c + d + e + f + g;
|
||||
int i = 150 - 40 + 12;
|
||||
int j = h - i + g;
|
||||
int k = 10;
|
||||
int l = 5;
|
||||
int m = 2;
|
||||
int n = 10;
|
||||
int o = k * l + m - n * this.value + c / e - f * g + h - j;
|
||||
int p = a + b + c;
|
||||
int q = p - k + o - l;
|
||||
int r = a + b - c * d / e - f + g - h * i + j * k * l - m - n + o / p
|
||||
* q;
|
||||
System.out.println(" meh " + r);
|
||||
System.out.println(y);
|
||||
y += 'a';
|
||||
this.testVars(a, y);
|
||||
this.test1(10);
|
||||
pouet2();
|
||||
this.pouet2();
|
||||
int s = pouet2();
|
||||
}
|
||||
|
||||
public static void testDouble() {
|
||||
double f = -5;
|
||||
double g = -4;
|
||||
double h = -3;
|
||||
double i = -2;
|
||||
double j = -1;
|
||||
double k = 0;
|
||||
double l = 1;
|
||||
double m = 2;
|
||||
double n = 3;
|
||||
double o = 4;
|
||||
double p = 5;
|
||||
|
||||
long ff = -5;
|
||||
long gg = -4;
|
||||
long hh = -3;
|
||||
long ii = -2;
|
||||
long jj = -1;
|
||||
long kk = 0;
|
||||
long ll = 1;
|
||||
long mm = 2;
|
||||
long nn = 3;
|
||||
long oo = 4;
|
||||
long pp = 5;
|
||||
|
||||
float fff = -5;
|
||||
float ggg = -4;
|
||||
float hhh = -3;
|
||||
float iii = -2;
|
||||
float jjj = -1;
|
||||
float kkk = 0;
|
||||
float lll = 1;
|
||||
float mmm = 2;
|
||||
float nnn = 3;
|
||||
float ooo = 4;
|
||||
float ppp = 5;
|
||||
|
||||
double abc = 65534;
|
||||
double def = 65535;
|
||||
double ghi = 65536;
|
||||
double jkl = 65537;
|
||||
|
||||
double mno = 32769;
|
||||
double pqr = 32768;
|
||||
double stu = 32767;
|
||||
double vwx = 32766;
|
||||
|
||||
long aabc = 65534;
|
||||
long adef = 65535;
|
||||
long aghi = 65536;
|
||||
long ajkl = 65537;
|
||||
|
||||
long amno = 32769;
|
||||
long apqr = 32768;
|
||||
long astu = 32767;
|
||||
long avwx = 32766;
|
||||
|
||||
float babc = 65534;
|
||||
float bdef = 65535;
|
||||
float bghi = 65536;
|
||||
float bjkl = 65537;
|
||||
|
||||
float bmno = 32769;
|
||||
float bpqr = 32768;
|
||||
float bstu = 32767;
|
||||
float bvwx = 32766;
|
||||
|
||||
double abcd = 5346952;
|
||||
long dcba = 5346952;
|
||||
float cabd = 5346952;
|
||||
|
||||
double zabc = 65534.50;
|
||||
double zdef = 65535.50;
|
||||
double zghi = 65536.50;
|
||||
double zjkl = 65537.50;
|
||||
|
||||
double zmno = 32769.50;
|
||||
double zpqr = 32768.50;
|
||||
double zstu = 32767.50;
|
||||
double zvwx = 32766.50;
|
||||
|
||||
float xabc = 65534.50f;
|
||||
float xdef = 65535.50f;
|
||||
float xghi = 65536.50f;
|
||||
float xjkl = 65537.50f;
|
||||
|
||||
float xmno = 32769.50f;
|
||||
float xpqr = 32768.50f;
|
||||
float xstu = 32767.50f;
|
||||
float xvwx = 32766.50f;
|
||||
|
||||
float ymno = -5f;
|
||||
float ypqr = -65535f;
|
||||
float ystu = -65536f;
|
||||
float yvwx = -123456789123456789.555555555f;
|
||||
double yvwx2 = -123456789123456789.555555555;
|
||||
int boom = -606384730;
|
||||
float reboom = -123456790519087104f;
|
||||
float gettype = boom + 2 + 3.5f;
|
||||
System.out.println(gettype);
|
||||
}
|
||||
|
||||
public static void testCall1(float b) {
|
||||
System.out.println("k" + b);
|
||||
}
|
||||
|
||||
public static void testCall2(long i) {
|
||||
new PrintStream(System.out).println("k" + i);
|
||||
}
|
||||
|
||||
public static void testCalls(TestIfs d) {
|
||||
testCall2(3);
|
||||
TestIfs.testIF(5);
|
||||
System.out.println(d.getClass());
|
||||
}
|
||||
|
||||
public static void testLoop(double a) {
|
||||
while (a < 10) {
|
||||
System.out.println(a);
|
||||
a *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
public void testVarArgs(int p, long[] p2, String... p3) {
|
||||
|
||||
}
|
||||
|
||||
public void testString( )
|
||||
{
|
||||
String a = "foo";
|
||||
String b = new String("bar");
|
||||
System.out.println(a + b);
|
||||
}
|
||||
|
||||
public synchronized int pouet2() {
|
||||
int i = 0, j = 10;
|
||||
System.out.println("test");
|
||||
|
||||
while (i < j) {
|
||||
try {
|
||||
i = j++ / i;
|
||||
} catch (RuntimeException re) {
|
||||
i = 10;
|
||||
}
|
||||
}
|
||||
this.value = i;
|
||||
return 90;
|
||||
}
|
||||
|
||||
public int pouet3() {
|
||||
return 80;
|
||||
}
|
||||
|
||||
public int go() {
|
||||
System.out.println(" test_base(500, 3) " + this.test_base(500, 3));
|
||||
return test + test2 + 10;
|
||||
}
|
||||
|
||||
public void testAccessField() {
|
||||
TestArr$ays a = new TestArr$ays();
|
||||
a.d = new byte[5];
|
||||
a.d[2] = 'c';
|
||||
System.out.println("test :" + a.d[2]);
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
Toast toast = Toast.makeText(getApplicationContext(), "this is a test ! " + 42, Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
/*
|
||||
TestLoops o = new TestLoops();
|
||||
o.testIrreducible(test3, test2);
|
||||
*/
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
public class TestArr$ays {
|
||||
|
||||
public static class InternField {
|
||||
public static byte[] b;
|
||||
}
|
||||
|
||||
private byte[] b;
|
||||
public byte[] d;
|
||||
|
||||
public TestArr$ays( ) {
|
||||
b = new byte[5];
|
||||
}
|
||||
|
||||
public TestArr$ays( byte [] b ) {
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public TestArr$ays( int i ) {
|
||||
byte [] a = { 1, 2, 3, 4, 5 };
|
||||
b = a;
|
||||
}
|
||||
|
||||
public void testEmptyArrayByte( ) {
|
||||
byte [] b = new byte[5];
|
||||
InternField.b = b;
|
||||
}
|
||||
|
||||
public void testFullArrayByte( ) {
|
||||
byte[] b = { 1, 2, 4, 39, 20 };
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public void testModifArrayByte( ) {
|
||||
b[2000000] = 2;
|
||||
}
|
||||
|
||||
public void testInstanceInternArrayByte( ){
|
||||
InternField f = new InternField();
|
||||
f.b = new byte[5];
|
||||
f.b[2] = 40;
|
||||
}
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
public class TestExceptions {
|
||||
|
||||
public int testException1( int a )
|
||||
{
|
||||
try {
|
||||
a = 5 / 0;
|
||||
} catch ( ArithmeticException e ) {
|
||||
a = 3;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
public static int testException2( int a, int b ) throws ArrayIndexOutOfBoundsException
|
||||
{
|
||||
int [] t = new int[b];
|
||||
|
||||
if ( b == 10 )
|
||||
b++;
|
||||
|
||||
for( int i = 0; i < b; i++ )
|
||||
{
|
||||
t[i] = 5;
|
||||
}
|
||||
|
||||
return a + t[0];
|
||||
}
|
||||
|
||||
public int testException3( int a, int[] t )
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if ( a % 2 == 0 )
|
||||
{
|
||||
try {
|
||||
result = t[a];
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
result = 1337;
|
||||
}
|
||||
}
|
||||
else if ( a % 3 == 0 ) {
|
||||
result = a * 2;
|
||||
} else {
|
||||
result = t[0] - 10;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public int testException4( int a )
|
||||
{
|
||||
int res = 15;
|
||||
|
||||
res += a;
|
||||
|
||||
try {
|
||||
Runtime b = Runtime.getRuntime();
|
||||
b.notifyAll();
|
||||
} catch( RuntimeException e ) {
|
||||
System.out.println("runtime " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
Runtime c = Runtime.getRuntime();
|
||||
c.wait();
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
System.out.println("runtime " + e.getMessage());
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println("exception e " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
res /= a;
|
||||
} catch (Exception e) {
|
||||
System.out.println("exception e " + e.getMessage());
|
||||
}
|
||||
|
||||
System.out.println("end");
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
public static void testTry1(int b)
|
||||
{
|
||||
int a = 15;
|
||||
try {
|
||||
if ( b % 2 == 0)
|
||||
{
|
||||
a = a / b;
|
||||
if ( a - 3 == 4 )
|
||||
System.out.println("lll");
|
||||
}
|
||||
else {
|
||||
a = a * b;
|
||||
System.out.println("ppp");
|
||||
}
|
||||
} catch(ArithmeticException e){
|
||||
System.out.println("oupla");
|
||||
}
|
||||
}
|
||||
|
||||
public static void testCatch1(int b)
|
||||
{
|
||||
int a = 15;
|
||||
try {
|
||||
if ( b % 2 == 0 )
|
||||
{
|
||||
a = a / b;
|
||||
if ( a - 3 == 4 )
|
||||
System.out.println("mmm");
|
||||
} else {
|
||||
a = a * b;
|
||||
System.out.println("qqq");
|
||||
}
|
||||
} catch(ArithmeticException e)
|
||||
{
|
||||
if ( a == 12 )
|
||||
System.out.println("test");
|
||||
else {
|
||||
b += 3 * a;
|
||||
System.out.println("test2 " + b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void testExceptions( String [] z )
|
||||
{
|
||||
System.out.println( "Result test1 : " + new TestExceptions().testException1( 10 ) );
|
||||
|
||||
System.out.println( "=================================" );
|
||||
try {
|
||||
System.out.println( "Result test2 : " + testException2( 5, 10 ) );
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
System.out.println( "Result test2 : " + testException2( 5, 9 ) );
|
||||
}
|
||||
|
||||
System.out.println( "=================================" );
|
||||
int [] t = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
System.out.println( "Result test3 : " + new TestExceptions().testException3( 8, t ) );
|
||||
System.out.println( "Result test3 : " + new TestExceptions().testException3( 9, t ) );
|
||||
System.out.println( "Result test3 : " + new TestExceptions().testException3( 7, t ) );
|
||||
}
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
public class TestIfs {
|
||||
private boolean P, Q, R, S, T;
|
||||
|
||||
public static int testIF(int p) {
|
||||
int i;
|
||||
|
||||
if (p > 0) {
|
||||
i = p * 2;
|
||||
} else {
|
||||
i = p + 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int testIF2(int p) {
|
||||
int i = 0;
|
||||
|
||||
if (p > 0) {
|
||||
i = p * 2;
|
||||
} else {
|
||||
i = p + 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int testIF3(int p) {
|
||||
int i = 0;
|
||||
if (p > 0) {
|
||||
i = p * 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int testIF4(int p, int i) {
|
||||
if (p > 0 && p % 2 == 3) {
|
||||
i += p * 3;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int testIF5(int p, int i) {
|
||||
if ((p <= 0 && i == 0) || (p == i * 2 || i == p / 3)) {
|
||||
i = -p;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int testIfBool(int p, boolean b) {
|
||||
int i = 0;
|
||||
if ( p > 0 && b )
|
||||
i += p * 3;
|
||||
else if (b)
|
||||
i += 5;
|
||||
else
|
||||
i = 2;
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int testShortCircuit(int p) {
|
||||
int i = 0;
|
||||
if (p > 0 && p % 2 == 3) {
|
||||
i = p + 1;
|
||||
} else {
|
||||
i = -p;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int testShortCircuit2(int p) {
|
||||
int i = 0;
|
||||
if (p <= 0 || p % 2 != 3)
|
||||
i = -p;
|
||||
else
|
||||
i = p + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int testShortCircuit3(int p, int i) {
|
||||
if ((p <= 0 && i == 0) || (p == i * 2 || i == p / 3)) {
|
||||
i = -p;
|
||||
} else {
|
||||
i = p + 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int testShortCircuit4(int p, int i) {
|
||||
if ((p <= 0 || i == 0) && (p == i * 2 || i == p / 3))
|
||||
i = -p;
|
||||
else
|
||||
i = p + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
public void testCFG() {
|
||||
int I = 1, J = 1, K = 1, L = 1;
|
||||
|
||||
do {
|
||||
if (P) {
|
||||
J = I;
|
||||
if (Q)
|
||||
L = 2;
|
||||
else
|
||||
L = 3;
|
||||
K++;
|
||||
} else {
|
||||
K += 2;
|
||||
}
|
||||
System.out.println(I + "," + J + "," + K + "," + L);
|
||||
do {
|
||||
if (R)
|
||||
L += 4;
|
||||
} while (!S);
|
||||
I += 6;
|
||||
} while (!T);
|
||||
}
|
||||
|
||||
public void testCFG2(int a, int b, int c) {
|
||||
a += 5;
|
||||
b += a * 5;
|
||||
if (a < b) {
|
||||
if (b < c) {
|
||||
System.out.println("foo");
|
||||
} else {
|
||||
System.out.println("bar");
|
||||
}
|
||||
}
|
||||
a = 10;
|
||||
while (a < c) {
|
||||
a += c;
|
||||
do {
|
||||
b = a++;
|
||||
System.out.println("baz");
|
||||
} while (c < b);
|
||||
b++;
|
||||
}
|
||||
System.out.println("foobar");
|
||||
if (a >= 5 || b * c <= c + 10) {
|
||||
System.out.println("a = " + 5);
|
||||
}
|
||||
System.out.println("end");
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
|
||||
public class TestInvoke {
|
||||
|
||||
public TestInvoke( ) {
|
||||
TestInvoke1(42 );
|
||||
}
|
||||
|
||||
public int TestInvoke1( int a )
|
||||
{
|
||||
return TestInvoke2( a, 42 );
|
||||
}
|
||||
|
||||
public int TestInvoke2( int a, int b )
|
||||
{
|
||||
return TestInvoke3( a, b, 42 );
|
||||
}
|
||||
|
||||
public int TestInvoke3( int a, int b, int c )
|
||||
{
|
||||
return TestInvoke4( a, b, c, 42 );
|
||||
}
|
||||
|
||||
public int TestInvoke4( int a, int b, int c, int d )
|
||||
{
|
||||
return TestInvoke5( a, b, c, d, 42 );
|
||||
}
|
||||
|
||||
public int TestInvoke5(int a, int b, int c, int d, int e)
|
||||
{
|
||||
return TestInvoke6( a, b, c, d, e, 42 );
|
||||
}
|
||||
|
||||
public int TestInvoke6( int a, int b, int c, int d, int e, int f )
|
||||
{
|
||||
return TestInvoke7( a, b, c, d, e, f, 42);
|
||||
}
|
||||
|
||||
public int TestInvoke7( int a, int b, int c, int d, int e, int f, int g )
|
||||
{
|
||||
return TestInvoke8( a, b, c, d, e, f, g, 42);
|
||||
}
|
||||
|
||||
public int TestInvoke8( int a, int b, int c, int d, int e, int f, int g, int h )
|
||||
{
|
||||
return a * b * c * d * e *f * g *h;
|
||||
}
|
||||
|
||||
}
|
@ -1,238 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
import android.content.pm.LabeledIntent;
|
||||
import android.util.Log;
|
||||
|
||||
public class TestLoops {
|
||||
|
||||
protected static class Loop {
|
||||
public static int i;
|
||||
public static int j;
|
||||
}
|
||||
|
||||
public void testWhile() {
|
||||
int i = 5, j = 10;
|
||||
while (i < j) {
|
||||
j += i / 2.0 + j;
|
||||
i += i * 2;
|
||||
}
|
||||
Loop.i = i;
|
||||
Loop.j = j;
|
||||
}
|
||||
|
||||
public void testWhile2() {
|
||||
while(true)
|
||||
System.out.println("toto");
|
||||
}
|
||||
|
||||
public void testWhile3(int i, int j)
|
||||
{
|
||||
while ( i < j && i % 2 == 0 )
|
||||
{
|
||||
i += j / 3;
|
||||
}
|
||||
}
|
||||
|
||||
public void testWhile4(int i, int j)
|
||||
{
|
||||
while ( i < j || i % 2 == 0 )
|
||||
{
|
||||
i += j / 3;
|
||||
}
|
||||
}
|
||||
|
||||
public void testWhile5(int i, int j, int k )
|
||||
{
|
||||
while ( ( i < j || i % 2 == 0 ) && ( j < k || k % 2 == 0) )
|
||||
i += k - j;
|
||||
}
|
||||
|
||||
public void testFor() {
|
||||
int i, j;
|
||||
for (i = 5, j = 10; i < j; i += i * 2) {
|
||||
j += i / 2.0 + j;
|
||||
}
|
||||
Loop.i = i;
|
||||
Loop.j = j;
|
||||
}
|
||||
|
||||
public void testDoWhile() {
|
||||
int i = 5, j = 10;
|
||||
do {
|
||||
j += i / 2.0 + j;
|
||||
i += i * 2;
|
||||
} while (i < j);
|
||||
Loop.i = i;
|
||||
Loop.j = j;
|
||||
}
|
||||
|
||||
public int testNestedLoops(int a) {
|
||||
if (a > 1000) {
|
||||
return testNestedLoops(a / 2);
|
||||
} else {
|
||||
while (a > 0) {
|
||||
a += 1;
|
||||
while (a % 2 == 0) {
|
||||
a *= 2;
|
||||
while (a % 3 == 0) {
|
||||
a -= 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
public void testMultipleLoops() {
|
||||
int a = 0;
|
||||
while (a < 50)
|
||||
a += 2;
|
||||
while (a % 3 == 0)
|
||||
a *= 5;
|
||||
while (a < 789 && a > 901)
|
||||
System.out.println("woo");
|
||||
}
|
||||
|
||||
public int testDoWhileTrue(int n) {
|
||||
do {
|
||||
n--;
|
||||
if (n == 2)
|
||||
return 5;
|
||||
if (n < 2)
|
||||
n = 500;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
public int testWhileTrue(int n) {
|
||||
while (true) {
|
||||
n--;
|
||||
if (n == 2)
|
||||
return 5;
|
||||
if (n < 2)
|
||||
n = 500;
|
||||
}
|
||||
}
|
||||
|
||||
public int testDiffWhileDoWhile(int n) {
|
||||
while (n != 2) {
|
||||
if (n < 2)
|
||||
n = 500;
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
|
||||
public void testReducible(boolean x, boolean y) {
|
||||
int a = 0, b = 0;
|
||||
if (x)
|
||||
while (y) {
|
||||
a = b + 1;
|
||||
b++;
|
||||
}
|
||||
else
|
||||
while (y) {
|
||||
b++;
|
||||
a = b + 1;
|
||||
}
|
||||
Loop.i = a;
|
||||
Loop.j = b;
|
||||
}
|
||||
|
||||
public void testIrreducible(int a, int b) {
|
||||
while (true) {
|
||||
if (b < a) {
|
||||
Log.i("test", "In BasicBlock A");
|
||||
}
|
||||
b = a - 1;
|
||||
Log.i("test2", "In BasicBlock B");
|
||||
}
|
||||
}
|
||||
|
||||
public int testBreak( boolean b ) {
|
||||
int a = 0, c = 0;
|
||||
while(true) {
|
||||
System.out.println("foo");
|
||||
a += c;
|
||||
c += 5;
|
||||
if ( a == 50 )
|
||||
b = true;
|
||||
if ( b )
|
||||
break;
|
||||
}
|
||||
return a + c;
|
||||
}
|
||||
|
||||
public int testBreakbis( boolean b ) {
|
||||
int a = 0, c = 0;
|
||||
do {
|
||||
System.out.println("foo");
|
||||
a += c;
|
||||
c += 5;
|
||||
if ( a == 50 )
|
||||
b = true;
|
||||
if ( b )
|
||||
break;
|
||||
} while(true);
|
||||
return a + c;
|
||||
}
|
||||
|
||||
public int testBreakMid( boolean b ) {
|
||||
int a = Loop.i, c = Loop.j;
|
||||
while(true) {
|
||||
System.out.println("foo");
|
||||
a += c;
|
||||
c += 5;
|
||||
if ( a == 50 )
|
||||
b = !b;
|
||||
if ( b ) break;
|
||||
System.out.println("bar");
|
||||
a *= 2;
|
||||
}
|
||||
return a + c;
|
||||
}
|
||||
|
||||
public int testBreakDoWhile( boolean b ) {
|
||||
int a = 0, c = 0;
|
||||
do {
|
||||
System.out.println("foo");
|
||||
a += c;
|
||||
c += 5;
|
||||
if ( a == 50 )
|
||||
b = true;
|
||||
}while ( b );
|
||||
return a + c;
|
||||
}
|
||||
|
||||
public int testBreak2( boolean b ) {
|
||||
int a = 0, c = 0;
|
||||
while (true) {
|
||||
System.out.println("foo");
|
||||
a += c;
|
||||
c += 5;
|
||||
if ( a == 50 && b )
|
||||
break;
|
||||
}
|
||||
return a + c;
|
||||
}
|
||||
|
||||
public void testBreak3( boolean b ) {
|
||||
int a = 0, c = 0;
|
||||
while ( true ){
|
||||
System.out.println("foo");
|
||||
a += c;
|
||||
c += 5;
|
||||
if ( a == 50 && b )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void testBreak4( boolean b, int d ) {
|
||||
int a = 0, c = 0;
|
||||
while ( c < 50 ) {
|
||||
System.out.println("foo");
|
||||
a += c;
|
||||
c +=5;
|
||||
if ( a == d )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
public class TestQuickSort {
|
||||
public int a = 10;
|
||||
|
||||
public static void Main(String[] args) {
|
||||
int[] intArray = new int[args.length];
|
||||
for (int i = 0; i < intArray.length; i++) {
|
||||
intArray[i] = Integer.parseInt(args[i]);
|
||||
}
|
||||
QuickSort(intArray, 0, intArray.length - 1);
|
||||
for (int i = 0; i < intArray.length; i++) {
|
||||
System.out.println(intArray[i] + " ");
|
||||
}
|
||||
}
|
||||
|
||||
public static void QuickSort(int[] array, int left, int right) {
|
||||
if (right > left) {
|
||||
int pivotIndex = (left + right) / 2;
|
||||
int pivotNew = Partition(array, left, right, pivotIndex);
|
||||
QuickSort(array, left, pivotNew - 1);
|
||||
QuickSort(array, pivotNew + 1, right);
|
||||
}
|
||||
}
|
||||
|
||||
static int Partition(int[] array, int left, int right, int pivotIndex) {
|
||||
int pivotValue = array[pivotIndex];
|
||||
Swap(array, pivotIndex, right);
|
||||
int storeIndex = left;
|
||||
for (int i = left; i < right; i++) {
|
||||
if (array[i] <= pivotValue) {
|
||||
Swap(array, storeIndex, i);
|
||||
storeIndex++;
|
||||
}
|
||||
}
|
||||
Swap(array, right, storeIndex);
|
||||
return storeIndex;
|
||||
}
|
||||
|
||||
static void Swap(int[] array, int index1, int index2) {
|
||||
int tmp = array[index1];
|
||||
array[index1] = array[index2];
|
||||
array[index2] = tmp;
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
public class TestQuickSort2 {
|
||||
|
||||
public int a = 10;
|
||||
|
||||
public static void Main(String[] args) {
|
||||
int[] intArray = new int[args.length];
|
||||
for (int i = 0; i < intArray.length; i++) {
|
||||
intArray[i] = Integer.parseInt(args[i]);
|
||||
}
|
||||
quicksort(intArray, 0, intArray.length - 1);
|
||||
for (int i = 0; i < intArray.length; i++) {
|
||||
System.out.println(intArray[i] + " ");
|
||||
}
|
||||
}
|
||||
|
||||
public static void quicksort(int[] array, int lo, int hi) {
|
||||
int i = lo;
|
||||
int j = hi;
|
||||
|
||||
int pivot = array[lo + (hi - lo) / 2];
|
||||
|
||||
while(i <= j) {
|
||||
|
||||
while(array[i] < pivot) {
|
||||
i++;
|
||||
}
|
||||
|
||||
while(array[j] > pivot) {
|
||||
j--;
|
||||
}
|
||||
|
||||
if(i <= j) {
|
||||
int temp = array[i];
|
||||
array[i] = array[j];
|
||||
array[j] = temp;
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
if(lo < j) {
|
||||
quicksort(array, lo, j);
|
||||
}
|
||||
|
||||
if(i < hi) {
|
||||
quicksort(array, i, hi);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package tests.androguard;
|
||||
|
||||
public class TestSynthetic {
|
||||
|
||||
public static void TestSynthetic1( ){
|
||||
final Object o = new Object();
|
||||
|
||||
new Thread(){
|
||||
public void run(){
|
||||
System.out.println( "o : " + o.hashCode() );
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public static void TestSynthetic2() {
|
||||
System.out.println( "o : " +
|
||||
new Object(){
|
||||
public int toto(char c){
|
||||
return Integer.parseInt("" + c);
|
||||
}
|
||||
}.toto('k')
|
||||
);
|
||||
}
|
||||
|
||||
public static void TestSynthetic3( ){
|
||||
Integer o = Integer.valueOf(5);
|
||||
|
||||
new Thread(){
|
||||
Integer o = this.o;
|
||||
public void run(){
|
||||
System.out.println( "o : " + o.hashCode() );
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public static void TestSynthetic4( final int t ) {
|
||||
final Object o = new Object();
|
||||
|
||||
new Thread(){
|
||||
public void run(){
|
||||
synchronized(o){
|
||||
if ( t == 0 ) {
|
||||
TestSynthetic1();
|
||||
}
|
||||
else {
|
||||
TestSynthetic2();
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
|
||||
System.out.println("end");
|
||||
}
|
||||
|
||||
|
||||
public class Bridge<T> {
|
||||
public T getT(T arg){
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
|
||||
public class BridgeExt extends Bridge<String>{
|
||||
public String getT(String arg){
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestBridge( ){
|
||||
TestSynthetic p = new TestSynthetic();
|
||||
TestSynthetic.Bridge<Integer> x = p.new Bridge<Integer>();
|
||||
System.out.println("bridge<integer> " + x.getT(5));
|
||||
TestSynthetic.Bridge<String> w = p.new BridgeExt();
|
||||
System.out.println("bridgeext " + w.getT("toto"));
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lawrence Nahum, Ottavio Fontolan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
@ -1,75 +0,0 @@
|
||||
ABCore - Android Bitcoin Core
|
||||
=============================
|
||||
|
||||
[![Build Status](https://travis-ci.org/greenaddress/abcore.svg?branch=master)](https://travis-ci.org/greenaddress/abcore)
|
||||
|
||||
<a href="http://abco.re"> <img src="http://abco.re/assets/images/schema.png" alt="Infographic" width="650" height="650"></a>
|
||||
|
||||
Web site: <a href="http://abco.re">abco.re</a>
|
||||
|
||||
Warning: This app is still in a very Proof of Concept/Alpha stage.
|
||||
|
||||
<a href="https://f-droid.org/packages/com.greenaddress.abcore/" target="_blank">
|
||||
<img src="https://f-droid.org/badge/get-it-on.png" height="90"/></a>
|
||||
<a href="https://play.google.com/apps/testing/com.greenaddress.abcore" target="_blank">
|
||||
<img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png" height="90"/></a>
|
||||
|
||||
If you want to try it, you can also get it directly from GitHub [here](https://github.com/greenaddress/abcore/releases/tag/v0.62alphaPoC).
|
||||
|
||||
What is Android Bitcoin Core?
|
||||
-----------------------------
|
||||
|
||||
Android Bitcoin Core is an Android app that fetches bitcoin core daemon built for Android using the NDK and is meant to make it easier
|
||||
to run Bitcoin Core daemon node on always on Android set top box devices and home appliances as well as mobile devices.
|
||||
|
||||
The full node software (Core 0.15.1 and Knots) is meant to be used as a personal node when on the go (either by using a mobile wallet that allows to connect to a remote and specific node or even directly on your mobile device).
|
||||
|
||||
ABCore works on x86, x86_64, armhf and arm64 Android (any version from Lollipop onwards - sdk 21). Mips is not supported.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
ABCore is released under the terms of the MIT license. See [COPYING](COPYING) for more
|
||||
information or see https://opensource.org/licenses/MIT.
|
||||
|
||||
Privacy
|
||||
-------
|
||||
|
||||
ABCore doesn't do any kind of phone home, doesn't have In-App Purchase or advertising.
|
||||
|
||||
During the initial configuration it connects to Github to fetch the required binaries and once it is installed it only communicates with the rest of the Bitcoin network like any normal full node.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
ABCore requires a fair amount of ram (tested with 2GB) and a fair amount of disk space (tested with 256GB for non pruned node) as well as a decent always on connection - 3G or 4G is not adviced.
|
||||
|
||||
We also do not advice to use this as a wallet at this time, we advice to use this as your personal blockchain anchor when on the go with wallets that support to set a personal node.
|
||||
|
||||
The contributors of ABCore are not liable for any cost or damage caused by the app including but not limited to data charges/penalties.
|
||||
|
||||
Acknowledgement
|
||||
---------------
|
||||
|
||||
- Development
|
||||
|
||||
Lawrence Nahum
|
||||
twitter.com/LarryBitcoin
|
||||
|
||||
- Graphic Content
|
||||
|
||||
Ottavio Fontolan
|
||||
otta88.box (at) gmail (dot) com
|
||||
|
||||
- Testing & UX
|
||||
|
||||
Gabriele Domenichini
|
||||
twitter.com/gabridome
|
||||
|
||||
- Community Manager
|
||||
|
||||
Timothy Redaelli
|
||||
twitter.com/drizztbsd
|
||||
timothy.redaelli (at) gmail (dot) com
|
||||
|
||||
Special thanks to the [Bitcoin Core dev team](https://bitcoincore.org/), the [Arch Linux](https://www.archlinux.org/) teams and to [Alessandro Polverini](https://github.com/Polve) for the [Java RPC client](https://github.com/Polve/JavaBitcoindRpcClient).
|