Ассемблерные головоломки Крис Касперски ака мыщъх Хакер, номер #081, стр. 081-112-5 Немного медитации и решение найдено. Если заслать в стек регистр AX, затем уменьшить указатель верхушки стека на единицу и извлечь регистр AX, то в AL попадет мусор, а в AH — младший байт оригинального регистра AX, в результате чего наша задача будет решена! Весь код угадывается в 0Bh байт, что на 0Ah байт короче, чем в прошлый раз. Это стоило бы отметить! [подготовка регистра AH в работе (улучшенный вариант)] 00000000: 40 inc ax 00000001: 40 inc ax 00000002: 40 inc ax 00000003: 40 inc ax 00000004: 40 inc ax 00000005: 40 inc ax 00000006: 40 inc ax 00000007: 40 inc ax 00000008: 40 inc ax 00000009: 50 push ax 0000000A: 4C dec sp 0000000B: 58 pop ax С регистром DX мы разделываемся аналогичным образом (многократным вычитанием), а вот с INT 21h (CDh 21h) все обстоит значительно сложнее - без самомодифицирующегося кода здесь просто никак. На этот случай в нашем арсенале есть, по меньшей мере, две команды для работы с памятью: sub byte:[index_reg16],reg8 и sub byte:[BP+im8],reg8. Естественно, нам необходимо знать смещение инструкции "INT 21h" в машинном коде, а на данном этапе оно еще не известно, так как перед ним располагается самомодифицирующийся код, длину которого мы еще не готовы назвать. Хорошо, условимся считать, что INT 21h располагается по смещению 66h от начала файла, что соответствует 166h в памяти (базовый адрес загрузки для com-файлов равен 100h). Начальное значение регистра SI равно 100h, что существенно упрощает нашу задачу. Остается разобраться с INT 21h (СDh 21h). Если закодировать эту команду как 23h 21, а затем отнять от нее 56h, мы добьемся того, что так долго искали. В машинном представлении это может выглядеть так: [формирование инструкции INT 21h с помощью самомодифицирующегося кода] XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 00000000: 56 push si 00000001: 5D pop bp 00000002: 6A 56 push 056 00000004: 59 pop cx 00000005: 28 4E 66 sub [bp][00066],cl … 00000066: 23 21 Этому соответствует следующая текстовая строка: "V]jVY(Nf…#!". Не слишком литературно, конечно, но зато целиком из печатных символов! Команда "RETN" с опкодом C3h укрощается аналогично. Короче говоря, первый этап ручного ассемблирования можно считать пройденным. Как и все готовые решения, он скрывает весь накал страстей и не передает треска мозговых извилин. Это только с виду кажется, что задачка решается просто. На самом деле, она требует нестандартного мышления, хорошего значения структуры машинных команд, медитации и длительных размышлений, пытающихся втиснуть заданную функциональность в ограниченный диапазон читабельных байт. Впрочем, это всего лишь начало. Настоящее веселье наступает потом, когда хакер пытается превратить читабельный текст в осмысленную фразу. Очевидно, что наш первоначальный вариант (абракадабра в стиле "-*)-*)-*)-*)-*)-*)HHHH…V]jVY(Nf…#!") ничем подобным не является. |