The HelloKitty ransomware group, like other ransomware gangs, implements a double extortion model, stealing sensitive documents from victims before encrypting them.
Then, the threat actors threaten to leak the stolen data to force the victim into paying the ransom.
The ransomware samples seem to evolve quickly and frequently, with different versions making use of the .crypted or .kitty file extensions for encrypted files.
Some newer samples make use of a Golang packer that ensures the final ransomware code is only loaded in memory, most likely to evade detection by security solutions.
Some notes on using libntruencrypt.

Providing a source of randomness
================================
libntruencrypt needs a cryptographically secure source of random bits!
The library contains an internal deterministic random bit generator (DRBG) that can be used to whiten an external random bit source that is of low entropy. However, if a source of cryptographically random bits is available (such as /dev/urandom on Linux) it can be used directly without whitening.
The mechanism is selected by calling one of two instantiation functions:
DRBG_HANDLE handle;
ntru_crypto_drbg_instantiate(…, &handle); /* HMAC based DRBG */
–or–
ntru_crypto_drbg_external_instantiate(…, &handle); /* External Source */
The later interface is substantially simpler, and is preferable on most
platforms. The following two sections describe how to use the interfaces.
Regardless of the instantiation method, a DRBG handle is destroyed by calling
ntru_crypto_drbg_uninstantiate(&handle);
Note: If you use NTRU for quantum resistance and use an external DRBG, make sure it is instantiated with sufficient entropy! For security of k bits you should instantiate your DRBG with 2*k bits of entropy from the external source. The internal DRBG does this for you.
HMAC-DRBG
=========
One of the inputs to ntru_crypto_drbg_instantiate is an ENTROPY_FN. If you use the internal HMAC-DRBG it is imperative that you write your entropy function correctly. ENTROPY_FN is typedef’d as
typedef uint8_t (*ENTROPY_FN)(ENTROPY_CMD cmd, uint8_t *out);
and an ENTROPY_CMD is one of
INIT,
GET_NUM_BYTES_PER_BYTE_OF_ENTROPY
GET_BYTE_OF_ENTROPY.
On input INIT your entropy function must perform any initialization of your external source that is necessary and return 1 on success or 0 on failure.
On GET_NUM_BYTES_PER_BYTE_OF_ENTROPY your entropy function must output (by setting `out’) a value between 1 and 8 representing the entropy of your random source. A value of k indicates that the one cryptographically random byte can be extracted from k bytes of output from your source. For instance an output of 1 indicates that the source is perfectly random, and an output of 8 indicates that you can only extract one bit of randomness from each byte of your source’s output. Your entropy function should return 1 indicating success.
On GET_BYTE_OF_ENTROPY your function must put one byte of output from your random source in `out’ and return 1 on success, 0 on failure.
Example: Suppose your platform provides a getrandombyte functio int getrandombyte(void *out);
that outputs 1 perfectly random byte at out and returns 0 on success. The following is a reasonable ENTROPY_FN:
uint8_t
get_entropy(
ENTROPY_CMD cmd,
uint8_t *out)
{
if (cmd == INIT)
return 1;
if (out == NULL)
return 0;
if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY)
{
*out = 1;
return 1;
}
if (cmd == GET_BYTE_OF_ENTROPY)
{
if(0 == getrandombyte(out))
return 1;
}
return 0;
}
To use your get_entropy function:
uint32_t rc;
DRBG_HANDLE handle;
uint32_t sec_strength = 256;
rc = ntru_crypto_drbg_instantiate(sec_strength, NULL, 0,
&get_entropy, &handle);
if(rc != DRBG_RESULT(DRBG_OK))
{ … }
The internal HMAC-DRBG is seeded with 3/2 * sec_strength * k bits of input
from get_entropy where k is the value returned by
get_entropy(GET_NUM_BYTES_PER…).
The maximum value of sec_strength is 256.
The second and third arguments are for specifying an optional
‘personalization string’ of up to 32 bytes of non-secret data that are to be
used in conjunction with the entropy source to seed the DRBG (see NIST SP
900-80A for details).
External random sources
=======================
If you trust an external random source, for example because you are using
libntruencrypt inside of a larger crypto suite that provides a random source,
then you can use that source directly.
One of the inputs to ntru_crypto_drbg_external_instantiate is a pointer to
a RANDOM_BYTES_FN, typedef’d as
typedef uint32_t (*RANDOM_BYTES_FN)(uint8_t *out, uint32_t num_bytes);
To use an external random source you simply wrap it in an RANDOM_BYTES_FN.
Example: Suppose your platform provides a getrandom function
int getrandom(void *buf, size_t buflen);
that accepts a buflen between 1 and 256 and returns either the number of
bytes output or -1 on failure.
#include “ntru_crypto_drbg.h”
…
uint32_t randombytes(uint8_t *out, uint32_t num_bytes)
{
size_t i;
while(num_bytes > 0)
{
if(num_bytes > 256) {
i = 256;
} else {
i = num_bytes;
}
i = getrandom(out, i);
if(i == -1)
DRBG_RET(DRBG_ENTROPY_FAIL);
num_bytes -= i;
out += i;
}
DRBG_RET(DRBG_OK);
}
Note the use of DRBG_RET. This is required.
To use your randombytes function:
uint32_t rc;
DRBG_HANDLE handle;
rc = ntru_crypto_drbg_external_instantiate(&randombytesfn, &handle);
if(rc != DRBG_RESULT(DRBG_OK))
{ … }
Parameter sets
==============
libntruencrypt provides all of the NTRUEncrypt parameter sets defined in the
IEEE 1363.1 standard — a superset of those defined in X9.98. In the table
below the line labeled Product contains the parameter sets that are unique to
1363.1. These parameter sets are also faster and more compact than the other
sets in their respective columns, and these sets are preferable unless X9.98
compatibility is required. The column headers denote estimated bit security.
112 128 192 256
Product NTRU_EES401EP2 NTRU_EES439EP1 NTRU_EES593EP1 NTRU_EES743EP1
Size NTRU_EES401EP1 NTRU_EES449EP1 NTRU_EES677EP1 NTRU_EES1087EP2
Balanced NTRU_EES541EP1 NTRU_EES613EP1 NTRU_EES887EP1 NTRU_EES1171EP1
Speed NTRU_EES659EP1 NTRU_EES761EP1 NTRU_EES1087EP1 NTRU_EES1499EP1
Cryptographic functions
=======================
All of the cryptographic functions support two calling mechanisms. One to
obtain the lengths of any buffers that need to be allocated before performing
the operation, and a second to actually perform the operation
The DRBG inputs to keygen and encrypt are ignored when getting the buffer
lengths, and the DRBG need not be initialized at that time.
Keygen
NULL public_key requests public_key_len, NULL private_key requests
private_key_len. drbg argument is ignored.
Example:
/* Get public/private key buffer sizes */
rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2,
&public_key_len, NULL,
&private_key_len, NULL);
if(rc != NTRU_RESULT(NTRU_OK)) {…}
/* Allocate memory for keys */
…
/* Perform the key generation */
rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2,
&public_key_len, public_key,
&private_key_len, private_key);
if(rc != NTRU_RESULT(NTRU_OK)) {…}
Encrypt
NULL ciphertext requests length, drbg, plaintext_len and plaintext arguments
are ignored.
Example:
/* Get the ciphertext buffer size */
rc = ntru_crypto_ntru_encrypt(drbg, public_key_len, public_key,
0, NULL,
&ciphertext_len, NULL);
if(rc != NTRU_RESULT(NTRU_OK)) {…}
/* Allocate memory for ciphertext */
…
/* Perform the encryption */
rc = ntru_crypto_ntru_encrypt(drbg, public_key_len, public_key,
message_len, message,
&ciphertext_len, ciphertext);
if(rc != NTRU_RESULT(NTRU_OK)) {…}
Decrypt
NULL plaintext requests length, ciphertext_len and ciphertext arguments
are ignored.
Example:
/* Get maximum plaintext length */
rc = ntru_crypto_ntru_decrypt(private_key_len, private_key,
0, NULL,
&max_msg_len, NULL);
/* Allocate memory for plaintext */
…
/* Perform the encryption.
* Note that plaintext_len will contain the actual output length
* on success
*/
rc = ntru_crypto_ntru_decrypt(private_key_len, private_key,
ciphertext_len, ciphertext,
&plaintext_len, plaintext);
if(rc != NTRU_RESULT(NTRU_OK)) {…}
pw:xss.is

You must be logged in to post a comment.