MASTG-TECH-0044: Process Exploration
When testing an app, process exploration can provide the tester with deep insights into the app's process memory. It can be achieved via runtime instrumentation and allows performing tasks such as:
- Retrieving the memory map and loaded libraries.
- Searching for occurrences of certain data.
- After searching, obtain the location of a certain offset in the memory map.
- Performing a memory dump and inspecting or reverse engineering the binary dataoffline.
- Reverse engineering a native library while it's running.
As you can see, these passive tasks help us collect information. This Information is often used for other techniques, such as method hooking.
In the following sections, you will be using r2frida to retrieve information straight from the app runtime. Please refer tor2frida's official installation instructions. First, start by opening an r2frida session to the target app (e.g.HelloWorld JNI APK) that should be running on your Android phone (connected via USB). Use the following command:
r2frida://usb//sg.vantagepoint.helloworldjniSee all options with
r2 frida://?.
Once in the r2frida session, all commands start with:. For example, in radare2 you'd runi to display the binary information, but in r2frida you'd use:i.
Memory Maps and Inspection¶
You can retrieve the app's memory maps by running:dm. The output in Android can get very long (e.g. between 1500 and 2000 lines). To narrow your search and see only what directly belongs to the app, apply a grep (~) by package name:dm~<package_name>:
[0x00000000]>:dm~sg.vantagepoint.helloworldjni0x000000009b2dc000-0x000000009b361000rw-/dev/ashmem/dalvik-/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.art(deleted)0x000000009b361000-0x000000009b36e000---/dev/ashmem/dalvik-/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.art(deleted)0x000000009b36e000-0x000000009b371000rw-/dev/ashmem/dalvik-/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.art(deleted)0x0000007d103be000-0x0000007d10686000r--/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.vdex0x0000007d10dd0000-0x0000007d10dee000r--/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.odex0x0000007d10dee000-0x0000007d10e2b000r-x/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.odex0x0000007d10e3a000-0x0000007d10e3b000r--/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.odex0x0000007d10e3b000-0x0000007d10e3c000rw-/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.odex0x0000007d1c499000-0x0000007d1c49a000r-x/data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so0x0000007d1c4a9000-0x0000007d1c4aa000r--/data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so0x0000007d1c4aa000-0x0000007d1c4ab000rw-/data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so0x0000007d1c516000-0x0000007d1c54d000r--/data/app/sg.vantagepoint.helloworldjni-1/base.apk0x0000007dbd23c000-0x0000007dbd247000r--/data/app/sg.vantagepoint.helloworldjni-1/base.apk0x0000007dc05db000-0x0000007dc05dc000r--/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.artWhile you're searching or exploring the app memory, you can always verify where you're located at each moment (where your current offset is located) in the memory map. Instead of noting and searching for the memory address in this list, you can simply run:dm.. You'll find an example in the following section, "In-Memory Search".
If you're only interested in the modules (binaries and libraries) that the app has loaded, you can use the command:il to list them all:
[0x00000000]>:il0x000000558b1fd000app_process640x0000007dbc859000libandroid_runtime.so0x0000007dbf5d7000libbinder.so0x0000007dbff4d000libcutils.so0x0000007dbfd13000libhwbinder.so0x0000007dbea00000liblog.so0x0000007dbcf17000libnativeloader.so0x0000007dbf21c000libutils.so0x0000007dbde4b000libc++.so0x0000007dbe09b000libc.so...0x0000007d10dd0000base.odex0x0000007d1c499000libnative-lib.so0x0000007d2354e000frida-agent-64.so0x0000007dc065d000linux-vdso.so.10x0000007dc065f000linker64As you might expect, you can correlate the addresses of the libraries with the memory maps: e.g. the native library of the app is located at0x0000007d1c499000 and optimized dex (base.odex) at0x0000007d10dd0000.
You can also use an objection to display the same information.
$objection-s-p-nsg.vantagepoint.helloworldjnistartsg.vantagepoint.helloworldjnion(google:8.1.0)[usb]# memory list modulesSavetheoutputbyadding`--jsonmodules.json`tothiscommandNameBaseSizePath---------------------------------------------------------------------------------------------------------------------------------------------------app_process640x558b1fd00032768(32.0KiB)/system/bin/app_process64libandroid_runtime.so0x7dbc8590001982464(1.9MiB)/system/lib64/libandroid_runtime.solibbinder.so0x7dbf5d7000557056(544.0KiB)/system/lib64/libbinder.solibcutils.so0x7dbff4d00077824(76.0KiB)/system/lib64/libcutils.solibhwbinder.so0x7dbfd13000163840(160.0KiB)/system/lib64/libhwbinder.sobase.odex0x7d10dd0000442368(432.0KiB)/data/app/sg.vantagepoint.helloworldjni-1/oat/arm64/base.odexlibnative-lib.so0x7d1c49900073728(72.0KiB)/data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.soYou can even directly see the size and the path to that binary in the Android file system.
In-Memory Search¶
In-memory search is a very useful technique to test for sensitive data that might be present in the app memory.
See r2frida's help on the search command (:/?) to learn about the search command and get a list of options. The following shows only a subset of them:
[0x00000000]>:/?/search/jsearchjson/wsearchwide/wjsearchwidejson/xsearchhex/xjsearchhexjson...You can adjust your search by using the search settings:e~search. For example,:e search.quiet=true; will print only the results and hide search progress:
[0x00000000]>:e~searchesearch.in=perm:r--esearch.quiet=falseFor now, we'll continue with the defaults and concentrate on string search. This app is actually very simple. It loads the string "Hello from C++" from its native library and displays it to us. You can start by searching for "Hello" and see what r2frida finds:
[0x00000000]>:/HelloSearching5bytes:48656c6c6f...hits:110x13125398hit0_0HelloWorldJNI0x13126b90hit0_1HelloWorld!0x1312e220hit0_2HellofromC++0x70654ec5hit0_3Hello0x7d1c499560hit0_4HellofromC++0x7d1c4a9560hit0_5HellofromC++0x7d1c51cef9hit0_6HelloWorldJNI0x7d30ba11bchit0_7HelloWorld!0x7d39cd796bhit0_8Hello.java0x7d39d2024dhit0_9Hello;0x7d3aa4d274hit0_10HelloNow you'd like to know where these addresses actually are. You may do so by running the:dm. command for all@@ hits matching the globhit0_*:
[0x00000000]>:dm.@@hit0_*0x0000000013100000-0x0000000013140000rw-/dev/ashmem/dalvik-mainspace(regionspace)(deleted)0x0000000013100000-0x0000000013140000rw-/dev/ashmem/dalvik-mainspace(regionspace)(deleted)0x0000000013100000-0x0000000013140000rw-/dev/ashmem/dalvik-mainspace(regionspace)(deleted)0x00000000703c2000-0x00000000709b5000rw-/data/dalvik-cache/arm64/system@[email protected]0x0000007d1c499000-0x0000007d1c49a000r-x/data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so0x0000007d1c4a9000-0x0000007d1c4aa000r--/data/app/sg.vantagepoint.helloworldjni-1/lib/arm64/libnative-lib.so0x0000007d1c516000-0x0000007d1c54d000r--/data/app/sg.vantagepoint.helloworldjni-1/base.apk0x0000007d30a00000-0x0000007d30c00000rw-0x0000007d396bc000-0x0000007d3a998000r--/system/framework/arm64/boot-framework.vdex0x0000007d396bc000-0x0000007d3a998000r--/system/framework/arm64/boot-framework.vdex0x0000007d3a998000-0x0000007d3aa9c000r--/system/framework/arm64/boot-ext.vdexAdditionally, you can search for occurrences of thewide version of the string (:/w) and, again, check their memory regions:
[0x00000000]>:/wHelloSearching10bytes:480065006c006c006f00hits:60x13102acchit1_0480065006c006c006f000x13102b9chit1_1480065006c006c006f000x7d30a53aa0hit1_2480065006c006c006f000x7d30a872b0hit1_3480065006c006c006f000x7d30bb9568hit1_4480065006c006c006f000x7d30bb9a68hit1_5480065006c006c006f00[0x00000000]>:dm.@@hit1_*0x0000000013100000-0x0000000013140000rw-/dev/ashmem/dalvik-mainspace(regionspace)(deleted)0x0000000013100000-0x0000000013140000rw-/dev/ashmem/dalvik-mainspace(regionspace)(deleted)0x0000007d30a00000-0x0000007d30c00000rw-0x0000007d30a00000-0x0000007d30c00000rw-0x0000007d30a00000-0x0000007d30c00000rw-0x0000007d30a00000-0x0000007d30c00000rw-They are in the same rw- region as one of the previous strings (0x0000007d30a00000). Note that searching for the wide versions of strings is sometimes the only way to find them, as you'll see in the following section.
In-memory search can be very useful to quickly know if certain data is located in the main app binary, inside a shared library, or in another region. You may also use it to test the behavior of the app regarding how the data is kept in memory. For instance, you could analyze an app that performs a login and search for occurrences of the user password. Also, you may check if you still can find the password in memory after the login is completed to verify if this sensitive data is wiped from memory after its use.
Memory Dump¶
You can dump the app's process memory with objection and Fridump. To take advantage of these tools on a non-rooted device, the Android app must be repackaged withfrida-gadget.so and re-signed. A detailed explanation of this process can be found at Dynamic Analysis on Non-Rooted Devices. To use these tools on a rooted device, simply have frida-server installed and running.
Note: When using these tools, you might get several memory access violation errors, which can normally be ignored. These tools inject a Frida agent and try to dump all the mapped memory of the app regardless of the access permissions (read/write/execute). Therefore, when the injected Frida agent tries to read a region that's not readable, it'll return the correspondingmemory access violation errors. Refer to the previous section "Memory Maps and Inspection" for more details.
With objection, it is possible to dump all memory of the running process on the device by using the commandmemory dump all.
$objection--namesg.vantagepoint.helloworldjnistartsg.vantagepoint.helloworldjnion(google:8.1.0)[usb]# memory dump all /Users/foo/memory_Android/memoryWilldump719rw-images,totalling1.6GiBDumping1002.8MiBfrombase:0x14140000[------------------------------------]0%00:11:03(sessiondetachmessage)process-terminatedDumping8.0MiBfrombase:0x7fc753e000[####################################] 100%Memorydumpedtofile:/Users/foo/memory_Android/memoryIn this case, there was an error, which is probably due to memory access violations as we already anticipated. This error can be safely ignored as long as we are able to see the extracted dump in the file system. If you have any problems, a first step would be to enable the debug flag
-dwhen running objection or, if that doesn't help, file an issue inobjection's GitHub.
Next, we can find the "Hello from C++" strings with radare2:
$r2/Users/foo/memory_Android/memory[0x00000000]>izz~Hellofrom11360x000652700x000652701415()asciiHellofromC++Alternatively, you can use Fridump. This time, we will input a string and see if we can find it in the memory dump. For this, open the MASTG Hacking Playground (Java) app, navigate to "OMTG_DATAST_002_LOGGING" and enter "owasp-mstg" in the password field. Next, run Fridump:
python3fridump.py-Usg.vp.owasp_mobile.omtg_android-sCurrentDirectory:/Users/foo/git/fridumpOutputdirectoryissetto:/Users/foo/git/fridump/dumpStartingMemorydump...Oops,memoryaccessviolation!-------------------------------]0.28%CompleteProgress:[##################################################] 99.58% CompleteRunningstringsonallfiles:Progress:[##################################################] 100.0% CompleteFinished!Tip: Enable verbosity by including the flag
-vif you want to see more details, e.g. the regions provoking memory access violations.
It will take a while until it's completed, and you'll get a collection of *.data files inside the dump folder. When you add the-s flag, all strings are extracted from the dumped raw memory files and added to the filestrings.txt, which is also stored in the dump directory.
lsdump/dump/1007943680_dump.datadump/357826560_dump.datadump/630456320_dump.data...strings.txtFinally, search for the input string in the dump directory:
$grep-nriowasp-mstgdump/Binaryfiledump//316669952_dump.datamatchesBinaryfiledump//strings.txtmatchesThe "owasp-mstg" string can be found in one of the dump files as well as in the processed strings file.