-
Notifications
You must be signed in to change notification settings - Fork 237
Medusa
When running medusa, the first step is to select the device that you are going to use during your review. For this reason, medusa will display the currently detected devices and prompt you to choose one by entering the corresponding index number:
After this, medusa will display various info, regarding the device but also the currently active modules:
Make sure that a frida server is running on this device and you are good to go !
IMPORTANT: Medusa has an autocomplete functionality in order to indicate the available options. Simply said, you can always press the tab button to see your available options. For example, pressing the tab after the 'show' command, it yields
meaning that, after show you can either type: all, categories, mods or snippets
Medusa counts more than 90 modules, which are inactive until you add them to the stashed ones (we will see how). To navigate between these modules and find the right ones to stash, you can you the following commands:
The 'search' command can be used to search for the module that fit your needs based on a given keyword. For example, to search for HTTP communications related hooks, you can simply type:
The 'show' command, combined with an options can be used for the following tasks:
- Show all available modules:
show all
Modules are grouped according to their functionality, to see the available groups type:
- Display the available module categories:
show categories
- Display the available modules for the selected category
show mods [category]
- To list your stashed modules, type:
show mods
Let's say you found a super useful frida script and you want to save it, so you can use it later. You can add it under the /medusa/snippets directory and later import it using the import command:
While using medusa, to list those scripts, simply type: show snippets
Use the info [module-name]
command to get details about a hook and its functionality:
To use the modules you first have to stash them, meaning that first you have to add them in a list of modules which later are going to be unified to a single script and run under a frida session.
To stash a module simply type: use
followed by the module name. Here are some tips regarding this command:
- Pressing tab after the
use
command will list all the available modules - Typing the initial letters of a module followed by a tab after the
use
command will list all the modules starting with those letters:
- Typing
use
followed by the initial letters of a module category will add all the modules of this category:
To un-stash a module, simply type rem
followed by the module name. Furthermore, the same options with the use
can be used (tab, initial letters etc.)
You can empty the stashed modules by typing reset
. Keep in mind that this will also reset the unified script !
Some modules have to be stashed before others. For example the SSL unpinning modules have to be stashed always firsts. For this reason you can use swap
to change the order of your stashed modules:
Finally, you can stash modules which have not been loaded from the standard modules directory using the following command:
add [full-path-to-module]
After stashing your modules, the next step is to compile them to a single script. This script is called agent.js
and you can find it under the medusa/ directory, although most of the times you won't have to deal with it. That being said, in order to compile your script, simply type compile
.
Sometimes you might need to add delay on loading your script (e.g. it may take time for libraries to be loaded so Frida won't be able to find them). To do so you can type: compile -t X
where X is the delay time in milliseconds.
After you have selected, stashed and compiled your modules in to a unified script, the next step is to run the application. There are two main ways of doing that:
- Start or restart the app and attach to it, with:
run -f [package - name]
orrun -n [package - number]
- Attach to the application while it is running, with
run [package-name]
Regarding the first, you can simply type run -f
followed by a tab, to get the installed packages. Alternatively, to start a session using a package number, type list
and get the index number that corresponds to the app that you want to run from the output:
Regarding the second option, you can use the run
followed by a tab in order to get the available packages and attach to the one you are interested about.
When a session starts Medusa prints various info regarding the Frida server (that runs in the device) and the running application:
While in session, you have the following set of commands available:
As it is depicted above, the in-session commands are pretty much self-explanatory. Regarding the (t)race
and (r)e(s)et
, they can be used to modify the scratchpad script on the fly (refer to the scratchpad section to get info about this module).
Each module intercepts a subset of Android APIs related to a specific functionality. For example the webviews/hook_webviews intercepts calls related to the Webview class, the intents/* to Intent and so on. To cover the gap of intercepting methods that belong to the app itself, Medusa provides a special module which is called scratchpad. That being said, it is possible to intercept Java or Native calls with a single command by using the hook
command and its options.
The scratchpad can be stashed/un-stashed similarly to any module using the use scratchpad
and rem scratchpad
respectively. It is also added by default in case you issue a hook
or pad
command. The available options regarding this module are the following:
-
hook -a [class_name]
Example:hook -a com.dropbox.android.activity.d
. This option will add "hooks" to all the methods of the com.dropbox.android.activity.d and when a method will be invoked Medusa will log (if possible) its arguments and the value that it returns:
-
hook -f
This option can be used to intercept a single class method (including the constructor) and log its arguments, the returned value but also a stack trace of the methods that lead to this call. You can hook as many methods as you wish by entering a submenu and providing the requested information:
When one of the hooked methods gets called the output will be as follows:
You can also use the jtrace full_path_to_method
to achieve the same result. Example: jtrace com.dropbox.android.activity.d.d
-
hook -n
This option can be used to intercept a single native method by giving its name or offset:
While most of the options are self-explanatory, the backtrace will print the call stack to the intercepted method, the 'memory read' will try to dump the method's arguments and returned values using a buffer size which is given in the subsequent input.
-
hook -r
Resets the current hooks and clears the scratchpad.
To further edit the scratchpad you can use the pad
command which will open for edit it using vim:
The scratchpad can also be modified during a session, using the in-session menu's (t)race and (r)e(s)et options:
You can save your favourite Frida scripts under the medusa/snippets directory and import them to the scratchpad using the import
command. For example, assuming that you want to import the example.js script, then:
- Remove the
Java.perform(function() { }
keeping only the part highlighted below:
- Save it as /medusa/snippets/example.js
- Use the
import example
to add it to the scratchpad
You can view the currently saved scripts by issuing the command snippet
followed by a tab and then snippet [snippet_name]
to view the script's code:
Medusa provides a wide variety of commands in order to simplify hooking of native methods. You can start by listing the loaded libraries of an application by issuing the libs
command:
You can use the -a
to list (a)ll the loaded native libraries, -s
for the (s)ystem related ones and -j
to list the application's native libraries.
The --attach
option (which is usually better) will use an already running instance of the app and attach to it in order to list the libraries.
The next step is to enumerate the application's exported methods. Use the enumerate [package name] [libname] <--attach>
to do that:
You can now hook any of these methods using the hook -n
command as it was explained above.
Finally, you can force the application to load a native library by using the load package_name /full/path/to/library.so
You can view, search, write or dump the application's memory using the memops
or memmap
command. The former needs a library to be attached to while the later is more flexible as it can be used to view or dump any memory region of the app.
Important: The application must be running in order for both of these commands to work !
Type memops package_name libnative.so
By the time that Medusa will be successfully attached to the app you can use the memops's submenu to operate:
`|(E)xit |r@offset |w@offset |⏎ |scan |(h)elp| dump|:``
-
Starting with the
r
option, you can use it in order to read a memory region given a specific offset. For example, the r@100 will add the 0x64 to the base address of the library and dump a memory region starting from the new address up to 0x128 bytes. You can read continued memory regions by using the r@X (where X is an offset) and then pressing the enter key. -
The
w
works in a similar way, but it can be used in order to (w)rite instead of reading the content of a memory address. It can be useful to dynamically patch an instruction and modify the code flow. -
The
scan
can be used to scan the memory region given a string or byte array -
The
dump
command will dump the memory region starting from the base address up to the base address + module size. The result will be saved in the local directory as 'libname' followed by the 'dat' extension.
Similarly to memops, memmap can be used to explore the application's memory without "depending" on a specific module. That being said, first make sure that the android application is running and then type memmap package_name
. Finally, choose a memory region from the presented submenu:
After selecting a memory region, the process is similar to memops:
Currently we support only read and dump, but other options will soon be available.
Regarding the dump: Medusa will dump the working memory region in chunks and save them under the [current dir]/dump/ folder
You can get details about a Java class of an Android application by running:
describe_java_class full.path.to.class.name
This will add code to the scratchpad that will log the details of a class during an active session:
You can get current the value of a Java object's field (assuming that there is an existing instance) by running:
get package_name full.path.to.class.field
Medusa provides additional commands that can be use automate boring processes. These commands include:
-
c
executes a shell command. Example:
-
cc
executes a shell command to the connected device:
-
shell
opens an interactive shell. -
clear
clears the screen. -
list
lists the current device's installed packages. -
type
sends a word to the android device
-
dexload /device/path/to/dex
forces the android application to load a dex file from a given directory -
dump package_name
dumps the dex files of a given package name -
status
prints the loaded device id, libraries, native functions of the last loaded package (assuming that you run the native libraries related commands before). -
strace package_name
pseudo strace for Android apps -
list
lists the connected device's package names -
list package_name path
prints path details of an installed application
-
loaddevice
reloads the device (in case the device is gone) or loads another device.
-
reload [-r recipe_file]
reloads the medusa modules. Use it, when you change a module and you want to instantly reload it. Add the "-r recipe_file" option to load a previous session (see saving a session).
Medusa Wiki
Medusa Wiki
-
- Searching for the right module
- Getting info about a module
- Stashing / un-stashing
- Compiling
- Starting a session
- Hooking beyond the modules
- Importing Frida scripts
- Working with native libraries
- Working with the application's memory
- Getting Class and Object snapshots
- Useful utilities
- Saving a session (recipe)