Spearing data in mobile memory: R2Frida memory search
Posted by Francesco Tamagni NowSecure MarketingThe NowSecure team builds some of the best static and dynamic analysis technology for mobile apps available anywhere in the world. Two (of many) elements of the team’s success are the open-source frameworks/tools Frida — for injecting JavaScript into native apps as they run — and Radare — for reverse engineering almost any type of file.
The creators of those two renowned tools — NowSecure Security Researchers Ole André Vadla Ravnås and Sergi Alvarez respectively — integrated them at the end of last year. The combination resulted in R2Frida or what Ole has called, “the ultimate static analysis [Radare] on dynamic steroids [Frida].” NowSecure Researcher Francesco Tamagni recently made significant improvements to R2Frida’s memory-search capabilities, and he answered some questions about those updates and how they make R2Frida even better.
Who will use the new memory-search feature and how will it help them?
Francesco Tamagni: The ability to search patterns in process memory at real-time speed is a crucial aspect of reverse engineering. It’s essential for scaling the problem down and focusing on where interesting things happen. Security researchers, CTF (capture-the-flag) players, developers, or system integrators using R2Frida as a lightweight, yet advanced, debugging tool all benefit from this improvement.
Having a high performance search primitive enables users to build more complex analysis tasks on top of it — for example by combining results from different related searches in the same amount of time it took to perform just one search in the past.
What can people do now with R2Frida that they couldn’t before you added the memory-search feature?
FT: Searching in process memory was already possible with R2Frida because it’s an i/o plugin, which provides Radare with read/write access to the memory of a process. The impact of using Frida’s Memory.scan
in such an integrated way is mostly about performance, because all the searching logic is run on the client process. This cuts down most of the overhead and makes searching faster.
Another advantage of the new feature is that it’s easy to restrict a search to certain memory regions using the information Frida provides: it’s possible to filter by permission, filter by path (if the region maps a file), or just search in the region of the current offset. All of this is specified via the e search.in
configuration variable.
What are the new /w
and /v
search commands?
FT: The /w
command is for searching wide strings, namely strings in which each character is represented using two bytes. At the moment, what’s implemented in R2Frida is similar to what Radare2 already does, which is “expanding” each ASCII character of the input in a two-byte pair (interleaving with zeroes) and using the resulting pattern to perform a hex search using Frida’s Memory.scan
. The /v
command is useful for searching for numeric values stored in memory because it accounts for the endianess of the system as stated in the Radare2 configuration variable cfg.bigendian
. Under the hood, again, a hex pattern is created accordingly and searched for.
Can you give a specific example of how someone might use the new feature?
FT: One common task when evaluating the security of an app is to figure out how user credentials are handled. For example, how is the user logged in after the first time without the app asking the user for their password yet again?
A best practice for secure mobile development is to send out the password only when necessary, then reuse an anonymous unique token which expires after some time. This would free the application from the burden of storing user’s password locally, which, if not implemented carefully, may lead to private information leaks.
One way to quickly test for this behavior is to search for the password in memory, both right after the first registration / login, and whenever the app starts up again. In the first case, it’s common to find the password in memory, while in the second case you can only find it when the app stores it and loads it every time.
Here’s an example of searching for the password within the “My Vodafone” app provided by Vodafone,one of the leading mobile carriers in Italy. My password is “verydumbpassword!”.
Here’s the first memory search – performed upon first login:
$ r2 frida://$MY_IPHONE_ID/"My Vodafone"
[0x00000000]> / veryd
Searching 5 bytes: 76 65 72 79 64
hits: 5
0x108645c52 hit0_0 verydS x`hda P
0x108646280 hit0_1 veryd3`bd
0x15d757d40 hit0_2 verydumbpassword!p^0]*^
0x15ea04e00 hit0_3 verydumbpassword!^ ^X
0x15ebb4d10 hit0_4 verydumbpassword! G=-^^
Here, you see another memory search after restarting the app:
$ r2 frida://$MY_IPHONE_ID/"My Vodafone"
[0x00000000]> / veryd
Searching 5 bytes: 76 65 72 79 64
hits: 3
0x110b5ffa0 hit0_0 veryds0 R
0x111163e22 hit0_1 veryd3g{`$ Q0C
0x14c72f9e1 hit0_2 verydumbpassword!rLrL>[LrL
[0x00000000]>
The password is clearly visible in memory, so there is evidence that it’s stored locally and gets loaded each time the app starts up. Now, please note that this is not necessarily a vulnerability. The app uses a keychain wrapper, and so it’s likely that the password is stored securely. A penetration tester knows their next step is to check whether this password is stored securely (e.g., in the keychain using safe attributes) or not. This can be done easily using Frida to instrument various aspects of the iOS keychain.
What was the hardest part about developing these new R2Frida search features?
FT: The challenge was to integrate it properly with the existing Radare search feature, specifically:
Reading configuration parameters from a running Radare2 session, such as from-to address limits
Setting flags for search hits in the same way Radare does
To achieve these goals, the JavaScript agent can now send a subset of commands back to the running Radare2 session on the host and receive asynchronous responses. The ability to send simple commands to a host’s Radare session will be useful for other features too.
Developing a new feature in R2Frida mostly means crystallizing a best practice of Frida usage into a nicely integrated Radare2 command. That’s challenging and excessively fun.
What makes you most proud about the new memory-search capabilities in R2Frida?
R2Frida is really powerful and constantly evolving. I’m proud to place another few bricks into it upon which others can build to make it even more useful. There’s a lot going on with Radare2 and Frida, so it’s fun to be in the middle of this and help out. Also, enhancing R2Frida opens up new use cases which end up improving both Radare2 and Frida in the process.