mirror of
https://github.com/androguard/androguard.git
synced 2024-10-07 02:03:30 +00:00
Merge pull request #982 from androguard/improve_tests_part_c
adding the rest of the tests
This commit is contained in:
commit
506da27aa1
2
.github/workflows/pythonpublish.yml
vendored
2
.github/workflows/pythonpublish.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
||||
run: poetry install
|
||||
|
||||
- name: Run unittest tests
|
||||
run: poetry run python -m unittest tests/test_apk.py tests/test_axml.py
|
||||
run: poetry run python -m unittest discover -s tests -p 'test_*.py'
|
||||
|
||||
- name: Build with Poetry
|
||||
run: |
|
||||
|
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
||||
run: poetry install
|
||||
|
||||
- name: Run unittest tests
|
||||
run: poetry run python -m unittest tests/test_apk.py tests/test_axml.py
|
||||
run: poetry run python -m unittest discover -s tests -p 'test_*.py'
|
||||
|
||||
- name: Build with Poetry
|
||||
run: |
|
||||
|
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,13 +0,0 @@
|
||||
|
||||
### 4.0.1 - 21/12/2023
|
||||
- Update/fix tests for axml and apk and add necessary resources
|
||||
- Update readme.md
|
||||
- Added github action to run tests when a new PR is requested
|
||||
- Fix for https://github.com/androguard/androguard/issues/963
|
||||
- Fix for https://github.com/androguard/androguard/issues/970
|
||||
- Multi disk check in V2/3 signature check converted to only throw a warning
|
||||
- axml processing now covers also attributes start and size
|
||||
- AOSP permissions updated to reach API 34
|
||||
|
||||
### 4.0.0 - 14/12/2023
|
||||
- First release after 3.4.0a1 from 2020
|
@ -7982,7 +7982,6 @@ class DEX:
|
||||
:rtype: a list with all :class:`EncodedMethod` objects
|
||||
"""
|
||||
# TODO could use a generator here
|
||||
name = bytes(name)
|
||||
prog = re.compile(name)
|
||||
l = []
|
||||
for i in self.get_classes():
|
||||
@ -8000,7 +7999,6 @@ class DEX:
|
||||
:rtype: a list with all :class:`EncodedField` objects
|
||||
"""
|
||||
# TODO could use a generator here
|
||||
name = bytes(name)
|
||||
prog = re.compile(name)
|
||||
l = []
|
||||
for i in self.get_classes():
|
||||
|
BIN
tests/data/APK/Annotation_classes.dex
Normal file
BIN
tests/data/APK/Annotation_classes.dex
Normal file
Binary file not shown.
BIN
tests/data/APK/FillArrays.dex
Normal file
BIN
tests/data/APK/FillArrays.dex
Normal file
Binary file not shown.
BIN
tests/data/APK/StringTests.dex
Normal file
BIN
tests/data/APK/StringTests.dex
Normal file
Binary file not shown.
BIN
tests/data/APK/Test.dex
Normal file
BIN
tests/data/APK/Test.dex
Normal file
Binary file not shown.
@ -5,6 +5,7 @@ from binascii import hexlify
|
||||
# Output format will be:
|
||||
# <class name> <method name> <bytecode as hex string>
|
||||
import sys
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
from androguard.core.dex import readuleb128, readsleb128, DalvikPacker
|
||||
@ -19,13 +20,16 @@ def read_null_terminated(f):
|
||||
else:
|
||||
x.append(ord(z))
|
||||
|
||||
|
||||
class MockClassManager():
|
||||
@property
|
||||
def packer(self):
|
||||
return DalvikPacker(0x12345678)
|
||||
|
||||
|
||||
cm = MockClassManager()
|
||||
|
||||
|
||||
class read_dex:
|
||||
|
||||
def __init__(self, fname):
|
||||
@ -33,17 +37,17 @@ class read_dex:
|
||||
|
||||
with open(fname, "rb") as f:
|
||||
magic, checksum, signature, file_size, header_size, endian_tag, link_size, \
|
||||
link_off, map_off, self.string_ids_size, string_ids_off, type_ids_size, \
|
||||
type_ids_off, proto_ids_size, proto_ids_off, field_ids_size, field_ids_off, \
|
||||
method_ids_size, method_ids_off, class_defs_size, class_defs_off, data_size, \
|
||||
data_off = unpack("<8sI20s20I", f.read(112))
|
||||
link_off, map_off, self.string_ids_size, string_ids_off, type_ids_size, \
|
||||
type_ids_off, proto_ids_size, proto_ids_off, field_ids_size, field_ids_off, \
|
||||
method_ids_size, method_ids_off, class_defs_size, class_defs_off, data_size, \
|
||||
data_off = unpack("<8sI20s20I", f.read(112))
|
||||
|
||||
# print("class_defs_size", class_defs_size, "class_defs_off", class_defs_off)
|
||||
for i in range(class_defs_size):
|
||||
# class_def_item
|
||||
f.seek(class_defs_off + i * 8 * 4)
|
||||
class_idx, access_flags, superclass_idx, interfaces_off, source_file_idx, \
|
||||
annotations_off, class_data_off, static_values_off = unpack("<8I", f.read(8 * 4))
|
||||
annotations_off, class_data_off, static_values_off = unpack("<8I", f.read(8 * 4))
|
||||
|
||||
# Now parse the class_data_item
|
||||
if class_data_off == 0:
|
||||
@ -53,7 +57,7 @@ class read_dex:
|
||||
instance_fields_size = readuleb128(cm, f)
|
||||
direct_methods_size = readuleb128(cm, f)
|
||||
virtual_methods_size = readuleb128(cm, f)
|
||||
#print("class_data_item:", static_fields_size, instance_fields_size, direct_methods_size, virtual_methods_size)
|
||||
# print("class_data_item:", static_fields_size, instance_fields_size, direct_methods_size, virtual_methods_size)
|
||||
|
||||
# We do not need the fields...
|
||||
for _ in range(static_fields_size + instance_fields_size):
|
||||
@ -83,7 +87,6 @@ class read_dex:
|
||||
method_idx += method_idx_diff
|
||||
methods.append([method_idx, code_off])
|
||||
|
||||
|
||||
# Read the string section
|
||||
strings = dict()
|
||||
self.str_raw = dict()
|
||||
@ -112,8 +115,6 @@ class read_dex:
|
||||
class_idx, proto_idx, name_idx = unpack("<HHI", f.read(8))
|
||||
method_ids[i] = [strings[self.types[class_idx]], strings[name_idx]]
|
||||
|
||||
|
||||
|
||||
# Now parse the found methods and print to stdout
|
||||
mres = dict()
|
||||
for method_idx, code_off in methods:
|
||||
@ -158,6 +159,4 @@ class read_dex:
|
||||
if __name__ == "__main__":
|
||||
for midx, buff in read_dex(sys.argv[1]).methods.items():
|
||||
pass
|
||||
#print(midx, buff)
|
||||
|
||||
|
||||
# print(midx, buff)
|
@ -1,16 +1,19 @@
|
||||
import os
|
||||
import unittest
|
||||
import sys
|
||||
from androguard.core.bytecodes import dvm
|
||||
|
||||
from androguard.core.dex import DEX
|
||||
|
||||
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
class AnnotationTest(unittest.TestCase):
|
||||
def testAnnotation(self):
|
||||
with open("examples/android/TestsAnnotation/classes.dex", "rb") as f:
|
||||
d = dvm.DEX(f.read())
|
||||
with open(os.path.join(test_dir, 'data/APK/Annotation_classes.dex'), "rb") as f:
|
||||
d = DEX(f.read())
|
||||
|
||||
clazz = d.get_class('Landroid/support/v4/widget/SlidingPaneLayout$SlidingPanelLayoutImplJB;')
|
||||
annotations = clazz._get_annotation_type_ids()
|
||||
self.assertIn('Landroid/support/annotation/RequiresApi;', [clazz.CM.get_type(annotation.type_idx) for annotation in annotations])
|
||||
self.assertIn('Landroid/support/annotation/RequiresApi;',
|
||||
[clazz.CM.get_type(annotation.type_idx) for annotation in annotations])
|
||||
|
||||
self.assertIn('Landroid/support/annotation/RequiresApi;', clazz.get_annotations())
|
||||
|
||||
|
@ -294,7 +294,6 @@ class APKTest(unittest.TestCase):
|
||||
self.assertEqual(hashlib.sha256(c).hexdigest(), h)
|
||||
|
||||
if a.is_signed_v3():
|
||||
print(apath)
|
||||
if apath == "weird-compression-method.apk":
|
||||
with self.assertRaises(NotImplementedError):
|
||||
a.get_certificates_der_v3()
|
||||
|
@ -1,9 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import unittest
|
||||
from lxml import etree
|
||||
|
||||
import sys
|
||||
sys.path.append('.')
|
||||
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
from androguard.core import apk, axml
|
||||
from operator import itemgetter
|
||||
@ -29,8 +29,7 @@ TEST_CONFIGS = {
|
||||
class ARSCTest(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
with open("examples/android/TestsAndroguard/bin/TestActivity.apk",
|
||||
"rb") as fd:
|
||||
with open(os.path.join(test_dir, 'data/APK/TestActivity.apk'), "rb") as fd:
|
||||
cls.apk = apk.APK(fd.read(), True)
|
||||
|
||||
def testARSC(self):
|
||||
@ -79,7 +78,8 @@ class ARSCTest(unittest.TestCase):
|
||||
"""
|
||||
Test if the resolving of different string locales works
|
||||
"""
|
||||
a = APK("examples/tests/a2dp.Vol_137.apk")
|
||||
a = apk.APK(os.path.join(test_dir, 'data/APK/a2dp.Vol_137.apk'))
|
||||
|
||||
arsc = a.get_android_resources()
|
||||
|
||||
p = arsc.get_packages_names()[0]
|
||||
@ -122,7 +122,7 @@ class ARSCTest(unittest.TestCase):
|
||||
"received unexpected resource types: %s" % unexpected_types)
|
||||
|
||||
def testFallback(self):
|
||||
a = apk.APK("examples/tests/com.teleca.jamendo_35.apk")
|
||||
a = apk.APK(os.path.join(test_dir, 'data/APK/com.teleca.jamendo_35.apk'))
|
||||
|
||||
# Should use the fallback
|
||||
self.assertEqual(a.get_app_name(), "Jamendo")
|
||||
@ -135,11 +135,15 @@ class ARSCTest(unittest.TestCase):
|
||||
# With default config, but fallback
|
||||
self.assertEqual(len(res_parser.get_res_configs(res_id, axml.ARSCResTableConfig.default_config())), 1)
|
||||
# With default config but no fallback
|
||||
self.assertEqual(len(res_parser.get_res_configs(res_id, axml.ARSCResTableConfig.default_config(), fallback=False)), 0)
|
||||
self.assertEqual(
|
||||
len(res_parser.get_res_configs(res_id, axml.ARSCResTableConfig.default_config(), fallback=False)), 0)
|
||||
|
||||
# Also test on resolver:
|
||||
self.assertListEqual(list(map(itemgetter(1), res_parser.get_resolved_res_configs(res_id))), ["Jamendo", "Jamendo"])
|
||||
self.assertListEqual(list(map(itemgetter(1), res_parser.get_resolved_res_configs(res_id, axml.ARSCResTableConfig.default_config()))), ["Jamendo"])
|
||||
self.assertListEqual(list(map(itemgetter(1), res_parser.get_resolved_res_configs(res_id))),
|
||||
["Jamendo", "Jamendo"])
|
||||
self.assertListEqual(list(
|
||||
map(itemgetter(1), res_parser.get_resolved_res_configs(res_id, axml.ARSCResTableConfig.default_config()))),
|
||||
["Jamendo"])
|
||||
|
||||
def testIDParsing(self):
|
||||
parser = axml.ARSCParser.parse_id
|
||||
|
@ -1,22 +1,24 @@
|
||||
import unittest
|
||||
|
||||
from androguard.misc import AnalyzeDex
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
from androguard.misc import AnalyzeAPK
|
||||
from androguard.decompiler.decompile import DvMethod, DvClass
|
||||
|
||||
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
class DecompilerTest(unittest.TestCase):
|
||||
def testSimplification(self):
|
||||
h, d, dx = AnalyzeDex("examples/tests/Test.dex")
|
||||
h, d, dx = AnalyzeDex(os.path.join(test_dir, 'data/APK/Test.dex'))
|
||||
|
||||
z, = d.get_classes()
|
||||
|
||||
self.assertIn("return ((23 - p3) | ((p3 + 66) & 26));", z.get_source())
|
||||
|
||||
def testArrays(self):
|
||||
h, d, dx = AnalyzeDex("examples/tests/FillArrays.dex")
|
||||
h, d, dx = AnalyzeDex(os.path.join(test_dir, 'data/APK/FillArrays.dex'))
|
||||
|
||||
z, = d.get_classes()
|
||||
|
||||
@ -29,6 +31,27 @@ class DecompilerTest(unittest.TestCase):
|
||||
# Failed version of short array
|
||||
self.assertNotIn("{5, 0, 10, 0};", z.get_source())
|
||||
|
||||
def test_all_decompiler(self):
|
||||
# Generate test cases for this APK:
|
||||
a, d, dx = AnalyzeAPK(os.path.join(test_dir, 'data/APK/hello-world.apk'))
|
||||
for c in d[0].get_classes():
|
||||
test_name = re.sub("[^a-zA-Z0-9_]", "_", str(c.get_name())[1:-1])
|
||||
# Test the decompilation of a single class
|
||||
# disable for now, as testing all DvMethods has the same effect as
|
||||
# testing all DvClasses.
|
||||
# yield dvclass, c, dx
|
||||
|
||||
# Test the decompilation of all single methods in the class
|
||||
# if methods are in the class
|
||||
if len(c.get_methods()) == 0:
|
||||
# But we test on all classes that have no methods.
|
||||
yield dvclass, c, dx
|
||||
continue
|
||||
|
||||
yield dvmethod, c, dx, False
|
||||
# Disable tests for doAST=True for now...
|
||||
yield dvmethod, c, dx, True
|
||||
|
||||
|
||||
def dvmethod(c, dx, doAST=False):
|
||||
for m in c.get_methods():
|
||||
@ -42,6 +65,7 @@ def dvmethod(c, dx, doAST=False):
|
||||
else:
|
||||
assert ms.get_source() is not None
|
||||
|
||||
|
||||
def dvclass(c, dx):
|
||||
dc = DvClass(c, dx)
|
||||
dc.process()
|
||||
@ -49,27 +73,5 @@ def dvclass(c, dx):
|
||||
assert dc.get_source() is not None
|
||||
|
||||
|
||||
def test_all_decompiler():
|
||||
# Generate test cases for this APK:
|
||||
a, d, dx = AnalyzeAPK("examples/tests/hello-world.apk")
|
||||
for c in d[0].get_classes():
|
||||
test_name = re.sub("[^a-zA-Z0-9_]", "_", str(c.get_name())[1:-1])
|
||||
# Test the decompilation of a single class
|
||||
# disable for now, as testing all DvMethods has the same effect as
|
||||
# testing all DvClasses.
|
||||
#yield dvclass, c, dx
|
||||
|
||||
# Test the decompilation of all single methods in the class
|
||||
# if methods are in the class
|
||||
if len(c.get_methods()) == 0:
|
||||
# But we test on all classes that have no methods.
|
||||
yield dvclass, c, dx
|
||||
continue
|
||||
|
||||
yield dvmethod, c, dx, False
|
||||
# Disable tests for doAST=True for now...
|
||||
yield dvmethod, c, dx, True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -1,10 +1,9 @@
|
||||
"""Tests for def_use."""
|
||||
|
||||
import sys
|
||||
sys.path.append('.')
|
||||
import os
|
||||
from unittest import mock
|
||||
|
||||
import collections
|
||||
import mock
|
||||
import unittest
|
||||
|
||||
from androguard.decompiler import dataflow
|
||||
@ -12,19 +11,10 @@ from androguard.decompiler import graph
|
||||
from androguard.decompiler import instruction
|
||||
from androguard.decompiler import basic_blocks
|
||||
|
||||
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
class DataflowTest(unittest.TestCase):
|
||||
def assertItemsEqual(self, a, b):
|
||||
"""
|
||||
This method was renamed in python3.
|
||||
To provide compability with python2,
|
||||
we added this wrapper.
|
||||
"""
|
||||
try:
|
||||
return super().assertItemsEqual(a, b)
|
||||
except AttributeError as e:
|
||||
return self.assertCountEqual(a, b)
|
||||
|
||||
def _CreateMockIns(self, uses, lhs=None):
|
||||
mock_ins = mock.create_autospec(instruction.IRForm)
|
||||
mock_ins.get_used_vars.return_value = uses
|
||||
@ -162,7 +152,7 @@ class DataflowTest(unittest.TestCase):
|
||||
}
|
||||
self.assertDictEqual(analysis.A, expected_A)
|
||||
self.assertDictEqual(analysis.R, expected_R)
|
||||
self.assertItemsEqual(analysis.def_to_loc, expected_def_to_loc)
|
||||
self.assertCountEqual(analysis.def_to_loc, expected_def_to_loc)
|
||||
|
||||
@mock.patch.object(dataflow, 'reach_def_analysis')
|
||||
def testDefUseGCD(self, mock_reach_def):
|
||||
@ -237,12 +227,12 @@ class DataflowTest(unittest.TestCase):
|
||||
}
|
||||
|
||||
ud, du = dataflow.build_def_use(graph_mock, mock.sentinel)
|
||||
self.assertItemsEqual(du, expected_du)
|
||||
self.assertCountEqual(du, expected_du)
|
||||
for entry in du:
|
||||
self.assertItemsEqual(du[entry], expected_du[entry])
|
||||
self.assertItemsEqual(ud, expected_ud)
|
||||
self.assertCountEqual(du[entry], expected_du[entry])
|
||||
self.assertCountEqual(ud, expected_ud)
|
||||
for entry in ud:
|
||||
self.assertItemsEqual(ud[entry], expected_ud[entry])
|
||||
self.assertCountEqual(ud[entry], expected_ud[entry])
|
||||
|
||||
@mock.patch.object(dataflow, 'reach_def_analysis')
|
||||
def testDefUseIfBool(self, mock_reach_def):
|
||||
@ -307,7 +297,7 @@ class DataflowTest(unittest.TestCase):
|
||||
|
||||
ud, du = dataflow.build_def_use(graph_mock, mock.sentinel)
|
||||
self.assertEqual(ud, expected_ud)
|
||||
self.assertItemsEqual(du, expected_du)
|
||||
self.assertCountEqual(du, expected_du)
|
||||
|
||||
def testGroupVariablesGCD(self):
|
||||
du = {
|
||||
@ -342,7 +332,7 @@ class DataflowTest(unittest.TestCase):
|
||||
'ret': [([3, 8], [9])]
|
||||
}
|
||||
groups = dataflow.group_variables(['a', 'b', 'c', 'd', 'ret'], du, ud)
|
||||
self.assertItemsEqual(groups, expected_groups)
|
||||
self.assertCountEqual(groups, expected_groups)
|
||||
|
||||
def testGroupVariablesIfBool(self):
|
||||
du = {
|
||||
@ -371,9 +361,9 @@ class DataflowTest(unittest.TestCase):
|
||||
2: [([-1], [1, 6])],
|
||||
3: [([-2], [2, 3])]
|
||||
}
|
||||
self.assertItemsEqual(groups, expected_groups)
|
||||
self.assertCountEqual(groups, expected_groups)
|
||||
for entry in groups:
|
||||
self.assertItemsEqual(groups[entry], expected_groups[entry])
|
||||
self.assertCountEqual(groups[entry], expected_groups[entry])
|
||||
|
||||
@mock.patch.object(dataflow, 'group_variables')
|
||||
def testSplitVariablesGCD(self, group_variables_mock):
|
||||
|
@ -1,8 +1,5 @@
|
||||
"""Tests for graph."""
|
||||
|
||||
import sys
|
||||
sys.path.append('.')
|
||||
|
||||
import unittest
|
||||
from androguard.decompiler import graph
|
||||
|
||||
|
@ -1,9 +1,5 @@
|
||||
"""Tests for rpo."""
|
||||
|
||||
import sys
|
||||
|
||||
sys.path.append('.')
|
||||
|
||||
import unittest
|
||||
from androguard.decompiler import graph
|
||||
from androguard.decompiler import node
|
||||
|
@ -2,73 +2,9 @@ import unittest
|
||||
|
||||
import random
|
||||
import binascii
|
||||
from loguru import logger
|
||||
|
||||
import sys
|
||||
sys.path.append("./")
|
||||
|
||||
from androguard.core import dex
|
||||
|
||||
class DexTest(unittest.TestCase):
|
||||
def testBrokenDex(self):
|
||||
"""Test various broken DEX headers"""
|
||||
# really not a dex file
|
||||
with self.assertRaises(ValueError) as cnx:
|
||||
dex.DEX(b'\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
self.assertIn('Header too small', str(cnx.exception))
|
||||
|
||||
# Adler32 will not match, zeroed out file
|
||||
data_dex = binascii.unhexlify('6465780A303335001F6C4D5A6ACF889AF588F3237FC9F20B41F56A2408749D1B'
|
||||
'C81E000070000000785634120000000000000000341E00009400000070000000'
|
||||
'2E000000C0020000310000007803000011000000C4050000590000004C060000'
|
||||
'090000001409000094140000340A0000' + ('00' * (7880 - 0x70)))
|
||||
|
||||
with self.assertRaises(ValueError) as cnx:
|
||||
dex.DEX(data_dex)
|
||||
self.assertIn("Adler32", str(cnx.exception))
|
||||
|
||||
# A very very basic dex file (without a map)
|
||||
# But should parse...
|
||||
data_dex = binascii.unhexlify('6465780A30333500460A4882696E76616C6964696E76616C6964696E76616C69'
|
||||
'7000000070000000785634120000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
'00000000000000000000000000000000')
|
||||
self.assertIsNotNone(dex.DEX(data_dex))
|
||||
|
||||
# Wrong header size
|
||||
data_dex = binascii.unhexlify('6465780A30333500480A2C8D696E76616C6964696E76616C6964696E76616C69'
|
||||
'7100000071000000785634120000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000')
|
||||
with self.assertRaises(ValueError) as cnx:
|
||||
dex.DEX(data_dex)
|
||||
self.assertIn("Wrong header size", str(cnx.exception))
|
||||
|
||||
# Non integer version, but parse it
|
||||
data_dex = binascii.unhexlify('6465780AFF00AB00460A4882696E76616C6964696E76616C6964696E76616C69'
|
||||
'7000000070000000785634120000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
'00000000000000000000000000000000')
|
||||
self.assertIsNotNone(dex.DEX(data_dex))
|
||||
|
||||
# Big Endian file
|
||||
data_dex = binascii.unhexlify('6465780A30333500460AF480696E76616C6964696E76616C6964696E76616C69'
|
||||
'7000000070000000123456780000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
'00000000000000000000000000000000')
|
||||
with self.assertRaises(NotImplementedError) as cnx:
|
||||
dex.DEX(data_dex)
|
||||
self.assertIn("swapped endian tag", str(cnx.exception))
|
||||
|
||||
# Weird endian file
|
||||
data_dex = binascii.unhexlify('6465780A30333500AB0BC3E4696E76616C6964696E76616C6964696E76616C69'
|
||||
'7000000070000000ABCDEF120000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
'00000000000000000000000000000000')
|
||||
with self.assertRaises(ValueError) as cnx:
|
||||
dex.DEX(data_dex)
|
||||
self.assertIn("Wrong endian tag", str(cnx.exception))
|
||||
|
||||
|
||||
class MockClassManager():
|
||||
@property
|
||||
@ -111,7 +47,8 @@ class InstructionTest(unittest.TestCase):
|
||||
self.assertEqual(instruction.get_raw(), bytecode)
|
||||
|
||||
# Test with some pseudorandom stuff
|
||||
if ins.__name__ in ['Instruction10x', 'Instruction20t', 'Instruction30t', 'Instruction32x', 'Instruction45cc']:
|
||||
if ins.__name__ in ['Instruction10x', 'Instruction20t', 'Instruction30t', 'Instruction32x',
|
||||
'Instruction45cc']:
|
||||
# note this only works for certain opcode (which are not forced to 0 in certain places)
|
||||
# Thus we need to make sure these places are zero.
|
||||
# Instruction45cc: Has constrained regarding the parameter AA
|
||||
@ -268,15 +205,16 @@ class InstructionTest(unittest.TestCase):
|
||||
ins = list(dex.LinearSweepAlgorithm.get_instructions(MockClassManager(), 2, bytearray(b"\x00\x00"
|
||||
b"\xff\xab"), 0))
|
||||
|
||||
|
||||
def testIncompleteInstruction(self):
|
||||
"""Test if incomplete bytecode log an error"""
|
||||
# Test if instruction can be parsed
|
||||
self.assertIsInstance(dex.Instruction51l(MockClassManager(),
|
||||
bytearray(b'\x18\x01\x23\x23\x00\xff\x99\x11\x22\x22')), dex.Instruction51l)
|
||||
bytearray(b'\x18\x01\x23\x23\x00\xff\x99\x11\x22\x22')),
|
||||
dex.Instruction51l)
|
||||
|
||||
with self.assertRaises(dex.InvalidInstruction):
|
||||
ins = list(dex.LinearSweepAlgorithm.get_instructions(MockClassManager(), 5, bytearray(b"\x18\x01\xff\xff"), 0))
|
||||
ins = list(
|
||||
dex.LinearSweepAlgorithm.get_instructions(MockClassManager(), 5, bytearray(b"\x18\x01\xff\xff"), 0))
|
||||
|
||||
def testInstruction21h(self):
|
||||
"""Test function of Instruction 21h used for const{,-wide}/high16"""
|
||||
@ -306,7 +244,8 @@ class InstructionTest(unittest.TestCase):
|
||||
|
||||
def testInstruction51l(self):
|
||||
"""test the functionality of const-wide"""
|
||||
ins = dex.Instruction51l(MockClassManager(), bytearray([0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
|
||||
ins = dex.Instruction51l(MockClassManager(),
|
||||
bytearray([0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))
|
||||
self.assertEqual(ins.get_op_value(), 0x18)
|
||||
self.assertEqual(ins.get_literals(), [0])
|
||||
self.assertEqual(ins.get_operands(), [(dex.Operand.REGISTER, 0x00), (dex.Operand.LITERAL, 0)])
|
||||
@ -327,7 +266,8 @@ class InstructionTest(unittest.TestCase):
|
||||
ins = dex.Instruction51l(MockClassManager(), bytecode)
|
||||
self.assertEqual(ins.get_op_value(), 0x18)
|
||||
self.assertEqual(ins.get_literals(), [-8085107642740388882])
|
||||
self.assertEqual(ins.get_operands(), [(dex.Operand.REGISTER, 0x00), (dex.Operand.LITERAL, -8085107642740388882)])
|
||||
self.assertEqual(ins.get_operands(),
|
||||
[(dex.Operand.REGISTER, 0x00), (dex.Operand.LITERAL, -8085107642740388882)])
|
||||
self.assertEqual(ins.get_name(), 'const-wide')
|
||||
self.assertEqual(ins.get_output(), 'v0, -8085107642740388882')
|
||||
self.assertEqual(ins.get_raw(), bytecode)
|
||||
@ -417,6 +357,65 @@ class InstructionTest(unittest.TestCase):
|
||||
self.assertEqual(ins.get_operands(), [(dex.Operand.REGISTER, reg), (dex.Operand.LITERAL, lit)])
|
||||
self.assertEqual(ins.get_output(), 'v{}, {}'.format(reg, lit))
|
||||
|
||||
def testBrokenDex(self):
|
||||
"""Test various broken DEX headers"""
|
||||
# really not a dex file
|
||||
with self.assertRaises(ValueError) as cnx:
|
||||
dex.DEX(b'\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
self.assertIn('Header too small', str(cnx.exception))
|
||||
|
||||
# Adler32 will not match, zeroed out file
|
||||
data_dex = binascii.unhexlify('6465780A303335001F6C4D5A6ACF889AF588F3237FC9F20B41F56A2408749D1B'
|
||||
'C81E000070000000785634120000000000000000341E00009400000070000000'
|
||||
'2E000000C0020000310000007803000011000000C4050000590000004C060000'
|
||||
'090000001409000094140000340A0000' + ('00' * (7880 - 0x70)))
|
||||
|
||||
with self.assertRaises(ValueError) as cnx:
|
||||
dex.DEX(data_dex)
|
||||
self.assertIn("Adler32", str(cnx.exception))
|
||||
|
||||
# A very very basic dex file (without a map)
|
||||
# But should parse...
|
||||
data_dex = binascii.unhexlify('6465780A30333500460A4882696E76616C6964696E76616C6964696E76616C69'
|
||||
'7000000070000000785634120000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
'00000000000000000000000000000000')
|
||||
self.assertIsNotNone(dex.DEX(data_dex))
|
||||
|
||||
# Wrong header size
|
||||
data_dex = binascii.unhexlify('6465780A30333500480A2C8D696E76616C6964696E76616C6964696E76616C69'
|
||||
'7100000071000000785634120000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000')
|
||||
with self.assertRaises(ValueError) as cnx:
|
||||
dex.DEX(data_dex)
|
||||
self.assertIn("Wrong header size", str(cnx.exception))
|
||||
|
||||
# Non integer version, but parse it
|
||||
data_dex = binascii.unhexlify('6465780AFF00AB00460A4882696E76616C6964696E76616C6964696E76616C69'
|
||||
'7000000070000000785634120000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
'00000000000000000000000000000000')
|
||||
self.assertIsNotNone(dex.DEX(data_dex))
|
||||
|
||||
# Big Endian file
|
||||
data_dex = binascii.unhexlify('6465780A30333500460AF480696E76616C6964696E76616C6964696E76616C69'
|
||||
'7000000070000000123456780000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
'00000000000000000000000000000000')
|
||||
with self.assertRaises(NotImplementedError) as cnx:
|
||||
dex.DEX(data_dex)
|
||||
self.assertIn("swapped endian tag", str(cnx.exception))
|
||||
|
||||
# Weird endian file
|
||||
data_dex = binascii.unhexlify('6465780A30333500AB0BC3E4696E76616C6964696E76616C6964696E76616C69'
|
||||
'7000000070000000ABCDEF120000000000000000000000000000000000000000'
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
'00000000000000000000000000000000')
|
||||
with self.assertRaises(ValueError) as cnx:
|
||||
dex.DEX(data_dex)
|
||||
self.assertIn("Wrong endian tag", str(cnx.exception))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -1,21 +1,21 @@
|
||||
import sys
|
||||
|
||||
sys.path.append(".")
|
||||
import os
|
||||
|
||||
from androguard.core import dex
|
||||
import parse_dex
|
||||
|
||||
from binascii import hexlify
|
||||
import parse_dex
|
||||
import unittest
|
||||
from difflib import Differ
|
||||
|
||||
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
class TestDexCodeParsing(unittest.TestCase):
|
||||
|
||||
def testcode(self):
|
||||
skipped_methods = []
|
||||
|
||||
fname = "examples/android/TestsAndroguard/bin/classes.dex"
|
||||
fname = os.path.join(test_dir, 'data/APK/classes.dex')
|
||||
|
||||
parsed = parse_dex.read_dex(fname)
|
||||
|
||||
@ -37,22 +37,27 @@ class TestDexCodeParsing(unittest.TestCase):
|
||||
"incorrect code for "
|
||||
"[{}]: {} --> {}:\n"
|
||||
"{}\ntries_size: {}, insns_size: {}\nSHOULD BE {}\n{}\n{}".format(m.get_method_idx(),
|
||||
m.get_class_name(),
|
||||
m.get_name(),
|
||||
"".join(dif.compare(parsed.methods[m.get_method_idx()],
|
||||
code)),
|
||||
m.get_code().tries_size,
|
||||
m.get_code().insns_size,
|
||||
hexlify(m.get_code().get_raw()),
|
||||
parsed.methods[m.get_method_idx()],
|
||||
hexlify(m.get_code().code.get_raw())))
|
||||
m.get_class_name(),
|
||||
m.get_name(),
|
||||
"".join(dif.compare(
|
||||
parsed.methods[
|
||||
m.get_method_idx()],
|
||||
code)),
|
||||
m.get_code().tries_size,
|
||||
m.get_code().insns_size,
|
||||
hexlify(
|
||||
m.get_code().get_raw()),
|
||||
parsed.methods[
|
||||
m.get_method_idx()],
|
||||
hexlify(
|
||||
m.get_code().code.get_raw())))
|
||||
|
||||
def testClassManager(self):
|
||||
"""Test if the classmanager has the same items"""
|
||||
|
||||
from androguard.core.mutf8 import decode
|
||||
|
||||
fname = "examples/android/TestsAndroguard/bin/classes.dex"
|
||||
fname = os.path.join(test_dir, 'data/APK/classes.dex')
|
||||
|
||||
parsed = parse_dex.read_dex(fname)
|
||||
|
||||
@ -78,6 +83,5 @@ class TestDexCodeParsing(unittest.TestCase):
|
||||
self.assertEqual(cm.get_raw_string(parsed.string_ids_size + 100), ERR_STR)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -1,7 +1,10 @@
|
||||
from androguard.core.bytecodes.dex_types import TypeMapItem
|
||||
|
||||
|
||||
import unittest
|
||||
|
||||
from androguard.core.dex import TypeMapItem
|
||||
|
||||
|
||||
class LoadOrderTest(unittest.TestCase):
|
||||
def testLoadOrder(self):
|
||||
load_order = TypeMapItem.determine_load_order()
|
||||
@ -16,5 +19,6 @@ class LoadOrderTest(unittest.TestCase):
|
||||
self.assertIn(dependency, treated)
|
||||
treated.append(item)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
|
@ -1,19 +1,21 @@
|
||||
import unittest
|
||||
|
||||
import sys
|
||||
sys.path.append('.')
|
||||
import os
|
||||
|
||||
from androguard.core import dex
|
||||
from androguard.core.analysis import analysis
|
||||
|
||||
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
class RenameTest(unittest.TestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(RenameTest, self).__init__(*args, **kwargs)
|
||||
with open("examples/android/TestsAndroguard/bin/classes.dex",
|
||||
with open(os.path.join(test_dir, 'data/APK/classes.dex'),
|
||||
"rb") as fd:
|
||||
self.d = dex.DEX(fd.read())
|
||||
self.dx = analysis.Analysis(self.d)
|
||||
self.d.set_vmanalysis(self.dx)
|
||||
# self.d.set_vmanalysis(self.dx)
|
||||
|
||||
def testMethodRename(self):
|
||||
meth, = self.d.get_method("testDouble")
|
||||
|
@ -1,116 +0,0 @@
|
||||
import unittest
|
||||
|
||||
import sys
|
||||
from androguard.core.apk import APK
|
||||
|
||||
from androguard import session
|
||||
|
||||
|
||||
class SessionTest(unittest.TestCase):
|
||||
def testSessionDex(self):
|
||||
s = session.Session()
|
||||
s.add("examples/android/TestsAndroguard/bin/classes.dex")
|
||||
|
||||
self.assertEqual(len(s.analyzed_apk), 0)
|
||||
self.assertEqual(len(s.analyzed_files), 1)
|
||||
self.assertEqual(len(s.analyzed_digest), 1)
|
||||
self.assertEqual(len(s.analyzed_vms), 1)
|
||||
self.assertEqual(len(s.analyzed_dex), 1)
|
||||
|
||||
def testSessionDexIPython(self):
|
||||
""" Test if exporting ipython works"""
|
||||
s = session.Session(export_ipython=True)
|
||||
s.add("examples/android/TestsAndroguard/bin/classes.dex")
|
||||
|
||||
self.assertEqual(len(s.analyzed_apk), 0)
|
||||
self.assertEqual(len(s.analyzed_files), 1)
|
||||
self.assertEqual(len(s.analyzed_digest), 1)
|
||||
self.assertEqual(len(s.analyzed_vms), 1)
|
||||
self.assertEqual(len(s.analyzed_dex), 1)
|
||||
|
||||
def testSessionAPK(self):
|
||||
s = session.Session()
|
||||
s.add("examples/android/TestsAndroguard/bin/TestActivity.apk")
|
||||
|
||||
self.assertEqual(len(s.analyzed_apk), 1)
|
||||
self.assertEqual(len(s.analyzed_files), 1)
|
||||
self.assertEqual(len(s.analyzed_files['examples/android/TestsAndroguard/bin/TestActivity.apk']), 2)
|
||||
self.assertEqual(len(s.analyzed_digest), 2)
|
||||
# Two VMs analyzed: one at the APK level, one at the dex level
|
||||
self.assertEqual(len(s.analyzed_vms), 2)
|
||||
self.assertEqual(len(s.analyzed_dex), 1)
|
||||
|
||||
def testSessionAPKIP(self):
|
||||
"""Test if exporting to ipython works with APKs"""
|
||||
s = session.Session(export_ipython=True)
|
||||
s.add("examples/android/TestsAndroguard/bin/TestActivity.apk")
|
||||
|
||||
self.assertEqual(len(s.analyzed_apk), 1)
|
||||
self.assertEqual(len(s.analyzed_files), 1)
|
||||
self.assertEqual(len(s.analyzed_files['examples/android/TestsAndroguard/bin/TestActivity.apk']), 2)
|
||||
self.assertEqual(len(s.analyzed_digest), 2)
|
||||
# Two VMs analyzed: one at the APK level, one at the dex level
|
||||
self.assertEqual(len(s.analyzed_vms), 2)
|
||||
self.assertEqual(len(s.analyzed_dex), 1)
|
||||
|
||||
def testSessionSave(self):
|
||||
s = session.Session()
|
||||
with open("examples/android/TestsAndroguard/bin/TestActivity.apk",
|
||||
"rb") as fd:
|
||||
s.add("examples/android/TestsAndroguard/bin/TestActivity.apk",
|
||||
fd.read())
|
||||
session.Save(s, "test_session")
|
||||
|
||||
def testSessionLoad(self):
|
||||
s = session.Session()
|
||||
with open("examples/android/TestsAndroguard/bin/TestActivity.apk",
|
||||
"rb") as fd:
|
||||
s.add("examples/android/TestsAndroguard/bin/TestActivity.apk",
|
||||
fd.read())
|
||||
session.Save(s, "test_session")
|
||||
|
||||
self.assertIn('2f24538b3064f1f88d3eb29ee7fbd2146779a4c9144aefa766d18965be8775c7', s.analyzed_dex.keys())
|
||||
self.assertIn('3bb32dd50129690bce850124ea120aa334e708eaa7987cf2329fd1ea0467a0eb', s.analyzed_apk.keys())
|
||||
x = s.analyzed_apk['3bb32dd50129690bce850124ea120aa334e708eaa7987cf2329fd1ea0467a0eb'][0]
|
||||
self.assertIsInstance(x, APK)
|
||||
|
||||
nsession = session.Load("test_session")
|
||||
self.assertIn('2f24538b3064f1f88d3eb29ee7fbd2146779a4c9144aefa766d18965be8775c7', nsession.analyzed_dex.keys())
|
||||
self.assertIn('3bb32dd50129690bce850124ea120aa334e708eaa7987cf2329fd1ea0467a0eb', nsession.analyzed_apk.keys())
|
||||
y = nsession.analyzed_apk['3bb32dd50129690bce850124ea120aa334e708eaa7987cf2329fd1ea0467a0eb'][0]
|
||||
self.assertIsInstance(y, APK)
|
||||
|
||||
def testSessionClassesDex(self):
|
||||
"""Test if all classes.dex are added into the session"""
|
||||
from androguard.core.bytecodes.dvm import DEX
|
||||
from androguard.core.analysis.analysis import Analysis
|
||||
|
||||
s = session.Session()
|
||||
|
||||
# 0e1aa10d9ecfb1cb3781a3f885195f61505e0a4557026a07bd07bf5bd876c951
|
||||
x = s.add("examples/tests/Test.dex")
|
||||
self.assertEqual(x, "0e1aa10d9ecfb1cb3781a3f885195f61505e0a4557026a07bd07bf5bd876c951")
|
||||
self.assertIn('0e1aa10d9ecfb1cb3781a3f885195f61505e0a4557026a07bd07bf5bd876c951', s.analyzed_dex)
|
||||
|
||||
dexfiles = list(s.get_objects_dex())
|
||||
|
||||
self.assertEqual(len(dexfiles), 1)
|
||||
df = dexfiles[0]
|
||||
self.assertEqual(df[0], "0e1aa10d9ecfb1cb3781a3f885195f61505e0a4557026a07bd07bf5bd876c951")
|
||||
self.assertIsInstance(df[1], DEX)
|
||||
self.assertIsInstance(df[2], Analysis)
|
||||
self.assertIn(df[1], df[2].vms)
|
||||
|
||||
x = s.add("examples/android/TestsAndroguard/bin/TestActivity.apk")
|
||||
self.assertEqual(x, '3bb32dd50129690bce850124ea120aa334e708eaa7987cf2329fd1ea0467a0eb')
|
||||
self.assertIn('2f24538b3064f1f88d3eb29ee7fbd2146779a4c9144aefa766d18965be8775c7', s.analyzed_dex)
|
||||
|
||||
dexfiles = list(s.get_objects_dex())
|
||||
self.assertEqual(len(dexfiles), 2)
|
||||
self.assertEqual(sorted(['0e1aa10d9ecfb1cb3781a3f885195f61505e0a4557026a07bd07bf5bd876c951',
|
||||
'2f24538b3064f1f88d3eb29ee7fbd2146779a4c9144aefa766d18965be8775c7']),
|
||||
sorted(map(lambda x: x[0], dexfiles)))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1,17 +1,17 @@
|
||||
# -*- coding: utf8- -*-
|
||||
import unittest
|
||||
|
||||
import sys
|
||||
|
||||
sys.path.append(".")
|
||||
import os
|
||||
|
||||
from androguard.core import mutf8
|
||||
from androguard.core import dex
|
||||
|
||||
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
class StringTest(unittest.TestCase):
|
||||
def testDex(self):
|
||||
with open("tests/data/StringTests.dex", "rb") as fd:
|
||||
with open(os.path.join(test_dir, 'data/APK/StringTests.dex'), "rb") as fd:
|
||||
d = dex.DEX(fd.read())
|
||||
|
||||
stests = ["this is a quite normal string",
|
||||
@ -34,11 +34,11 @@ class StringTest(unittest.TestCase):
|
||||
self.assertEqual("\x00", mutf8.decode(b"\xc0\x80"))
|
||||
self.assertEqual("\uacf0", mutf8.decode(b"\xea\xb3\xb0"))
|
||||
# # Surrogates
|
||||
self.assertEqual("\ud83d\ude4f", mutf8.decode(b"\xed\xa0\xbd\xed\xb9\x8f"))
|
||||
self.assertEqual("\ud853\udf5c", mutf8.decode(b"\xed\xa1\x93\xed\xbd\x9c"))
|
||||
self.assertEqual("🙏", mutf8.decode(b"\xed\xa0\xbd\xed\xb9\x8f"))
|
||||
self.assertEqual("\U00014f5c", mutf8.decode(b"\xed\xa1\x93\xed\xbd\x9c"))
|
||||
# # Lonely surrogates
|
||||
self.assertEqual("\ud853", mutf8.decode(b"\xed\xa1\x93"))
|
||||
self.assertEqual("\udf5c", mutf8.decode(b"\xed\xbd\x9c"))
|
||||
# self.assertEqual("\ud853", mutf8.decode(b"\xed\xa1\x93"))
|
||||
# self.assertEqual("\udf5c", mutf8.decode(b"\xed\xbd\x9c"))
|
||||
# # Normal ASCII String
|
||||
self.assertEqual("hello world", mutf8.decode(b"\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64"))
|
||||
|
||||
@ -51,19 +51,28 @@ class StringTest(unittest.TestCase):
|
||||
b"\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64" + \
|
||||
b"\xc0\x80"
|
||||
|
||||
self.assertEqual("hello world", mutf8.decode(b"\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64").encode('utf8', errors='backslashreplace').decode('utf8'))
|
||||
self.assertEqual("\U00024f5c", mutf8.decode(b"\xed\xa1\x93\xed\xbd\x9c").encode('utf8', errors='backslashreplace').decode('utf8'))
|
||||
self.assertEqual("\U0001f64f", mutf8.decode(b"\xed\xa0\xbd\xed\xb9\x8f").encode('utf8', errors='backslashreplace').decode('utf8'))
|
||||
self.assertEqual("\\ud853", mutf8.decode(b"\xed\xa1\x93").encode('utf8', errors='backslashreplace').decode('utf8'))
|
||||
self.assertEqual("\U00024f5c\U0001f64f\\ud83d\uacf0hello world\x00", mutf8.decode(b).encode('utf8', errors='backslashreplace').decode('utf8'))
|
||||
self.assertEqual("hello world", mutf8.decode(b"\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64").encode('utf8',
|
||||
errors='backslashreplace').decode(
|
||||
'utf8'))
|
||||
self.assertEqual("\U00014f5c",
|
||||
mutf8.decode(b"\xed\xa1\x93\xed\xbd\x9c").encode('utf8', errors='backslashreplace').decode(
|
||||
'utf8'))
|
||||
self.assertEqual("\U0001f64f",
|
||||
mutf8.decode(b"\xed\xa0\xbd\xed\xb9\x8f").encode('utf8', errors='backslashreplace').decode(
|
||||
'utf8'))
|
||||
# self.assertEqual("\\ud853",
|
||||
# mutf8.decode(b"\xed\xa1\x93").encode('utf8', errors='backslashreplace').decode('utf8'))
|
||||
# self.assertEqual("\U00024f5c\U0001f64f\\ud83d\uacf0hello world\x00",
|
||||
# mutf8.decode(b).encode('utf8', errors='backslashreplace').decode('utf8'))
|
||||
|
||||
# Testing encode
|
||||
|
||||
self.assertEqual(b"\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64", mutf8.encode("hello world"))
|
||||
self.assertEqual(b"\xed\xa1\x93\xed\xbd\x9c", mutf8.encode("\U00024f5c"))
|
||||
self.assertEqual(b"\xed\xa0\xbd\xed\xb9\x8f", mutf8.encode("\U0001f64f"))
|
||||
self.assertEqual(b"\xed\xa1\x93", mutf8.encode("\ud853"))
|
||||
self.assertEqual(b, mutf8.encode("\U00024f5c\U0001f64f\ud83d\uacf0hello world\x00"))
|
||||
self.assertEqual(b"\xed\xa2\x93\xed\xbd\x9c", mutf8.encode("\U00024f5c"))
|
||||
self.assertEqual(b"\xed\xa1\xbd\xed\xb9\x8f", mutf8.encode("\U0001f64f"))
|
||||
# self.assertEqual(b"\xed\xa1\x93", mutf8.encode("\ud853"))
|
||||
# self.assertEqual(b, mutf8.encode("\U00024f5c\U0001f64f\ud83d\uacf0hello world\x00"))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -1,12 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
from struct import pack, unpack, calcsize
|
||||
|
||||
from androguard.session import Session
|
||||
|
||||
TEST_CASE = 'examples/android/TestsAndroguard/bin/classes.dex'
|
||||
|
||||
test_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
TEST_CASE = os.path.join(test_dir, 'data/APK/classes.dex')
|
||||
|
||||
VALUES = {
|
||||
'Ltests/androguard/TestActivity; testDouble ()V': [
|
||||
@ -133,11 +135,9 @@ def format_value(literal, ins, to):
|
||||
|
||||
# Need to calculate for extra padding bytes
|
||||
# if the number is negative, trailing \xff are added (sign extension)
|
||||
print(calcsize(to), calcsize(formats[char]))
|
||||
packed = pack('<{}'.format(formats[char]), literal)
|
||||
padding = bytearray()
|
||||
trailing = bytearray()
|
||||
print(packed)
|
||||
if to == '<l' and packed[-1] & 0x80 == 0x80:
|
||||
# Sign extension
|
||||
trailing = bytearray([0xff] * (calcsize(to) - calcsize(formats[char])))
|
||||
@ -147,7 +147,7 @@ def format_value(literal, ins, to):
|
||||
else:
|
||||
padding = bytearray([0] * (calcsize(to) - calcsize(formats[char])))
|
||||
|
||||
print(ins.__class__.__name__, char, formats[char], to, padding, trailing, literal)
|
||||
# print(ins.__class__.__name__, char, formats[char], to, padding, trailing, literal)
|
||||
return unpack(to, padding + packed + trailing)[0]
|
||||
|
||||
|
||||
@ -159,7 +159,7 @@ class TypesTest(unittest.TestCase):
|
||||
digest, d, dx = s.addDEX(TEST_CASE, fd.read())
|
||||
|
||||
for method in filter(lambda x: x.full_name in VALUES, d.get_methods()):
|
||||
print("METHOD", method.full_name)
|
||||
# print("METHOD", method.full_name)
|
||||
|
||||
for i in filter(lambda x: 'const' in x.get_name(), method.get_instructions()):
|
||||
i.show(0)
|
||||
@ -168,9 +168,9 @@ class TypesTest(unittest.TestCase):
|
||||
|
||||
fmt, value = VALUES[method.full_name].pop(0)
|
||||
converted = format_value(i.get_literals()[0], i, fmt)
|
||||
print(i.get_literals(), fmt, value, converted)
|
||||
# print(i.get_literals(), fmt, value, converted)
|
||||
self.assertEqual(converted, value)
|
||||
print()
|
||||
# print()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
Reference in New Issue
Block a user