# Отчёт о киберугрозе АСД-С:2023-00007 (SmallWorm)
## Общее описание
SmallWorm - сетевой червь, заражающий сетевые маршрутизаторы посредством уязвимости АСД-А:2023-00002
Когда червь попадает на устройство, он начинает атаку по следующему алгоритму:
1. Взламывает устройства в сети (не перемещаясь на них) -- считывает данные взломанного устройства, затем уничтожает его. Данные, считанные со взломанного устройства добавляются к данным текущего.
2. Шифрует данные текущего устройства [(xor-шифрованием)](#xor-шифрование), оставляя на машине вместе с зашифрованными данными 4-байтный хеш ключа шифрования
3. Перемещается на новое устройство, запоминая на нём ключ, которым зашифрованы данные, и подсеть, из которой пришёл [(адрес и маска подсети)](#подсети)

## Форматы данных

### Формат-A
Когда червь переезжает на новое устройство, вместе с изначальными данными машины он хранит ключ шифрования данных предыдущего устройства; подсеть, из которой пришёл (адрес и маску подсети); и данные со взломанных машин, вместе с их IP адресами в формате-А.

### Формат-B
Перед переездом на новую машину, червь шифрует все данные на ней (то есть, после дешифровки мы получаем данные в формате A или C). Шифрование происходит 4-битным ключом, хеш которого сохраняется перед зашифрованными данными.
Хеширование происходит следующем алгоритмом, представленном в псевдокоде (все числа в бинарном формате находятся в little-endian):
```Rust
uint32 hash(uint32 key) {
int32 n = 12;
do
key = ((key >> 8) ^ key) * 0x6B + n;
while (--n != 0);
return key;
}
```
### Формат-C
Первое заражённое устройство не имеет предка, то есть, червю не требуется хранить ключ и маску подсети, из которой он пришёл. Помимо этого, с первой машины не происходит взлома других устройств, червь просто упаковывает данные машины в формат-C (то есть, добавляет перед данными 4 байта нулей), шифрует данные (в формат-B), и переезжает на новую машину.
Вероятно, 4-байтовая заглушка из нулей нужна чтобы после дешифровки данных нельзя было перепутать формат-А и C, т.к. формат-A начинается с 4-байтного ключа, который не может быть нулём.

## Справочные данные
### Подсети
В протоколе IP адрес устройства задаётся 32-битным числом, обычно записываемого по байтам, например `192.168.1.2` это число `3232235778`.
Адреса объединяются в подсети, задаваемые базовым адресом и маской подсети - количеством значащих бит в числе, например все адреса от `192.168.1.0` до `192.168.1.255` задаются маской `192.168.1.0/24`, это значит что первые `24` бита (три байта) одинаковые для всех машин подсети, а отличается последний байт. Таким образом, подсети `192.168.1.0/24` и `192.168.1.57/24` эквивалентны, но обычно принято обращать незначащие биты в `0`.
### XOR-шифрование
Один из самых простых способов зашифровать данные, основанный на том, что операция исключающего ИЛИ (XOR) является обратимой, то есть если `x = data ^ key`, то `data = x ^ key`.
Простая реализация xor шифрования (и одновременно дешифрования) на C++ может выглядеть так
```C++
std::vector<char> xor_encrypt(const std::vector<char>& data, const std::vector<char>& key) {
std::vector<char> result(data.size());
for (int i = 0; i < data.size(); ++i)
result[i] = data[i] ^ key[i % key.size()];
return result;
}
```