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 second part, we’re presenting the HTTP communication with the C2 server, the commands received via SMS that were implemented by the spyware, the live audio surveillance functionality, and the keylogging activity. You can consult the first part of the Pegasus analysis here.
Analyst: @GeeksCyber
Technical analysis
SHA256: ade8bef0ac29fa363fc9afd958af0074478aef650adeb0318517b48bd996d5d5
Communication Methods
1. HTTP Communication
The agent constructs the following URL that contains the C2 server, which can be extracted from the initial configuration or a command sent via SMS:
The malware adds “SessionId1” and “SessionId2” to the HTTP headers:
Figure 3 reveals the following values:
- SessionId1 = f, which is the token stored on the phone
- SessionId2 = c, which is the AES key used to encrypt the files exfiltrated to the C2 server
- b – AES key that is used to encrypt the SessionId1 and SessionId2 fields
- a – AES IV that is used during the encryption of the SessionId1 and SessionId2 fields
The implementation of the AES algorithm is displayed in the figure below.
The template of the HTTP request is displayed in figure 5:
The HTTP response should be an XML file containing at least the following fields: “response”, “code”, and “message”. The application parses the XML response by overriding the startElement, endElement, and characters methods:
The agent verifies if the XML response contains the following main commands: “dumpCmd”, “upgrade”, “camCmd”, and “emailAttCmd” (those were described in part 1). In the case of the “upgrade” command, the threat actor must specify the URL to download the package from and others parameters (see figure 7).
The implementation of the overriding functions is shown below:
2. SMS/MMS/WAP
As in the case of the iOS version, the package can receive commands in SMS messages that are disguised as Google authentication codes. It searches for “your google verification code” in the message and extracts the index of the “s=” parameter:
The malware computes the MD5 hash of the Token + SMS[0, index+2), which is truncated to 8 bytes and compares it with SMS[index+2, final] in order to verify the authenticity of the command:
The command structure is “text:[6 digits][Command number]a=[Ack ID]&[Command Arguments]&s=<Message Signature>” and the following regular expression is used to parse it: “.*[:]\d{6}(\d)[\n]?(.*)”.
The following function is utilized to extract the fields from the command and to add it to a commands queue:
The agent verifies if the phone is Roaming via a function call to isNetworkRoaming:
If the device is Roaming and the “romingSetted” config value is disabled (0), the application can’t accept commands via HTTP, SMS, and MQTT:
The commands received via SMS will be described in the following paragraphs (numbers in range 0-8).
Command 0
The first command is “KILL” and can be used to perform self deletion on the phone:
The process sets the intent action to “KILL”, retrieves a PendingIntent that will perform a broadcast, and schedules an alarm, as displayed below.
The application creates a HandlerThread that will perform the necessary operations:
The getSubscriberId function is used to obtain the unique subscriber ID, and the deletion operation continues. A detailed explanation regarding this operation can be found in the 1st part of the Pegasus analysis – Suicide functionality section.
Command 1
This command is used to send a “Ping” message via SMS or HTTP. Depending on the value received in the parameters (“0” or “1”), the spyware chooses between the two communication channels:
The Ack ID received in the command and a counter value will be part of the SMS message that is sent:
The process logs the phone number to send messages to, the Ack ID, and the counter. It computes the time after the last network communication with C2 in seconds:
In the case of HTTP communication, the agent creates a Handler object and calls the postDelayed function with a delay of 5 seconds:
The malware creates an XmlSerializer object that will be encrypted using the AES algorithm and then sent to a C2 server via HTTP. Finally, it checks if the data was successfully sent:
Command 2
In this case, the process tries to compute the index of “&” in the arguments. The resulting two values will be used to modify the “adrate” and “adlocation” configuration options:
For example, if the “adrate” value is set to 0 then the malware stops the location monitoring functionality. However, if the “adlocation” value is 0 or “adrate” < “adlocation” then the malware starts the functionality:
When stopping the location monitoring functionality, the process sets the intent action to “finishLocationMonitor” and calls the cancel method:
The getSystemService function is utilized to retrieve a handle to the location service. The agent receives data about the location from the network and passive providers (see figure 29).
Command 3
The process configures the following config options:
- “WindowTargetSms” – SMS number used in the outbound communication
- “Skypi” – Phone number used to trigger the live audio surveillance functionality
- “NetworkWindowAddresess”
The entire list of config options that can be set using this command is presented at the end of the Lookout’s paper.
Command 4
The application obtains the index of “&” in the arguments and creates two values representing the camera snapshot number and time, as shown in figure 31.
The snapshot source type and the phone camera resolution are logged using the Log.i method:
The agent tries to take a snapshot of the screen using a binary called “/system/bin/screencap”. The photo is saved at “/data/data/com.network.android/bqul4.dat”. A deep dive into the screenshot functionality can be found in the 1st part of the Pegasus analysis.
Command 5
In this case, the malware specifies a file or a directory listing to be exfiltrated. This information can be transmitted in the “f=” and “p=” parameters:
The process changes permissions to 777 for the targeted file using the “superuser binary”. It verifies the existence of the file by calling the File.exists method and expects a non-empty file:
The application creates a directory called “/data/data/com.network.android/chnkr/” using the File.mkdirs function. The targeted file is copied to the newly created folder, and the malware broadcasts the “new_chunker_file_event” intent to all BroadcastReceivers in order to exfiltrate data:
Command 6
This command prepares the phone to accept an audio surveillance call that will be detailed in the “Live Audio Surveillance” section.
Command 7
The package enables the call recording functionality by setting the “window canada” config value to true:
Command 8
The agent extracts the configured C2 servers and sends a request to one of them in order to ask for new commands, as shown in the figure below.
It sets the intent action to “httpPing”, the intent data to “PING: <Current time in milliseconds>”, retrieves a PendingIntent that will perform a broadcast, and schedules an alarm:
Outbound SMS
The malware logs the message “MO sendSmsMO Ping SMS MO Start to number: ” + WindowTargetSms, which is the phone number used in the outbound communication:
The agent extracts the following information: the current location of the device, the numeric name (MCC+MNC) of the registered operator, the GSM cell ID, the GSM location area code, the IMEI and IMSI of the device (see figure 43).
The application obtains the unique subscriber ID that is validated based on its length:
SmsManager.getDefault is utilized to retrieve the SmsManager. The process creates two Intents with the “SMS_SENT” and “SMS_DELIVERED” parameters and then broadcasts them via a call to getBroadcast. Finally, the SMS containing the information extracted above is sent using sentTextMessage:
The getResultCode method is used to verify if the message was successfully sent. If that’s not the case, the SMS is re-sent in 1 minute:
The application logs the number of times it re-sent the SMS using the Log.i method:
Live Audio Surveillance
The threat actor can enable this functionality only when multiple conditions are met at the same time. The functionality can be activated when the phone receives a call from the attacker’s number, and it will allow capturing the audio via the device’s microphone.
The first condition to be met is that the phone’s screen is OFF, which is verified using a variable that should be false. The malware verifies if the screen is ON or OFF by calling the isScreenOn method. The configuration option called “Skypi” should be not null:
The process makes sure that the user didn’t cancel the previous live surveillance operation, as displayed in the figure below.
The phone should be in the idle state, and the phone’s screen should be locked. The inKeyguardRestrictedInputMode function is used to verify the last condition:
The configuration option called “forwarding” indicates whether call forwarding is enabled on the phone. This feature should be disabled for the functionality to work:
The agent extracts the value of the “STAY_ON_WHILE_PLUGGED_IN” constant. It expects the device to stay off even if it’s charging:
The microphone should not be in use for the functionality to work:
isWiredHeadsetOn is utilized to confirm that a wired headset is not connected to the phone:
isBluetoothA2dpOn is utilized to confirm that a Bluetooth A2DP audio peripheral is not connected to the phone:
The spyware doesn’t expect communications to use Bluetooth SCO at the time of the audio surveillance. It calls the isBluetoothScoOn method for this purpose:
The music should not be active during the time of the operation, as highlighted below:
The final condition that must be met is that either the phone is not Roaming or the functionality was configured by the TA to be performed even if the device is Roaming:
Now we’ll describe the functionality after all of the above conditions are met.
Audio recording
The application creates a MediaRecorder object that can be used to record audio and video:
The agent sets the audio mode to 2 (MODE_IN_CALL – a call is established), calls the setStreamSolo function with a True parameter, sets the audio source to be used depending on the phone’s build model, sets the format of the output file to 2 (MPEG4 media file format), and sets the audio encoder to 1 (AMR_NB – narrowband audio codec):
The directory “/data/data/com.network.android/network_cache/” is created by the spyware:
The output file is “/data/data/com.network.android/network_cache/cache1.dat<Integer>”, and the recording is started by calling the prepare and start functions:
The audio files can be exfiltrated by incorporating them into XML files, as displayed in the figure below.
Phone Calls
The following columns can be extracted from the Call logs: “number”, “type”, “date”, “duration”, “_id”, and “logtype” (see figure 72).
The agent implements a different functionality for calls coming from these two numbers: “*762646466” and “*7626464633”. If the phone receives a call from the first number/second number, then the “romingSetted” configuration option is set to true/false. This option controls how the phone communicates with the C2 server (via SMS, HTTP, MQTT) when it’s Roaming:
Keylogging
As we’ve already seen, the spyware logs relevant messages regarding the activities performed:
The malware expects to find the “superuser binary” called “/system/csk” on the device:
The files containing the keystrokes will be stored in the “/data/local/tmp/ktmu” folder. The content of these files will be exfiltrated using XmlSerializer objects with specific tags:
The application tries to identify the process ID of the keyboard process:
It extracts the process ID for the input method service that is currently selected from the “default_input_method” value. The getRunningAppProcesses function is utilized to obtain a list of running processes on the phone, and then the spyware extracts the process ID and name of the keyboard process:
The libk binary found in the “/res/raw” directory is copied to a new file called “/data/local/tmp/libuml.so”. The shared object is injected (using the addk binary) in the keyboard process identified above and will be responsible for the keylogging activity:
The captured keystrokes will be stored in a file called “/data/local/tmp/ktmu/ulmndd.tmp”, as shown in figure 83.
The agent stores the bitwise NOT of every keystroke in the file using the fwrite instruction:
The temporary file storing the captured keystrokes is renamed as “/data/local/tmp/ktmu/finidk.<current timestamp>”. The current timestamp is obtained using the time syscall:
Great content.