Next Generation Malware Delivery & Covert Communications

Download as pdf or txt
Download as pdf or txt
You are on page 1of 12

Next Generation Malware Delivery &

Covert Communications

Chef
Introduction
This paper is based on an idea that I thought of randomly one day while writing VX code. There
has been a saturation in the VX scene where techniques have been reused over and over again.
This goes for the same with code reuse (thanks github). However, I don’t want to count out the
real ones. you know who you are. The overall goal of the implant is to silently implant on the
system and enable a trust. Almost 99% of encrypted samples revolve around the same generic
ones we have seen for years (RSA, AES, TwoFish, XoR, ext.). In recent years there has been a
new campaign to establish a quantum proof encryption. We are in a new age of technology
where we have quantum based computers. The fastest quantum computer being 53 Qubits. NIST
created a Call for Proposal which would allow 26 different methods.

Disclaimer
The PoC has been redacted due to the possible risk it would introduce to organizations and
systems. This will require the engineering to take the time to program and piece together to code.
I am more than open to questions to help along the way with the development should someone
be interested enough. Should you want to review any source code please direct message me for
verification.
I am proposing a unique method that can be utilized by any offensive operation that has time &
resources. What do I mean by time? Well, let’s say 2 months minimum. This is counting
development, controlled testing, and preparation, and deployment. Obviously you can use this on
penetration tests thought so don’t count that out. It will take a bit of time to get a generalized
understanding of how to really interface with these separate technologies. However, I will do my
best to explain everything as simple as possible.
The idea is to create a malware that will bind to the system creating a trust that will allow for
technologies to be delivered with ease and bypass anti-virus solutions during scan time & run
time. We all know they will get caught eventually no matter how you change the strings, calls, or
dynamic implementation. It should be noted that this is not going to make your malware FUD.
It’s up to you as the offensive engineer to encrypt, morph, or pack the sample.
I propose a method of delivery and infection that will require a couple of things
- Key Pair
- Device Unique Identifier
- Covert Channel of Communication
We can accomplish this by using the following solutions
- NTRU + SIDH (ECDSA)
- Unique Hash Based on System
- LibZMQ (Binary Protocol)
Now we are left with a simple question. We are left with a couple of questions
- What are these solutions?
- How do they work?
NTRU
The NTRU public key cryptosystem is a lattice-based alternative to RSA and ECC and is based
on the shortest vector problem in a lattice. Since both encryption and decryption use only simple
polynomial multiplication., these operations are very fast compared to other asymmetric
encryption schemes. NTRU consists of three components:
- NTRUEncrypt public key encryption
- NTRUMLS digital signature scheme
- PASS digital signature scheme
Resource
https://medium.com/tixlcurrency/the-essence-of-ntru-key-generation-encryption-decryption-
7c0540ef8441
https://assets.onboardsecurity.com/static/downloads/NTRU/resources/NTRU-PKCS-Tutorial.pdf

SIDH
SIDH is used to establish a secret key between two parties over an otherwise insecure
communication channel. It is analogous to the Diffie-Hellman key exchange, but is based on
walks in a super singular isogeny graph and is designed to resist to quantum based attacks. SIDH
distinguishes itself from similar systems such as NTRU and Ring-LEW by support perfect
forward secrecy. We want to use this encryption schema to avoid any form of replay attacks and
provide perfect forward secrecy.
Resource
https://eprint.iacr.org/2018/267.pdf

LibZMQ
ZeroMQ looks like an embeddable networking library but acts like a concurrency framework. It
gives you sockets that carry atomic messages across various transports like in-process, inter-
process, TCP, and multicast. You can connect sockets N-to-N with patterns like fan-out, pub-
sub, task distribution, and request-reply. Its asynchronous I/O model gives you scalable
multicore applications, built as asynchronous message-processing tasks. ZMQ comes with 5
basic patterns
- Exclusive Pair
- Publish/Subscribe
- Push/Pull
- Asynchronous Request/Response
- Synchronous Request/Response
When setting up a server/client communication you will need to create a context. Contexts help
manage sockets that are created as well as the number of threads ZMQ utilizes. Create one when
you initialize a process and destroy it as the process is terminated. Keep in mind that contexts
can also be shared between threads. These sockets can recognized as thread safe
- ZMQ_CLIENT
- ZMQ_SERVER
- ZMQ_DISH
- ZMQ_RADIO
- ZMQ_SCATTER
- ZMQ_GATHER
ZMQ offers different connections
- ipc (only available on Linux)
- inproc
- tcp
- epgm, pgm
- tcp
Below is an image representing the communication vectors possible.

Code Examples
TCP
Local Address to a socket
/* Assign the in-process name "#1" */
rc = zmq_bind(socket, "inproc://#1");
assert (rc == 0);
/* Assign the in-process name "my-endpoint" */
rc = zmq_bind(socket, "inproc://my-endpoint"); assert (rc == 0);

Connecting a socket
Connecting using an IP address
rc = zmq_connect(socket, "tcp://192.168.1.1:5555");
assert (rc == 0);
/* Connecting using a DNS name */
rc = zmq_connect(socket, "tcp://server1:5555"); assert (rc == 0);

Inproc
Assign the in-process name "#1"
rc = zmq_bind(socket, "inproc://#1");
assert (rc == 0);
/* Assign the in-process name "my-endpoint" */
rc = zmq_bind(socket, "inproc://my-endpoint"); assert (rc == 0);

Connect to the in-process name "#1"


rc = zmq_connect(socket, "inproc://#1");
assert (rc == 0);
/* Connect to the in-process name "my-endpoint" */
rc = zmq_connect(socket, "inproc://my-endpoint"); assert (rc == 0);

PGM
Connecting to the multicast address 239.192.1.1, port 5555,
using the first Ethernet network interface on Linux
and the Encapsulated PGM protocol
rc = zmq_connect(socket, "epgm://eth0;239.192.1.1:5555");
assert (rc == 0);
/* Connecting to the multicast address 239.192.1.1, port 5555, */
/* using the network interface with the address 192.168.1.1 */
/* and the standard PGM protocol */
rc = zmq_connect(socket, "pgm://192.168.1.1;239.192.1.1:5555"); assert (rc == 0);

IPC
Assign the pathname "/tmp/feeds/0"
rc = zmq_bind(socket, "ipc:///tmp/feeds/0"); assert (rc == 0);

Connect to the pathname "/tmp/feeds/0"


rc = zmq_connect(socket, "ipc:///tmp/feeds/0"); assert (rc == 0);

The code listed above shows a representation of how to utilize ZMQ in different ways. The
actual code is pretty simple to set-up.
How Does It Work?
Let’s start with the encryption schema, we want to create some form of Key Pair that we can use
to create a bounded trust between systems. An initial campaign will need to be conducted to
generate mass key-pairs with victims. This is done by utilizing NTRU for key pair generation
and SIDH for Perfect Forward Secrecy (PFS) and Elliptic Curve Digital Signature Algorithm
(ECDSA). We add Perfect Forward Secrecy, Elliptic Curve Digital Signature Algorithm, and
ZMQ to eliminate and possible replay attacks. Replay attacks occur when the analyst captures
the traffic and is able to resend the entire message and key together. In order to defeat this, we
need establish completely random session keys.
ZMQ is going to be the socket connection. We can attach a binary network protocol. Once
you’ve created the network transport layer you may create different channels with multiple
addresses. When utilizing channels, you may use “In-Proc://pipe” to distribute to these different
channels. When creating the encryption schema, you may also choose any extension you want
i.e. .xvr .fyu .loz. Last we need some way to identify the machine as that machine only. This can
be accomplished by creating a Device Unique Identifier. Once you obtain a DUID you then are
able to create a strong hash that will be your true Device Unique Identifier. When the initial
campaign is conducted we want to ensure that only that party can decrypt the payload. This is
done by using a unidirectional communication so once encrypted only the receiving party may
decrypt. This will ensure that third party researchers can’t reverse engineer the sample from “In
The Wild”. I believe that it should also be noted that this would better work for targeted attacks.
The server side will need some form of database to store the keys and device unique identifiers.
We can store the output into something like SQLite. However, if you are going to scale bigger
and have multiple operators then it would be wise to use something else. SQLite is very small
and portable. It doesn’t require any extra configuration since it’s a server-less installation and
also completed within a couple minutes. The ultimate goal is to create a uni-directional payload
delivery schema that will diminish attribution and keep the engineer anonymous.
You can see in the image above the database will store the keys and device unique identifier.
Once you have created this you are ready to conduct the campaign to send the implant. The
delivery would be conducted by sending the implant with a decryption routine. Once the implant
is decrypted you may continue with execution. Obviously it’s up to you as the engineer to create
the proper payload with precautions that will bypass anti-virus solutions.
Below is a visual representation of the uni-directional communication and covert channel
communication.

Break Down of Technologies


LibZMQ
LibZMQ is a C library for ZeroMQ. Keep in mind that there are multiple different languages
supported. ZMQ allows the programmer to send information from server to client (vice versa)
using sockets. If we were to integrate super singular isogeny key exchange (SIDH). This would
allow the attacker to deliver information through a unique network stream without the traffic
being decrypted or replay attacked, even with quantum technology.
LibZMQ also has no maximum size of information that can be sent, meaning 2688-bit key
exchanges should not be an issue. However, ZeroMQ will return an error of `ENOMEM` which
means “insufficient storage space is available”. This means that there was not enough space in
the heap to store the key temporarily. Smaller messages are stored within the stack, not the heap.
This error is highly unlikely to occur and should never become an issue.
So, the idea is to send data out into a pool of peers. However, only one of our peers will be able
to decrypt the content. There are two main options for this with ZeroMQ.
The ‘ROUTER’ socket talks to a set of peers and addresses the content to one specific peer.
However, it will drop the data if the peer is nonexistent or cannot establish a connection.
The ‘DEALER’ socket talks to all peers, the peers will hold the data until a new peer is found.
However, it will never drop and discard the content.
Which means `ROUTER` sockets will inform every peer who we are sending the data too and
the `DEALER` content will not specify who we are sending it too, but will sync all data to every
peer.
My opinion would be to use the `ROUTER` socket, because if our content is encrypted. The
network can know who we are sending the data too, but not what we are sending. Which is better
than syncing the encrypted data to every peer. If we also use super singular isogeny key
exchange (SIDH) as mentioned before, we can send traffic through peers with it being quantum
resistant.
NTRU
NTRU has support for C, Python, and Java. The NTRU Public Key Cryptosystem uses a ring R
and two prime ideals p and q in R. Listed below is a screenshot of the key creation, encryption
and decryption. It would be too annoying to format the actual mathematical details. If you don’t
have any background information on encryption and algorithms, then it would be wise to do a
little bit of research on the topic to get a full understanding of what it’s doing and what relation it
plays to computers. There is a possibility of people utilizing dictionary attacks against NTRU.
Fujisaki-Okamoto transformations can be utilized to add padding. In a real world use-case FOT
isn’t feasible and very difficult to implement. You will be required to have an extensive
background in cryptography.

Resources
https://cs.uni-
paderborn.de/fileadmin/informatik/fg/cuk/Lehre/Abschlussarbeiten/Bachelorarbeiten/2014/BA_Lippert
_FOT_final.pdf
SIDH
Supersingulary Isogeny Deffie-Hellman is a form of post quantum deffie-hellman key exchange
with a non-abelian structure utilizing isogenies. I highly suggest you take the time to look into
what isogenies are and how they play into cryptography. There will be a resource below for you
to visit. I would also advise that you read up on RSA, Elliptic Curve, and Diffie-Hellman. SIDH
creates one of the smallest keys for quantum robustness. The perfect forward secrecy portion
stop the long term key from being compromised.
Resources
https://eprint.iacr.org/2019/1321.pdf

DUID
Device Unique Identifiers are extremely important in this scenario. The DUID is going to serve
as the identifier for the target system. When this is created we are ensuring that only that party
can decrypt the payload. There are numerous different techniques out there public, but they don’t
seem to fair very well. So when working with DUID its important to pick something that cannot
be defeated. Some methods being hooking, registry key changes, and mac address changing. In
this case it would be proper to include some kind of hashing that you can associate to the DUID
that is created from the operating system.
In regard to Linux I would suggest looking to http://www.nongnu.org/dmidecode/. Another
option would be to utilize HAL service.
“hal-get-property –udi /org/desktop/Hal/devices/computer –key system.hardware.uuid”
Now the windows portion is a little different. Windows prepared a feature that allows you to
collect DUID based on storage devices.
You can read the MDSN and header file here
https://docs.microsoft.com/en-us/windows-hardware/drivers/storage/device-unique-identifiers--
duids--for-storage-devices
Per MDSN the DUID is defined by a STORAGE_DEVICE_UNIQUE_IDENTIFIER structure
the first version of this structure includes a combination of the following identifiers:
STORAGE_DEVICE_ID_DESCRIPTOR

STORAGE_DEVICE_DESCRIPTOR

SOTRAGE_DEVICE_LAYOUT_SIGNATURE

They do have some limitations those are listed below


- DUIDs often contain binary contents that cannot be displayed
- DUIDs are not always null-terminated. DUID consumers must check the size member
of the STORAGE_DEVICE_LAYOUT_SIGNATURE structure to determine the
length of the DUID
- DUID consumers must use CompareStorageDuids to compare DUIDs instead of
comparing them byte by byte
- Enumerators must not attempt to use DUIDs to identify device objects for PnP
purposes. Multipath systems have more than one device that share the same DUID.
However, for PnP, device IDs must be unique.
Initiators can query for the DUID information data using a
IOCTL_STORAGE_QUERY_PROPERTY request with the property ID of
StorageDeviceUniqueProperty
There is a way to defeat the possible double DUID problem. You can compare DUIDs and see if
there is a match. Should there be no match then the final key DUID key will be established.

You might also like