Summary
Pegasus is a spyware developed by the NSO group that was repeatedly analyzed by Amnesty International and CitizenLab. In this article, we dissect the Android version that was initially analyzed by Lookout in this paper, and we recommend reading it along with this post. During our research about Pegasus for Android, we’ve found out that vendors wrongly attributed some undocumented APK files to Pegasus, as highlighted by a researcher here. We’ve splitted the analysis into 3 parts because of the code’s complexity and length. We’ve also tried to keep the sections name proposed by Lookout whenever it was possible so that anybody could follow the two approaches more easily. In this last part, we’re presenting the WAP Push messages that could be used to autoload content on the phone without user interaction, the C2 communication over the MQTT protocol, the exploitation of a vulnerability in MediaPlayer that was not disclosed before, and the ability of the spyware to track phone’s locations. You can consult the second part of the Pegasus analysis here.
Analyst: @GeeksCyber
Technical analysis
SHA256: ade8bef0ac29fa363fc9afd958af0074478aef650adeb0318517b48bd996d5d5
Pegasus initialization
The agent extracts the Android version, a string that uniquely identifies the build, and tries to retrieve a configuration value called “isItFirstRunEver” that indicates if this is the first run of the malware:
The process verifies whether the “/data/data/com.network.android” directory exists on the device; otherwise, it is created. The existence of the directory means that this is not the first execution of the malware, and the “isItFirstRunEver” value is set to false using the putBoolean function:
It checks the existence of the malicious APK file on the phone and will use the superuser binary called “/system/csk” to run commands with root privileges:
A check for an antidote file called “/sdcard/MemosForNotes” is performed, and the spyware removes itself if this file is found (see figure 4).
The agent calls multiple functions that steal information from the targeted applications, as shown in the figure below.
A value called “screen_off_timeout”, which represents the number of milliseconds before the device goes to sleep or begins to dream after inactivity, is extracted by the process and is compared with 15 seconds. Other configuration values such as “wasPhoneWasUnmutedAfterTapNicly” [sic], “originalVibrateValue”, and “originalRingerValue” are also extracted from configuration:
WAP Push Messages
The process logs a message that indicates a change in the WAP settings:
It retrieves the file permissions of “/data/data/com.android.mms/shared_prefs/com.android.mms_preferences.xml” and changes them using the chmod command:
The LD_LIBRARY_PATH environment variable is modified, and the above file’s permissions are set to read & write (0666):
The agent changes the WAP settings to enable push messages, as highlighted in the figure below.
The malware verifies if the Build.FINGERPRINT value contains “JPKJ2”, and it stops the Messages app:
The superuser binary called “/system/csk” is expected to be found on the phone (see figure 14).
The malicious process checks for the existence of the SMS/MMS database at “/data/data/com.android.providers.telephony/databases/mmssms.db”:
The permissions of the “mmssms.db”, “mmssms.db-shm”, and “mmssms.db-wal” databases are changed to 0777 (read, write, & execute for owner, group and others):
The agent opens one of the above databases and runs the following SQL query via a function call to rawQuery:
The index of the “href”, “_id”, “read”, “seen”, and “thread_id” columns is extracted:
The spyware tries to delete some WAP push messages that could be used to automatically open a link in a browser on the phone without user interaction:
The WAP messages are deleted by calling the SQLiteDatabase.delete method:
Message Queue Telemetry Transport (MQTT)
Another way to communicate with the command and control infrastructure is using the MQTT protocol.
The “should_use_mqtt” configuration value establishes whether the agent is allowed to communicate with the C2 servers via MQTT, as shown below:
Another config value called “mqttAllowedConnectionType” indicates if the phone is allowed to communicate via MQTT while it’s connected to Wi-Fi (value = 1), mobile data (value = 4), or when the device is roaming (value = 8):
The malware retrieves connection status information about all network types via a function call to getAllNetworkInfo and compares the type of the network with “WIFI” and “MOBILE”:
The isNetworkRoaming function is utilized to verify whether the phone is roaming:
The application extracts the current date and ensures that the token id found in the configuration is not null:
The following values are obtained from the configuration:
- mqttIdPref – identify a client in combination with the username
- mqttQos – quality of service for MQTT connections
- mqttHost – attacker’s MQTT host
- mqttPort – MQTT port number
The “mqttUsername” config value represents the username used during the authentication with the MQTT server, and the “mqttPassword” value is the password used during the authentication process:
The malware logs a message containing the MQTT URL, username, and password and then calls a function that will start the communication:
The MQTT broker URL is constructed by the malicious process:
The “mqttKaTimer” configuration value represents the MQTT keep alive timer (see figure 35).
Finally, the process makes network connections with the attacker’s infrastructure over MQTT and compares the broker URL with “tcp://”, “ssl://”, and “local://”:
The maximum number of reconnection attempts is stored in a configuration value called “mqttRecCount”:
The agent tries to subscribe to an MQTT topic specified in the configuration, as highlighted in figure 39.
The application logs multiple messages that indicate the successful connection and the subscription to the topic:
The NetworkInfo.isConnected method is used to verify whether there is an active internet connection on the device:
The binary receives the messages from within the topic on the broker that contain commands to be executed:
All commands are added to a queue as we already described in part 2:
The parameter “s=” contains a checksum that will be checked against another computed value in order to confirm that the command was transmitted by the threat actor:
The command transmitted via MQTT contains a token value that identifies the infected device, as displayed in the figure below.
The command will not be executed if the checksums don’t match:
The commands received via SMS that we already described here can be also transmitted using the MQTT protocol:
Email attachments
The emailAttCmd command can be used to retrieve emails and attachments from the EmailProviderBody.db database:
Download files
The malware has the ability to download additional files/packages from a remote URL (see figure 50).
The process opens a connection to a specific URL using the openConnection function and sets the read timeout to 120s and the connect timeout to 1800s:
The response body is read by calling the URLConnection.getInputStream and BufferedInputStream.read functions:
A file is populated with the buffer downloaded from the remote URL via a call to FileOutputStream.write:
Vulnerability exploitation in MediaPlayer
To the best of our knowledge, this is the first mention that Pegasus for Android exploited a vulnerability in MediaPlayer. Unfortunately, the file responsible for exploitation called “/data/data/com.network.android/output.mp3” is empty, and we couldn’t retrieve its content:
The MP3 file is populated at runtime using the FileOutputStream.write function. The file’s permissions are set to 511 by the malware:
The setDataSource method is utilized to set the data source for MediaPlayer. The application prepares and starts the playback, which we believe would result in exploiting a vulnerability:
Track phone’s location
Pegasus spyware has the ability to monitor the device’s location. It verifies if the GPS provider is active by calling the isProviderEnabled function and then obtains location information using the requestLocationUpdates function:
The location is stored in an XMLSerializer object containing the latitude, the longitude, the altitude of the location, the estimated horizontal accuracy radius, and the speed at the time of the location:
The process retrieves the current location of the device via a call to getCellLocation and the numeric name (MCC+MNC) of the current registered operator using getNetworkOperator. The GSM cell id and the GSM location area code are also stored in the XMLSerializer object:
Other relevant activities
The agent compares the Android version with 2.3 and then the phone model with a list, as shown below:
As we already described in part 1, the malware has the capability to upgrade itself:
The application obtains the serial number of the SIM and extracts the “local” configuration value:
The “NetworkWindowSim” config value is extracted and compared with the value described above. If these two values don’t match, it means that the SIM was changed, and the config value is changed accordingly (see figure 68).
The spyware verifies if the “/data/reinslock” file exists on the device, which indicates that the application was reinstalled:
As we’ve seen during the entire analysis, the threat actor didn’t make any efforts to hide the true purpose of the APK. Figure 70 reveals the message stating that Pegasus was successfully initialized:
This concludes our 3-part analysis of Pegasus for Android. We believe that some of the functionalities presented here are also used by recent malware families, and our analysis might represent the first step in detecting them.
Wonderful!