Pkg.CDEX — API for parsing Android CompactDex containers¶
Overview¶
The Pkg.CDEX module contains the API for parsing Android ART CompactDex (CDEX) containers and converting them back to standard DEX. CompactDex is an ART internal DEX variant introduced in Android 9 (Pie); dex2oat produces it inside VDEX containers and on-device ART consumes it natively. CDEX packs each method’s CodeItem header from 16 bytes down to 4 bytes, externalizes per-method debug_info_off values into a CompactOffsetTable, and adds a 24-byte tail to the standard DEX header. Existing DEX tools (decompilers, disassemblers, baksmali) cannot consume CompactDex directly, so this module provides a CDEXObject.ConvertToDEX() method that rebuilds a standard DEX file. When the CDEX is being scanned inside a parent VDEX, the parent’s quickening info is forwarded automatically and quickened bytecode is unquickened in place.
Parsing a CompactDex File¶
The following code example demonstrates how to parse a CompactDex container, inspect its header and method count, and convert it to a standard DEX:
from Pro.Core import *
from Pkg.CDEX import *
def cdexToDex(in_fname, out_fname):
c = createContainerFromFile(in_fname)
if c.isNull():
return
obj = CDEXObject()
if not obj.Load(c) or not obj.Initialize():
return
print("version:", obj.GetVersion(),
"methods:", obj.GetMethodCount(),
"classes:", obj.GetClassDefCount())
dex = obj.ConvertToDEX()
if not dex.isNull() and dex.size() > 0:
dex.save(out_fname)
Module API¶
Pkg.CDEX module API.
Classes:
This class represents an Android ART CompactDex (CDEX) container.
- class CDEXObject¶
Bases:
Pro.Core.CFFObjectThis class represents an Android ART CompactDex (CDEX) container.
CompactDex is an ART internal DEX variant introduced in Android 9 (Pie). It packs each method’s CodeItem header from 16 bytes down to 4 bytes, externalizes per-method
debug_info_offvalues into a CompactOffsetTable, and adds a 24-byte tail to the standard DEX header. CompactDex files are produced bydex2oatand embedded inside VDEX containers; on-device they are never extracted as standalone files. This class parses the CompactDex layout and exposes aConvertToDEX()method that rebuilds a standard DEX file consumable by existing DEX tools.Methods:
ConvertToDEX([quickening_info])Converts the CompactDex into a standard DEX file consumable by existing DEX tools.
DecodeCodeItem(code_off)Decodes a packed CompactDex CodeItem header at the given offset.
GetClassDef(idx)Returns the parsed class definition at the given zero-based index as a dictionary with keys
class_idx,access_flags,superclass_idx,interfaces_off,source_file_idx,annotations_off,class_data_off,static_values_off.Returns the number of class definitions declared in the file.
GetDebugInfoOffset(method_idx)Returns the per-method
debug_info_offdecoded from the CompactOffsetTable.Returns a dictionary with every parsed CompactDex header field.
Returns the parsed entries of the DEX
map_listsection.Returns the list of methods that carry a CodeItem.
Returns the number of method ids declared in the file.
Returns the CompactDex version string.
IndexToString(idx)Resolves a string index to its UTF-8 string value.
TypeIndexToString(idx)Resolves a type index to its descriptor string (e.g.
- ConvertToDEX(quickening_info: Optional[bytes] = None) → Pro.Core.NTContainer¶
Converts the CompactDex into a standard DEX file consumable by existing DEX tools.
The conversion expands each
cdexCodeback to a regulardexCode, splices in the per-methoddebug_info_offfrom the CompactOffsetTable, transforms the header, rewrites class datacode_offulebs, updates downstream offsets and recomputes the SHA-1 signature plus Adler-32 checksum. Whenquickening_infois supplied (typically forwarded by a parent VDEX scan provider), quickened opcodes are unquickened in place.
- Parameters
quickening_info (Optional[bytes]) – Optional VDEX quickening info blob.
- Returns
Returns the rebuilt DEX as an
NTContainer, or an invalid container on failure.- Return type
- DecodeCodeItem(code_off: int) → Tuple[int, int, int, int, int, int]¶
Decodes a packed CompactDex CodeItem header at the given offset.
The result is
(registers_size, ins_size, outs_size, tries_size, insns_size, preheader_size_bytes). The preheader (when present) is read from the words precedingcode_off.
- Parameters
code_off (int) – The offset of the CodeItem in the file.
- Returns
Returns the decoded fields.
- Return type
Tuple[int, int, int, int, int, int]
- GetClassDef(idx: int) → Optional[Dict[str, int]]¶
Returns the parsed class definition at the given zero-based index as a dictionary with keys
class_idx,access_flags,superclass_idx,interfaces_off,source_file_idx,annotations_off,class_data_off,static_values_off. ReturnsNoneif the index is out of range.
- Parameters
idx (int) – The zero-based class definition index.
- Returns
Returns the class definition fields, or
None.- Return type
Optional[Dict[str, int]]
- GetClassDefCount() → int¶
Returns the number of class definitions declared in the file.
- Returns
Returns the class def count.
- Return type
int
- GetDebugInfoOffset(method_idx: int) → int¶
Returns the per-method
debug_info_offdecoded from the CompactOffsetTable.Returns
0if the method has no debug info, or if the index is out of range.
- Parameters
method_idx (int) – The zero-based method index.
- Returns
Returns the debug info offset.
- Return type
int
- GetHeader() → Dict[str, Any]¶
Returns a dictionary with every parsed CompactDex header field.
Standard DEX header fields are present (
magic,checksum,signature,file_size,header_size,endian_tag,link_size,link_off,map_off,string_ids_size/off,type_ids_size/off,proto_ids_size/off,field_ids_size/off,method_ids_size/off,class_defs_size/off,data_size,data_off) along with CompactDex-specific fields (feature_flags,debug_info_offsets_pos,debug_info_offsets_table_offset,debug_info_base,owned_data_begin,owned_data_end).
- Returns
Returns the header dictionary.
- Return type
Dict[str, Any]
- GetMapItems() → List[Dict[str, int]]¶
Returns the parsed entries of the DEX
map_listsection.Each entry is a dictionary with
type,sizeandoffsetkeys.
- Returns
Returns the list of map items.
- Return type
List[Dict[str, int]]
- GetMethodCodeOffsets() → List[Tuple[int, int]]¶
Returns the list of methods that carry a CodeItem.
Each tuple is
(method_idx, code_off)wherecode_offpoints at a packedcdexCodestructure inside the data section.
- Returns
Returns the list of (method index, code offset) pairs.
- Return type
List[Tuple[int, int]]
- GetMethodCount() → int¶
Returns the number of method ids declared in the file.
- Returns
Returns the method count.
- Return type
int
- GetVersion() → str¶
Returns the CompactDex version string. Currently always
"001".
- Returns
Returns the version string.
- Return type
str
- IndexToString(idx: int) → str¶
Resolves a string index to its UTF-8 string value. Returns an empty string when the index is out of range or the string cannot be decoded.
- Parameters
idx (int) – The zero-based string index.
- Returns
Returns the decoded string.
- Return type
str
- TypeIndexToString(idx: int) → str¶
Resolves a type index to its descriptor string (e.g.
"Lcom/foo/Bar;"). Returns an empty string when the index is out of range.
- Parameters
idx (int) – The zero-based type index.
- Returns
Returns the type descriptor.
- Return type
str