DTRASH является генератором мусора с использованием данных. Принцип его
действия таков, что на вход ему подается список адресов, которые можно
использовать, флаги, буфер и др., а на выходе имеется команда в буфере и ее
длина. Всего движок способен генерировать около 30-40 команд различных
опкодов,если не считать модификаций одних и тех же команд типа rcl reg,1 и
rcl reg,im.Помимо обращений к памяти используются общие регистры и операнды.
Главная процедура (тут использован C call):
DWORD Dtrash( VOID* DataTable, // указатель на адреса
DWORD DataCnt, // их количество
VOID* TrashTable, // указатель на таблицу,
// необходимую генератору.
VOID* OutBufer, // выходной буфер
DWORD Flags, // флаги
DWORD* Seed, // указатель на seed
DWORD *(RND(DWORD* SEED,DWORD Range)) // указатель на процедуру ГСЧ
);
Как выходной параметр генератор возвращает в EAX длину полученной команды.
Список адресов (адреса) представляет собой массив структур:
typedef struct{
DWORD getd_dRVA
DWORD getd_cRVA
DWORD getd_cSize
DWORD getd_cdType
} node;
Где вторе и третье поля игнорируются, а используются лишь getd_RVA,
содержащее RVA данных и getd_cdType- размер данных во втором байте и тип
обращения к ним - в первом. Сам список может быть получен путем анализа
обращения программы к данным, но стоит помнить, что при генерировании команд
на запись следует учесть размер данных т.к. не факт, что там данные
выровнены, т.е. используются какая-то величина (чаше dword) вместо байтов и
слов и все переменные на границе этой величины, да так, что программа и не
"знает" об этом. Но и если выровнены,то неизвестно на какую границу ;)
Генератор использует свою таблицу для работы. Ее можно включать как данные в
код, другими словами - включать ее инклудник,либо же,что более универсально,
использовать процедуру,которая распакует таблицы (где-то 300 байт) в буфер:
VOID trash_init(
VOID* Ptr // указатель на буфер
)
После этого можно передать адрес буфера в главную процедуру и вызвать ее.
Для задания параметров генерирования мусора используются флаги:
DTF_READ
0000000000000000b
генерировать команды на чтение
DTF_WRITE
0000000000000001b
генерировать команды на запись
DTF_MFLAGS
0000000000000010b
использовать флаги мусором?
DTF_EAX
0000000100000000b
использовать AL/AX/EAX
DTF_ECX
0000001000000000b
использовать CL/CX/ECX
DTF_EDX
0000010000000000b
использовать DL/DX/EDX
DTF_EBX
0000100000000000b
использовать BL/BX/EBX
DTF_ESP
0001000000000000b
использовать AH/SP/ESP
DTF_EBP
0010000000000000b
использовать CH/BP/EBP
DTF_ESI
0100000000000000b
использовать DH/SI/ESI
DTF_EDI
1000000000000000b
использовать BH/DI/EDI
DTF_ALL
1111111100000000b
использовать все регистры
Использованные регистры зависят и от размера входных данных. Так при размере
данных в 1 байт и включенном флаге DTF_EAX будет использоваться лишь AL ,но
при включении флага DTF_ESP ,будет еще генерироваться и AH. Тоже касается и
остальных однобайтовых регистров.
Если размер данных - 4 байта, то к ним может использоваться обращение как к
1/2/4 байтовой переменной.