CodeCode ExecutionExecution
AnalysisAnalysis
InIn MobileMobile AppsApps
Wait. I know GDB.Wait. I know GDB.
I don't need this...I don't need this...
So, let's try another title...So, let's try another title...
HowHow not to shootnot to shoot
yourself in the footyourself in the foot
while debuggingwhile debugging
MobileMobile appsapps
About MeAbout Me
Abdullah Joseph / @MalwareCheese
 
Mobile Security Team Lead @ Adjust
We do mobile attribution, ad fraud analysis and some data stuff (processing 25 petabytes
every 10 days received   )
I like binary stuff
Crypto stuff too. Not so much web and network stuff
About MeAbout Me
Abdullah Joseph / @MalwareCheese
 
Mobile Security Team Lead @ Adjust
We do mobile attribution, ad fraud analysis and some data stuff (processing 25 petabytes
every 10 days received   )
I like binary stuff
Crypto stuff too. Not so much web and network stuff
Bonus only for Nanosec: I graduated from APU. Bachelor's
in Game Design
Let's start with a CTFLet's start with a CTF
FindingsFindings
Code block takes input and puts it in [s]
At 0x080486d3, our input and obj.sekrutBuffer get XORed
together
The result has to equal obj.greetingMessage which gets
compared together in 0x080486e6
obj.sekrutBuffer holds the following byte 
blob: 
)x06x16O+50x1eQx1b[x14Kb]+Sx10TQCMT]
What did we learn?What did we learn?
Debugger == God ModeDebugger == God Mode
Switching to MobileSwitching to Mobile
Let's go for Android
How do we get the output ofHow do we get the output of
getSecretKey()getSecretKey() dynamically? dynamically?
Disassemble the app (with “apktool” or similar tool)
Set the “app:debuggable” flag to true
Rebuild the app
Sign the app (with Appium’s Sign.jar or similar)
Decompile the app to get the Java sources (with CFR decompiler or jadx)
Setup a gradle project inside the decompiled sources
Setup an IDE, like Android Studio, and port the decompiled java code to it
Setup the testing device to have that app in the “Wait for debugger” list of apps
in “Settings” -> “Developer Mode”
Setup breakpoints on the “getSecretKey()” function
Run the app. It should say “Wait for Debugger” now
Use JDWP to run the app and break at “getSecretKey()” function
Examine the return value
More info here: https://stackify.com/java-remote-debugging/
Let's talk aboutLet's talk about
binary instrumentationbinary instrumentation
Also known as "Function Hooking"
Let's talk aboutLet's talk about
binary instrumentationbinary instrumentation
Also known as "Function Hooking"
“ The ability to insert a practically unlimited
amount of code at any location in a binary to
observe or modify that binary’s behavior
 
-- Dennis Andriesse - Practical Binary Analysis
https://frida.re
https://www.frida.re/docs/hacking/
So now...So now...
So now...So now...
So now...So now...
How do we get the output ofHow do we get the output of
getSecretKey()getSecretKey() dynamically? dynamically?
// myagent.js
// ===================
Java.perform(() => {
let activity = Java.use("com.adjust.myapp.MainActivity");
Activity.getSecretKey.implementation = () => {
var retval = this.getSecretKey(this, arguments);
console.log("getSecretKey() called");
console.log(`retval = ${retval}`);
return retval;
};
});
// ===================
// Run with:
// $ frida -U -f com.adjust.myapp -l myagent.js
FallbacksFallbacks
AKA: What Frida cannot do / is not
FallbacksFallbacks
AKA: What Frida cannot do / is not
Not a ptrace-based debugger
LLDB and GDB are debuggers capable of deep
analysis of every Instruction
Frida HAS a lot of debugger functionality, but its
main purpose is to aid in binary analysis and hook
into parts of the binary to execute arbitrary
instructions
What this means is that, if you're intending to step-
into every function and analyze it's execution, it
might be better to use LLDB/GDB
FallbacksFallbacks
AKA: What Frida cannot do / is not
FallbacksFallbacks
AKA: What Frida cannot do / is not
Not the only instrumentation framework
DynamoRIO (open-source & free)
Intel PIN (free but closed-source)
However, it is the easiest one to use and the only one that
supports multiple architectures and VM environments
(AKA: Android and iOS) by default.
Use Case #1Use Case #1
Analysis: Memory Dumper &Analysis: Memory Dumper &
ScannerScanner
$ memdumper/memdump.py -U -p com.myapp.adjust -v
INFO:Starting Memory dump...
DEBUG:Too big, splitting the dump into chunks
DEBUG:Number of chunks: 80
DEBUG:Save bytes: 0x12C00000 till 0x13589680
DEBUG:Save bytes: 0x13589680 till 0x13F12D00
DEBUG:Save bytes: 0x13F12D00 till 0x1489C380
DEBUG:Save bytes: 0x1489C380 till 0x15225A00
DEBUG:Save bytes: 0x15225A00 till 0x15BAF080
...
DEBUG:Save bytes: 0x223F4900 till 0x22D7DF80
DEBUG:Save bytes: 0x22D7DF80 till 0x23707600
DEBUG:Save bytes: 0x23707600 till 0x24090C80
DEBUG:Save bytes: 0x24090C80 till 0x24A1A300
DEBUG:Save bytes: 0x24A1A300 till 0x253A3980
DEBUG:Save bytes: 0x253A3980 till 0x25D2D000
DEBUG:Save bytes: 0x25D2D000 till 0x266B6680
DEBUG:Save bytes: 0x266B6680 till 0x2703FD00
DEBUG:Save bytes: 0x2703FD00 till 0x279C9380
DEBUG:Save bytes: 0x279C9380 till 0x28352A00
$ strings -n 5 dump/*.data | uniq | ack -i secret
THIS IS A SECRET STRING!!!
THIS IS A SECRET STRING!!!
THIS IS A SECRET STRING!!!
THIS IS A SECRET STRING!!!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Use Case #2Use Case #2
Native Android FunctionNative Android Function
HookerHooker
10x times easier than GDB or LLDB scripting (!)
[0] % native_stalker/native_stalker.py 
--process com.myapp.adjust 
--library libnative-lib.so 
--addr 0x00009610 
--binary /path/to/my/app/libnative-lib.so 
--verbose
INFO:Analyzing with R2...
INFO:Retrieving PLT section...
INFO:.plt [0x8AE0] -> [0x92D0]
INFO:Prepping Frida...
INFO:Resuming process...
INFO:Hooking library loaders...
JS: loaders(): {"0":"libnative-lib.so","1":38416,"2":35552,"3":37584}
INFO:Awaiting hook callbacks...
JS: Library [native-lib] loaded with java.lang.String.loadLibrary
[+] JS: stalk_func(): {"0":"libnative-lib.so","1":38416,"2":35552,"3":37584}
[+] JS: Library base addr: 0x8b2c1000
[+] JS: Hooking [0x8b2ca610]...
INFO:Tracing 38416@libnative-lib.so concluded with 11 calls:
0x8b80 -> sym.imp.free
0x8c40 -> fcn.00008c40
0x8b30 -> fcn.00008b30
0x8b90 -> fcn.00008b90
0x8c50 -> fcn.00008c50
0x8b40 -> sym.imp.fopen
0x8ba0 -> fcn.00008ba0
0x8bc0 -> fcn.00008bc0
0x8b70 -> sym.imp.getline
0x8c30 -> fcn.00008c30
0x8b20 -> sym.imp.__android_log_vprint
INFO:Done. You can exit the script now...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
MiscMisc
Dynamic Analysis
Trace any (Dalvik/Objc/Native) function
Dump saved files
Memory scanner
Automated crypto keys scanner
One-time watchpoints
Monitor file system access
SSL pinning bypass
Code Execution
Invoke app functionality under controlled circumstances
Modify device properties (great for regression tests)
MiscMisc
Dynamic Analysis
Trace any (Dalvik/Objc/Native) function
Dump saved files
Memory scanner
Automated crypto keys scanner
One-time watchpoints
Monitor file system access
SSL pinning bypass
Code Execution
Invoke app functionality under controlled circumstances
Modify device properties (great for regression tests)
https://github.com/afjoseph/mobsec_toolbox
https://github.com/iddoeldor/frida-snippets
https://awakened1712.github.io/hacking/hacking-frida/
Abdullah JosephAbdullah Joseph
Reach me
@MalwareCheese
Abdullah JosephAbdullah Joseph
Reach me
@MalwareCheese
We are hiring Binary Dudes
and Dudettes!

NanoSec Conference 2019: Code Execution Analysis in Mobile Apps - Abdullah Joseph

  • 1.
  • 2.
    Wait. I knowGDB.Wait. I know GDB. I don't need this...I don't need this... So, let's try another title...So, let's try another title...
  • 3.
    HowHow not toshootnot to shoot yourself in the footyourself in the foot while debuggingwhile debugging MobileMobile appsapps
  • 4.
    About MeAbout Me AbdullahJoseph / @MalwareCheese   Mobile Security Team Lead @ Adjust We do mobile attribution, ad fraud analysis and some data stuff (processing 25 petabytes every 10 days received   ) I like binary stuff Crypto stuff too. Not so much web and network stuff
  • 5.
    About MeAbout Me AbdullahJoseph / @MalwareCheese   Mobile Security Team Lead @ Adjust We do mobile attribution, ad fraud analysis and some data stuff (processing 25 petabytes every 10 days received   ) I like binary stuff Crypto stuff too. Not so much web and network stuff Bonus only for Nanosec: I graduated from APU. Bachelor's in Game Design
  • 6.
    Let's start witha CTFLet's start with a CTF
  • 9.
    FindingsFindings Code block takesinput and puts it in [s] At 0x080486d3, our input and obj.sekrutBuffer get XORed together The result has to equal obj.greetingMessage which gets compared together in 0x080486e6 obj.sekrutBuffer holds the following byte  blob:  )x06x16O+50x1eQx1b[x14Kb]+Sx10TQCMT]
  • 10.
    What did welearn?What did we learn? Debugger == God ModeDebugger == God Mode
  • 11.
    Switching to MobileSwitchingto Mobile Let's go for Android
  • 13.
    How do weget the output ofHow do we get the output of getSecretKey()getSecretKey() dynamically? dynamically?
  • 14.
    Disassemble the app(with “apktool” or similar tool) Set the “app:debuggable” flag to true Rebuild the app Sign the app (with Appium’s Sign.jar or similar) Decompile the app to get the Java sources (with CFR decompiler or jadx) Setup a gradle project inside the decompiled sources Setup an IDE, like Android Studio, and port the decompiled java code to it Setup the testing device to have that app in the “Wait for debugger” list of apps in “Settings” -> “Developer Mode” Setup breakpoints on the “getSecretKey()” function Run the app. It should say “Wait for Debugger” now Use JDWP to run the app and break at “getSecretKey()” function Examine the return value More info here: https://stackify.com/java-remote-debugging/
  • 16.
    Let's talk aboutLet'stalk about binary instrumentationbinary instrumentation Also known as "Function Hooking"
  • 17.
    Let's talk aboutLet'stalk about binary instrumentationbinary instrumentation Also known as "Function Hooking" “ The ability to insert a practically unlimited amount of code at any location in a binary to observe or modify that binary’s behavior   -- Dennis Andriesse - Practical Binary Analysis
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
    So now...So now... Howdo we get the output ofHow do we get the output of getSecretKey()getSecretKey() dynamically? dynamically?
  • 23.
    // myagent.js // =================== Java.perform(()=> { let activity = Java.use("com.adjust.myapp.MainActivity"); Activity.getSecretKey.implementation = () => { var retval = this.getSecretKey(this, arguments); console.log("getSecretKey() called"); console.log(`retval = ${retval}`); return retval; }; }); // =================== // Run with: // $ frida -U -f com.adjust.myapp -l myagent.js
  • 25.
  • 26.
    FallbacksFallbacks AKA: What Fridacannot do / is not Not a ptrace-based debugger LLDB and GDB are debuggers capable of deep analysis of every Instruction Frida HAS a lot of debugger functionality, but its main purpose is to aid in binary analysis and hook into parts of the binary to execute arbitrary instructions What this means is that, if you're intending to step- into every function and analyze it's execution, it might be better to use LLDB/GDB
  • 27.
  • 28.
    FallbacksFallbacks AKA: What Fridacannot do / is not Not the only instrumentation framework DynamoRIO (open-source & free) Intel PIN (free but closed-source) However, it is the easiest one to use and the only one that supports multiple architectures and VM environments (AKA: Android and iOS) by default.
  • 29.
    Use Case #1UseCase #1 Analysis: Memory Dumper &Analysis: Memory Dumper & ScannerScanner
  • 30.
    $ memdumper/memdump.py -U-p com.myapp.adjust -v INFO:Starting Memory dump... DEBUG:Too big, splitting the dump into chunks DEBUG:Number of chunks: 80 DEBUG:Save bytes: 0x12C00000 till 0x13589680 DEBUG:Save bytes: 0x13589680 till 0x13F12D00 DEBUG:Save bytes: 0x13F12D00 till 0x1489C380 DEBUG:Save bytes: 0x1489C380 till 0x15225A00 DEBUG:Save bytes: 0x15225A00 till 0x15BAF080 ... DEBUG:Save bytes: 0x223F4900 till 0x22D7DF80 DEBUG:Save bytes: 0x22D7DF80 till 0x23707600 DEBUG:Save bytes: 0x23707600 till 0x24090C80 DEBUG:Save bytes: 0x24090C80 till 0x24A1A300 DEBUG:Save bytes: 0x24A1A300 till 0x253A3980 DEBUG:Save bytes: 0x253A3980 till 0x25D2D000 DEBUG:Save bytes: 0x25D2D000 till 0x266B6680 DEBUG:Save bytes: 0x266B6680 till 0x2703FD00 DEBUG:Save bytes: 0x2703FD00 till 0x279C9380 DEBUG:Save bytes: 0x279C9380 till 0x28352A00 $ strings -n 5 dump/*.data | uniq | ack -i secret THIS IS A SECRET STRING!!! THIS IS A SECRET STRING!!! THIS IS A SECRET STRING!!! THIS IS A SECRET STRING!!! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
  • 31.
    Use Case #2UseCase #2 Native Android FunctionNative Android Function HookerHooker 10x times easier than GDB or LLDB scripting (!)
  • 32.
    [0] % native_stalker/native_stalker.py --process com.myapp.adjust --library libnative-lib.so --addr 0x00009610 --binary /path/to/my/app/libnative-lib.so --verbose INFO:Analyzing with R2... INFO:Retrieving PLT section... INFO:.plt [0x8AE0] -> [0x92D0] INFO:Prepping Frida... INFO:Resuming process... INFO:Hooking library loaders... JS: loaders(): {"0":"libnative-lib.so","1":38416,"2":35552,"3":37584} INFO:Awaiting hook callbacks... JS: Library [native-lib] loaded with java.lang.String.loadLibrary [+] JS: stalk_func(): {"0":"libnative-lib.so","1":38416,"2":35552,"3":37584} [+] JS: Library base addr: 0x8b2c1000 [+] JS: Hooking [0x8b2ca610]... INFO:Tracing 38416@libnative-lib.so concluded with 11 calls: 0x8b80 -> sym.imp.free 0x8c40 -> fcn.00008c40 0x8b30 -> fcn.00008b30 0x8b90 -> fcn.00008b90 0x8c50 -> fcn.00008c50 0x8b40 -> sym.imp.fopen 0x8ba0 -> fcn.00008ba0 0x8bc0 -> fcn.00008bc0 0x8b70 -> sym.imp.getline 0x8c30 -> fcn.00008c30 0x8b20 -> sym.imp.__android_log_vprint INFO:Done. You can exit the script now... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
  • 33.
    MiscMisc Dynamic Analysis Trace any(Dalvik/Objc/Native) function Dump saved files Memory scanner Automated crypto keys scanner One-time watchpoints Monitor file system access SSL pinning bypass Code Execution Invoke app functionality under controlled circumstances Modify device properties (great for regression tests)
  • 34.
    MiscMisc Dynamic Analysis Trace any(Dalvik/Objc/Native) function Dump saved files Memory scanner Automated crypto keys scanner One-time watchpoints Monitor file system access SSL pinning bypass Code Execution Invoke app functionality under controlled circumstances Modify device properties (great for regression tests) https://github.com/afjoseph/mobsec_toolbox https://github.com/iddoeldor/frida-snippets https://awakened1712.github.io/hacking/hacking-frida/
  • 35.
  • 36.
    Abdullah JosephAbdullah Joseph Reachme @MalwareCheese We are hiring Binary Dudes and Dudettes!