хм.. ну например: Код (Text): mov eax, 123h mov ebx, 987h xor eax, ebx mov dword[$], 08EBD831h ; <-- Инструкция модифицирует сама себя. jmp $-10 ; Передаем управление на предыдущую инструкцию ret В результате eax будет равен не 8A4h, а по прежнему 123h, несмотря на то, что он вначале ксорится с 987h. Это происходит потому, что инструкция mov dword[$], 08EBD831h затирает сама себя байтами 08EBD831h, что представляет собой две инструкции: Код (Text): xor eax, ebx jmp $+8 Они и ксорят еще раз eax на ebx, а как известно (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a Ну и далее перепрыгивается полузатертая инструкция, и исполнение кода продолжается как и должно было. P.S. Ну у тебя естественно должно стоять "section '.code' code readable writeable executable" P.P.S. Это под fasm. Под masm32 несколько сложнее с выбором опций линковки.
mix_mix Cпасибо. Пример который я видел ранее тоже использует xor. Код (Text): mov cx,3 _e: mov di,offset tau ;add di,cx mov al,cs:[di] xor al,01H mov cs:[di],al loop _e tau: mov cx,0336H Т.е надо понимать это часто используемый конструктив ?
Дабы не плодить тем,спрошу в этом топике. Предположим я получил IVT(interrupt vector table) и знаю адрес 21H.Тогда я могу оформить любой int 21H в виде например: DB 9AH DB 45H DB 04H DB 0D9H DB 0EH Т.е можно "замутить" процедуру. Все бы здорово и работает,но не понятна одна вещь вызов функции 4СH. Куда будет возврат из ядра DOS если программы уже нет
Зачем? Вызывать DOS я так понял будешь по сохранённому адресу старого обработчика.? Тогда туда, откуда вызвал и вернётся.
mov AX,4C00H call DOS По 4С00H-"освобождает всю выделенную процессу память,закрывает все дескрипторы, из PSP восстанавливает векторы...." пусть DOS proc ..... DB 9AH DB 45H DB 04H DB 0D9H DB 0EH .... ret DOS endp Т.е iret,a потом ret (так же вроде правильно описывать процедуры).Куда будет этот ret ?
Вообще перед CALL DOS надо сделать PUSHF - как и делает INT xx Только сейчас понял - из 4ch ведь возврата нет, то есть произойдёт передача управления в дочерний процесс (обычно тов. комманд.ком) который при следующем же вызове int 21 передаст управление неизвестно куда.
Otebebe Вот пример Код (Text): mov eax,12345678h call metka1 dd ? metka1: pop edi stosd Т.о. можно создать прогу, которая будеть базонезависима и самомодифицирующая себя.
Otebebe Да еще забыл - на современных процессорах используется предвыборка комманд, потому чтобы быть уверенным, что самомодифицирующийся код будет исполняться правильно необходимо исполнить после модификации любую инструкцию сериализации типа cpuid или mov eax,cr3 mov cr3,eax
PROFi Угу, а также автоматическое отслеживание записи в код, поэтому старые фокусы с предвыборкой как на 486 давно не прокатывают. К тому же P4 и атлоны, в отличие от P6, работают с преддекодированными инструкциями и поэтому щучат модификацию в окне до 1Кб от исполняемого в данный момент кода, отсюда и большие тормоза при самомодификации
Otebebe Я так понимаю, человек подменяет прерывание 21h и тихо сваливает. Есть два выхода из этой ситуации. 1) Воспользоваться эквивалентом Ah=4Ch /int 21h которых целых два 1) int 20h и 2) push 0 /ret, если что-то осталось в стеке или просто ret, если sp такое же как и при старте программы. 2) Подменить прерывание 21h, перебросив его на какое-нибудь незадействованное, например на XXh, и выйти из программы по 4Ch int XXh
PROFi Код (Text): mov eax,12345678h call metka1 dd ? metka1: pop edi stosd Что-то не могу проникнуться ...:-(.Ну перенесли содержимое EAX по адресу из ES:EDI... там где dd ? как мы туда попадем ? или мы не должны туда попасть а должны в какое-то др. место ? Или надо подразумевать что в EAX оп.код и мы скопировав его бросаемся к нему ? Сорри...
показан пример самомодифицируещегося кода, необязательно туда будет вообще переход, но код сам себя модифицировал.
Mikl__ Сейчас попытаюсь расказать чего хочу... Каждая прг. после старта имеет PSP. Пусть мы имеем примитивный обработчик прерывания.(для 1СH.его длина (у меня)~ 34H байта). Хочется скопировать его в PSP(c offset 80H ) и через 251СH "завести" его адрес в IVT. А потом из PSP-же (из обработчика ?( например через 3 секунды)) "выбросить" (4C00H) "инициализатора" (основную прг.) PSP есть.Прграммы нету. ТSR ?
Так и объясните в чём заключается модификация ....8-) Вот пример бесконечной модификации регистра АХ: ;---------------- A: inc AX jmp A: ;---------------- Но нужна ли такая бесконечность ?
Одно дело - модификация регистра, другое - модификация кода. Первое - это просто обычное исполнение кода (инструкций). Второе - изменение самих инструкций!!! Короче, вот тебе пример от Профи, тока измененный: Код (Text): mov eax,12345678h call metka1 mov ebx,0FFFFFFFFh retn metka1: pop edi mov [edi+1],eax call edi Т.е. изначально в третьей строке было mov ebx,0FFFFFFFFh, а после модификации станет mov ebx,12345678h. Т.е. ты по сути меняешь инструкцию mov (точнее ее операнд), а не сам регистр. В результате, код выполнится немного не так, как ВЫГЛЯДЕЛ с самого начала.
ну простейшее применение - оптимизация... вместо того чтобы песать Код (Text): asd dd ? mov [asd],ebx ...большой кусок кода mov eax,[asd] можно сделоть Код (Text): mov [asd+1],ebx ...большой кусок кода asd: mov eax,12345678h