View
241
Download
2
Category
Preview:
Citation preview
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 1
Decompiling Android Crypto Apps For Fun and Evidence
Alex CaithnessOWASP/BCS Mobile & Malware Forensics Day
2016/01/22
Me (Briefly)• Member of R&D team at CCL• Background is mobile/embedded forensics• Wrote Epilog, Dunk!, PIP, etc.• Likes:
– Python– Hex Editors– Databases– The command line
• Not a crypto expert– But turns out you might not have to be…
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 2
This Presentation (Briefly)• The problems posed by crypto apps• Why all may not be lost• Case studies of some apps we’ve worked on to suggest:
– Tools – Techniques– Skills to develop
The Problem• Cryptography
– Stops us from seeing data !– Users are increasingly paranoid about their data– Crypto/security becoming a selling point for the
average user– Increasingly common
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 3
The Brightside• Decryption easier on the end-point than during transmission • If the device is able to view/access the data at least part of
the “keys” must be stored locally• Programmers can be lazy, stupid, greedy
– Doing crypto properly is hard– Only has to be “good enough” for most users– Or just has to look like it’s working
• We might be able to find a way in…
Types of Apps• App Lockers• File Lockers• Secure Messaging
– Secure always, or just during transmission?
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 4
Decompiling• Reverse engineering based on observation of
behaviour alone is hard– Time consuming– Only ever going to be a really good guess
• Being able to read the code which does the work in the app gives a quicker, more definitive answer
Decompiling• Many programming languages are “compiled”
– The human readable/writable code is turned into instructions which a machine can execute more directly
• Decompiling takes the compiled instructions (eg. machine code, byte code) and turns it back into a (more) human readable form
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 5
Decompiling• Compilation is usually not a reversible process
– What was originally written will not be recovered exactly
– Code layout, variable names can be lost– Optimisations performed by compiler may lead to a
set of instructions which are functionally similar but are performed in quite different ways
• Still requires interpretation and understanding
An Apology• This presentation will involve looking at and talking
about code (mostly Java)• Any important code snippets will be kept short and
explained• Besides, there’s never been a better time to learn to
program if you work in DF…
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 6
Methodology• Acquire the APK• Decompile• Search code
– Hopeful searches and educated guesses– Based on stored data
• Navigate code to find key functional code • Reverse engineer
Getting the APK• .apk (Android Application Package) file • Installation package for an Android Application• Usually still resident on device under “data/app”• Can be acquired using a (rooted) test device or from a 3rd
party app store• Actually just a .zip archive with a particular file/folder
structure
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 7
classes.dex• Compiled Dalvik Byte-
code– All non-processor-specific
functionality here– Not human readable (not a
normal human anyway)– Usually compiled from Java
code
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 8
baksmali• Baksmali is a disassembler for .dex files
– By “Jesusfreke”– http://code.google.com/p/smali– Decompiles to a project folder structure
containing “.smali” files (human readable byte-code)
baksmalijava -jar baksmali-2.0.5.jar classes.dex
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 9
baksmali# static fields.field private static final DEVICE_ID_HASH_PREFS_KEY:Ljava/lang/String; = "deviceIdHash"
.field private static final PREFS_NAME:Ljava/lang/String; = "FBAdPrefs"
.field public static final TAG:Ljava/lang/String;
.field private static childDirected:Z
.field private static deviceIdHash:Ljava/lang/String;
.field private static final emulatorProducts:Ljava/util/Collection;.annotation system Ldalvik/annotation/Signature;
value = {"Ljava/util/Collection","<","Ljava/lang/String;",">;"
}.end annotation
.end field
baksmali# static fields.field private static final DEVICE_ID_HASH_PREFS_KEY:Ljava/lang/String; = "deviceIdHash"
.field private static final PREFS_NAME:Ljava/lang/String; = "FBAdPrefs"
.field public static final TAG:Ljava/lang/String;
.field private static childDirected:Z
.field private static deviceIdHash:Ljava/lang/String;
.field private static final emulatorProducts:Ljava/util/Collection;.annotation system Ldalvik/annotation/Signature;
value = {"Ljava/util/Collection","<","Ljava/lang/String;",">;"
}.end annotation
.end field
Not too friendly for a non-programmer (and not that friendly for a programmer).
Can find constants being assigned with relative ease, which might be useful
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 10
classes.dex• smali is useful, but can be a slog to work
through• Being able to view as Java would be preferable
Dalvik to Java• Option 1 (dex2jar + jd/cfr):
– dex2jar is a utility to convert a .dex file into a Java .jar archive
• http://github.com/pxb1988/dex2jar
• Creates a jar file in the same directory as the classes.dex file
d2j-dex2jar classes.dex
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 11
Dalvik to Java• Option 1 (dex2jar + jd/cfr):
– jd is a utility which decompiles a .jar file to Java• There is also a GUI version (jd-gui)• http://jd.benow.ca• Just drag and drop .jar file in the window!
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 12
Dalvik to Java• Option 1 (dex2jar + jd/cfr):
– cfr is another option for decompiling the .jar file• http://www.benf.org/other/cfr• No GUI here…
• Creates a folder structure of .java source files• Decompiles slightly differently to jd
java –jar cfr_0_97 classes-dex2jar.jar –outputdir cfr-output
Dalvik to Java• Option 2 (jadx):
– jadx is a utility which converts directly from a .dexfile to Java source code
• https://github.com/skylot/jadx• Also has a GUI version
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 13
Dalvik to Java• Option 3 (JEB)
– JEB is a commercially available decompiler with many additional features
– GUI Based– Not free (subscription based)– www.pnfsoftware.com/jeb
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 14
Dalvik to Java• The output from each process is slightly different • My preference is usually for Jadx as I find the output
to be more readable and complete in most areas –but it can sometimes be a “bit crashy”
• In both cases I prefer to read the code in a “proper” IDE…
Export the source…
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 15
“A Proper IDE”• IDE: Integrated Development Environment
– We’re not doing development per se– However, IDEs tend to have advanced features for viewing, navigating,
searching and annotating the code– Very useful while reverse engineering
• For Java I use “InteliJ IDEA”– From Jet Brains– https://www.jetbrains.com/idea/download– Free “Community Edition” is more than enough for our needs
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 16
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 17
And then just click next a few times. The defaults work fine for our needs
“A Decent Search Tool”• The other tool I find essential is a tool that can run
regular expression searches over our source folder– I like dnGrep
• https://dngrep.github.io/• Very flexible• Text, Xpath, Regular Expressions and Fuzzy/Phonetic text searching
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 18
Case Study: Clean Master• Clean Master Security Antivirus AppLock• Application which (amongst other functionality)
allowed locking of applications behind a pattern lock• NB: not the same as the Android Lock Screen
pattern, but still a 3 x 3 grid• Caused an issue during examination
Case Study: Clean Master
2 3 4
1
2 3 4
1
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 19
2 3 4
1
2 3 4
1
Case Study: Clean Master
Decompiling• Jadx was refusing to play nicely (being “a bit
crashy”)• Used combination of dex2jar and jd• Exported the code and loaded into IntelliJ
IDEA
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 20
Searching The Source• Began with some hopeful generic search terms:
– lock– pattern
• Too many hits and lots of “noise” due to the use of Regex in the code base itself
• Filtered out the most common useless matches using negative lookaround:(?<!regex\.)pattern(?!\.compile)
Very promising! Imports for a class called “LockPatternView”, with a qualified name
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 21
Searching The Source• Gives us a place in the
source to start working from
• But there are other clues we can look for…
Searching The Source
• Finding where the pattern is stored is useful– Could possibly derive from the code…– …or do what I did and just dig around in the extracted files
• Above snippet is found in the application’s preferences file• Fair to guess this might be the encoded pattern?
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 22
Searching The Source
• Field names in preferences files, keys in databases etc. make great search terms in the decompiled source
• They will often be near to, or referenced by code which populates that field
Searching The Source• Search term:
– “lock_pattern”– (With the quotes; we’re searching for a string
literal, not just these words)
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 23
Searching The Source
This looks really good – two functions, referencing that key in the preferences; one appears to set that value, the other gets it.
public void a(String paramString){
GlobalPref.a().b("lock_pattern", paramString);}
public String b(){
return GlobalPref.a().a("lock_pattern", "");}
The code which generates the encoded pattern must ultimately call this code
This could be our gateway into the code!
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 24
public void a(String paramString){
GlobalPref.a().b("lock_pattern", paramString);}
public String b(){
return GlobalPref.a().a("lock_pattern", "");}
NB we will see a lot of things called a, b, c, d etc.When the code was compiled, many “symbols” (names of things) will have been stripped out.The de-compilation will give things simple names when nothing is found.
Right clicking the name of a function/method and selecting “Find Usages” should highlight all occurrences of this code being called in the codebase.
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 25
This should work, and usually does… but due to the way the code was decompiled the IDE couldn’t resolve the search
So I used dnGrep in that folder:
public static void b(List<LockPatternView$Cell> paramList){
if (paramList == null);while (paramList.size() == 0)
return;String str1 = a(paramList);String str2 = d(str1);com.ijinshan.c.a.a.a("LockPattern", "save pattern, " + str1 + ", " + str2);d.a().a(str2);
}
This is where the search led.
A method which takes in a list of “LockPatternView Cells” and ends up setting the lock_pattern value using the method we saw previously.
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 26
Reverse Engineering The Algorithm
public static void b(List<LockPatternView$Cell> paramList){
if (paramList == null);while (paramList.size() == 0)
return;String str1 = a(paramList);String str2 = d(str1);com.ijinshan.c.a.a.a("LockPattern", "save pattern, " + str1 + ", " + str2);d.a().a(str2);
}
This code is just checking that the list of “LockPatternView Cells” isn’t empty.
Not interesting, let’s ignore it!
Reverse Engineering The Algorithm
public static void b(List<LockPatternView$Cell> paramList){
String str1 = a(paramList);String str2 = d(str1);com.ijinshan.c.a.a.a("LockPattern", "save pattern, " + str1 + ", " + str2);d.a().a(str2);
}This code is just performing some logging.
Not interesting, let’s ignore it!
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 27
Reverse Engineering The Algorithmpublic static void b(List<LockPatternView$Cell> paramList){String str1 = a(paramList);String str2 = d(str1);d.a().a(str2);
}
This is the interesting functional code…
1. A list of “LockPatternView Cells” comes in.2. We do “a” to it, which gives us a string.3. We do “d” to that string, which turns it into another string.4. We store that string using the method we originally found.
Along with “Find Usages”, “Go To Declaration” are your best friends.
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 28
public static String a(List<LockPatternView$Cell> paramList){
if (paramList == null)return "";
int n = paramList.size();String str = "";
for (int i = 0; i < n; i++){
LockPatternView$Cell localCell = paramList.get(i);str = str + String.valueOf(3 * localCell.a() + localCell.b());
}return str;
}
Most of this code is setting up a loop to get each “LockPatternView Cell” in the list.For every item in the list, a calculation is being performed on that item, and the result is added to a string.
Reverse Engineering The Algorithmstr = str + String.valueOf(3 * localCell.a() + localCell.b());
This is the calculation:Each “LockPatternView Cell” has a value “a” and a value “b”“a” is multiplied by 3“b” is added to the result
Looking in the code for LockPatternView$Cell we find the following, which makes the meaning of “a” and “b” clear:
public String toString(){return "(ROW=" + a() + ",COL=" + b() + ")";
}
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 29
Reverse Engineering The Algorithm
2 3 4
1
0 1 2
0
1
2
(Row x 3) + Col
(2 x 3) + 0 = 6(1 x 3) + 0 = 3(1 x 3) + 1 = 4(1 x 3) + 2 = 5
"6345"
Reverse Engineering The Algorithmpublic static void b(List<LockPatternView$Cell> paramList){String str1 = a(paramList); // string of number (3row+col)String str2 = d(str1);d.a().a(str2);
}
This is the interesting functional code…
1. A list of “LockPatternView Cells” comes in. 2. We do “a” to it, which gives us a string of numbers (3 x row) + col3. We do “d” to that string, which turns it into another string.4. We store that string using the method we originally found.
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 30
Reverse Engineering The Algorithmprivate static String d(String paramString){
if (TextUtils.isEmpty(paramString))return "";
return b(paramString);}
More mostly boring code, checking if the string is empty
If it’s not we do “b” to the string…
Reverse Engineering The Algorithmpublic static final String b(String paramString){
if (paramString == null)return "";
if (paramString.length() == 0)return "";
BigInteger localBigInt1 = new BigInteger(paramString.getBytes());BigInteger localBigInt2 = new BigInteger("011100100010101001110101110110");
return localBigInt2.xor(localBigInt1).toString(16);}
Again, more boring “is the string empty?” code…
Ignore it!
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 31
Reverse Engineering The Algorithmpublic static final String b(String paramString){
BigInteger localBigInt1 = new BigInteger(paramString.getBytes());BigInteger localBigInt2 = new BigInteger("011100100010101001110101110110");
return localBigInt2.xor(localBigInt1).toString(16);}
Two “BigIntegers” (just big numbers) are created:• One is generated by converting the pattern string into the underlying
bytes (encoded as UTF-8)• The other is the number: 011100100010101001110101110110 (that’s
not binary, just a really big number with only 1’s and 0’s in)
Reverse Engineering The Algorithm
These two big numbers are XOR’d together, and the result is converted to its hexadecimal representation.
NB. The presence of big numbers and “XOR” operations is a dead giveaway that some form of encryption/encoding is going on
public static final String b(String paramString){
BigInteger localBigInt1 = new BigInteger(paramString.getBytes());BigInteger localBigInt2 = new BigInteger("011100100010101001110101110110");
return localBigInt2.xor(localBigInt1).toString(16);}
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 32
Reverse Engineering The Algorithmpublic static void b(List<LockPatternView$Cell> paramList){String str1 = a(paramList); // string of number (3row+col)String str2 = d(str1); // encrypted using xord.a().a(str2); // store in preferences file
}
This is the interesting functional code…
1. A list of “LockPatternView Cells” comes in. 2. We do “a” to it, which gives us a string of numbers (3 x row) + col3. We do “d” to that string, which turns it into another string (encoded by
XOR’ing the bytes against a big long number)4. We store that string using the method we originally found.
Reverse Engineering The Algorithm
• And that is how this value ends up here• To decrypt it we reverse the algorithm:
– Read the value as an integer– XOR it with 011100100010101001110101110110– Convert the result into bytes– Convert bytes into a string (should be a string of numbers)– Divide each number by 3 (discarding the remainder) to get the row – The remainder gives us the column
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 33
Case Study: Photo Locker• App by “HandyApps” which protects photos
– Actually uses encryption, which is a surprise!– A Video Locker application is also available (which appears
to work identically)
• Jadx worked best for decompiling this app – Other methods worked (insofar as they didn’t crash) but
output was ugly
Encrypted files are usually found on the shared media partition in a folder called “.PL”
Encrypted files are given a “.pl” extension at the end of their file name.
Curiously, only the start of the file is encrypted (confirmed by entropy analysis, presence of expected JPEG file footer FFD9, and later by inspecting the code)
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 34
Case Study: Photo locker
Case Study: Photo Locker• A cursory glance in the preferences file also reveals
this promising looking string to search the code for:
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 35
Searching The Code• The regex search along with a number of
“Find Usage” + “Go To Declaration” led to two files
• “KeyEncryption” governs the encryption/decryption the Secret Key
• “Encryption” governs the encryption and decryption of the photos– The key used is derived from the decrypted Secret
key
Searching The Code
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 36
Searching The Code
This is where we confirmed that only the first 2KB of the file is actually encrypted.
Searching The Code
The header of the file gives us details of the encryption scheme:• AES• Counter Mode• No Padding• Counter initial value: 0xfedcba9876543210
We do not have the block size (but we can work that out when we know the key size)
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 37
public static String generateKey(String userEmail) throws ResultErrorException {try {
byte[] keySpec = (Salt + userEmail + password).getBytes("UTF-8");MessageDigest sha = MessageDigest.getInstance("SHA-1");Log.d("ENC", sha.getProvider().getName());byte[] bytes = Arrays2.copyOf(sha.digest(keySpec), (int)Response.BYE);return Base64.encodeToString(bytes, false);
} catch (UnsupportedEncodingException e) {e.printStackTrace();throw new ResultErrorException();
} catch (NoSuchAlgorithmException e2) {e2.printStackTrace();throw new ResultErrorException();
}}
This function (defined in Encryption): • Takes in the user’s email (which is what the SECRET_KEY turns out to be!) • Returns the key for the file encryption.
public static String generateKey(String userEmail) throws ResultErrorException {try {
byte[] keySpec = (Salt + userEmail + password).getBytes("UTF-8");MessageDigest sha = MessageDigest.getInstance("SHA-1");Log.d("ENC", sha.getProvider().getName());byte[] bytes = Arrays2.copyOf(sha.digest(keySpec), (int)Response.BYE);return Base64.encodeToString(bytes, false);
} catch (UnsupportedEncodingException e) {e.printStackTrace();throw new ResultErrorException();
} catch (NoSuchAlgorithmException e2) {e2.printStackTrace();throw new ResultErrorException();
}}
Lots of boring error handling and logging code - let’s ignore it!
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 38
Reverse Engineering The Algorithm
byte[] keySpec = (Salt + userEmail + password).getBytes("UTF-8");MessageDigest sha = MessageDigest.getInstance("SHA-1");byte[] bytes = Arrays2.copyOf(sha.digest(keySpec), (int)Response.BYE);return Base64.encodeToString(bytes, false);
private static final String Salt = "HANDY_APPS";private static final String password = "secure locker";
Reverse Engineering The Algorithm
byte[] keySpec = (Salt + userEmail + password).getBytes("UTF-8");MessageDigest sha = MessageDigest.getInstance("SHA-1");byte[] bytes = Arrays2.copyOf(sha.digest(keySpec), (int)Response.BYE);return Base64.encodeToString(bytes, false);
• Combine the salt, user’s email and password• eg. “HANDY_APPSuser@email.comsecure locker”
• Get the bytes that make up this string (encoded as UTF-8)
private static final String Salt = "HANDY_APPS";private static final String password = "secure locker";
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 39
Reverse Engineering The Algorithm
byte[] keySpec = (Salt + userEmail + password).getBytes("UTF-8");MessageDigest sha = MessageDigest.getInstance("SHA-1");byte[] bytes = Arrays2.copyOf(sha.digest(keySpec), (int)Response.BYE);return Base64.encodeToString(bytes, false);
• Create a SHA-1 Algorithm
private static final String Salt = "HANDY_APPS";private static final String password = "secure locker";
Reverse Engineering The Algorithmbyte[] keySpec = (Salt + userEmail + password).getBytes("UTF-8");MessageDigest sha = MessageDigest.getInstance("SHA-1");byte[] bytes = Arrays2.copyOf(sha.digest(keySpec), (int)Response.BYE);return Base64.encodeToString(bytes, false);
• Get the digest (the hash) of the keyspec• Copy only the first 16 bytes (also tells us the block size)
• “Response.BYE” is a constant from a standard email library, the value it represents is 16.
• This appears to be an attempt to obfuscate the code (not a very good attempt)
• (The key is then converted to Base64, but will be converted back for use)
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 40
Decrypting the Files• With the derived key and encryption settings
we are able decrypt the files– (Well the first 2048 bytes anyway…)
Decrypting the Files
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 41
Summary• Encryption can make you feel sad• But programmers are lazy and often don’t
know how to use encryption properly• And even if they do, breaking encryption at an
end point is much easier than in transmission
Summary• Decompiling Apps is sometimes an “inexact science”
– use the tool which works best each time• Make searches based upon observed data • Or just guess, that works sometimes too• Working in a proper IDE is much easier than fumbling
around in a text editor• Learning to program is a good idea (and fun)
Decompiling Android Crypto Apps for Fun and Evidence – Alex Caithness
© CCL Group Ltd. 2015-2016 42
Contact• Alex Caithness• alex.caithness@cclgroupltd.com• 01789 261 200
Recommended