Skip to content

Commit 2b5013e

Browse files
committed
Add core library with radare2 in axmlreader
1 parent e296f97 commit 2b5013e

File tree

3 files changed

+49
-35
lines changed

3 files changed

+49
-35
lines changed

quark/core/axmlreader/__init__.py

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import pkg_resources
1010
import rzpipe
11+
import r2pipe
1112

1213
# Resource Types Definition
1314
# Please reference to
@@ -84,7 +85,7 @@ class AxmlReader(object):
8485
A Class that parses the Android XML file
8586
"""
8687

87-
def __init__(self, file_path, structure_path=None):
88+
def __init__(self, file_path, core_library="rizin", structure_path=None):
8889
if structure_path is None:
8990
structure_path = pkg_resources.resource_filename(
9091
"quark.core.axmlreader", "axml_definition"
@@ -96,10 +97,13 @@ def __init__(self, file_path, structure_path=None):
9697
f" of Rizin in {structure_path}"
9798
)
9899

99-
self._rz = rzpipe.open(file_path)
100-
self._rz.cmd(f"pfo {structure_path}")
100+
if core_library == "rizin":
101+
self._core = rzpipe.open(file_path)
102+
else:
103+
self._core = r2pipe.open(file_path)
104+
self._core.cmd(f"pfo {structure_path}")
101105

102-
self._file_size = int(self._rz.cmd("i~size[1]"), 16)
106+
self._file_size = int(self._core.cmd("i~size[1]"), 16)
103107
self._ptr = 0
104108

105109
self._cache = {}
@@ -110,7 +114,7 @@ def __init__(self, file_path, structure_path=None):
110114
raise AxmlException("Filesize exceeds theoretical lower bound.")
111115

112116
# File Header
113-
header = self._rz.cmdj("pfj axml_ResChunk_header @ 0x0")
117+
header = self._core.cmdj("pfj axml_ResChunk_header @ 0x0")
114118

115119
self._data_type = header[0]["value"]
116120
self._axml_size = header[2]["value"]
@@ -133,7 +137,7 @@ def __init__(self, file_path, structure_path=None):
133137
return
134138

135139
# String Pool
136-
string_pool_header = self._rz.cmdj("pfj axml_ResStringPool_header @ 8")
140+
string_pool_header = self._core.cmdj("pfj axml_ResStringPool_header @ 8")
137141

138142
string_pool_size = string_pool_header[0]["value"][2]["value"]
139143

@@ -163,18 +167,18 @@ def __init__(self, file_path, structure_path=None):
163167
self._stringCount = string_pool_header[1]["value"]
164168
stringStart = string_pool_header[4]["value"]
165169

166-
self._rz.cmd(f"f string_pool_header @ 0x8 ")
170+
self._core.cmd(f"f string_pool_header @ 0x8 ")
167171
string_pool_index = header_size + self._ptr
168-
self._rz.cmd(f"f string_pool_index @ { string_pool_index }")
172+
self._core.cmd(f"f string_pool_index @ { string_pool_index }")
169173
string_pool_data = stringStart + self._ptr
170-
self._rz.cmd(f"f string_pool_data @ { string_pool_data }")
174+
self._core.cmd(f"f string_pool_data @ { string_pool_data }")
171175

172176
self._ptr += string_pool_size
173177
if self._ptr >= self._axml_size:
174178
return
175179

176180
# Resource Map (Optional)
177-
header = self._rz.cmdj(f"pfj axml_ResChunk_header @ {self._ptr}")
181+
header = self._core.cmdj(f"pfj axml_ResChunk_header @ {self._ptr}")
178182

179183
header_type = header[0]["value"]
180184
if header_type == RES_XML_RESOURCE_MAP_TYPE:
@@ -201,7 +205,7 @@ def __iter__(self) -> Iterator[ResChunkHeader]:
201205
:yield: header of a resource chunk defined in the binary
202206
"""
203207
while self._axml_size - self._ptr >= 16:
204-
header = self._rz.cmdj(f"pfj axml_ResXMLTree_node @ {self._ptr}")
208+
header = self._core.cmdj(f"pfj axml_ResXMLTree_node @ {self._ptr}")
205209

206210
node_type = header[0]["value"][0]["value"]
207211
header_size = header[0]["value"][1]["value"]
@@ -224,7 +228,7 @@ def __iter__(self) -> Iterator[ResChunkHeader]:
224228
chunk = {"Address": self._ptr, "Type": node_type}
225229

226230
if node_type == RES_XML_START_ELEMENT_TYPE:
227-
ext = self._rz.cmdj(
231+
ext = self._core.cmdj(
228232
f"pfj axml_ResXMLTree_attrExt @ { ext_ptr }"
229233
)
230234

@@ -235,7 +239,7 @@ def __iter__(self) -> Iterator[ResChunkHeader]:
235239
# node['AttrCount'] = ext[4]['value']
236240

237241
elif node_type == RES_XML_END_ELEMENT_TYPE:
238-
ext = self._rz.cmdj(
242+
ext = self._core.cmdj(
239243
f"pfj axml_ResXMLTree_endElementExt @ { ext_ptr }"
240244
)
241245

@@ -246,15 +250,15 @@ def __iter__(self) -> Iterator[ResChunkHeader]:
246250
RES_XML_START_NAMESPACE_TYPE,
247251
RES_XML_END_NAMESPACE_TYPE,
248252
]:
249-
ext = self._rz.cmdj(
253+
ext = self._core.cmdj(
250254
f"pfj axml_ResXMLTree_namespaceExt @ { ext_ptr }"
251255
)
252256

253257
chunk["Prefix"] = ext[0]["value"][0]["value"]
254258
chunk["Uri"] = ext[1]["value"][0]["value"]
255259

256260
elif node_type == RES_XML_CDATA_TYPE:
257-
ext = self._rz.cmdj(
261+
ext = self._core.cmdj(
258262
f"pfj axml_ResXMLTree_cdataExt @ { ext_ptr }"
259263
)
260264

@@ -281,7 +285,7 @@ def get_string(self, index):
281285
if index < 0 or index >= self._stringCount:
282286
return None
283287

284-
return self._rz.cmdj(
288+
return self._core.cmdj(
285289
f"pfj Z @ string_pool_data + `pfv n4 "
286290
f"@ string_pool_index+ {index}*4` + 2"
287291
)[0]["string"]
@@ -296,14 +300,14 @@ def get_attributes(self, chunk: ResChunkHeader) -> List[ResValue]:
296300
return None
297301
extAddress = int(chunk["Address"]) + 16
298302

299-
attrExt = self._rz.cmdj(f"pfj axml_ResXMLTree_attrExt @ {extAddress}")
303+
attrExt = self._core.cmdj(f"pfj axml_ResXMLTree_attrExt @ {extAddress}")
300304

301305
attrAddress = extAddress + attrExt[2]["value"]
302306
attributeSize = attrExt[3]["value"]
303307
attributeCount = attrExt[4]["value"]
304308
attributes = []
305309
for _ in range(attributeCount):
306-
attr = self._rz.cmdj(
310+
attr = self._core.cmdj(
307311
f"pfj axml_ResXMLTree_attribute @ {attrAddress}"
308312
)
309313

@@ -402,6 +406,6 @@ def get_xml_tree(self) -> XMLElementTree:
402406

403407
def __del__(self):
404408
try:
405-
self._rz.quit()
409+
self._core.quit()
406410
except BaseException:
407411
pass

quark/core/r2apkinfo.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ def permissions(self) -> List[str]:
228228
229229
:return: a list of permissions.
230230
"""
231-
axml = AxmlReader(self._manifest)
231+
axml = AxmlReader(self._manifest, core_library="radare2")
232232
permission_list = set()
233233

234234
for tag in axml:
@@ -249,7 +249,7 @@ def application(self) -> XMLElement:
249249
:return: an application element
250250
"""
251251

252-
axml = AxmlReader(self._manifest)
252+
axml = AxmlReader(self._manifest, core_library="radare2")
253253
root = axml.get_xml_tree()
254254

255255
return root.find("application")
@@ -261,7 +261,7 @@ def activities(self) -> List[XMLElement]:
261261
262262
:return: a list of all activities
263263
"""
264-
axml = AxmlReader(self._manifest)
264+
axml = AxmlReader(self._manifest, core_library="radare2")
265265
root = axml.get_xml_tree()
266266

267267
return root.findall("application/activity")
@@ -273,7 +273,7 @@ def receivers(self) -> List[XMLElement]:
273273
274274
:return: a list of all receivers
275275
"""
276-
axml = AxmlReader(self._manifest)
276+
axml = AxmlReader(self._manifest, core_library="radare2")
277277
root = axml.get_xml_tree()
278278

279279
return root.findall("application/receiver")

tests/core/test_axmlreader.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@
1111
from quark.core.axmlreader import AxmlReader, ResValue
1212

1313

14+
15+
@pytest.fixture(
16+
scope="function",
17+
params=(("radare2"), ("rizin")),
18+
)
19+
def core_library(request):
20+
core_lib = request.param
21+
yield core_lib
22+
23+
1424
def extractManifest(samplePath: PathLike) -> str:
1525
folder = Path(samplePath).parent
1626

@@ -27,8 +37,8 @@ def MANIFEST_PATH_14d9f(SAMPLE_PATH_14d9f):
2737

2838
class TestAxmlReader:
2939
@staticmethod
30-
def testIter(MANIFEST_PATH_14d9f) -> None:
31-
axmlReader = AxmlReader(MANIFEST_PATH_14d9f)
40+
def testIter(core_library, MANIFEST_PATH_14d9f) -> None:
41+
axmlReader = AxmlReader(MANIFEST_PATH_14d9f, core_library)
3242
expectedTag = {"Address": 3728, "Type": 256, "Prefix": 9, "Uri": 10}
3343

3444
tag = next(iter(axmlReader))
@@ -37,23 +47,23 @@ def testIter(MANIFEST_PATH_14d9f) -> None:
3747
helper.assertDictEqual(tag, expectedTag)
3848

3949
@staticmethod
40-
def testFileSize(MANIFEST_PATH_14d9f):
41-
axmlReader = AxmlReader(MANIFEST_PATH_14d9f)
50+
def testFileSize(core_library, MANIFEST_PATH_14d9f):
51+
axmlReader = AxmlReader(MANIFEST_PATH_14d9f, core_library)
4252
assert axmlReader.file_size == 7676
4353

4454
@staticmethod
45-
def testAxmlSize(MANIFEST_PATH_14d9f):
46-
axmlReader = AxmlReader(MANIFEST_PATH_14d9f)
55+
def testAxmlSize(core_library, MANIFEST_PATH_14d9f):
56+
axmlReader = AxmlReader(MANIFEST_PATH_14d9f, core_library)
4757
assert axmlReader.axml_size == 7676
4858

4959
@staticmethod
50-
def testGetString(MANIFEST_PATH_14d9f):
51-
axmlReader = AxmlReader(MANIFEST_PATH_14d9f)
60+
def testGetString(core_library, MANIFEST_PATH_14d9f):
61+
axmlReader = AxmlReader(MANIFEST_PATH_14d9f, core_library)
5262
assert axmlReader.get_string(13) == "manifest"
5363

5464
@staticmethod
55-
def testGetAttributes(MANIFEST_PATH_14d9f):
56-
axmlReader = AxmlReader(MANIFEST_PATH_14d9f)
65+
def testGetAttributes(core_library, MANIFEST_PATH_14d9f):
66+
axmlReader = AxmlReader(MANIFEST_PATH_14d9f, core_library)
5767
manifestTag = list(axmlReader)[1]
5868

5969
expectedAttributes = [
@@ -68,8 +78,8 @@ def testGetAttributes(MANIFEST_PATH_14d9f):
6878
assert expectedAttrib == attrib
6979

7080
@staticmethod
71-
def testGetXmlTree(MANIFEST_PATH_14d9f):
72-
axmlReader = AxmlReader(MANIFEST_PATH_14d9f)
81+
def testGetXmlTree(core_library, MANIFEST_PATH_14d9f):
82+
axmlReader = AxmlReader(MANIFEST_PATH_14d9f, core_library)
7383
xml = axmlReader.get_xml_tree()
7484
manifestLabel = xml.getroot()
7585
assert len(manifestLabel.findall("uses-sdk")) == 1

0 commit comments

Comments
 (0)