An evidence-based Android cache forensics model

advertisement
An evidence-based
Android cache
forensics model
By
Felix Jeyareuben Chandrakumar
Thesis submitted to the University of South Australia
School of Information Technology & Mathematical Sciences in fulfilment
of the requirements for the degree of Master of Science
(Cyber Security and Forensic Computing)
Supervisor: Dr Kim-Kwang Raymond Choo
Associate Supervisor: Ben Martini
Adelaide, South Australia
2-Jun-2014
2
Chapter Guide
Chapter Guide ................................................................................... i
Table of Contents ............................................................................. ii
List of Figures .................................................................................. v
List of Tables .................................................................................. vi
List of Abbreviations ....................................................................... vii
Abstract
..................................................................................viii
Declaration ................................................................................... ix
Acknowledgements ........................................................................... x
Chapter 1:
Introduction ................................................................... 1
Chapter 2:
Literature Review............................................................ 3
Chapter 3:
Conceptual Android Cache Forensic Process ..................... 11
Chapter 4:
A Case Study ............................................................... 15
Chapter 5:
Conclusion and Future Work ........................................... 36
Reference list ................................................................................. 38
Appendix A – Complete List of Studied Apps ...................................... 42
Appendix B – Design and Implementation Notes ................................. 46
Appendix C – Source Code ............................................................... 48
i
Table of Contents
Chapter Guide ................................................................................... i
Table of Contents ............................................................................. ii
List of Figures .................................................................................. v
List of Tables .................................................................................. vi
List of Abbreviations ....................................................................... vii
Abstract
..................................................................................viii
Declaration ................................................................................... ix
Acknowledgements ........................................................................... x
Chapter 1:
Introduction ................................................................... 1
1.1
Overview ....................................................................................... 1
1.2
Research aims and questions ........................................................... 2
1.3
Summary of Thesis Chapters ............................................................ 2
Chapter 2:
Literature Review............................................................ 3
2.1
Google Android ............................................................................... 3
2.2
PC Caches ...................................................................................... 4
2.3
Forensic Models .............................................................................. 4
2.4
Literature gaps ............................................................................... 9
2.2.1 Cache Diversity....................................................................................................................... 9
2.2.2 Undocumented Caches .......................................................................................................... 9
2.2.3 Lack of Analysis Tools ........................................................................................................... 10
2.2.4 Rapid Changes ...................................................................................................................... 10
Chapter 3:
Conceptual Android Cache Forensic Process ..................... 11
3.1
Extending Mckemmish’s Model .................................................................................... 12
3.1.1.1
Classification ................................................................................................................. 13
3.1.1.2
Extraction ...................................................................................................................... 13
3.1.1.3
Cache Analysis ............................................................................................................... 14
3.1.1.4
Cache Reports ............................................................................................................... 14
Chapter 4:
4.1
A Case Study ............................................................... 15
Experimental Setup ....................................................................... 15
ii
4.1.1
Assumptions .................................................................................................................. 16
4.1.1.1
Android mobile phone is rooted ................................................................................... 16
4.1.1.2
Developer mode enabled.............................................................................................. 16
4.1.1.3
USB debugging is enabled ............................................................................................. 16
4.1.1.4
Internal storage is not encrypted.................................................................................. 16
4.1.2
Hardware Used ............................................................................................................. 16
4.1.3
Cache Locations ............................................................................................................ 17
4.1.4
Acquisition of cache and data partitions ...................................................................... 17
4.1.5
Acquisition using dd ...................................................................................................... 17
4.1.5.1
Connect the Android device to the computer .............................................................. 18
4.1.5.2
Go to super-user mode ................................................................................................. 18
4.1.5.3
List the mounted partitions .......................................................................................... 18
4.1.5.4
Unmount the partitions ................................................................................................ 19
4.1.5.5
Take image of the partitions ......................................................................................... 19
4.2
Findings ....................................................................................... 20
4.2.1
System caches ............................................................................................................... 20
4.2.2
Application caches ........................................................................................................ 20
4.2.2.1
Generic Caches .............................................................................................................. 20
4.2.2.2
Webview Cache............................................................................................................. 22
4.2.2.3
SQLite DB Cache ............................................................................................................ 26
4.2.2.4
Image Cache .................................................................................................................. 26
4.2.2.5
Serialized Java Objects .................................................................................................. 27
4.2.2.6
DiskLruCache ................................................................................................................. 28
4.2.2.7
Custom Format ............................................................................................................. 29
4.3
Open Source Android Cache Viewer Prototype .................................. 30
4.3.1
cache_r.0 ....................................................................................................................... 30
4.3.2
WebView Cache ............................................................................................................ 31
4.3.3
YouTube Cache.............................................................................................................. 33
4.3.4
Android Image Gallery Cache........................................................................................ 33
4.3.5
SQLite DB Cache ............................................................................................................ 34
4.3.6
Unknown Cache ............................................................................................................ 34
Chapter 5:
Conclusion and Future Work ........................................... 36
5.1
Research Summary ....................................................................... 36
5.2
Future Work ................................................................................. 36
iii
Reference list ................................................................................. 38
Appendix A – Complete List of Studied Apps ...................................... 42
Appendix B – Design and Implementation Notes ................................. 46
Appendix C – Source Code ............................................................... 48
AndroidCacheViewer.cs ................................................................................................................ 48
CacheIdentity.cs ............................................................................................................................ 49
Plugins/ CacheAbstract.cs ............................................................................................................. 49
CacheInterface.cs .......................................................................................................................... 55
CacheBD0.cs .................................................................................................................................. 55
CacheR0.cs .................................................................................................................................... 57
Gallery3dCache.cs ......................................................................................................................... 60
NotImplemented.cs ...................................................................................................................... 60
SQLiteDB.cs ................................................................................................................................... 61
WebViewCache.cs ......................................................................................................................... 62
YouTubeCache.cs .......................................................................................................................... 67
iv
List of Figures
Figure 1 – Android Architecture (Adapted from Gandhewar and Sheikh 2011).... 4
Figure 2 - Model of Forensic Computing (Adapted from McKemmish 1999) ........ 5
Figure 4 - Palmer's Model (Adapted from Palmer 2001) .................................. 7
Figure 5 – Enhanced Digital Investigation Process (Adapted from Baryamureeba
& Tushabe 2004) ....................................................................................... 8
Figure 6 – Our proposed Android Cache Taxonomy....................................... 11
Figure 7 - Conceptual Android Cache Forensic Process .................................. 13
Figure 8 - List of files for WebView Cache .................................................... 23
Figure 9 - JPEG and Timestamp in YouTube Cache ....................................... 28
Figure 10 - cache_r.0 Details ..................................................................... 31
Figure 11 - cache_r.0 Data ........................................................................ 31
Figure 12 - WebView Cache Index .............................................................. 32
Figure 13 - WebView Cache Data ............................................................... 32
Figure 14 - WebView Cache External Data ................................................... 33
Figure 15 - YouTube Cache ....................................................................... 33
Figure 16 - Android Image Gallery ............................................................. 34
Figure 17 - SQLite DB Cache ..................................................................... 34
Figure 18 - Unknown Cache....................................................................... 35
v
List of Tables
Table
Table
Table
Table
Table
Table
Table
Table
Table
Table
1 –List of Apps Studied in Detail ........................................................ 16
2 - Structure of cache_r.0 ................................................................ 21
3 - Structure of cache_bd.0 .............................................................. 22
4 - WebView cache index file............................................................. 24
5 - Structure of block file .................................................................. 25
6 - Structure of a Cache Entry ........................................................... 26
7 - Index file of Android Gallery ......................................................... 27
8 - Data file of Android Gallery .......................................................... 27
9 - Structure of Journal File .............................................................. 29
10 – Complete List of Studied Apps ................................................... 45
vi
List of Abbreviations
API - Application Program Interface
DFRWS – Digital Forensic Research Workshop
ADB - Android Debugging Bridge
SD Card – Secure Digital Card
CPU – Central Processing Unit
GPU – Graphics Processing Unit
RAM – Random Access Memory
GB – Gigabytes
JPEG – Joint Photographic Experts Group
LRU – Least Recently Used
DB - Database
vii
Abstract
Android is the most popular and widely used mobile operating systems.
Although Android is one of the most actively researched area in the field
of mobile forensics, analysis of Android caches is an understudied
research topic – the focus of this thesis. Due to the diversity of caches
and the developer’s heavy reliance on third-party libraries, this thesis
proposes a cache taxonomy based on its usage, as the key to
investigating Android caches is to first classify and identify them. This
helps to ensure the choice of appropriate tool(s) to extract potential
evidential data. A systematic process to forensically extract, analyse and
investigate Android caches is proposed, which is based on the widely
accepted McKemmish (1995) forensic model. The proposed Android Cache
Forensic Process, the primary contribution of this thesis, is validated using
nearly 100 popular apps. Previously unknown cache formats are decoded
and several undocumented cache formats used commonly by Android
apps are documented. Based on the findings, an Android Cache Viewer
prototype is developed which is the secondary contribution of this thesis.
This working prototype, as demonstrated in this thesis, is able to
successfully decode Android caches and display the contents in a user
friendly manner.
viii
Declaration
I declare that:
This thesis presents work carried out by myself and does not incorporate
without acknowledgment any material previously submitted for a degree
or diploma in any university; to the best of my knowledge it does not
contain any materials previously published or written by another person
except where due reference is made in the text; and all substantive
contributions by others to the work presented, including jointly authored
publications, is clearly acknowledged.
Signed: Felix Jeyareuben Chandrakumar
ix
Date: 2-Jun-2014
Acknowledgements
First and foremost, I thank God for the knowledge and wisdom that He
had given me during this thesis period, and indeed, throughout my life: "I
can do all things through Christ who strengthens me." (Philippians 4: 13).
I thank my wife, Esther and my two young daughters, Felicia and Olivia
for their support, encouragement, patience and love. I thank my parents
for their love and support throughout my life.
I thank my supervisor, Dr Kim-Kwang Raymond Choo and my associate
supervisor, Ben Martini for their excellent academic support for doing this
research. I also thank our program director, Dr Elena Sitnikova and
lecturers Dr Lin Liu and Dr Sameera Mubarak for their excellent academic
teaching and support during the course of my study.
I thank my employer, Hewlett Packard for granting me leave when I am
required to attend workshops and meetings in the University. I thank
Google for creating Android and making it open source, without which my
thesis would have not existed. I thank Microsoft for providing its Visual
Studio software free for the student community through Dreamspark
which helped me to build the Android Cache viewer prototype. I thank the
several other open source tools and libraries I had used and referred in
my thesis.
I thank everyone who I haven’t mentioned here but helped me in making
this thesis possible.
x
Chapter 1:
Introduction
1.1
Overview
Android, as of December 2013, has reportedly 79% of the mobile market
share (Fingas 2014). As of July 2013, Google Play had more than 1
million Android apps published with an estimated 50 billion downloads per
year (Victor 2013). This is a remarkable growth in a short period of time.
According to Sundar Pichai, Senior Vice President of Chrome and Apps in
Google, there are reportedly more than 1 Billion Android device
activations as of September 2013 (Sundar Pichai 2013). Due to the
popularity of Android devices, they could either be used for criminal
activities as well becoming a target for cybercriminal activities (e.g.
infected by malware to facilitate data theft). This is not surprisingly as the
amount and nature of data stored on Android and other mobile devices
had grown from simple contact list a decade back to several gigabytes of
potentially sensitive and personally identifiable information today.
As Butler and Choo (2013, p.1) explained:
[g]iven the increase in ICT [including mobile devices] in everyday
life, digital forensics is increasingly being used in the courts in
Australia and overseas. The concept central to digital forensic is
digital evidence.
Digital forensics is the process of gathering evidence of some type of an
incident or crime that has involved ICT including mobile devices. These
data can be in the form of simple contacts, browsing histories, notes and
encrypted data, and the challenges are well documented (Hoog 2011);
(Hooper, Martini & Choo 2013);(Martini & Choo 2013). For example, in
Android Architecture, the standard libraries or the API (Application
Program Interface) sit in between the Linux kernel and the Application
framework (Xuguang 2009). As the developers are using the same APIs,
these APIs may use caches for their own operations (Google 2014), and
potential sources of evidence in an investigation. While general
information on Android architectural and developer information such as
the cache partitions and app cache locations are available (Raja 2012),
there is a lack of specific information regarding app caches and how to
extract artefacts from the caches. In addition, research efforts on the
extraction artefacts from Android devices have been limited to-date (Hoog
2011).
1
It is not surprising as mobile forensics is relatively new (Barmpatsalou et
al. 2013), and therefore, not as well understood in comparison to other
areas of digital forensics. This thesis aims to contribute towards this
knowledge gap.
1.2
Research aims and questions
This research aims to identify different formats of app caches, and to
understand, document and classify the various cache formats.
The two research questions are as follow:
1. What is the process or methodology that must be followed to
forensically analyse Android caches?
2. How can we make use of a forensically sound process to build new
tools and utilities to analyse unknown and undocumented cache file
formats?
To answer the above research questions as well as assisting digital
forensic practitioners, examiners, and researchers when undertaking
forensic analysis of Android app caches, this research will:
1. Propose a conceptual Android Cache Forensic Process, and
2. Design an open source prototype of an Android Cache Viewer.
1.3
Summary of Thesis Chapters
The structure of this thesis is as follows.
Chapter 2 examines the current digital forensic literature.
Chapter 3 outlines the proposed conceptual Android Cache Forensic
Process based on McKemmish’s (1999) model, as well as the Android
Cache Taxonomy.
Chapter 4 describes the application of the proposed conceptual Android
Cache Forensic Process to the analysis of different caches used by Android
apps. The prototype of an Android Cache Viewer and its potential
applications are also presented in this chapter.
Chapter 5 concludes this thesis and outlines future work.
2
Chapter 2:
Literature Review
2.1
Google Android
Android architecture has a number of layers namely Applications,
Application framework, Libraries, Android Runtime and the Linux Kernel.
Android uses only the kernel portion of the Linux for its core system
services. The core libraries provides the functionality of Java
Programming language. Android Runtime consists of core libraries and the
Delvik VM (Virtual Machine). Dalvik VM is a license free Java based VM
(Xuguang 2009).
Below is the list of libraries that are part of Android architecture:









Libc is c standard library.
SSL is a library for Secure Socket Layer
SGL is the 2D image engine library.
OpenGL or ES is the 3D image engine library.
Media Framework library forms the core part of Android multi-media
SQLite library is for the use of embedded database
WebKit, which is the same layout engine used in Google Chrome,
also forms part of Android Architecture.
FreeType is a library for Bitmap and Vector
SurfaceManager is a library to manage windows for different
applications.
3
Figure 1 – Android Architecture (Adapted from Gandhewar and Sheikh
2011)
A framework is a component that can be reused. All Android applications
are based on the application framework which includes a rich and
extendable Views, Content Providers that enables applications to access
and share data with other applications, Resource Manager to manage
localized strings, layouts and other resources, Notification manager to
provide notifications and Activity Manager which manages the life-cycle of
the applications (Liu & Yu 2011).
The standard internal memory partitions on Android are as follows:






/boot - which enables the mobile to boot
/system - which contains the Android Operating System
/recovery - for the purpose of recovery console
/data - which contains the user data
/cache - where frequently used data and app components are
stored and
/misc - where miscellaneous system settings are stored
Apart from the above list, /sdcard which represents the external SD card
and /sd-ext which is an additional partition in the SD card (Raja 2012).
2.2
PC Caches
Unlike Android caches, forensic analysis of web caches for different
browsers on personal computers are studied and well documented (Oh,
Lee & Lee 2011). Forensic analysis on internet explorer cache was well
studied and widely used for more than a decade (Jones 2003). Firefox,
starting from version 3 uses SQLite database for storing caches, browser
history, bookmarks (Pereira 2009). Google Chrome also uses SQLite
database for storing caches, browser history and bookmarks and forensic
analysis of it is well studied and documented (kristinn 2010). Recovery
method for deleted record in SQLite databases used by browsers are well
studied and documented (Jeon et al. 2012).
2.3
Forensic Models
Forensic computing is a field of specialization using computer technology
for investigation of computer based and traditional crimes. It is the
process of identification of potential evidences, preserving evidences from
change, analysing those evidences by professionals and presenting legally
4
acceptable evidence in court (McKemmish 1999). Cache forensics in
Android mobile devices also involves these same processes of identifying,
preserving, analysing and presenting.
Caches are commonly network data that is stored locally on flash memory
and reused when the same data is requested instead of fetching the same
data from the network. Nearly all browsers, including mobile browsers
cache data. This cached information is a potential source of evidence.In
this section, we will review the existing literature for identifying caches,
preserving the identified caches, analysing the cache formats and discuss
means of presenting the analysed caches to the court.
The McKemmish model is primarily focused on identification, preservation,
analysis and presentation of digital evidence. However McKemmish also
mentions four rules for forensic computing namely, minimal handling of
original, account for any change, comply with rules of evidence and not to
exceed our knowledge on the subject (McKemmish 1999). As caches can
be a type of electronic evidence, all of McKemmish’s four key elements
and the rules applies.
Figure 2 - Model of Forensic Computing (Adapted from McKemmish 1999)
5
In addition to McKemmish’s (1999) model, a number of forensic models
have been proposed. The Computer Forensic Process proposed by (Pollitt
1995) is, perhaps, one of the earliest digital forensic models. It has 4
steps, namely: Acquisition, Identification, Evaluation and Admission as
evidence. This is comparable to Mckemmish’s model. For example:
Identification, Evaluation or Analysis are common across both models.
However, the lack of preservation and presentation phases are a major
drawback in Pollitt’s model.
The model proposed by (Palmer 2001a) during the first Digital Forensic
Research Workshop (DFRWS) in 2001 is similar to that of Pollitt’s Model,
but it comprises seven steps, namely: Identification, Preservation,
Collection, Examination, Analysis, Presentation and Decision.







Identification step involves event or crime detection, resolving
signature, profile detection, anomalous detection, complaints, audit
analysis etc.
Preservation step involves case management, imaging technologies,
chain of custody and time synchronization.
Collection step involves preservation of evidence, using approved
methods, software and hardware, legal authority, using lossless
compression, sampling, data reduction and recovery techniques.
Examination step involves preservation of evidence, traceability,
validation techniques, filtering techniques, pattern matching, hidden
data discovery and hidden data extraction.
Analysis step involves preservation of evidence, traceability,
statistical, protocols, data mining, timeline, link and special.
Presentation step involves documentation, expert testimony,
clarification, mission impact statement, recommended
countermeasure and statistical interpretation.
Finally the decision step.
Palmer (2001a) model adapted Pollitt’s (1995) Model and McKemmish’s
(1999) Model. More specifically, Palmer’s (2001a) model includes the four
key elements of McKemmish’s (1999) Model – Identification, Preservation,
Analysis and Presentation –and the Collection, Examination and Decision
steps from Pollitt’s (1995) Model – see Figure 3.
6
Figure 3 - Palmer's Model (Adapted from Palmer 2001)
It is important to note that Examination and Analysis are separate steps
in Palmer’s Model but both these steps are merged as one in the
Mckemmish model. The usefulness for the two separate phases Collection
and Preservation are also questioned (Palmer 2001b).
Reith, Carr and Gunsch (2002) also proposed a forensic model and the
nine phases are as follows:.
1. Identification – To identify the incident.
2. Preparation – Preparation of tools and techniques, receiving
authorisation, support from management etc.
3. Approach – To maximize the collection of evidence.
4. Preservation – Preservation of digital evidence
5. Collection – Duplicating digital evidence using legally acceptable
procedures.
6. Examination – Systematic search of evidence.
7. Analysis – Analysing the evidences.
8. Presentation - Explanation of conclusion or presenting evidence to
court
9. Returning Evidence – Returning digital property to proper owner
Comparing this model with earlier models and DFRWS 2001, it has added
three new phases called Preparation, Approach and return of Evidence but
omits the Decision phase. The authors considered their model to be an
7
enhancement to DFRWS 2001 model.
The model suggested by Carrier and Spafford (2003) has seventeen
phases which are grouped into five. These five groups are Readiness,
Deployment, Physical Investigation, Digital Investigation and Review. This
model is very different from the other forensic models which were
discussed above. This model groups all phases as investigations but
divides into physical and digital. It can be viewed as an attempt to also
include the non-digital phases to provide a more generalized forensic
model.
Methodologies were classified into simple models, advanced models and
complex models. Simple models contains Identification, Preservation,
Collection, Examination, Analysis, Presentation and Decision (Broucek &
Turner 2006). Advanced models was introduced by Carrier and Spafford
in getting physical with the digital investigation process, which is based
on crime scene theory for physical investigation (Carrier & Spafford
2003). This model was also further enhanced (Baryamureeba & Tushabe
2004).
Figure 4 – Enhanced Digital Investigation Process (Adapted from
Baryamureeba & Tushabe 2004)
The above diagram from Integrated Digital Investigation Model
(Baryamureeba & Tushabe 2004) explains that the advanced model splits
the digital investigation into a separate phase, rather than just one phase
as demonstrated in McKemmish’s model, which is a simple model.
The European Cyber-tools Online Search for Evidence (CTOSE)
Foundation has developed a high level methodology to assist the
companies to do computer forensics. CTOSE is a complex and a
comprehensive model that spans across all evidence handling. It is also
8
flexible across different organisations and countries (Urry & Mitchison
2003).
Collection and analysis are integral steps in the digital forensic process.
Collection generally occurs once, generally as an image, and analysis
relies upon the collected image. In this methodology, an Android bootable
image is created to extract Android partitions including cache and data
forensically, without tampering with any data from the mobile (Vidas,
Zhang & Christin 2011). The general collection methodology proposed by
Vidas, Zhang & Christin is similar to McKemmish’s forensic computing
model, except it excludes the Identification and Presentation but focuses
on preservation and analysis specifically for Android mobiles.
2.4
Literature gaps
While there are several methodologies, there is no specific process or
technique to analyse Android app caches. This is probably due to the
recent entry of Android apps which became popular. Hence, there is a
need to have such a process to analyse Android caches. In addition to the
lack of process and methodologies, the following factors also complicate
forensic examination of Android app caches.
2.2.1 Cache Diversity
There is no universal cache format for Android Apps. App developers have
the liberty to decide which cache format is appropriate for them. While
Android itself provides support for caches, there are also other several
third-party cache libraries. Some of the third-party cache libraries are as
follows:





Volley (Kirkpatrick 2013)
Android Cache Library (VandalSoftware 2013)
Ignition (Käppler 2012)
FileCache (pbald 2011)
Picasso (Square 2013)
Also, a single Android app can make use of multiple cache libraries
depending on its requirements and the components used in it. There are
specific libraries for image caching, network caching etc. This diversity
poses a huge challenge in properly identifying potential evidences in
cache.
2.2.2 Undocumented Caches
Android cache structures used by apps are often not documented
9
properly. While clear API (Application Programming Interface)
documentation exists for developers to use a cache in the application, the
actual cache structures are generally not publicly documented for the
purpose of forensics. This is certainly a huge barrier to overcome. The
solution is not straight forward, but often involves analysing source code
and reverse engineering. This again poses a challenge in properly
identifying potential cache evidences.
2.2.3 Lack of Analysis Tools
Modern mobiles are no longer just telephones but a smartphone, with
powerful processing as a desktop computer or a laptop. With these swift
changes, the way that these smart phones must be analysed also
changes. While there are several forensic mobile data extracting tools
available and many desktop application aid in analysing data, there are
not many pre-existing tools to analyse specifically Android caches. Part of
the reason is also because, Android is relatively new and there are
millions of apps out there and each can have individual caching schemes.
This poses a challenge in properly analysing potential cache evidences.
2.2.4 Rapid Changes
Android 1.0 was released on September 2008 (Morrill 2008). With the
release of the latest version as of March 2014, Kit Kat 4.4, the API level
was upgraded to 19 times, and the current API level is 19. Hence, roughly
every 4 months, the API level increases, with new and more advanced
features. So, the knowledge of a particular version regarding caches used
by these new features, gets outdated every 4 months. This is a big
challenge for forensic investigators to properly analyse potential cache
evidences.
10
Chapter 3:
Conceptual Android Cache Forensic Process
Mobile forensics is always a challenge for law enforcement (Al-Zarouni
2006). Android forensics in particular have a host of challenges that must
be overcome (Hoog 2011). To overcome these issues and gaps, a new
process focused on cache forensics is required. With more than 1.2
million Android Apps (AppBrain 2014) in Google Play Store, there is a
wide range of apps and consequently diversity in the associated caches
(which are often undocumented). To facilitate forensic examination, a
transparent and robust classification is required. Classifying different
caches makes it easier for law enforcement to take appropriate steps
based on the cache branch.
Figure 5 – Our proposed Android Cache Taxonomy
Android caches are broadly divided into system caches and app caches.
System caches contain the Delvik virtual machine caches. App caches are
again divided into internal caches and external disk caches. External
11
caches are those that are stored in SD cards which has no security
attributes attached to them. Hence, any Android app can access these
caches. Internal or private caches are protected and available only to that
app and not available to any other app, unless the smartphone is rooted.
Irrespective of whether the cache is internal or external, app caches can
be broadly classified into component caches, Android API caches and
custom or third party caches.
3.1 Extending Mckemmish’s Model
Based on the cache taxonomy, different caches must be approached
differently. Delvik caches are mostly used for optimizing app execution,
scanning through applications (.apk) and building a tree of dependencies.
This will generally not contain any user data and as such is unlikely to
result in any potential evidence. App caches do contain user data and
must be carefully analysed. Most of the external disk caches do not
contain personal information or any information that is private to the
user. Internal storage is the default location for most of the apps that
may contain personal information.
Most of the gaps we have noted are technical barriers. McKemmish’s
model continues to be broadly applicable to Android cache forensics.
However the technologies used in various elements varies greatly. For
example, in preservation step, by default, most of the investigations take
a snapshot/image of the disk and analyse later. However, that may have
not been the case, two decades earlier. Hence, the preservation step is by
default became a part of the process. However, the analysis part requires
more effort with modern devices compared to the early days of mobile
phones. In those days, mobiles had contacts and nothing else. Today, it is
a computer in a pocket. This provides an imbalance in the four elements
in Mckemmish model, strictly speaking from an effort and volume of that
element as a result of technological advancement.
12
Figure 6 - Conceptual Android Cache Forensic Process
The process that is proposed here, which will be applied further in Android
Cache Viewer is based on extending McKemmish Model specifically for
Android Caches.
3.1.1.1
Classification
This is equivalent to the identification step in McKemmish Model of
forensic computing but not the same. Android caches are already
identified as potential evidences and there is no requirement to any
further identification. However, what is really required is a proper
classification. This classification helps to identify the steps and procedures
required to approach the investigation.
As we saw in cache taxonomy, there are several different caches used for
applications and each has a unique way to extract information. Hence,
classification is absolutely required for proper extraction and analysis of
Android caches.
3.1.1.2
Extraction
Preservation step is required to make sure that the potential evidence is
not tampered in anyway. With regards to mobile caches, the entire mobile
memory/SD partition is usually taken as a disk image and analysed
independently. From a cache perspective, the preservation step is mostly
13
by extraction.
Android partitions can be converted into an image file by using several
Unix tools, Android Debugging Bridge (ADB) and dd from BusyBox. This
partition can be mounted and analysed forensically. This way, the
preservation step from McKemmish Model can be successfully undertaken
during Extraction.
3.1.1.3
Cache Analysis
There are several tools to analyse mobile data. However, there are very
few known tools for forensic investigation of cache data.
There are several reasons identified:




Importance of actual data overshadows the cache data.
Cache implementations are often undocumented. The only place to
find them is in the source code comments.
Caches are at the liberty of the developer’s implementation.
Too many cache formats.
Android Cache Viewer, which is the primary contribution of this thesis, is
discussed in later sections, which helps to aid cache analysis for law
enforcement and forensic investigators. Each cache is unique and must be
analysed specifically. As we discussed earlier, without a proper
classification, it is not easy for systematic analysis.
3.1.1.4
Cache Reports
Presentation phase is the final element in McKemmish model which
describes the need to provide presentable documents as the court
requires. While it may include technical reports, it is not generally
composed solely of a technical report. With regards to Android cache
forensics, cache reports will often be included in the document which will
be presented to the court. Android cache viewer will be able to provide
cache reports.
14
Chapter 4:
A Case Study
4.1
Experimental Setup
In order to get the app caches, applications that are widely used i.e.
which has at least 1 million downloads or if the application is from a
significant brand or company, are considered. Nearly 100 apps were
identified and analysed for caches. The complete list of these apps is
available at the Appendix-A. Out of these 100 apps, 11 apps are selected
and studied in detail based on the usage of caches that are common
across other apps.
Different caches used by the same App
App Name
Web
View
Cache
SQLite
DB
Cache
Adobe Reader
Yes
Yes
Amazon Kindle
Yes
Carsales
Yes
Domain Real
Estate
Yes
eBay
Yes
Facebook
Yes
LinkedIn
Yes
NAB
Yes
Volley
Serialized
Java
Objects
Network
File
Caches
Yes
Yes JSON
Cache
Yes
Yes Image
Cache,
Gzipped
XML
Cache
Yes Image,
Audio and
Upload
Caches
15
Custom
Cache
Realestate.com.au Yes
Yes
Skype
Yes
Yes JSON
Cache
Yes
YouTube
Yes
Table 1 –List of Apps Studied in Detail
4.1.1
Assumptions
Making reasonable assumptions is part of every research experiment and
this research is no exception. Some of the assumptions made for this
research includes:
4.1.1.1
Android mobile phone is rooted
There are several discussions without any consensus regarding whether to
root an Android mobile phone or not, when a forensic investigation is
required. There are also suggestions on how to take a raw image of
internal storage including the partitions (Vidas, Zhang & Christin 2011).
However, for this experiment, we consider the mobile phone is rooted.
4.1.1.2
Developer mode enabled
Whether working on an extracted image which is booted using virtual
machine or an actual mobile, without developer mode, it is not possible to
enable USB debugging for it to communicate with standard Android tools
like adb. Hence, developer mode will be enabled for this experiment.
4.1.1.3
USB debugging is enabled
Android tools like adb can communicate only when debugging is enabled.
While other debugging methods can be used, for this experiment, USB
debugging will be used for convenience.
4.1.1.4
Internal storage is not encrypted
Encryption is one of the biggest challenges for law enforcement agencies
and forensic investigators. Mobile encryption by itself is a huge topic.
However, for this experiment, the mobile considered will not use any
advanced options like encrypted, which is not enabled by default.
4.1.2



Hardware Used
Mobile: Samsung Galaxy Note N7000
Android Version: 4.1.2 Jelly Bean
Chipset: Exynos
16




CPU: Dual-core 1.4 GHz ARM Cortex-A9
GPU: Mali-400
Memory Internal: 16 GB storage, 1 GB RAM
Memory Card: microSD, up to 64 GB, 2 GB included
4.1.3
Cache Locations
Each of the identified caches has separate locations in the Android storage
layout.



The cache used by Android VM known as Delvik is found in
/data/delvik-cache.
Private or internal App Cache are found in data location and
accessible only by the application, unless the phone is rooted.
External App Cache is used when caches are larger and the app
needs to make use of eternal memory. When an app ran out of
internal memory, it may try to use this eternal memory.
4.1.4
Acquisition of cache and data partitions
Most modern methods for acquisition of caches occurs when the
acquisition of mobile happens. There are two methods generally discussed
for the purpose of mobile acquisition.
The first method is traditionally used to take a partition image by rooting
the device and using adb to take partition image. This method does not
require much development skills but requires the phone to be rooted and
rooting the phone does affect the operating system but potential evidence
in the mobile device should remain intact and unaffected.
The second method however, uses a different approach to take partition
images using custom built boot images specifically for a mobile model. In
this method, a boot image is developed and loaded into the mobile using
the recovery console which allows the developed code to boot on the
mobile and the code helps to extract forensically the information in the
mobile. This method however, requires significant development skills,
significant testing of the utility for a mobile model and often slow. Even
though this method is promising from the forensic sense, it is not easy
and not affordable given the numerous Android mobile models released
each year.
4.1.5
Acquisition using dd
Any Android partition can be converted into an image file by using the
below steps. All the below steps uses the standard tools available from
Android.
17
4.1.5.1
Connect the Android device to the computer
In order to successfully connect an Android device, Google’s Android SDK
must be installed. Once installed, the Android debugging bridge,
commonly referred as adb can be accessible from the platform-tools
folder within the sdk.
D:\ADT\sdk\platform-tools>adb devices
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
List of devices attached
xxxxxxxxxxxxxx device
4.1.5.2
Go to super-user mode
Superuser mode can be accessed using switch user command.
shell@Android:/ $ su
su
root@Android:/ #
4.1.5.3
List the mounted partitions
In order to successfully take images of the partition, the partitions can be
listed using the mount command.
root@Android:/ # mount
mount
rootfs / rootfs ro,relatime 0 0
tmpfs /dev tmpfs rw,nosuid,relatime,mode=755 0 0
devpts /dev/pts devpts rw,relatime,mode=600 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,relatime 0 0
none /acct cgroup rw,relatime,cpuacct 0 0
tmpfs /mnt/asec tmpfs rw,relatime,mode=755,gid=1000 0 0
tmpfs /mnt/obb tmpfs rw,relatime,mode=755,gid=1000 0 0
none /dev/cpuctl cgroup rw,relatime,cpu 0 0
/dev/block/mmcblk0p9 /system ext4 ro,noatime,barrier=1,data=ordered
0 0
/dev/block/mmcblk0p7 /cache ext4
rw,nosuid,nodev,noatime,barrier=1,journal_async_commit,data=ordered
0 0
/dev/block/mmcblk0p1 /efs ext4
rw,nosuid,nodev,noatime,barrier=1,journal_async_commit,data=ordered
0 0
/dev/block/mmcblk0p12 /preload ext4
ro,nosuid,nodev,noatime,barrier=1,data=ordered 0 0
/dev/block/mmcblk0p10 /data ext4
18
rw,nosuid,nodev,noatime,barrier=1,journal_async_commit,data=ordered,
noauto_da_alloc,discard 0 0
/dev/block/mmcblk0p4 /mnt/.lfs j4fs rw,relatime 0 0
/sys/kernel/debug /sys/kernel/debug debugfs rw,relatime 0 0
/dev/block/vold/259:3 /storage/sdcard0 vfat
rw,dirsync,nosuid,nodev,noexec,noatime,nodiratime,uid=1000,gid=1015,
fmask=0002,dmask=0002,allow_utime=0020,codepage=
cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remountro,discard 0 0
4.1.5.4
Unmount the partitions
Once the partitions on which the folders /data and /cache are mounted,
we can easily unmount using the below command. Cache partition could
be unmounted, but unmounting data partition failed. However, this does
not cause any drawback in our process or steps because, live acquisition
in forensics is always done on an unmounted partition which is a standard
procedure.
root@Android:/ # umount /cache
umount /cache
root@Android:/ # umount /data
umount /data
failed: Device or resource busy
4.1.5.5
Take image of the partitions
Once the mounted partitions for data and cache are identified, the
following commands can be issued to take an image. While it is better to
unmount these partitions before taking an image, unfortunately,
unmounting data partition was not possible.
root@Android:/ # dd if=/dev/block/mmcblk0p7 bs=64K | gzip -c >
/sdcard/cache.img.gz
4K | gzip -c > /sdcard/cache.img.gz
<
3276800+0 records in
3276800+0 records out
209715200 bytes transferred in 60.809 secs (3448752 bytes/sec)
root@Android:/ # dd if=/dev/block/mmcblk0p10 bs=64K | gzip -c >
/sdcard/data.img.gz
64K | gzip -c > /sdcard/data.img.gz
<
33554432+0 records in
33554432+0 records out
2147483648 bytes transferred in 821.632 secs (2613680 bytes/sec)
19
4.2
Findings
There are several interesting findings that were identified during the
cache analysis.
4.2.1
System caches
System cache in Android is Dalvik VM Cache. For the purpose of faster
run time execution, byte-code alignment, verification and optimization are
done well ahead and stored as optimized DEX in dalvik cache. This
optimization happens when the application is first run after the
installation. The dalvik-cache is found in a system folder which can be
found at /data/data/dalvik-cache (Selvakumar 2012).
4.2.2
Application caches
Most apps use private caches in some way or the other. While some
Android developers specifically handle cache in their apps, most
developers may not even know that their app will cache internally
because they use certain APIs. A pattern of similarity is noticed across
apps and the usage of standard cache APIs creating stand set of cache
files. However, most of these cache file formats are undocumented. In
this research, some attempts had been made to document these
undocumented cache formats.
4.2.2.1
Generic Caches
Most of the analysed apps have these files. It is usually found inside the
Android private cache location and accompanied by two other folders
namely debug and testdata. It generally creates around 12 files or more.












cache_bd.0
cache_bd.m
cache_its.m
cache_its_ter.m
cache_r.0
cache_r.m
cache_vts_<package>.0
cache_vts_<package>.m
cache_vts_inaka_<package>.0
cache_vts_inaka_<package>.m
cache_vts_labl_<package>.0
cache_vts_labl_<package>.m
Below is the structure of cache_r.0 file
Length
4
Offset
0
Example
0x01 0x00
Description
A constant 0x01 0x00 0x00 0x01
20
0x00 0x01
4
4
0x35 0xbe
0x5d 0x0f
1
8
0xb4
1
1
9
10
0x12
0x0e
u = length
of url found
at offset 10
4
11
/building.list
11+u
4
15+u
4
19+u
1
2
23+u
24+u
0x18
0x01
0x20
0x9a
0x00
0x00
0x32
0xe8
v = length
of data
found at
offset 24+u
1
1
26+u
(data)
26+u+v
27+u+v
0x3a
0x12
w = length
of the
contenttype of
data
28+u+v
image/png
across all apps seems to be a
header for the record.
While confirmed as a date/time,
unable to yet decode to get
date/time back – require more
time and investigation.
Counter. Seems to decrease with
next record.
A constant 0x12 across all apps.
Length of the URL of the cached
data
URL of the cached data
0xc8
0x21
0xff 0x6c
A constant 0x18 0xc8 0x01 0x21
across all apps.
Unknown
0x00
0x00
A constant 0x00 0x00 0x00 0x00
across all apps.
A constant 0x32 across all apps.
It is assumed to be the length of
the data, but unable to confirm as
the bytes are not not decoded yet.
The actual data for which this
cache record is for.
0x97
A constant 0x3a across all apps.
The length of the content-type in
ASCII string.
Content-Type of the data.
Table 2 - Structure of cache_r.0
Below is the structure of cache_bd.0 file
Length
16
Offset
0
Example
0x35 0x37
Description
Unknown.
21
4
16
4
20
4
24
4
28
1
1
u=length of
data
32
33
34
0x31 0x64
0x66 0x34
0x36 0x30
0x36 0x39
0x39 0x61
0x35 0x37
0x34 0x35
0xFF 0xFF 0xFF
0xFF
0x00 0x00
0x01 0x43
0xC6 0xBE
0x65 0xDB
0x00 0x00
0x00 0x26
0A
24
A constant 0xFF 0xFF 0xFF 0xFF
across all apps seems to be a
header for the record.
Unknown
Unknown, Could be date/time.
Length of the Data
Seperator
Length of Data Record
Data
Table 3 - Structure of cache_bd.0
4.2.2.2
Webview Cache
When an app uses WebView component to load web pages, the pages and
other resources related to that page are cached in the private cache
location of each app. WebView in Android 4.4 and above by default uses
Chromium WebView while less than version 4.4 uses Android WebView
(Google 2013). This means, the WebView caches on Android versions less
than 4.4 will be different than the WebView Caches on version 4.4 and
above.
In this experiment, Android version 4.1.2_r2 is considered because
Android 4.4 is relatively new and only a few models exist.
WebView caches are found inside a directory called
webviewCacheChromium under the private cache location.
E.g., /data/data/<package_name>/cache/webviewCacheChromium
The cache consists of many files but only three different file formats.
There is only one index file, a few data_<number> files and several
f_xxxxxx where x is a hexadecimal number.
22
Figure 7 - List of files for WebView Cache
The WebView caches are stored on disk as a collection of block-files with
an index file and a collection of several external files. The Android source
header file disk_format.h located inside the project chromium under
net/disk_cache contains several important information regarding cache
structures and working mechanisms.
When cache data is larger than the block size specified in (net/addr.h),
then the cache is stored on a separate file called f_xxxxxx where x is a
hexadecimal number. Smaller data are stored in series of blocks on a
block file.
The index file which is just ‘index’ without any extensions, is a hash table
that maps the cache entry to the cache address value.
Length
4
Offset
0
4
4
4
4
4
4
8
12
16
20
4
4
4
24
28
32
4
8
36
40
Example
C3 CA 03 C1
(0xC103CAC3)
01 00 02 00
(Version 2.1)
01 00 00 00
(Flag 1 or 0)
01 00 00 00
(Flag 1 or 0)
E2 E5 E3 06 2C
51 2E 00
23
Description
Index Magic – File Identifier
Version
Number of entries currently stored
Total size of the stored data.
Last external file created.
Dirty Flag
Storage for usage data
Actual size of the table
Signals a previous crash.
Id of an ongoing test.
Creation time for this set of files.
208
8
4
20
48
256
264
268
20
288
20
308
4
4
4
28
4 times the
actual size
of the
table, value
located at
offset 28
312
316
320
324
352
Padded content
Pad
Flag to tell when cache is filled.
Sizes. Array of 5 entries with each
entry having 4 bytes.
Heads cache address. Array of 5
entries with each entry having 4
bytes.
Tails cache address. Array of 5
entries with each entry having 4
bytes.
Transaction cache address.
Actual in-flight operation.
In-flight operation list.
Pad
Cache Addresses, where each
address is of 4 bytes, as an array
of up to the actual size of the
table.
Table 4 - WebView cache index file
Block-file is the last element of the cache which stores blocks of data of a
given size. It can store data from one to four consecutive blocks and can
grow up to 64K blocks. It has a fixed size header used to track free of
blocks on the file. The first file contains the number of the second file, and
the second file contains the number of a third file, created when the
second file reaches its limit. Any given block can be located directly by its
address from these linked-chain of files, which contains the file number
and starting block inside the file.
Every time a new cache is initialized, it is done so with four block files
(data_0, data_1, data_2 and data_3) with each file dedicated to store
blocks of a given size. The number at the end of the file name is the block
file number which is in decimal.
There are two special types of blocks namely, an entry and a rankings
node. While entry node contains information related to the same cache
entry, a rankings node has volatile information that changes frequently
for a given entry. All cache entries also have a dirty identifier.
24
Length
4
Offset
0
4
4
2
2
4
4
8
10
12
16
20
16
36
16
52
4
56
20
60
2028
80
Example
C3 CA 04 C1
(0xC104CAC3)
00 00 02 00
(Version 2.0)
Description
Index Magic – File Identifier
Version
Index of this file.
Next file when this one is full.
Size of the blocks of this file.
Number of stored entries.
Current maximum number of
entries.
Counters of 4 empty entries for
each type.
Last used position for 4 entry
types.
Keep track of updates to the
header.
User. Represented as an array of 5
integers.
Allocation Bitmap. 507 total
entries. The value is derived from
max blocks.
Table 5 - Structure of block file
Length
4
4
Offset
0
4
4
4
8
12
4
16
4
8
4
4
16
20
24
32
36
40
16
56
Example
Description
Full hash of the key.
Next cache entry address with the
same hash or bucket.
Rankings node for this entry.
Reuse Count (how often it is
requested)
Refetch Count (how often it is
fetched from internet)
Current state.
Creation Date
Key Length
Optional address of a long key.
Size. 4 data streams for each entry
of size 4 bytes
Cache Address. 4 data streams for
each entry of size 4 bytes
25
4
72
20
160
76
26
Entry flags:
1 – Parent Entry
2 – Child Entry
Pad
Key as String.
Table 6 - Structure of a Cache Entry
The other files f_xxx are raw data files like Html, JavaScript etc., either
compressed or uncompressed files.
4.2.2.3
SQLite DB Cache
SQLite is a powerful, compact, embedded relational database
management system (Hipp & Kennedy 2007). Several Apps that take
advantage of SQLite database which is on public domain, used by default
by most modern browsers and has default developer support from
Android, instead of just files. These files can be viewed by any SQLite
database browser. Android Cache Viewer, the primary contribution of this
thesis provides default support for SQLite database caches.
4.2.2.4
Image Cache
Standard Android gallery uses a format different from other caches. It
creates of three files where one file is the index and the other two are
data files. One data file is active while the other is inactive. New entries
are appended into the active region until it exceeds the size limit. If it
exceeds the limit, the active file and the inactive file are interchanged,
and the new active file is simply truncated and the index for that file is
also cleared. The index file is a hash table (Android 2010b).
Length
4
4
Offset
0
4
4
8
4
4
12
16
4
20
Example
Description
Magic number: 0xB3273030
Max number of hash entries per
region.
Max number of data bytes per
region (including header).
The active growing region: 0 or 1.
The number of hash entries used in
the active region.
The number of data bytes used in
26
4
4
u = (12 *
Maximum
Entries
bytes).
v = (12 *
Maximum
Entries
bytes).
the active region.
Version number.
Checksum of bytes from 0 to 28.
Hash entries for region 0. The size
is u
24
28
32
32+u
Hash entries for region 1. The size
is also u.
Table 7 - Index file of Android Gallery
Length
4
Data
8
4
4
4,
u=length
U (value of
offset 16)
Offset
0
Example
Description
Magic number (Header:
0xBD248510
(Data is present as a blob and concatenated)
0
Key
8
Chksum
12
Offset
16
Length
20
Actual Data (or) Blob
Table 8 - Data file of Android Gallery
The structure is found in the below source location.

/Android-4.1.2_r2
/gallerycommon/src/com/android/gallery3d/common/BlobCache.jav
a
4.2.2.5
Serialized Java Objects
Some Android apps caches data in the form of serialized Java objects and
one good example is YouTube. Because serialized objects in various apps
can represent various structures, let us analyse YouTube as an example.
YouTube caches images as serialized objects. Skipping 0x95 bytes from
each of the .cache file located in the private cache directory, will yield a
JPEG image from the video watched. Offset 76-7D provides the
timestamp in milliseconds of the Unix epoch time.
27
Figure 8 - JPEG and Timestamp in YouTube Cache
In the above example, 0x000001442571F983 corresponds to Wed, 12 Feb
2014 09:33:50 GMT.
4.2.2.6
DiskLruCache
DiskLruCache is a least recently used cache implementation where cache
is written on the disk. In Android, this cache uses a specified amount of
space and each cache entry contains a key and a fixed number of values.
The values can be of any data even streams. The cache uses a journal file
which looks similar to the one below:
libcore.io.DiskLruCache
1
100
2
CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054
DIRTY 335c4c6028171cfddfbaae1a9c313c52
CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342
REMOVE 335c4c6028171cfddfbaae1a9c313c52
DIRTY 1ab96a171faeeee38496d8b330771a7a
CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234
READ 335c4c6028171cfddfbaae1a9c313c52
READ 3400330d1dfc7f3f7f4b8d4d803dfcf6
The first five lines are the header of the journal file.
Data Type
Header
Example
Description
28
String
String
String
String
Empty
String
Data
String
String
String
libcore.io.DiskLruCache
1
100
2
N/A
A constant string.
Disk Cache Version
Application Version
Value Count
Blank Line
CLEAN
335c4c6028171cfddfbaa
e1a9c313c52
1600
State of the cache entry
Key
Optional State Specific
Values
Table 9 - Structure of Journal File
Cache entries with DIRTY status is actively being created or updated.
Also, all successful DIRTY operation must be followed by a CLEAN or
REMOVE status. DIRTY lines with no CLEAN or REMOVE means, temporary
files must be removed. Cache entries can only be read from CLEAN track
entries. READ status tracks the LRU cache access. REMOVE status
indicates the removal of cache entry (Android 2010a).
A temporary file named "journal.tmp" will be used during compacting
journal file. This is helpful to data carve the journal.tmp for forensic
purposes.
Many apps like LinkedIn use DiskLruCache as it is a standard API. The
structure is found in the below source location.

\Android-4.1.2_r2\libcore\luni\src\main\java\libcore\io\
DiskLruCache.java
4.2.2.7
Custom Format
Several Apps also use custom and third party cache libraries which could
have different formats apart from what were discussed.
29
4.3
Open Source Android Cache Viewer Prototype
Android Cache Viewer is an open source application, which we have
developed and is one of the two contributions in this thesis. The
application is structured in a way that it can be extended easily (e.g.
allowing plug-in modules by other programmers). The application
attempts to cover most of the cache file structures and tries to provide a
reasonable view of what is inside the cache.
The application is built using C# and requires Microsoft’s .Net framework
4.0 or above. It runs and been tested on Windows XP, Vista/7 and
Windows 8/8.1.
The source code for Android Cache Viewer is uploaded to GitHub
(https://github.com/fcidau/Android-Cache-Viewer) and is released under
MIT License.
All cache formats discussed here are supported by Android Cache Viewer.
The formats include






Generic Cache (cache_r.0, cache_bd.0)
WebViewComponent Cache
SQLite DB cache
Image gallery cache
Serialized Object cache and
DiskLruCache format
Below are example screenshots from using the Android Cache Viewer.
4.3.1
cache_r.0
Below are the screenshots for cache_r.0 cache.
30
Figure 9 - cache_r.0 Details
Figure 10 - cache_r.0 Data
When cache_r.0 is opened, it lists all items as a tab, and each tab
contains a details section and a data section. The details section lists the
record values and the data displays the actual data. If the data is an
image, the picture is displayed.
4.3.2
WebView Cache
Below are the screenshots for cache_r.0 cache from Apps that use
WebView. WebView is used by almost any app that displays web content
31
on a browser component.
Figure 11 - WebView Cache Index
Figure 12 - WebView Cache Data
32
Figure 13 - WebView Cache External Data
WebView caches are displayed according to the internal data structure
and their linked external files. If the data is an image or a text file, it is
displayed as such.
4.3.3
YouTube Cache
YouTube stores images as serialization Java Objects. Opening these
caches will display the image present in them.
Figure 14 - YouTube Cache
4.3.4
Android Image Gallery Cache
33
Figure 15 - Android Image Gallery
4.3.5
SQLite DB Cache
The tool is capable of displaying all tables if the cache is a SQLite
database.
Figure 16 - SQLite DB Cache
4.3.6
Unknown Cache
When caches are unknown or unable to identify, the tool displays only the
ASCII text in them and replaces the non-printable character with a dot.
34
Figure 17 - Unknown Cache
35
Chapter 5:
Conclusion and Future Work
Android is the world’s most popular mobile platform with more than a
million new device activations every day, according to Android Developer
website. Google Play also has more than 1.2 million apps as of April 2014
(AppBrain 2014). Mobile digital forensics, particularly for Android is a
rapidly expanding field.
5.1
Research Summary
In this thesis, we have contributed towards a better understanding to
both research questions identified in Chapter 1.2, as explained below.
1. What is the process or methodology that must be followed to
forensically analyse Android caches?
In the thesis, we identified literature gaps and limitations in using existing
forensic models when examining Android caches. To assist forensic
researchers and practitioners in examining the wide range of caches used
by various Android Apps, a taxonomy for Android caches and the
conceptual Android Cache Forensics Model were proposed – see Chapter
3. We then studied more than 100 popular apps (i.e. apps that have more
than a million downloads or an app from a popular brand). Using the
Android Cache Forensics Model, we found that 11 apps appear to be using
some form of cache. These 11 apps were then studied in detail.
Previously unknown cache formats were decoded and several
undocumented cache formats used commonly by Android apps were
documented – see Chapter 4.
2. How can we make use of a forensically sound process to build new
tools and utilities to analyse unknown and undocumented cache file
formats?
Based on findings from Chapter 4, we designed Android Cache Viewer, an
open source prototype tool, to decode Android cache formats, such as
WebViewComponent Cache, SQLite DB cache, Image gallery cache,
Serialized Object cache and DiskLruCache. We demonstrate in Chapter
4.3 that the viewer can assist forensic investigators and law enforcement
in analysing undocumented Android cache formats with ease.
5.2
Future Work
Much work in this area remains to be done. For example, a potential
extension of this thesis is to add additional plugins for other
36
undocumented cache file structures, adding new cache formats as new
formats are introduced and making each plugin as independently loadable
modules. The source code for Android Cache Viewer prototype is uploaded
to GitHub (https://github.com/fcidau/Android-Cache-Viewer) and released
under MIT License for collaborative further development by the open
source community.
37
Reference list
Al-Zarouni, M 2006, 'Mobile handset forensic evidence: a challenge for law
enforcement'.
Android 2010a, DiskLruCache.java, The Android Open Source Project,
<https://android.googlesource.com/platform/packages/apps/Gallery2/+/
android4.1.2_r2/libcore/luni/src/main/java/libcore/io/DiskLruCache.java>.
Android 2010b, BlobCache.java, The Android Open Source Project,
<https://android.googlesource.com/platform/packages/apps/Gallery2/+/
android4.1.2_r2/gallerycommon/src/com/android/gallery3d/common/BlobCache
.java>.
AppBrain 2014, Number of Android applications, appbrain.com, viewed 16May-2014, <http://www.appbrain.com/stats/number-of-android-apps>.
Barmpatsalou, K, Damopoulos, D, Kambourakis, G & Katos, V 2013, 'A
critical review of 7 years of Mobile Device Forensics', digital investigation,
vol. 10, no. 4, pp. 323-349.
Baryamureeba, V & Tushabe, F 2004, 'The enhanced digital investigation
process model', Proceedings of the Fourth Digital Forensic Research
Workshop, Citeseer.
Broucek, V & Turner, P 2006, 'Winning the battles, losing the war?
Rethinking methodology for forensic computing research', Journal in
Computer Virology, vol. 2, no. 1, pp. 3-12.
Butler, A & Choo, K-KR 2013, 'IT standards and guides do not adequately
prepare IT practitioners to appear as expert witnesses: An Australian
perspective', Security Journal.
38
Carrier, B & Spafford, EH 2003, 'Getting physical with the digital
investigation process', International Journal of digital evidence, vol. 2, no. 2,
pp. 1-20.
Fingas, J 2014, Android climbed to 79 percent of smartphone market share in
2013, but its growth has slowed, updated 29-Jan-2014, engadget.com,
viewed 30-Jan-2014, <http://www.engadget.com/2014/01/29/strategyanalytics-2013-smartphone-share/>.
Google 2013, WebView for Android, Google Developers,
developers.google.com, viewed 1-Mar-2014,
<https://developers.google.com/chrome/mobile/docs/webview/overview
#what_version_of_chrome_is_it_based_on>.
Google 2014, LruCache, developer.android.com, viewed 26-May-2014,
<http://developer.android.com/reference/android/util/LruCache.html>.
Hipp, DR & Kennedy, D 2007, SQLite.
Hoog, A 2011, Android forensics: investigation, analysis and mobile security
for Google Android, Elsevier,
Hooper, C, Martini, B & Choo, K-KR 2013, 'Cloud computing and its
implications for cybercrime investigations in Australia', Computer Law &
Security Review, vol. 29, no. 2, pp. 152-163.
Jeon, S, Bang, J, Byun, K & Lee, S 2012, 'A recovery method of deleted record
for SQLite database', Personal and Ubiquitous Computing, vol. 16, no. 6, pp.
707-715.
Jones, KJ 2003, 'Forensic Analysis of Internet Explorer Activity Files',
Forensic Analysis of Microsoft Windows Recycle Bin Records.
Käppler, M 2012, Ignition, viewed 25-May-2014,
<https://github.com/mttkay/ignition>.
39
Kirkpatrick, F 2013, Volley: Easy, Fast Networking for Android, viewed 25May-2014,
<https://developers.google.com/events/io/sessions/325304728>.
kristinn 2010, 'Google Chrome Forensics', viewed 17-Jul-2014,
<http://digital-forensics.sans.org/blog/2010/01/21/google-chromeforensics/>.
Liu, J & Yu, J 2011, 'Research on development of android applications',
Fourth International conference on Intelligent Networks and Intelligent
Systems.
Martini, B & Choo, K-KR 2013, 'Cloud storage forensics: ownCloud as a case
study', digital investigation, vol. 10, no. 4, pp. 287-299.
McKemmish, R 1999, What is forensic computing?, Australian Institute of
Criminology,
Morrill, D 2008, 'Announcing the Android 1.0 SDK, release 1', viewed 30Mar-2014, <http://androiddevelopers.blogspot.com.au/2008/09/announcing-android-10-sdkrelease-1.html>.
Oh, J, Lee, S & Lee, S 2011, 'Advanced evidence collection and analysis of
web browser activity', digital investigation, vol. 8, pp. S62-S70.
Palmer, G 2001a, 'A road map for digital forensics research-report from the
first Digital Forensics Research Workshop (DFRWS)', Utica, New York.
Palmer, G 2001b, 'A road map for digital forensic research', First Digital
Forensic Research Workshop, Utica, New York, pp. 27-30.
pbald 2011, FileCache, viewed 25-May-2014,
<https://code.google.com/p/libs-for-android/wiki/FileCache>.
Pereira, MT 2009, 'Forensic analysis of the Firefox 3 Internet history and
40
recovery of deleted SQLite records', digital investigation, vol. 5, no. 3, pp.
93-103.
Pollitt, M 1995, 'Computer forensics: An approach to evidence in
cyberspace', Proceedings of the National Information Systems Security
Conference, pp. 487-491.
Raja, HQ 2012, Android Partitions Explained: boot, system, recovery, data,
cache & misc, 09-15, viewed 30-May-2014,
<http://www.addictivetips.com/mobile/android-partitions-explainedboot-system-recovery-data-cache-misc/>.
Reith, M, Carr, C & Gunsch, G 2002, 'An examination of digital forensic
models', International Journal of digital evidence, vol. 1, no. 3, pp. 1-12.
Selvakumar, G 2012, 'Constructing an Environment and Providing a
Performance Assessment of Android’s Dalvik Virtual Machine on x86 and
ARM', University of Kansas.
Square 2013, Picasso, viewed 25-May-2014,
<https://github.com/square/picasso>.
Sundar Pichai, VG 2013, '#AndroidKitKat', 30-Jan-2014,
<https://plus.google.com/+SundarPichai/posts/NeBW7AjT1QM>.
Urry, R & Mitchison, N 2003, 'CTOSE Project. Electronic Evidence:
gathering, securing, integrating, presenting', CTOSE Conference, Facultés
Universitaires Notre-Dame De la Paix, Namur, Belgium.
VandalSoftware 2013, Android Cache Library, viewed 25-May-2014,
<https://github.com/VandalSoftware/android-cache-lib>.
Victor 2013, Android's Google Play beats App Store with over 1 million apps,
now officially largest, updated 24-Jul-2013, phonearena.com, viewed 30Jan-2014, <http://www.phonearena.com/news/Androids-Google-Playbeats-App-Store-with-over-1-million-apps-now-officiallylargest_id45680>.
41
Vidas, T, Zhang, C & Christin, N 2011, 'Toward a general collection
methodology for Android devices', digital investigation, vol. 8, pp. S14-S24.
Xuguang, H 2009, 'An Introduction to Android', Dababase Lab. Inha
Univeristy.
Appendix A – Complete List of Studied Apps
In the below list, if the cache details column is blank, it means either the
cache directory is empty or no cache is found.
Application
Adobe Reader
Package
com.adobe.reader
Cache Details
webviewCache, sqlite db
cache
Amazon
Shopping
Amazon Kindle
AndFTP
Android Weather
AppMgr III
Apps 2 SD
Australian
Taxation Office
Australia Post
Bank of
Melbourne
Westpac
Banking
Bendigo Bank
BitTorrent
Booking.com
Box
Bupa
Carsales
com.amazon.mShop.Android
Abs workout
Cisco
Coles
Supermarket
ColorNote
com.caynax.a6w
com.cisco.Androidcisco
com.coles.Android.shopmate
com.amazon.kindle
lysesoft.andftp
com.devexpert.weather
com.a0soft.gphone.app2sd
com.IQBS.Android.app2sd
au.gov.ato.ATOTax
webviewCache
au.com.auspost.Android
org.bom.bank
org.westpac.bank
com.bendigobank.mobile
com.bittorrent.client
com.booking
com.box.Android
bupa.ProviderFinder
au.com.carsales
com.socialnmobile.dictapps.not
epad.color.note
42
webviewCache, custom
cache 'volley'
CommBank
Dick Smith
Dolphin Browser
Domain Real
Estate
Domino's Online
Ordering
Drive
eBay
com.commbank.netbank
cds.sniip.dicksmithapp
mobi.mgeek.TunnyBrowser
com.fairfax.domain
Emergency +
com.threesixtyentertainment.ne
sn
com.ahl.eventcinemas
com.evernote
com.facebook.katana
Event Cinemas
Evernote
Facebook
Firefox
Flight Specials
Flipboard
Foursquare
?Fringe 2014
Gmail
goMoney
Google Play
Books
Google Play
Store
GPS Tracking
Groupon
Gumtree AU
Hoyts
HSBC
IMDb
ING DIRECT
Australia
Banking
Instagram
Instant Heart
Rate
Job Seekers
LinkedIn
au.com.dominos.olo.Android.ap
p
com.google.Android.apps.docs
com.ebay.mobile
webviewCache, json cache
webviewCache, image
cache, serialized java
object, gzipped xml
webviewCache, image
cache, audio cache, upload
cache
org.mozilla.firefox
com.virginaustralia.flightspecial
s
flipboard.app
com.joelapenna.foursquared
com.adelaidefringe.fringe2014
com.google.Android.gm
com.anz.Android.gomoney
com.google.Android.apps.books
com.Android.vending
com.fsp.Android.c
com.groupon
com.ebay.gumtree.au
nz.co.vista.Android.movie
com.htsu.hsbcpersonalbanking
com.imdb.mobile
au.com.ingdirect.Android
com.instagram.Android
si.modula.Android.instantheartr
ate
au.gov.dhs.jobSeeker
com.linkedin.Android
43
webviewCache
MapMyRun
ME Bank
Medibank
Medicare
Express (Aust
Gov)
Facebook
Messenger
Yahoo!
Messenger
Virgin Mobile
My VMware
My Vodafone
Myer Christmas
MYER one
MyFitnessPal
NAB
NAB Flik
NIB Health
Insurance
Outlook.com
Facebook Pages
Manager
PayPal
Pinterest
Pizza Hut
Qantas
Realestate.com.
au
Royal Adelaide
Show
Run Keeper
Nike Running
Skype
Snapchat
St.George
Banking
Steam Gaming
Community
Students
Express (Aust
Gov)
Tango
com.mapmyrun.Android2
au.com.mebank.banking
au.com.medibank.phs
au.gov.dhs.expressplus.medicar
e
com.facebook.orca
com.yahoo.mobile.client.Androi
d.im
com.b2cloud.virginusagemeter
com.vmware.myvmware
au.com.vodafone.mobile.gss
com.myer.xmas
myer.com.Android
com.myfitnesspal.Android
au.com.nab.mobile
com.nab.nabflik
au.com.nib
webviewCache
com.outlook.Z7
com.facebook.pages.app
com.paypal.Android.p2pmobile
com.pinterest
com.yum.pizzahutau
au.com.qantas.qantas
au.com.realestate.app
webviewCache, sqlite db
cache, json cache
com.mobilenation.ras
com.fitnesskeeper.runkeeper.pr
o
com.nike.plusgps
com.skype.raider
com.snapchat.Android
org.stgeorge.bank
com.valvesoftware.Android.stea
m.community
au.gov.dhs.studentExpress
com.sgiggle.production
44
sqlite db, custom format
Tapatalk
Telstra 24x7
textPlus
The Weather
Channel
TripAdvisor
Twitter
Viber
Weatherzone
Woolworths
YouTube
Y! Mail
µTorrent
com.quoord.tapatalkpro.activity
com.telstra.mobile.Android.myt
elstra
com.gogii.textplus
com.weather.Weather
com.tripadvisor.tripadvisor
com.twitter.Android
com.viber.voip
au.com.weatherzone.Android.w
eatherzonefreeapp
com.woolworths
com.google.Android.youtube
com.yahoo.mobile.client.Androi
d.mail
com.utorrent.client
serialized java objects
Table 10 – Complete List of Studied Apps
45
Appendix B – Design and Implementation Notes
Design Choices
Android Cache Viewer is developed in Microsoft C# using Microsoft Visual
Studio 2013 Ultimate, taking advantage of Microsoft’s DreamSpark
program.
UML Diagram
Implementation Notes
The AndroidCacheViewer.cs class is a WinForm class which takes care of
the user interface. Each plugin usually extends CacheAbstract.cs which is
an abstract class, which in turn implements CacheInterface.cs interface.
The plugin may not extend CacheAbstract.cs but it must always
46
implement CacheInterface.cs interface. Although CacheAbstract.cs is
initially designed as an abstract, it does contain all the generic
implementations and common functions used across plugins in it. This
allows the actual cache-format logic to be simpler and efficient. The
plugin always gets the cache file location as input and returns the control
object, which is displayed by the WinForms. Hence, the plugin has the
liberty to decide how to display the cache in the user interface.
CacheIdentity.cs identifies the plugin and calls the corresponding plugin
implementation class. Identification is based on filenames and file
extensions.
The Android Cache Viewer is tested against all the apps studied in detail,
which are mentioned in Table 1, that share the same cache API.
47
Appendix C – Source Code
AndroidCacheViewer.cs
using
using
using
using
using
using
using
using
using
using
using
Android_Cache_Viewer.Plugins;
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.IO;
System.Linq;
System.Text;
System.Threading.Tasks;
System.Windows.Forms;
namespace Android_Cache_Viewer
{
public partial class AndroidCacheViewer : Form
{
string selected_file = "";
public AndroidCacheViewer()
{
InitializeComponent();
//
//openFileDlg.Filter = "YouTube|*.cache|Android
Gallery3D|*.*|cache_r.0|cache_r.0|cache_bd.0|cache_bd.0";
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
if(openFileDlg.ShowDialog(this)==DialogResult.OK)
{
selected_file = openFileDlg.FileName;
timerProcess.Start();
}
}
private void timerProcess_Tick(object sender, EventArgs e)
{
timerProcess.Stop();
displayPanel.Controls.Clear();
this.Text = "Android Cache Viewer : " + Path.GetFileName(selected_file);
CacheInterface cache = CacheIdentity.Identify(selected_file);
displayPanel.Controls.Clear();
displayPanel.Controls.Add(cache.showCache(selected_file));
}
private void supportToolStripMenuItem_Click(object sender, EventArgs e)
{
displayPanel.Controls.Clear();
Label lbl = new Label();
lbl.Text = "\r\nThe caches of the following apps are supported:\r\n\r\n";
lbl.Text += "YouTube (.cache), Android Gallery3D, cache_r.0, cache_bd.0";
lbl.Dock = DockStyle.Fill;
displayPanel.Controls.Add(lbl);
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
48
displayPanel.Controls.Clear();
Label lbl = new Label();
lbl.Text = "\r\nAndroid Cache Viewer is an open source software is developed by
Felix Jeyareuben Chandrakumar as a part of the thesis submitted to the University of South
Australia - School of Information Technology & Mathematical Sciences in fulfilment of the
requirements for the degree of Master of Science (Cyber Security and Forensic Computing).
The thesis was supervised by Dr Kim-Kwang Raymond Choo and Ben Martini.\r\n\r\nIcon http://www.iconarchive.com/artist/martz90.html";
lbl.Dock = DockStyle.Fill;
displayPanel.Controls.Add(lbl);
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
CacheIdentity.cs
using
using
using
using
using
using
using
Android_Cache_Viewer.Plugins;
System;
System.Collections.Generic;
System.IO;
System.Linq;
System.Text;
System.Threading.Tasks;
namespace Android_Cache_Viewer
{
class CacheIdentity
{
public static CacheInterface Identify(String filename)
{
if (filename.EndsWith(".cache"))
return new YouTubeCache();
else if (Path.GetFileNameWithoutExtension(filename).Equals("imgcache") &&
!filename.EndsWith(".idx"))
return new Gallery3dCache();
else if (filename.EndsWith("cache_r.0"))
return new CacheR0();
else if (filename.EndsWith("cache_bd.0"))
return new CacheBD0();
else if (filename.EndsWith(".db"))
return new SQLiteDB();
else if (filename.EndsWith("index") ||
Path.GetFileName(filename).StartsWith("data_")||Path.GetFileName(filename).StartsWith("f_")
)
return new WebViewCache();
else
return new NotImplemented();
}
}
}
Plugins/ CacheAbstract.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
49
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Android_Cache_Viewer.Plugins
{
class CacheAbstract : CacheInterface
{
public virtual Control showCache(string file)
{
Label lbl = new Label();
lbl.Text = "\r\nNot Implemented!";
lbl.Dock = DockStyle.Fill;
return lbl;
}
public static Image LoadImage(byte[] imageBytes)
{
Bitmap image = null;
byte[] mbytes = new byte[imageBytes.Length];
imageBytes.CopyTo(mbytes, 0);
MemoryStream inStream = new MemoryStream(mbytes);
image = new Bitmap(Image.FromStream(inStream));
inStream.Close();
//
return image;
}
public static string displayBytes(byte[] o, int offset, int length)
{
StringBuilder sb = new StringBuilder();
for(int i=offset;i<offset+length;i++)
{
sb.Append("0x"+Convert.ToInt16(o[i]).ToString("X") + " ");
}
//
string s = sb.ToString().Trim();
string[] arr = s.Trim().Split(new char[] (Victor));
string prev="";
int count = 1;
StringBuilder ss = new StringBuilder();
foreach(string a in arr)
{
if(prev==a)
count++;
else
{
50
ss.Append(prev);
ss.Append(" ");
if (count > 1)
{
ss.Append("(");
ss.Append(count);
ss.Append(" times) ");
}
count = 1;
prev = a;
}
}
ss.Append(prev);
ss.Append(" ");
if (count > 1)
{
ss.Append("(");
ss.Append(count);
ss.Append(" times) ");
}
return ss.ToString().Trim();
}
public static Control getContentControl(byte[] bytes)
{
Control ctrl = null;
if (bytes.Length > 5)
{
if ((bytes[0] == 'G' && bytes[1] == 'I' && bytes[2] == 'F') || (bytes[0] == 0xFF && bytes[1] ==
0xD8) || (bytes[0] == 0x89 && bytes[1] == 0x50 && bytes[2] == 0x4E && bytes[3] == 0x47))
{
ctrl = new PictureBox();
((PictureBox)ctrl).Image = LoadImage(bytes);
}
else if (bytes[0] == 0x1f && bytes[1] == 0x8b)
{
var bigStream = new GZipStream(new MemoryStream(bytes),
CompressionMode.Decompress);
var bigStreamOut = new System.IO.MemoryStream();
bigStream.CopyTo(bigStreamOut);
return getContentControl(bigStreamOut.ToArray());
}
else if (bytes[0] == 0x53 && bytes[1] == 0x51 && bytes[2] == 0x4C && bytes[3] == 0x69 &&
bytes[4] == 0x74 && bytes[5] == 0x65)
{
DataTable dt = new DataTable();
string rnd_file = Path.GetTempPath() + "/" + Path.GetRandomFileName();
File.WriteAllBytes(rnd_file, bytes);
string data_src = @"" + rnd_file;
SQLiteConnection cnn = new SQLiteConnection("Data Source=" + data_src);
51
cnn.Open();
SQLiteCommand mycommand = new SQLiteCommand(cnn);
mycommand.CommandText = "SELECT name FROM sqlite_master WHERE type='table'";
SQLiteDataReader reader = mycommand.ExecuteReader();
dt.Load(reader);
mycommand.Dispose();
reader.Dispose();
List<string> tables = new List<string>();
for (int row = 0; row < dt.Rows.Count; row++)
tables.Add(dt.Rows[row][0].ToString());
//
ctrl = new TabControl();
foreach (string table in tables)
{
TabPage page = new TabPage(table);
page.Controls.Add(getTablePage(rnd_file, table, cnn));
ctrl.Controls.Add(page);
}
cnn.Dispose();
}
else
{
ctrl = new TextBox();
((TextBox)ctrl).Multiline = true;
((TextBox)ctrl).ScrollBars = ScrollBars.Both;
((TextBox)ctrl).Text = displayFriendlyBytes(bytes, 0, bytes.Length);
((TextBox)ctrl).ReadOnly = true;
}
}
else
{
ctrl = new TextBox();
((TextBox)ctrl).Multiline = true;
((TextBox)ctrl).ScrollBars = ScrollBars.Both;
((TextBox)ctrl).Text = displayFriendlyBytes(bytes, 0, bytes.Length);
((TextBox)ctrl).ReadOnly = true;
}
ctrl.Dock = DockStyle.Fill;
return ctrl;
}
private static DataGridView getTablePage(string rnd_file, string tablename, SQLiteConnection
cnn)
{
DataGridView dgv = new DataGridView();
DataTable table = new DataTable();
SQLiteCommand mycommand = new SQLiteCommand(cnn);
mycommand.CommandText = "SELECT * FROM " + tablename;
52
SQLiteDataReader reader = mycommand.ExecuteReader();
table.Load(reader);
mycommand.Dispose();
reader.Dispose();
dgv.DataSource = table;
dgv.Dock = DockStyle.Fill;
return dgv;
}
public static string displayFriendlyBytes(byte[] o, int offset, int length)
{
StringBuilder sb = new StringBuilder();
for (int i = offset; i < offset + length; i++)
{
if (o[i] >= 32 && o[i] < 127 || (o[i] == '\r' || o[i] == '\n'))
sb.Append(Convert.ToChar(o[i]));
else
{
sb.Append(".");
}
}
return sb.ToString().Trim();
}
public static string displayHex(byte[] o, int offset, int length)
{
StringBuilder sb = new StringBuilder();
for (int i = offset; i < offset + length; i++)
{
sb.Append(Convert.ToInt16(o[i]).ToString("X").PadLeft(2,'0'));
}
return "0x"+sb.ToString().Trim();
}
public static int getInteger(byte[] o, int offset, int length)
{
int no = 0;
for (int i = offset + length - 1; i >= offset; i--)
{
no = no + (o[i] * (int)Math.Pow(256, offset + length - 1 - i));
}
return no;
}
public static long getLong(byte[] o, int offset, int length)
{
long no = 0;
for (int i = offset + length - 1; i >= offset; i--)
{
no = no + (o[i] * (long)Math.Pow(256, offset + length - 1 - i));
}
53
return no;
}
public static int getIntegerR(byte[] o, int offset, int length)
{
int no = 0;
for (int i = offset; i < offset + length; i++)
{
no = no + (o[i]*(int)Math.Pow(256, i - offset));
}
return no;
}
public static long getLongR(byte[] o, int offset, int length)
{
long no = 0;
for (int i = offset; i < offset + length; i++)
{
no = no + (o[i] * (long)Math.Pow(256, i - offset));
}
return no;
}
public static string displayString(byte[] o, int offset, int length)
{
StringBuilder sb = new StringBuilder();
for (int i = offset; i < offset + length; i++)
{
sb.Append(Convert.ToChar(o[i]));
}
return sb.ToString().Trim();
}
public static Bitmap ByteToImage(byte[] blob)
{
MemoryStream mStream = new MemoryStream();
byte[] pData = blob;
mStream.Write(pData, 0, Convert.ToInt32(pData.Length));
Bitmap bm = new Bitmap(mStream, false);
mStream.Dispose();
return bm;
}
public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
{
// Unix timestamp is seconds past epoch
System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0,
System.DateTimeKind.Utc);
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
return dtDateTime;
54
}
public static DateTime JavaTimeStampToDateTime(double javaTimeStamp)
{
// Java timestamp is millisecods past epoch
System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0,
System.DateTimeKind.Utc);
dtDateTime = dtDateTime.AddSeconds(Math.Round(javaTimeStamp / 1000)).ToLocalTime();
return dtDateTime;
}
}
}
CacheInterface.cs
using
using
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
System.Threading.Tasks;
System.Windows.Forms;
namespace Android_Cache_Viewer.Plugins
{
interface CacheInterface
{
Control showCache(string file);
}
}
CacheBD0.cs
using
using
using
using
using
using
using
using
System;
System.Collections.Generic;
System.Data;
System.IO;
System.Linq;
System.Text;
System.Threading.Tasks;
System.Windows.Forms;
namespace Android_Cache_Viewer.Plugins
{
class CacheBD0 : CacheAbstract
{
public override Control showCache(string file)
{
byte[] o = File.ReadAllBytes(file);
TabControl tab = new TabControl();
int idx = 0;
int counter = 0;
DataGridView dgv = null;
DataTable table = null;
byte[] data = null;
int length = -1;
StringBuilder sb = new StringBuilder();
TabPage page = null;
//string datastr = null;
while (o.Length > idx)
{
counter++;
55
dgv = new DataGridView();
table = new DataTable();
table.Columns.Add("Offset", typeof(int));
table.Columns.Add("Description", typeof(string));
table.Columns.Add("Value", typeof(string));
//
int offset = -1;
for (int i = 0; i < o.Length-4;i++)
{
if(o[i+idx]==0xFF && o[i+idx+1]==0xFF && o[i+idx+2]==0xFF &&
o[i+idx+3]==0xFF)
{
offset = i;
break;
}
}
table.Rows.Add(0 + idx, "Unknown", displayBytes(o, 0 + idx, offset));
table.Rows.Add(idx + offset + 0, "Constant", displayBytes(o, idx + offset +
0, 4));
table.Rows.Add(idx + offset + 4, "Unknown", displayBytes(o, idx + offset +
4, 4));
table.Rows.Add(idx + offset + 8, "Date/Time", displayBytes(o, idx + offset
+ 8, 4));
length = (int)(o[idx + offset + 12] * Math.Pow(256, 3) + o[idx + offset +
13] * Math.Pow(256, 2) + o[idx + offset + 14] * 256 + o[idx + offset + 15]);
table.Rows.Add(idx + offset + 12, "Data Length", length);
data = new byte[length];
Array.Copy(o, idx + offset + 16, data, 0, length);
//datastr = Encoding.UTF8.GetString(data).Trim();
int offset2=idx + offset + 16;
table.Rows.Add(offset2, "Data", "");
int l = 0;
for (int i = 0; i < data.Length;i++ )
{
if(data[i]==0x0A)//sep
{
table.Rows.Add(offset2 + i, "Seperator", displayBytes(o,offset2 +
i,1));
i++;
l = data[i];
table.Rows.Add(offset2 + i, "Record Length",Convert.ToInt16(l));
i++;
table.Rows.Add(offset2 + i, "Record", displayString(o, offset2 + i,
l));
i += l;
}
}
//table.Rows.Add(last_i, "Record", displayString(o, offset2 + last_i,
data.Length - last_i));
dgv.DataSource = table;
dgv.Dock = DockStyle.Fill;
dgv.ReadOnly = true;
page = new TabPage(counter.ToString());
page.Controls.Add(dgv);
tab.TabPages.Add(page);
idx = offset2 + length;
//break;
}
56
tab.Dock = DockStyle.Fill;
return tab;
}
}
}
CacheR0.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Android_Cache_Viewer.Plugins
{
class CacheR0 : CacheAbstract
{
public override Control showCache(string file)
{
byte[] o = File.ReadAllBytes(file);
TabControl tab = new TabControl();
int idx = 0;
int counter = 0;
DataGridView dgv = null;
DataTable table = null;
byte[] url_data = null;
int length = -1;
string url = null;
int end_offset = 0;
StringBuilder sb = new StringBuilder();
byte[] contentType = null;
int val = -1;
string ct = null;
TabPage page = null;
TabControl subtab = null;
TabPage subdata = null;
TabPage subpage = null;
Control data_ctrl = new Label();
while (o.Length > idx)
{
counter++;
subtab = new TabControl();
subdata = new TabPage("Data");
subpage = new TabPage("Details");
dgv = new DataGridView();
table = new DataTable();
table.Columns.Add("Offset", typeof(int));
table.Columns.Add("Description", typeof(string));
57
table.Columns.Add("Value", typeof(string));
table.Rows.Add(0 + idx, "Constant ", displayBytes(o, 0 + idx, 4));
table.Rows.Add(4 + idx, "Date/Time ", displayBytes(o, 4 + idx, 4));
table.Rows.Add(8 + idx, "Counter ", displayBytes(o, 8 + idx, 1));
table.Rows.Add(9 + idx, "Constant ", displayBytes(o, 9 + idx, 1));
length = (int)o[10 + idx];
table.Rows.Add(10 + idx, "Length of the URL", length);
url_data = new byte[length];
val = o[11 + idx];
if (val == 1)
idx++;
Array.Copy(o, 11 + idx, url_data, 0, length);
url = Encoding.UTF8.GetString(url_data);
table.Rows.Add(11 + idx, "URL of the cached data", url);
table.Rows.Add(11 + length + idx, "Constant ", displayBytes(o, 11 + length + idx, 4));
table.Rows.Add(15 + length + idx, "Unknown ", displayBytes(o, 15 + length + idx, 4));
table.Rows.Add(19 + length + idx, "Constant ", displayBytes(o, 19 + length + idx, 4)); // 0x0
0x0 0x0 0x0
table.Rows.Add(23 + length + idx, "Constant ", displayBytes(o, 23 + length + idx, 1));
table.Rows.Add(24 + length + idx, "Length", displayBytes(o, 24 + length + idx, 2));
end_offset = 0;
sb.Clear();
int init = 26 + length + idx;
bool image = false;
for (int i = init; i < o.Length; i++)
{
if (o[i] == 0x3A)
{
//data is PNG file.
if (o[init] == 0x89
&& o[init+1] == 'P'
&& o[init+2] == 'N'
&& o[init+3] == 'G'
&& o[i - 1] == 0x82
&& o[i - 2] == 0x60
&& o[i - 3] == 0x42)
{
end_offset = i;
image = true;
break;
}
else if (o[init] == 0x89
&& o[init + 1] == 'P'
&& o[init + 2] == 'N'
&& o[init + 3] == 'G'
&& (o[i - 1] != 0x82
|| o[i - 2] != 0x60
|| o[i - 3] != 0x42))
{
58
sb.Append(Convert.ToChar(o[i]));
continue;
}
else if (o[i + 1] > 32)
{
sb.Append(Convert.ToChar(o[i]));
continue;
}
else //if (o[i + 2] > 0x61 && o[i + 3] > 0x61 && o[i + 4] > 0x61 && o[i + 5] > 0x61)
{
end_offset = i;
break;
}
}
else
sb.Append(Convert.ToChar(o[i]));
}
if (image)
{
PictureBox data_ctrl2 = new PictureBox();
byte[] img_bytes = new byte[end_offset - init];
Array.Copy(o, init, img_bytes, 0, end_offset - init);
data_ctrl2.Image = ByteToImage(img_bytes);
data_ctrl2.Dock = DockStyle.Fill;
subdata.Controls.Remove(data_ctrl);
subdata.Controls.Add(data_ctrl2);
}
else
{
data_ctrl.Text = sb.ToString();
subdata.Controls.Add(data_ctrl);
}
table.Rows.Add(26 + length + idx, "Data", sb.ToString());
table.Rows.Add(end_offset, "Constant ", displayBytes(o, end_offset, 1));
table.Rows.Add(end_offset + 1, "Content-Type Length", o[end_offset + 1]);
contentType = new byte[o[end_offset + 1]];
Array.Copy(o, end_offset + 2, contentType, 0, o[end_offset + 1]);
ct = Encoding.UTF8.GetString(contentType);
table.Rows.Add(end_offset + 2, "Content-Type", ct);
idx = end_offset + 2+ct.Length;
dgv.DataSource = table;
dgv.Dock = DockStyle.Fill;
dgv.ReadOnly = true;
subpage.Controls.Add(dgv);
59
subtab.Dock = DockStyle.Fill;
subtab.Alignment = TabAlignment.Left;
subtab.TabPages.Add(subdata);
subtab.TabPages.Add(subpage);
page = new TabPage(counter.ToString());
page.Controls.Add(subtab);
tab.TabPages.Add(page);
}
tab.Dock = DockStyle.Fill;
return tab;
}
}
}
Gallery3dCache.cs
using
using
using
using
using
using
using
System;
System.Collections.Generic;
System.IO;
System.Linq;
System.Text;
System.Threading.Tasks;
System.Windows.Forms;
namespace Android_Cache_Viewer.Plugins
{
class Gallery3dCache : CacheAbstract
{
public override Control showCache(string file)
{
if (!file.EndsWith(".idx"))
{
byte[] obj = File.ReadAllBytes(file);
return getContentControl(obj.Skip(0x46).ToArray());
}
else
return new Label();
}
}
}
NotImplemented.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Android_Cache_Viewer.Plugins
{
class NotImplemented : CacheAbstract
{
public override Control showCache(string file)
{
return getContentControl(File.ReadAllBytes(file));
60
}
}
}
SQLiteDB.cs
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Android_Cache_Viewer.Plugins
{
class SQLiteDB : CacheAbstract
{
public override Control showCache(string file)
{
return getContentControl(File.ReadAllBytes(file));
}
}
}
61
WebViewCache.cs
using
using
using
using
using
using
using
using
System;
System.Collections.Generic;
System.Data;
System.IO;
System.Linq;
System.Text;
System.Threading.Tasks;
System.Windows.Forms;
namespace Android_Cache_Viewer.Plugins
{
class WebViewCache : CacheAbstract
{
Dictionary<string, byte[]> internal_files = null;
int last_file = 0;
public override Control showCache(string file)
{
internal_files = new Dictionary<string, byte[]>();
TabControl tab = new TabControl();
string cache_dir = file.Substring(0, file.Length Path.GetFileName(file).Length);
tab.TabPages.Add(getIndexPage(cache_dir));
tab.TabPages.Add(getDataPage(cache_dir, 0));
tab.TabPages.Add(getDataPage(cache_dir, 1));
tab.TabPages.Add(getDataPage(cache_dir, 2));
tab.TabPages.Add(getDataPage(cache_dir, 3));
string str_data = null;
byte[] bytes = null;
foreach(string ifile in internal_files.Keys)
{
bytes = internal_files[ifile];
str_data = Encoding.UTF8.GetString(bytes).Trim();
if (str_data!="")
{
TabPage page = new TabPage(ifile);
page.Controls.Add(getContentControl(bytes));
tab.TabPages.Add(page);
}
}
string file_idx = null;
for (int i = 0; i <= last_file;i++ )
{
file_idx = cache_dir+"/f_" + i.ToString("X").PadLeft(6, '0');
if (!File.Exists(file_idx))
continue;
bytes = File.ReadAllBytes(file_idx);
TabPage page = new TabPage("f_" + i.ToString("X").PadLeft(6, '0'));
page.Controls.Add(getContentControl(bytes));
tab.TabPages.Add(page);
}
tab.Dock = DockStyle.Fill;
return tab;
}
private TabPage getDataPage(string cache_dir, int p)
{
BinaryReader reader_data = new BinaryReader(new FileStream(cache_dir + "data_"
+ p.ToString(), FileMode.Open),Encoding.ASCII);
62
TabPage page = new TabPage("data_" + p.ToString());
DataGridView dgv = new DataGridView();
DataTable table = new DataTable();
page.Controls.Add(dgv);
table.Columns.Add("Offset", typeof(int));
table.Columns.Add("Description", typeof(string));
table.Columns.Add("Value", typeof(string));
table.Rows.Add(reader_data.BaseStream.Position, "Index Magic", "0x" +
reader_data.ReadUInt32().ToString("X"));
long position = reader_data.BaseStream.Position;
string minor_version = Convert.ToString(reader_data.ReadUInt16());
string major_version = Convert.ToString(reader_data.ReadUInt16());
table.Rows.Add(position, "Version", major_version + "." + minor_version);
table.Rows.Add(reader_data.BaseStream.Position, "Index of file",
reader_data.ReadInt16());
table.Rows.Add(reader_data.BaseStream.Position, "Next file",
reader_data.ReadInt16());
position = reader_data.BaseStream.Position;
int block_size = reader_data.ReadInt32();
switch (block_size)
{
case 36:
table.Rows.Add(position, "Block Size", block_size + " (Rankings)");
break;
case 256:
table.Rows.Add(position, "Block Size", block_size + " (Entry)");
break;
case 1024:
table.Rows.Add(position, "Block Size", block_size + " (Sparse)");
break;
case 4096:
table.Rows.Add(position, "Block Size", block_size);
break;
}
position = reader_data.BaseStream.Position;
int entry_count = reader_data.ReadInt32();
table.Rows.Add(position, "Stored Entry Count", entry_count);
position = reader_data.BaseStream.Position;
int max_entries = reader_data.ReadInt32();
table.Rows.Add(position, "Max Entries", max_entries);
for (int i = 0; i < 4;i++)
table.Rows.Add(reader_data.BaseStream.Position, "Empty Entries
["+i.ToString()+"]", reader_data.ReadInt32());
for (int i = 0; i < 4; i++)
table.Rows.Add(reader_data.BaseStream.Position, "Last Position [" +
i.ToString() + "]", reader_data.ReadInt32());
table.Rows.Add(reader_data.BaseStream.Position, "Update Tracker",
reader_data.ReadInt32());
for (int i = 0; i < 5; i++)
table.Rows.Add(reader_data.BaseStream.Position, "User [" + i.ToString() +
"]", reader_data.ReadInt32());
uint value = 0;
for (int i = 0; i < 2028; i++)
{
position = reader_data.BaseStream.Position;
value = reader_data.ReadUInt32();
if(value != 0)
table.Rows.Add(position, "AllocBitmap [" + i.ToString("X").PadLeft(4,
'0') + "]", value);
}
//////////
if (reader_data.BaseStream.Position != reader_data.BaseStream.Length)
{
63
UInt64 last_used = 0;
Int32 current_state = 0;
UInt32 hash = 0;
Int32 keylen = 0;
byte[] bytes = new byte[]{};
byte[] bytes_tmp = null;
int size_incr = 0;
for (int i = 0; i < max_entries; i++)
{
switch (block_size)
{
case 36:
position = reader_data.BaseStream.Position;
last_used = reader_data.ReadUInt64();
if (last_used != 0)
{
table.Rows.Add(position, "Entry [" +
i.ToString("X").PadLeft(4, '0') + "] Last Used", last_used.ToString());
table.Rows.Add(reader_data.BaseStream.Position, "
Last Modified", reader_data.ReadUInt64().ToString());
table.Rows.Add(reader_data.BaseStream.Position, "
Next", "0x" + reader_data.ReadUInt32().ToString("X").PadLeft(8, '0'));
table.Rows.Add(reader_data.BaseStream.Position, "
Previous", "0x" + reader_data.ReadUInt32().ToString("X").PadLeft(8, '0'));
table.Rows.Add(reader_data.BaseStream.Position, "
Content Address", "0x" + reader_data.ReadUInt32().ToString("X").PadLeft(8, '0'));
table.Rows.Add(reader_data.BaseStream.Position, "
Dirty Flag", reader_data.ReadInt32() == 1 ? "Yes" : "No");
reader_data.ReadInt32();
}
else
{
reader_data.ReadBytes(28);
}
break;
case 256:
hash = reader_data.ReadUInt32();
reader_data.BaseStream.Seek(16, SeekOrigin.Current);
current_state = reader_data.ReadInt32();
reader_data.BaseStream.Seek(-24, SeekOrigin.Current);
if (current_state == 0 && hash != 0)
{
table.Rows.Add(reader_data.BaseStream.Position, "Entry [" +
i.ToString("X").PadLeft(4, '0') + "] Hash",
reader_data.ReadUInt32().ToString("X").PadLeft(8, '0'));
table.Rows.Add(reader_data.BaseStream.Position, "
Next", "0x" + reader_data.ReadUInt32().ToString("X").PadLeft(8, '0'));
table.Rows.Add(reader_data.BaseStream.Position, "
Rankings Node", "0x" + reader_data.ReadUInt32().ToString("X").PadLeft(8, '0'));
table.Rows.Add(reader_data.BaseStream.Position, "
Reuse Count", "0x" + reader_data.ReadInt32());
table.Rows.Add(reader_data.BaseStream.Position, "
Refetch Count", "0x" + reader_data.ReadInt32());
table.Rows.Add(reader_data.BaseStream.Position, "
Current State", "0x" + reader_data.ReadInt32());
table.Rows.Add(reader_data.BaseStream.Position, "
Creation Time", "0x" + reader_data.ReadUInt64());
position = reader_data.BaseStream.Position;
keylen = reader_data.ReadInt32();
table.Rows.Add(position, "
Key Length",
keylen);
table.Rows.Add(reader_data.BaseStream.Position, "
Address of long key (Optional)", "0x" + reader_data.ReadUInt32());
for (int j = 0; j < 4; j++)
table.Rows.Add(reader_data.BaseStream.Position, "
64
Data Size [" + j + "]", "0x" + reader_data.ReadInt32());
for (int j = 0; j < 4; j++)
table.Rows.Add(reader_data.BaseStream.Position, "
Data Address [" + j + "]", "0x" + reader_data.ReadUInt32().ToString("X").PadLeft(8, '0'));
table.Rows.Add(reader_data.BaseStream.Position, "
Entry Flag", reader_data.ReadUInt32() == 1 ? "Parent" : "Child");
for (int j = 0; j < 5; j++)
reader_data.ReadInt32();
keylen = 0;
table.Rows.Add(reader_data.BaseStream.Position, "
Key", new string(reader_data.ReadChars(keylen)));
reader_data.ReadBytes(256 - 24 * 4 - keylen);
}
else
{
reader_data.ReadBytes(256);
}
break;
case 1024:
if (reader_data.PeekChar() == 0)
{
if (bytes.Length > 0)
internal_files.Add("data_" + p.ToString() + ": Entry" +
i, bytes);
bytes = new byte[] { }z;
size_incr = 0;
}
else
{
size_incr += 1024;
Array.Resize(ref bytes, size_incr);
bytes_tmp = reader_data.ReadBytes(1024);
Array.Copy(bytes_tmp, 0, bytes, size_incr - 1024,
bytes_tmp.Length);
}
break;
case 4096:
if (reader_data.PeekChar()==0)
{
if (bytes.Length > 0)
internal_files.Add("data_" + p.ToString() + ": Entry" +
i, bytes);
bytes = new byte[] { };
size_incr = 0;
}
else
{
size_incr += 4096;
Array.Resize(ref bytes, size_incr);
bytes_tmp = reader_data.ReadBytes(4096);
Array.Copy(bytes_tmp, 0, bytes, size_incr - 4096,
bytes_tmp.Length);
}
break;
default:
break;
}
}
}
dgv.DataSource = table;
dgv.Dock = DockStyle.Fill;
dgv.ReadOnly = true;
65
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
reader_data.Close();
return page;
}
private TabPage getIndexPage(string cache_dir)
{
BinaryReader reader_index = new BinaryReader(new FileStream(cache_dir +
"index", FileMode.Open));
TabPage page = null;
DataGridView dgv = new DataGridView();
DataTable table = new DataTable();
table.Columns.Add("Offset", typeof(int));
table.Columns.Add("Description", typeof(string));
table.Columns.Add("Value", typeof(string));
table.Rows.Add(reader_index.BaseStream.Position, "Index Magic", "0x" +
reader_index.ReadUInt32().ToString("X"));
long position = reader_index.BaseStream.Position;
string minor_version = Convert.ToString(reader_index.ReadUInt16());
string major_version = Convert.ToString(reader_index.ReadUInt16());
table.Rows.Add(position, "Version", major_version + "." + minor_version);
table.Rows.Add(reader_index.BaseStream.Position, "Number of entries",
reader_index.ReadInt32());
table.Rows.Add(reader_index.BaseStream.Position, "Total size",
reader_index.ReadInt32());
last_file = reader_index.ReadInt32();
table.Rows.Add(reader_index.BaseStream.Position, "Last external file created",
"f_" + reader_index.ReadInt32().ToString("X").PadLeft(6, '0'));
table.Rows.Add(reader_index.BaseStream.Position, "Dirty Flag",
reader_index.ReadInt32() == 1 ? "Yes" : "No");
table.Rows.Add(reader_index.BaseStream.Position, "Storage for usage data",
reader_index.ReadUInt32() == 1 ? "Yes" : "No");
//
position = reader_index.BaseStream.Position;
int size = reader_index.ReadInt32();
//if (size == 0)
//
size = 0x10000;
table.Rows.Add(position, "Actual size of the table", size);
table.Rows.Add(reader_index.BaseStream.Position, "Signals a previous crash",
reader_index.ReadInt32() == 1 ? "Yes" : "No");
table.Rows.Add(reader_index.BaseStream.Position, "Id of an ongoing test",
reader_index.ReadInt32());
//DateTime dt = UnixTimeStampToDateTime(reader.ReadUInt64());
table.Rows.Add(reader_index.BaseStream.Position, "Creation time for this set of
files", reader_index.ReadUInt64().ToString());
table.Rows.Add(reader_index.BaseStream.Position, "Pad",
displayBytes(reader_index.ReadBytes(52 * 4), 0, 52 * 4));
table.Rows.Add(reader_index.BaseStream.Position, "Padded content",
displayBytes(reader_index.ReadBytes(4 * 2), 0, 4 * 2));
table.Rows.Add(reader_index.BaseStream.Position, "Cache Filled Flag",
reader_index.ReadInt32() == 1 ? "Yes" : "No");
for (int i = 0; i < 5; i++)
table.Rows.Add(reader_index.BaseStream.Position, "Sizes [" + i + "]",
reader_index.ReadInt32());
for (int i = 0; i < 5; i++)
table.Rows.Add(reader_index.BaseStream.Position, "Heads cache address [" +
i + "]", reader_index.ReadUInt32());
for (int i = 0; i < 5; i++)
table.Rows.Add(reader_index.BaseStream.Position, "Tails cache address [" +
66
i + "]", reader_index.ReadUInt32());
table.Rows.Add(reader_index.BaseStream.Position, "Transaction cache address",
reader_index.ReadUInt32());
table.Rows.Add(reader_index.BaseStream.Position, "Actual in-flight operation",
reader_index.ReadInt32());
table.Rows.Add(reader_index.BaseStream.Position, "In-flight operation list",
reader_index.ReadInt32());
table.Rows.Add(reader_index.BaseStream.Position, "Pad",
displayBytes(reader_index.ReadBytes(4 * 7), 0, 4 * 7));
uint cacheAddr = 0;
//UInt16 cacheAddr16_01 = 0;
//UInt16 cacheAddr16_02 = 0;
byte[] bb = new byte[4];
for (int st = 0; st < size; st++)
{
position = reader_index.BaseStream.Position;
//cacheAddr16_01 = reader_index.ReadUInt16();
//cacheAddr16_02 = reader_index.ReadUInt16();
//cacheAddr = cacheAddr16_01 * (uint)256 + cacheAddr16_02;
cacheAddr = reader_index.ReadUInt32();
if (cacheAddr != 0)
{
table.Rows.Add(position, "Cache Addresses [" +
st.ToString("X").PadLeft(4, '0') + "]", "0x"+cacheAddr.ToString("X").PadLeft(8, '0'));
}
}
dgv.DataSource = table;
dgv.Dock = DockStyle.Fill;
dgv.ReadOnly = true;
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
page = new TabPage("index");
page.Controls.Add(dgv);
reader_index.Close();
return page;
}
}
}
YouTubeCache.cs
using
using
using
using
using
using
using
System;
System.Collections.Generic;
System.IO;
System.Linq;
System.Text;
System.Threading.Tasks;
System.Windows.Forms;
namespace Android_Cache_Viewer.Plugins
{
class YouTubeCache : CacheAbstract
{
public override Control showCache(string file)
{
byte[] obj = File.ReadAllBytes(file);
return getContentControl(obj.Skip(0x95).ToArray());
}
}
}
67
Download