Что вам нужно, это алгебраический дескриптор того, что делают коды операций, и набор алгебраических законов, которые позволяют вам определять эквивалентные операции.
Затем для каждой инструкции вы просматриваете ее алгебраическое описание (для примера,
XOR eax,mem[ecx]
с алгебраическим эквивалентом
eax exclusive_or mem[ecx]
перечислить алгебраические эквивалентности, используя такие алгебраические эквиваленты, как:
a exclusive_or b ==> (a and not b) or (b and not a)
для генерации эквивалентного алгебраического оператора для вашей инструкции XOR
eax exclusive_or mem[ecx] ==> (eax and not mem[ecx]) or (mem[ecx] and not eax)
Вы можете применить к этому более алгебраические законы, например, теорема де Моргана:
a or b ==> not (not a and not b)
чтобы получить
(not (not (eax and not mem[ecx])) and (not (mem[ecx] and not eax)))
На данный момент у вас есть спецификация алгебраического вычисления, которая будет делать
то же самое, что и оригинал. Вот твоя грубая сила.
Теперь вы должны «скомпилировать» это в машинные инструкции, сопоставляя какие инструкции
будет делать то, что это говорит. Как и любой компилятор, вы, вероятно, хотите оптимизировать
сгенерированный код (нет смысла извлекать mem [ecx] дважды). (Все это сложно ... это генератор кода!)
Результирующая последовательность кода будет выглядеть примерно так:
mov ebx, mem[ecx]
mov edx, ebx
not edx
and edx, eax
not eax
and eax, ebx
not eax
or eax, edx
Это много машин для сборки вручную.
Другой способ сделать это - воспользоваться системой преобразования программ, которая позволяет применять преобразования кода в исходный код. Затем вы можете закодировать «эквивалентности» как переписанные непосредственно в коде.
Одним из этих инструментов является наш набор инструментов для реинжиниринга программного обеспечения DMS .
DMS принимает определение языка (по сути, как EBNF), автоматически реализует синтаксический анализатор, сборщик AST и prettyprinter (антипарсер, возвращающий AST обратно в допустимый исходный текст).
[DMS в настоящее время не имеет EBNF для ASM86, но десятки EBNF для различных
сложные языки были созданы для DMS, включая несколько для разных ассемблеров не x86
Таким образом, вы должны определить ASM86 EBNF для DMS. Это довольно просто; DMS
имеет действительно сильный генератор парсеров].
Используя это, DMS позволит вам писать исходные преобразования непосредственно в коде. Вы можете написать следующие преобразования, которые напрямую реализуют эквивалент XOR и закон Деморгана:
domain ASM86;
rule obfuscate_XOR(r: register, m: memory_access):instruction:instruction
= " XOR \r, \m "
rewrites to
" MOV \free_register\(\),\m
NOT \free_register\(\)
AND \free_register\(\),\r
NOT \r
AND \r,\m
OR \r,\free_register\(\)";
rule obfuscate_OR(r1: register, r2: register):instruction:instruction
= " OR \r1, \r2"
rewrites to
" MOV \free_register\(\),\r1
NOT \free_register\(\)
AND \free_register\(\),\r2
NOT \r2
AND \r1,\r2
NOT \r1";
с некоторой дополнительной магией в мета-процедуре под названием "free_register", которая определяет, какие регистры
свободны в этот момент (от совпадения AST) в коде. (Если вы не хотите этого делать, используйте вершину стека
так же временно, как и в вашем примере).
Вам понадобится куча переписываний, чтобы покрыть все случаи, которые вы хотите запутать, с их комбинаторикой с регистрами и операндами памяти.
Затем можно попросить механизм преобразования применить эти преобразования случайным образом один или несколько раз в каждой точке кода для его шифрования.
Вы можете увидеть полностью обработанный пример некоторых алгебраических преобразований, применяемых с DMS.