Заклинание кода: Вав — Архив WASM.RU
Есть разные пути к Силе. И каждый по-разному себе её представляет. Кто-то представляет Силу как хитроумную шкатулку с невидимыми духами внутри, а кто-то день за днём пишет строки бессмысленного кода, двигающего колесо Сансары, и видит Силу в том, чтобы это колесо продолжалось вертеться. В погоне за Силой некоторые постигают дао программирования, другие продают душу Баалу, третьи призывают на помощь могучих демонов. Заклинание кода не является путём к Силе, оно является ключом ко многим путям. И пусть по ним вас ведёт безупречность.
В прошлой главе я рассказал, как читать Книгу Двойных Слов. Теперь вы можете колдовать почти любой 32-битный код, хотя кое-что и осталось недосказанным. Наверняка многие из вас хотели бы узнать, как можно на практике применить заклинание кода. Давайте рассмотрим простую самомодифирующуюся программу.
Предположим, в нашей программе есть следующий код:
Код (Text):
mov esi,50 mov edi,20 imul esi,5 add esi,edi mov eax,esiОчевидно, этот код вычисляет следующее значение в eax: esi*5+edi=50*5+20=270. А теперь мы хотим, чтобы наша программа модифицировала сама себя так, чтобы приведенный код превратился в:
Код (Text):
mov ecx,50 mov edx,20 imul edx,5 sub edx,ecx mov eax,edxЭто можно записать как edx*5-ecx=20*5-50=50. "Но возможно ли, чтобы программа без нашего участия сама себя изменила?", - может спросить иной читатель. Да, возможно. Разумеется, если мы правильно её запрограммируем и будем следовать канонам алхимии, а именно - смешивать всё в правильных пропорциях и давать свои зелья на пробу другим, прежде чем пить их самим.
Сначала давайте выясним, как будут выглядеть заколдованные инструкции. Первые две не представляют для нас особого труда, ведь мы уже работали с ними в предыдущих главах. Их заклинания выглядят так:
Код (Text):
db 0BEh ; mov ecx, 50 dd 50 db 0BFh ; mov edx, 20 dd 20Чтобы выяснить заклинание для третьей инструкции, следует обратиться к Книге Двойных Слов. Из всех опкодов нам подходит следующий:
Код (Text):
6B /r ib IMUL r32,r/m32,imm8Согласно описанию, в поле Reg задается регистр назначения, в R/M - регистр или адрес ячейки памяти с умножаемым значением, а за опкодом следует байт с множителем. Таким образом, у нас получается следующее:
Код (Text):
db 6Bh,11110110b,8С операцией сложения регистров мы также уже имели дело:
Код (Text):
db 3,11110111bКак вы должны помнить из предыдущей главы, "MOV регистр,регистр" можно закодировать двумя способами. Как выяснилось, FASM заколдовал нужную нам инструкцию сложения так:
Код (Text):
01 /r ADD r/m32,r32 Add r32 to r/m32А мы в предыдущих главах использовали следующую инструкцию:
Код (Text):
03 /r ADD r32,r/m32 Add r/m32 to r32Не страшно. Это просто результат того, что набор инструкций избыточный и к одной и той же цели ведут разные пути. Главное - аккуратно определить заклинание:
Код (Text):
db 1,11111110b ; 03(Опкод), 11(Mod)-111(Reg=EDI)-110(R/M=ESI)Теперь перейдем к самомодифицированию программы. Вот рабочий текст:
Код (Text):
format PE console entry start include '..\..\include\kernel.inc' include '..\..\include\user.inc' include '..\..\include\macro\stdcall.inc' include '..\..\include\macro\import.inc' include '..\..\include\macro\ccall.inc' section '.data' data readable writeable _d db '%d', 0 var dd 50 section '.code' code executable readable writeable start: mov [.mov_esi_imm],byte 0B9h mov [.mov_edi_imm],byte 0BAh mov [.imul_esi_imm+1],byte 11010010b mov [.add_esi_edi],byte 02Bh mov [.add_esi_edi+1],byte 11010001b mov [.mov_eax_esi+1],byte 11010000b ; Модифицируемый код .mov_esi_imm: mov esi,50 .mov_edi_imm: mov edi,20 .imul_esi_imm: imul esi,5 .add_esi_edi: add esi,edi .mov_eax_esi: mov eax,esi ; Проверка модификации push edx push _d call [printf] add esp, 8 invoke ExitProcess,0 section '.idata' import data readable writeable library kernel32,'kernel32.dll',\ msvcrt,'msvcrt.dll' kernel32: import ExitProcess,'ExitProcess' msvcrt: import printf,'printf'Строчка "section '.code' code executable readable writeable" указывает, что в сегмент кода можно писать. Мы модифицируем наш код очень простым методом: поверх имеющихся кодов записываем новые. После этого управление получает уже модифицированный код.
Как видите, самомодифицируемый код - это не так сложно: у вас есть код, и он сам себя модифицирует. © Aquila / WASM.RU
Заклинание кода: Вав
Дата публикации 20 дек 2002