Хороший программист не брезгует ассемблером. А тот, кто умеет использовать прием "перекрытие кода", тот уже близок к профессионалу. Осталось к уже изученному освоить приемы скрытия вызова функций, самомодификации кода, исполнения кода в стеке, шифрование кода или его части и еще чуть чуть – и вы профессионал или программист-фокусник!
Суть метода перекрытия кода состоит в том, что часть одной машинной команды может быть другой командой. Например, команда mov может загрузить в регистр число, которое на самом деле является кодом операции другой команды. Затем, другой командой необходимо в команде mov необходимо начало выполнения кода поставить на требуемый байт данных, которые посчитать кодом операции. При этом, необходимо учесть, что числа в памяти располагаются в таком порядке: сначала младшие части с меньшими адресами, а затем – старшие части со старшими (большими) адресами (в тексте программы – наоборот).
В ассемблерной программе можно задавать не абсолютные адреса, а смещение относительно текущего адреса:Код (ASM):
jmp $ + 25 ; переход на 25h байт «вперёд»; jmp $ - 15 ; переход на 15h байт «назад»
Идентификатор $ – это значение текущего счетчика адреса строки кода, в которой располагается этот символ. А выражение «$-» обозначает разницу между адресом строки кода, в которой располагается этот символ и того значения, которое указано за ним (или другой операции, которое применено к идентификатору $.
Напримеробозначает, что переменной len1 будет присвоено число, которое высчитывается как разница между текущим адресом, по которому располагается переменная $ и значением адреса переменной с именем mas1. А т.к. каждый байт адресуется своим адресом, то практически переменная len1 равняется числу байтов, которые отводятся для хранения массива mas1.Код (ASM):
mas1 DD 20 dup(1,2,4,6) ; резервирование ячеек памяти для mas1 dd 16 dup(1) ; 80+16=96 len1 equ ($-mas1) ; число байтов в mas1
Если после строки перед строкойКод (ASM):
mas1 DD 20 dup(1,2,4,6) ; резервирование ячеек памяти для mas1 dd 16 dup(1)расположить одну или несколько строк другого кода, то идентификатор посчитает результирующее число байтов на весь блок кода.Код (ASM):
len1 equ ($-mas1)
Рассмотрим блок кода:В памяти команда mov ax,05EBh запишется машинным кодом: 66:B8 EB05. Причем, значения 05EBh поменялись местами. В память программы числа записываются по правилу «младший байт – по младшему адресу».Код (ASM):
mov ax,05EBh jmp $ - 2
Так же необходимо помнить, что каждый байт в машинном коде имеет адрес и к любому байту по их адресу можно обратиться.
Следовательно, команда jmp $ - 2 обозначает, что из адреса строки, в которой указан идентификатор $ будет вычтено 2. Это значит, что будет пропущено 2 байта справа предыдущей строки кода 66:B8 EB05 и выполнится команда с кодом операции EB и операндом 05.
Перекрытие кода применяют к уже готовой программе при открытии ее ехе-файла в отладчике.
Алгоритм перекрытия кода заключается в следующем:
- Открывается ехе-файл программы в отладчике (в данном случае отладчик x64Dbg);
- Анализируется код в отладчике на предмет поиска мест применения перекрытия кода;
- Вставляется команда jmp $ с отрицательным или положительным приращением в соответствии с количеством байтов соседствующих команд. В этом случае, становится уместным применение «мусорного» кода;
- Компилируется программа и проверяется правильность применения перекрытия кода;
- Возврат к пункту 2 до тех пор, пока не выполнятся предъявляемые к программе требования.
Перекрытие кода. Часть 8.
Дата публикации 9 апр 2019
| Редактировалось 17 май 2019