Skip to main content

The resources.arsc file

Within an Android application lies a resources.arsc, which is a binary file containing resources of the application. The .arsc extension hints at Android Resource Storage Container which is a massive collection of chunks.

If we dumped the first line of the file, we would see the following:

00000000: 0200 0c00 f00b 0000 0100 0000 0100 1c00  ................

The .arsc file uses what is described as a ResChunk_header to describe the chunks within the file. This header is what starts the file off and is as follows:

ResChunk_header

NameSizeDescription
Type2 bytesThe type of the chunk
Header Size2 bytesThe size of the header
Size4 bytesThe size of the chunk

So knowing we have a little endian structure we can parse out this header. We get:

  • Type - 0x0002
  • Header Size - 0x000c
  • Size - 0x00000bf0

So we can leverage the ResourceTypes.h file in order to understand what this chunk is.

enum {
RES_NULL_TYPE = 0x0000,
RES_STRING_POOL_TYPE = 0x0001,
RES_TABLE_TYPE = 0x0002,
RES_XML_TYPE = 0x0003,
};

So we start the file with a RES_TABLE_TYPE chunk. This chunk is described as:

ResTable_header

NameSizeDescription
Header8 bytesThe type of the chunk
Package Count4 bytesThe number of packages

A pretty simple chunk that just helps understand how many ResTable_package chunks are within the file. So now that we understand that each chunk begins with a ResChunk_header we can safely read the next chunk to see what it is.

So now let's bring up the line again and mark what we've already read.

00000000: [0200 0c00 f00b 0000] 0100 0000 0100 1c00  ................

So we can see that the next chunk is a RES_STRING_POOL_TYPE (0x0001) chunk after reading the type of the ResChunk_header. This string pool chunk is described as:

NameSizeDescription
String Count4 bytesNumber of strings in the pool
Style Count4 bytesNumber of style span arrays in pool
Flags4 bytesWhether the strings are UTF-8 or UTF-16, sorted or not
String Offset4 bytesThe offset in bytes from header to the string data
Style Offset4 bytesThe offset in bytes from header to the style data

This chunk is a bit more complex than the previous chunk, but we can still parse it out. We learn how many strings and styles we have and where they start in the file. So Apktool works in this situation by reading those pools of data and storing them in memory. This allows us to reference them later on when we need to via the indicies.

The String Pool in itself has so many quirks and oddities that we will not be covering them in this document. If you want a deep dive on how the string pool works. This String Pool (TODO) document can help. For now just assume you can reference an index in the string pool and get a string back.

The String Pool is important to read first because it contains all the string values of the entire resource table. However, except not the names of entries or type identifiers are contained within that pool.

So now assuming we properly read the pool and/or skipped it from the information contained in the ResChunk_header we end up at another new chunk. Below is the relevant segment after the String Pool.

00000340: 0000 0000] 0002 2001 ac08 0000 7f00 0000  ...... .........
00000350: 6300 6f00 6d00 2e00 6900 6200 6f00 7400 c.o.m...i.b.o.t.
00000360: 7000 6500 6100 6300 6800 6500 7300 2e00 p.e.a.c.h.e.s...
00000370: 6100 7200 7300 6300 7400 6500 7300 7400 a.r.s.c.t.e.s.t.
  • ] - end of string pool.

So if we read another ResChunk_header we get a new type of chunk. This chunk is a RES_TABLE_TYPE (0x0200) chunk which is described as:

NameSizeDescription
Package Id4 bytesPackage Id
Package NameVariablePackage Name, null terminated
Type String Offset4 bytesOffset to the type symbol table, may be zero if inheriting from another package
Last Public Type String Offset4 bytesLast index in the above table of public types
Key Symbol Offset4 bytesOffset to the key symbol table, may be zero if inheriting from another package
Last Public Key Symbol Offset4 bytesLast index in the above table of key symbols
Type Id Offset4 bytesOffset to the specific type ids for split apks

This chunk suggests from the properties and explanation that this chunk will kick off the child ResTable_type and ResTable_typeSpec chunks.