Logo
blank Skip to main content

How to Use Frida for Dynamic Analysis and Reverse Engineering for Desktop and Mobile Apps 

Ensuring the security and reliability of software products is one of the biggest challenges for modern businesses. As a product grows, each new feature opens doors for potential security vulnerabilities and performance bottlenecks. 

Dynamic analysis and reverse engineering are two approaches that allow developers to explore the inner workings of their applications while they’re running. With these insights, developers can identify vulnerabilities and discover potential security issues.

In this article, you’ll learn how to analyze your app dynamically and uncover vulnerabilities using Frida. We’ll show you real-world examples of the Frida tool in action based on our own project experience. This article will be useful for security researchers, CTOs, and CSOs who want to ensure the protection of their products. 

What is dynamic analysis and why is it important?

Dynamic analysis and reverse engineering are two crucial cybersecurity methods that allow businesses to enhance product security.

Dynamic analysis allows cybersecurity specialists to evaluate the behavior of software while it’s running. This is effective for:

  • Vulnerability detection — uncover potential vulnerabilities and plan cybersecurity enhancements to protect your product from data breaches
  • Real-world simulation — understand how your product will behave in real-world conditions, allowing you to examine your product from the users’ perspective and see how it handles sensitive data and crucial operations
  • Performance optimization — beyond security, dynamic analysis helps optimize app performance, which can help you improve your product’s user experience and optimize infrastructure costs
  • Compliance assurance — identify potential breaches before they lead to compliance violations and penalties

Dynamic analysis is used in reverse engineering, which allows developers to dissect software and understand its inner workings even without source code or documentation. 

At Apriorit, we specialize in reverse engineering and use it to help businesses assess and improve the security of their software. This includes protecting it from breaches, malware attacks, and data leaks that can cause substantial reputational and monetary damage.

There are many tools that allow businesses to conduct dynamic analysis and reverse engineering. In our reversing projects, we often use Frida.

Want to bring your product’s security to the next level?

Make your software vulnerability-free with the help of Apriorit’s top reverse engineers and cybersecurity professionals.

What is Frida?

Frida is a dynamic open-source instrumentation toolkit that allows developers and reverse engineers to inject JavaScript code into running applications. Injection enables developers to trace function calls, modify function behavior, and intercept data in real time, making it an invaluable tool for dynamic analysis.

Frida provides a comprehensive set of APIs that can be used to interact with running applications. 

Frida's key features

Frida’s architecture is based on a client–server model. The Frida server runs on the target device or computer, while the client is used to interact with the server and inject JavaScript code into running applications.

Let’s look at a few examples of what dynamic app analysis tasks you can perform using Frida. We’ll start with desktop applications.

Dynamic analysis of a desktop application with Frida

Frida supports Windows, macOS, and Linux, making it a reliable choice for analyzing desktop applications regardless of the operating system they run on. Let’s look at some of the tasks you can perform with Frida.

Before we can perform any dynamic analysis or manipulation actions, we need to inject Frida into our desktop app. This is a relatively straightforward process:

  • Install Frida on the target system.
  • Use the command frida-server -l 0.0.0.0. This will start the Frida server and make it accessible to other devices on the network. 
  • Attach the Frida client to the target process and inject the Frida script.

Hooking MessageBox in a Windows desktop application

To demonstrate how to hook functions with Frida, let’s consider the example of hooking the MessageBox function in a Windows desktop application. This function is used to display a message box to the user, making it an excellent target for dynamic analysis.

To hook the MessageBox function using Frida, we first need to write a Frida script. The script will attach to the target process, find the address of the MessageBox function, and hook the function using the Interceptor. Here’s our custom script from one of our projects:

JavaScript
function hook_messagebox() {
  var user32 = Module.find("user32.dll");
  var MessageBoxA = user32.findExportByName("MessageBoxA");
 
  Interceptor.attach(MessageBoxA, {
	onEnter: function(args) {
  	    console.log("[*] MessageBox called.");
	}
  });
}
 
setTimeout(hook_messagebox, 0);

In this script, we use Module.findBaseAddress to find the base address of the user32.dll library, which contains the MessageBox function. We then get the address of the MessageBox function using the findExportByName method (for private methods, we can use add with offset). Finally, we use Interceptor.attach to hook the MessageBox function, logging a message to the console when the function is called.

To run this script, save it to a file (such as hook_messagebox.js) and run the Frida client with the following command:

JavaScript
frida -f target.exe -l hook_messagebox.js

This will attach Frida to the target process and inject the script. When the target process calls the MessageBox function, Frida will intercept the function and log a message to the console.

Read also

9 Best Reverse Engineering Tools for 2023 [Updated]

Enhance software security, maintain legacy code, and improve your product compatibility with third-party components using only the best reversing tools. Discover the most efficient programs along with practical examples of using them.

Learn more
9 Best Reverse Engineering Tools for 2023 [Updated]

Modifying NSURLRequest in a macOS desktop application

Another powerful capability of Frida in desktop applications is modifying data in real time. For example, let’s consider the case of a macOS desktop application that uses NSURLRequest to make HTTP requests. We can use Frida to modify the HTTP request before it is sent, enabling us to bypass security measures or modify the application’s behavior.

To modify the NSURLRequest in a macOS desktop application using Frida, we first need to write a Frida script. The script will attach to the target process, find the address of the NSURLRequest object, and modify its properties using JavaScript. Here’s an example:

JavaScript
function modify_nsurlrequest() {
  // Find the address of the NSURLRequest object
  var requestPtr = null;
  var objc_msgSend = new NativeFunction(Module.findExportByName("libobjc.A.dylib", "objc_msgSend"), "pointer", ["pointer", "pointer"]);
  Interceptor.attach(objc_msgSend, {
    onEnter: function (args) {
      var sel = ObjC.selectorAsString(args[1]);
      if (sel === "initWithURL:cachePolicy:timeoutInterval:") {
        requestPtr = args[0];
      }
    },
    onLeave: function (retval) {
      if (requestPtr !== null) {
        var request = new ObjC.Object(requestPtr);
        request.setValue_forHTTPHeaderField_("my-custom-header", "X-Custom-Header");
        requestPtr = null;
      }
    }
  });
}

// Attach to the target process and wait for it to start
Process.enumerateApplications({
  onMatch: function (info) {
    if (info.name === "TargetApp") {
      console.log("Attaching to " + info.name + " (" + info.pid + ")");
      // Attach to the process and wait for its main module to be loaded
      Process.attach(info.pid, {
        onModuleLoaded: function (module) {
          if (module.name === "TargetApp") {
            // Wait for the script runtime to be ready
            setTimeout(modify_nsurlrequest, 0);
          }
        }
      });
    }
  },
  onComplete: function () {
    console.log("Failed to find target process");
  }
});

This script uses the objc_msgSend function to intercept calls to the initWithURL:cachePolicy:timeoutInterval: method of the NSURLRequest class. When this method is called, we save the address of the initialized NSURLRequest object. When the method returns, we create an ObjC.Object instance representing the NSURLRequest object and modify its properties as desired.

Next, we use Process.enumerateApplications to find the target process by name. When the process is found, we attach to it using Process.attach and wait for its main module to be loaded. When the main module is loaded, we call the setTimeout function to schedule the call for the modify_nsurlrequest function during the next event loop iteration, giving the script runtime a chance to fully initialize.

Once the modify_nsurlrequest function is called, it will intercept calls to the NSURLRequest initializer method and modify the properties of any initialized NSURLRequest objects as desired.

These are just a few examples of dynamic analysis tasks you can perform with Frida in desktop applications. Let’s now take a look at Frida’s uses for mobile apps.

Dynamic analysis of a mobile app with Frida

Dynamic analysis is an effective way to identify vulnerabilities in mobile applications because it allows us to monitor application behavior in real time. 

Frida can be used to perform dynamic analysis of both Android and iOS applications. With Frida, we can hook into a running application and monitor its behavior, including function calls, network traffic, and memory use.

To use Frida for dynamic analysis of an application, we first need to install the application on a physical or virtual device. Then, we can attach Frida to the running process and start monitoring the application’s behavior.

Frida can be used with unrooted, rooted, and jailbroken devices. Installation is described in detail in the official Frida documentation. Generally, it involves running the run frida-server command on the target device and connecting to it using USB in debugging mode. 

Let’s take a look at some examples of what you can do with Frida to run dynamic analysis on your mobile app. 

Bypassing root detection

Many developers implement root detection to prevent users from running their applications on rooted devices. However, this can be bypassed using dynamic analysis with Frida.

Let’s look at an example where we use Frida to bypass root detection in an Android application. In this case, we’ll assume the application is using the SafetyNet API to check if the device is rooted.

To bypass root detection, we’ll use Frida to intercept the call to the SafetyNet API and modify the return value to indicate that the device is not rooted. Here’s the JavaScript code to achieve this:

JavaScript
Interceptor.attach(Module.findExportByName("libfoo.so", "safetynet_check"), {
	onLeave: function(retval) {
    	retval.replace(0x0);
	}
});

However, modern mobile apps and systems often employ multiple layers of security measures to detect and prevent various forms of tampering and unauthorized access. As a result, bypassing root detection in contemporary apps and systems may require more extensive and sophisticated hooking techniques.

You can find these techniques and implementation examples on CodeShare.

Related project

Improving a SaaS Cybersecurity Platform with Competitive Features and Quality Maintenance

Find out how bug fixes and new functionality helped our client make their platform more stable and competitive. Discover the success story of how Apriorit helped a SaaS cybersecurity provider receive appreciation from end users for quick fixes of reported issues and overall UI/UX improvements.

Project details
Improving a SaaS Cybersecurity Platform with Competitive Features and Quality Maintenance

Tampering with API Calls

Mobile applications often use APIs to communicate with backend servers. By tampering with API calls, an attacker can modify application behavior or steal sensitive data.

We’ll use this technique ethically for Frida dynamic instrumentation. Tampering with API calls can help you assess your app’s overall security, inspect traffic, and monitor behavior. 

Frida allows tampering with API calls in iOS applications. In this case, we’ll assume the application is using the URLSession API to make a request to a backend server.

To tamper with the API call, we’ll use Frida to intercept the call to the URLSession API and modify a request before it is sent to the server. Here’s the code to achieve this: 

JavaScript
Interceptor.attach(ObjC.classes.NSURLSession["- dataTaskWithRequest:completionHandler:"].implementation, {
	onEnter: function(args) {
    	var request = new ObjC.Object(args[2]);
    	var mutableRequest = request.mutableCopy();
        mutableRequest.addValue("YourModifiedHeaderValue", forHTTPHeaderField: "YourModifiedHeaderField");
    	args[2] = mutableRequest;
	}
});

By tampering with API calls, you can assess the application’s security vulnerabilities. At Apriorit, we use this method to simulate various attack scenarios and identify potential weaknesses in the way an application handles data, communicates with servers, or responds to unexpected inputs.

Reverse engineering with Frida

You can use Frida for reverse engineering. It provides a dynamic analysis environment that helps you examine how an application behaves while it’s running. Frida allows us to hook into an application’s execution flow, monitor and manipulate function calls and arguments, and intercept data being sent or received by the application.

At Apriorit, we use Frida for a variety of reverse engineering tasks, such as:

  • Extracting encryption keys
  • Analyzing network traffic
  • Tracing system calls
  • Identifying malware behavior
  • Researching proprietary protocols
  • Analyzing binary code

There are other activities like malware instrumentation with Frida, that allow cybersecurity specialists to reverse engineer malware. 

In this guide, we demonstrate the first three tasks using an Android application as an example. Frida is particularly well-suited for the Android platform, while other tools might be more suitable for reverse engineering tasks on desktop and iOS platforms.

Extracting encryption keys

The Apriorit team of security experts uses Frida to extract encryption keys used by an application to secure sensitive data. By hooking into the application’s encryption functions, we can intercept the keys being generated or used by the application and log them for further analysis.

Here’s a sample of a script that uses Frida to extract an encryption key from an application:

JavaScript
Java.perform(function () {
  var key = null;
 
  var keygen = Java.use('javax.crypto.KeyGenerator');
  var keygen_init = keygen.init.overload('int');
  keygen_init.implementation = function (keysize) {
	console.log('[*] Key size: ' + keysize);
	keygen_init.call(this, keysize);
	key = this.generateKey();
  };
 
  var cipher = Java.use('javax.crypto.Cipher');
  var cipher_init = cipher.init.overload('int', 'java.security.Key');
  cipher_init.implementation = function (opmode, secretKey) {
	console.log('[*] Secret key algorithm: ' + secretKey.getAlgorithm());
	console.log('[*] Secret key format: ' + secretKey.getFormat());
	console.log('[*] Secret key encoded: ' + secretKey.getEncoded());
	cipher_init.call(this, opmode, secretKey);
  };
});

This script hooks into the javax.crypto.KeyGenerator and javax.crypto.Cipher classes and intercepts their function calls. When the KeyGenerator initializes a new key, the script logs the key size and generates the key. When the Cipher is initialized with a secret key, the script logs information about the key.

Read also

The Evolution of Reverse Engineering: From Manual Reconstruction to Automated Disassembling

Handle security tasks of any complexity efficiently and quickly by fully automating reverse engineering activities. Discover the key techniques, tools, and methods recommended by our cybersecurity researchers.

Learn more

Analyzing network traffic

Frida can be used to analyze an application’s network traffic by hooking into network functions and intercepting data being sent or received by the application. This can be useful for identifying sensitive data being transmitted over the network, as well as for understanding how the application communicates with external services.

Here’s an example script that uses Frida to intercept network traffic:

JavaScript
Java.perform(function() {
  var URL = Java.use("java.net.URL");
  var HttpURLConnection = Java.use("java.net.HttpURLConnection");
  var OutputStreamWriter = Java.use("java.io.OutputStreamWriter");
  var BufferedReader = Java.use("java.io.BufferedReader");
 
  // Intercept the request
  HttpURLConnection.getOutputStream.implementation = function() {
	var outputStream = this.getOutputStream();
	var requestMethod = this.getRequestMethod();
	var url = this.getURL().toString();
 
	// Print out the request method and URL
	console.log("[+] Intercepted " + requestMethod + " request to " + url);
 
	// Read the request body
	var request = "";

      // Get the InputStream object
      var inputStream = this.getInputStream();

      // Create a new InputStreamReader object
      var inputStreamReader = InputStreamReader.$new.overload('java.io.InputStream', 'java.lang.String')(inputStream, 'UTF-8');

      // Create a new BufferedReader object
      var BufferedReader_instance = BufferedReader.$new.overload('java.io.Reader')(inputStreamReader);


	var line = "";
	while ((line = BufferedReader_instance.readLine()) != null) {
  	    request += line;
	}
 
	// Print out the request body
	console.log("[+] Request body: " + request);
 
	// Modify the request
	if (requestMethod == "POST") {
  	    var modifiedRequest = "param1=value1&param2=value2";
  	    console.log("[+] Modifying request body to: " + modifiedRequest);
  	    // Get the OutputStreamWriter constructor
          var OutputStreamWriter = Java.use('java.io.OutputStreamWriter');

          // Get the Charset and StandardCharsets classes
          var Charset = Java.use('java.nio.charset.Charset');
          var StandardCharsets = Java.use('java.nio.charset.StandardCharsets');

          // Get the OutputStream object
          var outputStream = this.getOutputStream();

          // Get the UTF-8 Charset object
          var utf8Charset = StandardCharsets.UTF_8;

          // Create a new OutputStreamWriter object
          var outputStreamWriter = OutputStreamWriter.$new.overload('java.io.OutputStream', 'java.nio.charset.Charset')(outputStream, utf8Charset);
          outputStreamWriter.write(modifiedRequest);
  	    outputStreamWriter.flush();
  	    outputStreamWriter.close();
	}
 
	return outputStream;
  };
 
  // Intercept the response
  HttpURLConnection.getInputStream.implementation = function() {
	var inputStream = this.getInputStream();
 
	// Read the response body
	var response = "";
	// Get the InputStream object
      var inputStream = this.getInputStream();

      // Create a new InputStreamReader object
      var inputStreamReader = InputStreamReader.$new.overload('java.io.InputStream', 'java.lang.String')(inputStream, 'UTF-8');

      // Create a new BufferedReader object
      var BufferedReader_instance = BufferedReader.$new.overload('java.io.Reader')(inputStreamReader);
	var line = "";
	while ((line = BufferedReader_instance.readLine()) != null) {
  	response += line;
	}
 
	// Print out the response body
	console.log("[+] Response body: " + response);
 
	return inputStream;
  };
});

This script intercepts HTTP requests and application responses and displays information about them, including:

  • Request method
  • URL
  • Request body
  • Response body

It also demonstrates how to use Frida to modify the request body before it is sent to the server. By intercepting network traffic in this way, security researchers can analyze how an application communicates with its backend servers, identify vulnerabilities and potential attack vectors, and develop exploits to take advantage of them. 

When combined with SSL pinning bypass mechanisms, Frida can also allow developers to manipulate traffic in addition to intercepting it.

Tracing system calls

Identifying malware behavior is an essential task in security research. Developers can use Frida for this task.

One approach to identifying malware behavior is to use Frida to trace system calls made by the application. System calls are the mechanisms by which applications interact with the operating system. By tracing these calls, security specialists or researchers can gain insights into the application’s behavior and identify potential vulnerabilities.

Another approach is to use Frida to trace the application’s interactions with the file system and other resources. By monitoring file system activity, researchers can identify any suspicious files or directories that an application may create or access.

Here’s an example of the script we created to trace system calls made by an application using Frida:

JavaScript
function WhoCalledMe(instance, amount) {
      var Thread = Java.use('java.lang.Thread')
      var threadinstance = Thread.$new()
      var stack = threadinstance.currentThread().getStackTrace()

      var stackClassNames = stack.map(function(x){return x.getClassName()})
      var index = stackClassNames.indexOf(instance.$className)
      if (index === -1) {
        console.log('failed to find calling class in the stacktrace: ' + stack + '\n class: ' + instance.$className)
        return
      }
      return stackClassNames.slice(index + 1, index + 1 + amount)
}

This script creates a new thread using java.lang.Thread and prints the number (based on the amount value) of class names from the call stack.

Depending on your needs, you can customize this script for tasks related to method call tracing, debugging, or profiling in a Java application.

Conclusion

Dynamic analysis plays a crucial role in identifying vulnerabilities in applications, as it allows you to look into your software’s inner workings.

In this article, we’ve discussed the powerful dynamic analysis tool Frida and its various use cases in security research and reverse engineering of desktop and mobile applications. 

If you’re looking for ways to protect your web, desktop, or mobile application from security threats, our cybersecurity team will be happy to assist you in creating a bulletproof security strategy and choosing tools that will best suit your needs. 

Ready to deliver a protected and competitive solution?

Detect and fix all security issues by leveraging the power of dynamic analysis and reverse engineering services from Apriorit.

Tell us about your project

Send us a request for proposal! We’ll get back to you with details and estimations.

By clicking Send you give consent to processing your data

Book an Exploratory Call

Do not have any specific task for us in mind but our skills seem interesting?

Get a quick Apriorit intro to better understand our team capabilities.

Book time slot

Contact us