The PingPull Trojan is written in Visual C++, it was used by threat actors to access a reverse shell and run arbitrary commands on compromised systems.
PingPull samples that use ICMP for C2 communications issue ICMP Echo Request (ping) packets to the C2 server. The C2 server will reply to these Echo requests with an Echo-Reply packet to issue commands to the system.”
PingPull Malware
PingPull was written in Visual C++ and provides a threat actor the ability to run commands and access a reverse shell on a compromised host. There are three variants of PingPull that are all functionally the same but use different protocols for communications with their C2: ICMP, HTTP(S) and raw TCP. In each of the variants, PingPull will create a custom string with the following structure that it will send to the C2 in all interactions, which analysts believe the C2 server will use to uniquely identify the compromised system:
PROJECT_[uppercase executable name]_[uppercase computer name]_[uppercase hexadecimal IP address]
Regardless of the variant, PingPull is capable of installing itself as a service with the following description:
Provides tunnel connectivity using IPv6 transition technologies (6to4, ISATAP, Port Proxy, and Teredo), and IP-HTTPS. If this service is stopped, the computer will not have the enhanced connectivity benefits that these technologies offer.
The description is the exact same as the legitimate iphlpsvc service, which PingPull purposefully attempts to mimic using Iph1psvc for the service name and IP He1per instead of IP Helper for the display name. Analysts have also seen a PingPull sample use this same service description but with a service name of Onedrive.
The three variants of PingPull have the same commands available within their command handlers.
PingPull would decrypt the received data and would parse the cleartext for the command and additional arguments in the following structure:
&[AES Key]=[command]&z0=[unknown]&z1=[argument 1]&z2=[argument 2]
Analysts are not sure of the purpose of the z0 parameter in the command string, as analysts observed PingPull parsing for this parameter but do not see the value being used. To confirm the structure of the command string, analysts used the following string when issuing commands in analysis environment, which would instruct PingPull to read the contents of a file at C:test.txt:
&P29456789A1234sS=C&z0=2&z1=c:\test.txt&z2=none
During analysis, PingPull would respond to the command string above with ya1JF03nUKLg9TkhDgwvx5MSFIoMPllw1zLMC0h4IwM=, which decodes to and decrypts (AES key P29456789A1234sS) to some text in a test file.x07x07x07x07x07x07x07, which is the content (PKCS5_PADDING-padded) of the file C:test.txt on analysis system.
ICMP Variant
PingPull samples that use ICMP for C2 communications issue ICMP Echo Request (ping) packets to the C2 server. The C2 server will reply to these Echo requests with an Echo Reply packet to issue commands to the system. Both the Echo Request and Echo Reply packets used by PingPull and its C2 server will have the same structure as follows:
[8-byte value]R[sequence number].[unique identifier string beginning with “PROJECT”]rntotal=[length of total message]rncurrent=[length of current message]rn[base64 encoded and AES encrypted data]
When issuing a beacon to its C2, PingPull will send an Echo Request packet to the C2 server with total and current set to 0 and will include no encoded and encrypted data.
After the R is a sequence number that increments when sending or receiving data that exceeds the maximum size of the ICMP data section. The sequence number is immediately followed by a period “.” and then the unique identifier string generated by PingPull that begins with PROJECT. The ICMP data section then includes total=[integer] and current=[integer], which are used by both PingPull and its C2 to determine the total length of the data transmitted and the length of the chunk of data transmitted in the current packet. The data transmitted in each ICMP packet comes in the form of a base64-encoded string of ciphertext generated using AES and the key specific to the sample. This encoded and encrypted data comes after the new line that immediately follows the “current” value. For instance, when responding to test command, PingPull sent the ICMP Echo Request packet to the C2 server, which has the expected base64-encoded string of ya1JF03nUKLg9TkhDgwvx5MSFIoMPllw1zLMC0h4IwM= for the results of the command.
HTTPS Variant
Another variant of PingPull uses HTTPS requests to communicate with its C2 server instead of ICMP. The initial beacon uses a POST request over this HTTPS channel, using the unique identifier string generated by PingPull as the URL.
The initial beacon is a POST request that did not have any data, which resulted in the Content-Length of 0 within the HTTP headers. When responding with the results to commands, PingPull will issue a second POST request using the same URL structure with the results in the data section in base64-encoded and encrypted form using the AES key.
TCP Variant
This variant of PingPull does not use ICMP or HTTPS for C2 communication, rather it uses raw TCP for its C2 communication. Much like the other C2 channels, the data sent in this beacon includes the unique identifier string generated by PingPull that begins with PROJECT. However, the TCP C2 channel begins with a 4-byte value for the length of data that follows, as seen in the following beacon structure:
[DWORD length of data that follows]PROJECT_[uppercase executable name]_[uppercase computer name]_[uppercase hexadecimal IP address].
The C2 response to the beacon begins with the data length of 64 bytes (0x40) followed by the base64-encoded string that represents the ciphertext of the command.
PingPull ran the command supplied by the C2 and sent the results in a packet that begins with a data length of 44 bytes (0x2c), followed by the expected base64-encoded string of ya1JF03nUKLg9TkhDgwvx5MSFIoMPllw1zLMC0h4IwM= for the results of the command.