Нашел я такой хитрый опкод (в 16-битной проге): C4 C4 58 00 Дизассемблеры (IDA и HIEW) ничего внятного сказать не могут. Отладчики сомневаются: wdw (Watcom debugger) считает, что C4 C4 - это les ax, ah debug.com уверен, что C4 C4 - это les ax, sp Притом если (в любом из них) выполнить команду trace, то отладчик остановится только после _следующей_ команды независимо от того, сколько байт она занимает. "Книга двойных слов" только добавляет "непоняток" - если я правильно ее понимаю, то прав debug.com. И это несмотря на то, что он выдает бред - не, например, les ax, [sp], а именно les ax, sp. Кто спец в дизассемблировании, подскажите, если не трудно: в чем тут хитрость и что этот опкод должен обозначать?
> C4 C4 58 00 C4 - это опокд команды LES reg, [указатель на память] а ты пытаешься использовать адресацию типа LES reg, reg, поэтому поведение процессора становится неопределенным, да и отладчиков/дизассемблеров тоже. > что он выдает бред - не, например, les ax, [sp], а именно les ax, sp. в 86 не было адресации типа [sp] к тому же, у тебя два старших бита второго байта равны 11, так что декодирование регистра как SP c формальной точки зрения выполненно правильно. но у данной машинной команды нет такого способа адресации!
> Притом если (в любом из них) выполнить команду trace, > то отладчик остановится только после _следующей_ > команды независимо от того, сколько байт она занимает. странно... avputil останавливается на пятом байте (т.е. отъедает один байт следующей команды), декодируя это как: C4 DB C4 ; U C4 58 00 LES BX,DWord ptr [BX+SI]+00 так же поступает и insight, декодируя это как: les ax,sp pop ax
В том-то и дело, что не я пытаюсь Я нашел этот код при анализе некоторой "навесной" защиты. зЫнаю (C) "Достучаться до небес" Но такой код я бы смог понять, а вот такой - не могу. Значит, есть какой-то другой... притом большей длины. Но вот какой? :-\ Пятый байт в моем случае - 2E (т.е. префикс CS, а дальше идет что-то вроде mov dx, word ptr [...], то есть "угадать" длину команды не получится (либо 4, либо 5). Сначала я решил, что проглючил, но потом решил перепроверить. Сделал тестовый COM-файл с таким содержимым: C4 C4 58 00 CC CC CD 20 открыл его в том же debug.com, сказал ему "g" и увидел, что исполнение останавливается на первом CC. Здесь уже никакие нюансы разных отладчиков срабатывать не должны, так что все-таки длина данной команды - 4 байта. Дальше - "страньше". В случае C4 C4 58 CC CC CC CD 20 исполнение останавливается на втором CC, т.е. длина команды опять 4 байта, а вот в случае С4 С4 СС СС СС СС СС 20 опять же на втором CC, т.е. длина команды уже 3 байта. :-\ Ладно, сейчас напишу "более правильный" тест (вообще без использования отладчика), а там посмотрим...
А если взглянуть на результаты работы такой "команды" ? У меня она не работает ни в 32-х, ни в 16-ти битном коде. Везде вывыливается в отладчик с UD-исключением. Может быть, это все же вызов обработчика исключения, установленного защитой, и без него это просто "мусор" >?
RobinFood Если это защита, то где-то может стоять прыжок на второй C4. Тогда для 16-бит будет С4 58 00 = les bx,[bx+si+0], а C4 CC = les cx,sp (или ah).
Chingachguk В моих тестах AX становится равным 1. Почему именно так - непонятно. ES не изменяется, но гарантии, что он не изменится при других условиях, естественно нету. Что в защите - смогу посмотреть не раньше, чем завтра. Но в любом случае хотелось бы понимания Первой моей мыслью тоже была мысль о вызове обработчика. Но в том-то и дело, что я уверен, что обработчик защитой не устанавливался. Хотя какая-то зацепка в твоих словах есть. Я гонял свои тесты только под NTVDM. Возможно, вся причина именно в этом - защита этот код выполняет только в том случае, если она уверена, что работает под NT (проверяет это с помощью int21h, ax=3306h). leo Не может В этом я уверен. Вот только ntvdm меня немного смущает... Сейчас нормальный тест доделаю (мало у меня опыта в _написании_ на асме), тогда кое-что прояснится Угу, только les cx,sp - это не меньший бред, чем les ax, sp
RobinFood "Угу, только les cx,sp - это не меньший бред, чем les ax, sp" Вот именно. С4 СС я привел в ответ на твое "опять же на втором CC, т.е. длина команды уже 3 байта". А вопрос в том, почему у _Chingachguk_ возникает #UD (в соответствии с интелом), а у тебя нет ? И kaspersky привел пример: "умный" avputil выделяет первый С4 как db. И trace у тебя пролетает - значит всетаки #UD, но твои отладчики это не фиксируют ? Напрашивается вывод, что С4 С4 - это мусор. Либо 1) для того, чтобы перейти на обработчик исключения, 2) либо где-то производится модификация первого С4 или прыжок на второй С4, 3) либо это просто мусор, на который программа в нормальном режиме никогда не попадает. "Не может. В этом я уверен" На 100% ? Что в проге нет ни одного Jcc или Call ? Или ты все проанализировал ? Я с такой фигней сам когда-то баловался - делаешь call (еще лучше несколько вложенных), который интенсивно работает со стеком и под шумок подправляет адрес возврата. В твоем случае возможен переход на второй C4 или дальше, или вообще без возврата в вызывающую процедуру.
_Chingachguk_ Нет! Нашел любопытный рецепт изучения команд : ставить JMP. 100 : c4 c4 58 00 ??? 104 : eb 1a jmp 120 106 : cc cc 120 : cc После g=100 попадаем на 120 ! Т.е. команда все-таки 4 байта длинной и она меняет AX ! Правда эксперименты с ES ничего не дали - у меня AX=1 после исполнения всегда( в debug.com W2K SP3). Если вызвать debug с программой - AX уже другой, т.е. точно читает память.
Это в каком таком соответствии? Процитируй, где написано, что такой опкод недопустим? Вот это хорошая мысль. Подумаю над ней, результат сообщу Ну, скажем так, на 99,99%. Переходов в проге дофигища, но я действительно все их проанализировал. 0,01% - это вероятность того, что я мог ошибиться; она была бы больше, но... у меня есть самодельный инжектор, заточенный именно под эту прогу. И одна из его фич - отслеживание прохождения "контрольных точек", которые я считаю важными. И если я задаю 2 точки - перед этим опкодом и после него, то они обе нормально проходят. Кстати, именно поэтому я уверен, что длина команды - ровно 4 байта.
<font color="1]„А вопрос в том, почему у _Chingachguk_ возникает #UD (в соответствии с интелом)“ Это в каком таком соответствии? Процитируй, где написано, что такой опкод недопустим?</font><!--color--> Не, я пять сек пробовал - всего лишь вот что: db C4,C4,58,00 в win32-коде и то же самое в 16-ти битном коде плюс db 66h перед ними в 16-ти битном: везде UD. Я смотрел невнимательно. Тонкость какая-та должна быть, попробуй все же посмотреть, кем заняты вектора исключений, особенно - ud, gpf.
RobinFood "Процитируй, где написано, что такой опкод недопустим?" Конечно, у интела звучит завуалировано "#UD - If source operand is not a memory location". Но формально байт ModR/M = C4 означает сочетание регистров AX и SP\AH. А это никаких довесков 58 00 не предполагает. Тогда это должно быть или les + push, или глюк - секретная команда интела. valterg "команда все-таки 4 байта длинной и она меняет AX !" А как насчет les + push ? SP проверял ? PS: в win32-коде C4 C4 однозначно вызывает invalid instruction, а Olly все, начиная с первого C4 считает мусором.
См., например, http://www.peterburg.h1.ru/other/c4c4.html или, возможно, /private/ntos Если кратко, то это некий способ (канал) связи 16-битного кода с ntvdm, разумеется, недокументированный.
leo Стек на месте стоит. Но в 98-м дает ошибку - недопустимая инструкция по адресу 200(!). Если же делать в командной строке, то комп виснет. Кстати на Virtual PC - все идентично получается. Может С4 это какой-то спец-код именно для ntvdm ?
Skif Похоже, что это именно то, что нужно Большое спасибо, теперь буду private смотреть (но уже чуть позже).
Почитал private, узнал много интересных вещей по сабжу. 1. Все самое интересное живет не в private\ntos, а в private\mvdm. 2. Самое интересное - это файлы bop.h, bios.c, bop_nt.c 3. C4 C4 58 00 - это ни много, ни мало, а "всего лишь" загрузка 32-битной DLL-библиотеки, на имя которой указывает DS:SI, и не просто загрузка, а еще и выполнение оттуда функции, на имя которой указывает ESI. Кроме того еще и DS:BX зачем-то используется. 4. В наших опытах не только AX становился равным 1, а еще и CF тоже устанавливался, и это должно было означать, что библиотека не была загружена. 5. Есть отладчик, который понимает такой опкод, и это WinDbg - он дизассемблирует это как BOP 58. И это при том, что я еще не дочитал до конца
В качестве подтверждения пункта 3 из предыдущего поста привожу аттач. Работает, естественно, только на NT+. Ну и, "чтоб два раза не вставать", мои благодарности: leo, за разъяснения о том, как нужно читать интеловские талмуды, skif, за подсказанное направление, в котором нужно копать, всем остальным за моральную поддержку, microsoft, за любезно предоставленные буквы P.S. В аттаче есть "глючок" (leak), который я исправить пока не могу, так как пока не дочитал эти самые буквы - вызов BOP(58,0) выделяет запись в какой-то из своих внутренних таблиц, а для освобождения этой записи потом нужно вызывать то ли BOP(58,1), то ли BOP(58,2), то ли еще что-то в этом роде - но это уже, IMHO, мелочи
2 RobinFood Если не затруднит, нельзя ли где-нибудь разместить (например, в этой ветке в виде аттача) файлы {bios.c, bop_nt.c} - в моей копии /private/... их, к сожалению, нет :-( Заранее благодарю.