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