Итак, Хакеры - это те, кто
взламывают сети. Крэкеры - это те, кто взламывает компьютерные
программы. Именно обучением крэк-мастерства мы сейчас и займемся.
Например, скачали вы какую-нибудь американскую прогу, весящую 10 мегов.
Качали вы ее, допустим, в течение двух часов. Запускаете ее. Она
нормально работает. Вы ей пользуетесь, пользуетесь и тут бах! Через 30
дней с момента первого запуска она требует от вас ввести серийный ключ,
иначе не будет запускаться. Позже вы узнаете, что чтобы получить этот
серийный ключ, вам предется всего-то навсего отдать за границу свои
кровные 500$. Вы этого хотите? Нет, конечно! За эти 500 буказоидов
знаете, что можно купить? Верно, компьютер можно новый купить. Лучше уж
второй комп себе купить, чем тратиться на эту софтинку. Ну и что же вам
делать? Отдавать 500 американских рублей? Или отказаться от такой
замечательной софтинки? Лучшим вариантом будет, конечно, крэкерство.
Лучше будет взламать эту тупую прогу, чтобы, наконец, она замолчала и
больше не просила ввести серийник.
А как это сделать непосвященному в деле крэкерства человеку?
Об этом и расскажет написанная снизу статья:
ВЗЛОМ
WINDOWS-ПРИЛОЖЕНИЙ
Для начала я научу вас пользоваться W32Dasm. Я не хочу вам давать
детальную помощь, как делать краки, но я могу научить вас самим
добывать себе умения и навыки взлома.
Когда вы используете W32Dasm, знайте, что он не даст вам серийные
номера или коды, он лишь покажет путь, где находится место, где можно
эти номера вводить. То, что я делаю каждый день при взломе программ,
будет описано в этом справочнике, шаг за шагом.
ИНСТРУМЕНТЫ
Из инструментов взлома вам нужно следующее : W32Dasm 8.5 или боолее
позднюю версию, Hacker's View 5.24, Norton Commander (я позднее
объясню, почему я его использую).
Turbo Pascal 7.0
TASM и TLINK 3.0
Все эти программы можно найти и скачать бесплатно на многих серверах,
достаточно только в Яndex'е набрать фразу, например "Скачать TASM" как
тут же посыпятся кучи ссылок.
ЧАСТЬ 1
: Как кракнуть Quick View Plus 4.0
Шаг 1. Запустите ORDER32.EXE
Шаг 2. Кликните на $49 Single User License (вы можете кликнуть и на
$59), затем ACCEPT, потом UNLOCK BY PHONE.
Шаг 3. Введите любой код для получения сообщения об ошибке (вы должны
записать это сообщение), потом выйдите из программы, кликнув на CANCEL.
Шаг 4. Запустите Norton Comander, перейдите в директорию QVP.
Шаг 5. Скопируйте ORDER32.EXE в ORDER32.EXX (для сохранности), а
затем скопируйте ORDER32.EXE в 1.EXE
(для использования в W32Dasm).
Шаг 6. Запустите W32Dasm и раздессимблируйте 1.EXE.
Шаг 7. После этого, кликните на STRING DATA REFERENCE, найдите там
сообщение "You have entered an incorrect code.Please check your entry"
(вы должны помнить,что это было сообщение об ошибке) и дважды щелкните
мышью по нему.
Шаг 8. Закройте SDR окно. Вы должны увидеть сообщение:
*
Possible reference to String Resource ID=00041: "You have entered...
:004049F8 6A29 push 00000029
:004049FA FF353CCE4000 push dword ptr [0040CE3C]
Шаг 9. ОК, теперь вы должны найти последнее сравнение типа CMP,JNE,
JE,TEST и т.д. перед сообщением об ошибке.
Нажимайте стрелку "вверх", пока не найдете :
:004049CD 755A jne 00404A29
*
Possible reference to String Resource ID=00032: "You must select...
:004049CF 6A20 push 00000020
...
...
*
Possible reference to String Resource ID=00040: "Unlock Error"
Шаг 10. Теперь вы знаете, куда идет скачок при введении неправильного
кода. Теперь можно посмотреть, что произойдет, если "jne" на "je".
Убедитесь, что зеленая полоска находится на надписи:
004049CD 755A jne 00404A29, вы должны увидеть Offset address
внизу на статусной строке типа
@Offset 00003DCDh Это место, где вы можете внести изменения в
ORDER32.EXE.
Шаг 11. Перейдите обратно в Norton Commander, запустите HIEW
ORDER32.EXE, нажмите F4 для выбора режима декодирования (Decode
Mode), нажмите F5 и введите 3DCD.
Вы должны увидеть следующее :
00003DCD: 755A jne 000003E29
00003DCF: 6A20 push 020
00003DD1: FF15 call w,[di]
Шаг 12. Это то место, где вы можете изменить байты, нажмите F3, введите
74, нажмите F9 для обновления ORDER32.EXE. Выйдите из HIEW.
Шаг 13. Запустите ORDER32.EXE, введите любой код. Ура ! Мы сломали QVP
4.0 !
Но ! Что будет, если ввести настоящий серийный номер ? Появляется
сообщение об ошибке ! Что это ?
Шаг 14. Снова запустиите HIEW ORDER32.EXE, нажмите F4, выберите Decode,
нажмите F5 и введите 3DCD. Нажмите F3, введите EB, нажмите F9. Вы
прямо "прыгнете" на Unlocked диалог.
ЧАСТЬ 2
: Как кракнуть Hex WorkShop 2.51
Шаг 1. Запустите HWORKS32.EXE
Шаг 2. Кликните на HELP, About HEX Wo..
Шаг 3. Введите любой код, чтобы получить сообщение об ошибке (вы должны
записать это сообщение) и выйдите из программы.
Шаг 4. Запустите Norton Commander, перейдите в директорию HWS.
Шаг 5. Скопируйте файл HWORKS32.EXE в HWORKS32.EXX
(для сохранности) и скопируйте файл HWORKS32.EXE в 1.EXE (для
использования в W32Dasm).
Шаг 6. Запустите W32Dasm и "разберите" 1.EXE.
Шаг 7. После этого, нажмите мышью на FIND TEXT, введите
"You have entered an" (вы должны помнить, что
это
сообщение об ошибочно введенном серийном номере) и найдите
соответствующую строку (вы не сможете сделать это в SDR-окне !)
Шаг 8. Вы должны увидеть следующую строку :
Name: DialogID_0075, # of Controls=003, Caption:
"Registration Unsucce..
001-ControlID:FFFF, Control Class:""Control Text:"You have entered an..
002-ControlID:FFFF, Control Class:""Control Text:"Please confirm you..
Шаг 9. Оk, теперь вы знаете, что ControlID будет использоваться, когда
вы введете неверный код. Кликните FIND TEXT, введите
"dialogid_0075" и вы найдете:
*
Possible reference to DialogID_0075
:0041E233 6A75 push 00000075
:0041E235 8D8D10FFFFFF lea ecx, dword ptr [ebp+FF10]
Шаг 10. Теперь вы должны поискать последнюю ссылку, типа
CMP, JNE, JE и пр. перед диалогом об ошибке. Нажимайте клавишу "вверх",
пока не найдете :
:0041E145 837DEC00 cmp dword ptr [ebp-14], 00000000
:0041E149 0F8479000000 je 0041E1C8
:0041E14F 8B8DFCFEFFFF mov ecx, dword ptr [ebp+FEFC]
Шаг 11. Теперь вам нужно посмотреть, что произойдет, если "je" заменить
на "jne". Убедитесь, что зеленая полоска установлена на строке
:0041E149 0F8479000000 je 0041E1C8.
Вы должны на нижней статусной строке увидеть оффсетный адрес, типа :
@Offset0001D549h. Это то место, где вы сможете кракнуть HWORKS32.EXE
Шаг 12. Перейдите обратно в Norton Commander, запустите HIEW
HWORKS32.EXE, нажмите F4 для выбора режима декодирования (Decode Mode),
нажмите F5 и введите
ID549.
Вы должны увидеть следующее :
0001D549: 0F847900 je 00001D5C6 ---------- (1)
0001D54D: 0000 add [bx][si],al
0001D54F: 8B8DFCFE mov cx,[di][0FEFC]
Шаг 13. Это то место, где вы сможете изменить несколько байтов, нажмите
F3, введите 0F85, нажмите F9 для обновления файла HWORKS32.EXE.
Выйдите из HIEW.
Шаг 14. Запустите HWORKS32.EXE и введите любой код, работает ? НЕТ
!?!??!?!
Хе-хе-хе... Не волнуйтесь ! Снова перейдите в Нортон.
Скопируйте HWORKS32.EXX в HWORKS32.EXE (теперь
вы видите, почему я делаю копию файла с расширением
ЕХХ для сохранности). Теперь перейдите в W32Dasm, вы
должны перейти туда, где только что были (на 0041У145).
Шаг 15. Нажмите F3 для очередного поиска "DialogID_0075", вы должны
найти :
* Possible reference to DialogID_0075
:00430ADD 6A75 push 00000075
:00430ADF 8D8D10FFFFFF lea ecx, dword ptr [ebp+FF10]
Шаг 16. Ok, теперь вы теперь можете посмотреть на последние ссылки,
типа CMP, JNE, JE и т.д. перед диалогом об ошибке. Нажимайте
стрелку вверх, пока не найдете :
:004309EF 837DEC00 cmp dword ptr [ebp-14], 00000000
:004309F3 0F8479000000 je 00430A72
:004309F9 8B8DFCFEFFFF mov ecx, dword ptr [ebp+FEFC]
Шаг 17. Теперь вы можете посмотреть, что произойдет, если "je" заменить
на 'jne". (это должно сработать). Переместите
полоску на :004309F3 0F8479000000 je 00430A72. На статусной строке
внизу экрана вы должны следующее:
@Offset0002FDF3h (оффсетный адрес). Это то место, где
вы сможете кракнуть HWORKS32.EXE.
Шаг 18. Перейдите в Norton Commander, запустите HIEW
HWORKS32.EXE, нажмите F4 для выбора Decode Mode
(ASM), нажмите F5 и введите 2FDF3. Вы должны увидеть:
0002FDF3: 0F847900 je 00001D5C6 ---------- (1)
0002FDF7: 0000 add [bx][si],al
0002FDF9: 8B8DFCFE mov cx,[di][0FEFC]
Шаг 19. Это то место, где вы сможете изменить несколько байтов, нажмите
F3, введите 0F85, нажмите F9 для обновления файла HWORKS32.EXE.
Выйдите из HIEW.
Шаг 20. Запустите снова HWORKS32.EXE и введите любой код. Работает ?
Виола !!! Поздравляю !!! Вы кракнули HEX
WorkShop 2.51 !
ЧАСТЬ 3
:Как сделать собственный патч
Здесь напечатан исходный код на Паскале :
------------------------<cut
here>-------------------------------------------
Uses Crt;
Const A: Array[1..1] of Record {<-------- 1 byte to be patched}
A : Longint;
B : Byte;
End =
((A:$3DCD;B:$EB)); {<--------------- offset "3DCD" and byte "EB" to
be changed}
Var Ch:Char;
I:Byte;
F:File;
FN:file of byte;
Size:longint;
Begin
Writeln('TKC''s Little Patch');writeln('Crack for QVP 4.0 by TKC/PC
''97');
Assign(F,'ORDER32.EXE'); {<-------------- filename to be patched}
{$I-} Reset(F,1); {$I+}
If IOResult <> 0 then
begin
writeln('File not found!');
halt(1);
end;
For I:=1 to 1 do {<---------------------- 1 byte to be patched}
Begin
Seek(F,A[I].A);
Ch:=Char(A[I].B);
Blockwrite(F,Ch,1);
End;
Writeln('File successfully patched!');
End.
------------------------<cut
here>-------------------------------------------
Here's the source code for Assembler:
------------------------<cut
here>-------------------------------------------
DOSSEG
.MODEL SMALL
.STACK 500h
.DATA
.CODE
PatchL EQU 6
Buffer Db PatchL Dup(1)
handle dw ?
intro db "TKC's Little Patch",0dh,0ah,"Crack for QVP 4.0 by TKC/PC '97$"
FileName db "ORDER32.EXE",0 ;<------- filename to be patched
notfound db 0dh,0ah,"File not found!$"
cracked db 0dh,0ah,"File successfully patched. Enjoy!$"
Cant db 0dh,0ah,"Can't write to file.$"
Done db "File has been made.$"
String db 0EBh,0 ;<------------- byte "EB" to be patched
START:
mov ax,cs
mov ds,ax
mov dx,offset intro ;point to the time prompt
mov ah,9 ;DOS: print string
int 21h
jmp openfile
openfile:
mov ax,cs
mov ds,ax
mov ax,3d02h
mov dx,offset FileName
int 21h
mov handle,ax
cmp ax,02h
je filedontexist
jmp write
filedontexist:
mov ax,cs
mov ds,ax
mov dx,offset notfound
mov ah,9 ;DOS: print string
int 21h ;display the time prompt
jmp exit
Write:
mov bx,handle
mov cx,0000h
mov dx,3DCDh ;<------------- offset "3DCD"
mov ax,4200h
int 21h
mov cx,patchl
mov dx,offset String
mov ah,40h
mov cx,01h
int 21h
mov ax,cs
mov ds,ax
mov dx,offset cracked
mov ah,9 ;DOS: print string
int 21h ;display the time prompt
jmp Exit
Exit:
mov ah,3eh
int 21h
mov ax,4c00h
int 21h
END START
--------------------------<cut
here>-----------------------------------------
Заключительные слова :
Здесь несколько важных функций, используемых для крака :
Hex: Asm: Means
75 or 0F85 jne jump if not equal
74 or 0F84 je jump if equal
EB jmp jump directly to
90 nop no operation
77 or 0F87 ja jump if above
0F86 jna jump if not above
0F83 jae jump if above or equal
0F82 jnae jump if not above or equal
0F82 jb jump if below
0F83 jnb jump if not below
0F86 jbe jump if below or equal
0F87 jnbe jump if not below or equal
0F8F jg jump if greater
0F8E jng jump if not greater
0F8D jge jump if greater or equal
0F8C jnge jump if not greater or equal
0F8C jl jump if less
0F8D jnl jump if not less
0F8E jle jump if less or equal
0F8F jnle jump if not less or equal
Ваши небольшие знания по Ассемберу, вам, естественно, помогут, и они
вам потребуются для использования Soft-ICE. Кроме того, вы сможете
кракать эти куски с помощью W32Dasm как маньяк :-) Вы не сможете
дизассемблировать программы на Visual Basic, для него вам понадобятся
специальные декомпилеры.
SoftIce в
действии
Оглавление
1. Введение.
2. Что такое SoftIce?
3. Инсталляция.
4. Первые шаги.
5. Эпилог.
Введение
Цель данной статьи - ответы на вопросы, которые задают новички:
Что такое SoftIce, и для чего он нужен?
Я поставил SoftIce, что мне делать дальше?
Где взять русскую документацию?
Почему у меня ничего не работает?
Все эти вопросы возникают по одной простой причине: вся документация,
которую можно найти в Internet'e, написана на английском языке, автору
известна только одна статья на русском языке, и та, к сожалению, очень
не полная. Чтобы заполнить этот информационный вакуум, и было написано
это эссе. Сколько человек, столкнувшись с этими проблемами, "снесли"
SoftIce и забыли о нем как о страшном сне, подсчитать трудно, а жаль -
ведь это лучший отладчик на сегодняшний день.
Сразу хочется сделать несколько замечаний: первое, если вы после
прочтения этой статьи все-таки возьметесь за SoftIce, то вам придется
заняться английским языком, хотите вы этого или нет (почему - см.выше);
второе, данная статья не претендует на роль документации, она была
составлена как обзор той информации, которая была у автора на
английском языке, а это фирменное руководство от фирмы NuMega - автора
SoftIce-a, статьи и эссе, найденные в Интернете на различных сайтах,
посвященных SoftIce и Reverse Engineering. По этой причине в статье
возможны ошибки и неточности, автор будет благодарен за их исправление.
В статье описывается последняя версия SoftIce 3.24 для WIN95, но
большая часть сказанного относится и к предыдущим версиям.
Предполагается, что читающие эту статью имеют минимальные знания об
устройстве процессора и компьютера и представляют, что такое ассемблер.
Что такое SoftIce?
SoftIce состоит из отладчика уровня ядра (kernel mode debugger)
(собственно, это и есть отладчик) и утилиты загрузчик отладочной
информации (Symbol Loader). SoftIce – это универсальный отладчик,
которым можно отладить любой код, включая подпрограммы прерывания и
драйверы ввода-вывода. Утилита Symbol Loader загружает отладочную
информацию для вашего модуля, позволяет настроить SoftIce, и дает
возможность записать историю комманд (history buffer) в файл.
SoftIce совмещает в себе мощь аппаратного отладчика и удобство
символьного, он имеет следующие возможности:
Символьная отладка 32-битных приложений, отладка драйверов устройств
для WIN NT, драйверов для WIN95, VxD, 16-битных программ для DOS и
Windows.
Отладка фактически любого кода, включая подпрограммы прерывания и
внутренние подпрограммы WIN 95 и WIN NT.
Установка точек останова на операции чтения/записи в память,
чтения/записи портов ввода-вывода, прерываний.
Установка точек останова на сообщения Windows.
Установка точек останова, срабатывающих при определенных условиях
(условных точек останова), и действий, которые должны произойти при
срабатывании точки останова.
И многое другое ...
Symbol Loader позволяет прочитать отладочную информацию из отлаживаемых
программ (EXE, DLL, VxD, 386, OCX) и загрузить ее в отладчик, запустить
ваше приложение и автоматически установить точку останова на точку
входа в программу, записать в файл протокола отладки.
Инсталляция
Аппаратные требования (от NuMega):
Процессор:486 или Pentium.
ОЗУ:необходимо 16 Мб (хотя в свое время работал и на 8), желательно 32
Мб.
Мышка:обычная или PS (интересно, а кто в виндах без нее работает?).
Видеокарта:начиная с версии 3.2, в SoftIce входит универсальный
дисплейный адаптер, который должен работать с любой видеокартой, также
есть драйвера и для большого числа видеокарт.
SoftIce поддерживает работу с:
одной видеокартой (стандартный вариант)
с двумя видеокартами (вторая видеокарта должна быть MDA (Monochrome
Display Adapter) или Hercules-совместимая)
с двумя обычными видеокартами при условии, что они будут работать вместе
удаленную отладку (со вторым компьютером, который соединяется с первым
посредством COM-порта (remote debugging));
На диске занимает 5,8 Мб.
При инсталляции, как обычно, введите директорию, куда вы хотите
поставить SoftIce, выберите компоненты, которые хотите поставить, после
чего попадете в окно выбора видеоадаптера. SoftIce сам определяет
видеокарту, если она соответствует вашей - нажмите кнопку Test, экран
должен переключится в текстовый режим и вы увидите фразы “SoftIce is
totally awesome!” на всем экране, а в середине отсчет цифр от 5 до 1.
Если вы это увидели, то значит настройка видеоадаптера прошла успешно -
жмите кнопку Next, если же у вас сбилась развертка, пропало изображение
или повисла машина, то значит у SoftIce проблемы с видеокартой, для их
решения существуют два пути: первый, включить универсальный
видеоадаптер – должно помогать всегда (на моем Matrox Mistique проходит
только этот вариант), тогда SoftIce будет работать в окне: второй,
подобрать из числа представленных видеоадаптеров аналог вашему (у меня
с S3 TRIO 64 вис (правда SoftIce был 3.01), а с DS 2000 работал
на-ура); вам решать какой вариант лучше.
После выбора адаптера выберите тип мыши, которой вы пользуетесь (хотя
мышь можно и не ставить, без нее тяжело работать в SoftIce). Далее
разрешите модифицировать свой autoexec.bat для того, чтобы SoftIce
загружался при старте компьютера. Подтвердите выбранную конфигурацию и
следите за тем, как SoftIce ставится на вашу машину. На предложение
перезагрузить компьютер, согласитесь. После перезагрузки нажмите
клавиши Ctrl-D. Если вместо рабочего стола вы увидите какие-то
непонятные буквы и цифры, то считайте, что установку SoftIce на машину
вы закончили, и наступает этап настройки. Если же ничего не случилось,
или машина повисла при загрузке, то проверьте все ли вы правильно
сделали. Если SoftIce не загрузился, проверьте, прописана ли в
autoexec.bat строка запуска, она всегда последняя и выглядит
приблизительно так: C:\WINDEBUG\SICE324\WINICE.EXE, если нет -
пропишите ее с вашим путем. Если машина повисла, то причина, скорее
всего в неверной конфигурации видеоадаптера. Попробуете изменить ее.
Кстати, все настройки, которые вы проводили при инсталляции можно
изменить: Пуск – Программы – NuMega SoftIce.
Настройка:
Откройте на редактирование файл winice.dat, который находится в той же
директории что и SoftIce (в случае NT - в каталоге
%SystemPath%\system32\drivers), и уберите точку с запятой со следующих
строк:
; ***** Examples of export symbols that can be included for Windows 95
*****
;Change the path to the appropriate drive and directory
EXP=c:\windows\system\kernel32.dll - убрать;
EXP=c:\windows\system\user32.dll - убрать;
EXP=c:\windows\system\gdi32.dll - убрать;
Проверьте путь к файлам kernel32,user32,gdi32, он должен
соответствовать вашему (Актуально в случае, если windows ставилась в
каталог отличный от C:\WINDOWS).
Эта операция нужна для того, чтобы при отладке программы при вызове
системных функций вы увидели имя вызываемой функции, а не какой-то call
[xxxxxxxx].
Пример:
Call [USER32!GetWindow], вместо CALL [BFC01480].
На мой взгляд первое выглядит значительно информативней.
Исправьте строку INIT в соответствии с одним из примеров:
INIT="WR;WD;WL;X;" – если вы используете видеодрайвер для "родной"
видеокарты (полноэкранный режим).
INIT="SET FONT 3;SET ORIGIN -10 25;WR;WD 4;WL;WC 12;X;" – если вы
используете универсальный видеодрайвер (оконный режим).
INIT="SET FONT 1; SET ORIGIN 30 30;LINES 60;WIDTH 90;WR;WD 4;WL;WC
12;X;" – вариант, работающий на моей машине и выводящий на экран
максимум информации (оконный режим), возможно для вашей машины
потребуется изменить значение некоторых параметров.
Если вы хотите передвинуть окно с SoftIce, то используйте клавиши
Ctrl-Alt-(одна из клавиш управления курсором).
Более подробно команды и переменные SoftIce будут рассмотрены ниже,
тогда вы сможете настроить SoftIce на свой вкус.
Первые шаги
Если вы все еще читаете этот опус, то для вас настал долгожданный
момент истины :-), пора посмотреть как это все работает в деле. В
поставку SoftIce входит пример GdiDemo, его и будем отлаживать
(придерживаясь указаний фирмы NuMega).
Пример без проблем собрался в VC4 (не забудьте включить отладочную
информацию), в BC 5.02 пример тоже собрался, но отладочную информацию
Symbol Loader не увидел, хотя в TD она грузится. Тот, кому лень
собирать проект самому, может скачать его отсюда: Gdidemo.zip (или
отсюда), архив занимает 0.1 Мб.
1. Загрузка отлаживаемой программы.
Запускаем Symbol Loader, выбираем опцию Open module в меню File, идем
туда, где у вас лежит Gdidemo.exe, и открываем его, далее в меню Module
нажимаем на опцию Load. SL оттранслирует отладочную информацию в .NMS
файл, загрузит исходные файлы, запустит отлаживаемую программу (в
данном случае Gdidemo) и всплывет в SoftIce, где вы увидите исходный
текст программы.
Подсвеченная строка с номером 35 – это точка входа (entry point) в вашу
программу. Если SL вывел сообщение типа "An error occured during symbol
translation/load", значит в отлаживаемом файле отсутствует отладочная
информация, жмите OK и наслаждайтесь [диз]ассемблером.
2. Управление SoftIce'ом.
Если Вы все правильно сделали, то вы должны увидеть SoftIce разбитый на
несколько окон. Верхнее окно – Register Window (окно регистров) –
показывает состояние рабочих регистров процессора. Под ним находится
окно данных Data Window, в нем вы можете посмотреть или отредактировать
дамп памяти. Ниже находится Code Window (окно кода) – в нем находится
исходный текст программы (если вы загрузили отладочную информацию), или
дизассемблированный код программы. В самом низу находиться окно команд
- Command Window, в нем вы можете вводить команду и видеть результат их
выполнения. Самая нижняя строчка – строка помощи, в ней при вводе
подсвечиваются возможные варианты команд и их синтаксис. Удобнее всего
управлять SoftIce с помощью мышки, но можно и без нее, хотя и не так
удобно.
2.1 Управление с помощью мышки:
Вы можете: изменять размер окон и закрывать их (нельзя изменить размер
окна регистров и FPU); скроллировать окна как на одну строку, так и на
целый экран; изменять значение регистров, флагов, ячеек памяти,
устанавливать точки останова на исполнение, удалять из Watch Window
переменные, которые больше не нужны. Правая кнопка мыши вызывает
контекстное меню, в котором вы можете выбрать одну из представленных
команд; работают команды с буфером обмена Windows.
Изменение размера окна - подведите курсор к нижней границе того окна,
которому хотите изменить размер или закрыть его, нажмите левую кнопку
мыши и ведите ее вниз (увеличение размера) или вниз (уменьшение
размера), если хотите закрыть окно, подведите нижнюю границу к верхней,
в окне появится фраза Close current window и окно исчезнет.
Скроллинг на одну строку – подведите курсор к маленьким стрелочкам,
расположенным у границ того окна, которое хотите скроллировать и жмите
левую кнопку мыши (стрелочки появляются, если размер окна больше или
равен двум строчкам).
Скроллинг на экран – подведите курсор к большим стрелочкам
расположенным внутри того окна, которое хотите скроллировать и жмите
левую кнопку мыши (стрелочки появляются, если размер окна больше или
равен четырем строчкам).
Изменение значений регистров – подведите курсор к тому регистру,
значение которого хотите изменить, нажмите левую кнопку мыши и введите
число, если нужно изменить одну цифру, то подводите курсор к этой цифре
и меняйте.
Изменение значений флагов – подведите курсор к тому флагу, который
хотите изменить, нажмите левую кнопку мыши, после чего клавишей Ins
можно изменить значение флага на противоположное (маленькая буква
означает, что флаг не установлен, большая установлен).
Изменение значений ячеек памяти – подведите курсор к тому байту (слову,
двойному слову и т.д.), которое хотите изменить, нажмите левую кнопку
мыши и вводите ваше значение, если хотите изменить одну или несколько
цифр в числе, то подведите курсор с помощью клавиатуры к нужным числам
и меняйте.
Примечание: во всех случаях изменения значений они вступают в силу
после того, как вы переключитесь в любое другое окно, до этого можно
отменить последнее изменение, нажав Esc.
Установка точек останова на исполнение – подведите курсор к той строке
в Code Window, в которой хотите остановиться, и двойным щелчком по
левой кнопке мыши поставьте точку останова, строка подсветится.
Удаление из Watch Window переменных – установите курсор на переменную,
которую хотите удалить, нажмите левую кнопку мыши, переменная
подсветиться, нажмите кнопку Del – переменная исчезнет.
Контекстное меню – по правой кнопке мыши вы попадаете в контекстное
меню, в котором вам доступны команды:
Copy – копировать в буфер обмена адрес или данные, находящиеся под
курсором.
Paste – вставить в окно команд, адрес или данные находящиеся в буфере
обмена
Copy&Paste - копировать в буфер обмена адрес или данные,
находящиеся под курсором, и вставить их в окно команд.
Display – вывести в окно данных дамп памяти, расположенный по адресу,
над которым в данный момент находиться курсор (Аналог команды D).
Un-Assemble – вывести в Code Window исходный (если есть отладочная
информация) или дизассемблированный текст программы, находящийся по
адресу, над которым в данный момент находиться курсор (Аналог команды
U).
What – идентифицирует значение, находящееся под курсором с заранее
определенными (Аналог команды Wath).
Previous – отменяет предыдущую команду, введенную из контекстного меню
(работает с командами Display и Un-Assemble).
2.2 Управление с помощью клавиатуры:
Можете делать все то же самое, но будет отсутствовать контекстное меню
и буфер обмена.
Изменение размера окна – размер (в строках) непосредственно задается в
команде открытия окна, если нужно.
WC – открыть окно кода (Code Window).
WD – открыть окно данных (Data Window).
WF – открыть окно FPU Stack (FPU Stack Window).
WL – открыть окно локальных переменных (Locals Window).
WR – открыть окно регистров (Register Window).
WW – открыть окно слежения (Watch Window).
Повторный ввод этих команд без параметров закрывает соответствующие
окна, с параметрами – меняет размер.
По умолчанию курсор находиться в окне команд. Переместить курсор в
нужное окно можно следующими комбинациями клавиш (если вы находитесь в
окне команд (Command Windows)):
Перейти в окно кода (Code Window)Alt-C
Перейти в окно данных (Data Window)Alt-D
Перейти в окно локальных переменных (Locals Window)Alt-L
Перейти в окно регистров (Register Window)Alt-R
Перейти в окно слежения (Watch Window)Alt-W
В окно сопроцессора курсор переместить нельзя.
Повторное нажатие этих клавиш возвратит вас обратно в окно команд (все
вышесказанное действительно и для Code Window).
В окне данных переключиться между дампами в HEX и ASCII формате можно с
помощью клавиши Tab, с ее же помощью можно переходить между регистрами
в окне регистров.
Скроллинг на одну строку – переходите в нужное окно и клавишами
управления курсор вверх и курсор вниз скроллируете окно.
Скроллинг на экран - переходите в нужное окно и клавишами PageUp и
PageDown скроллируете окно.
Примечание: Code и Data Window можно скроллировать и не переключаясь в
них из окна команд, для этого нужно кроме управляющих клавиш удерживать
еще Alt для Data Window и Ctrl для Code Window.
Изменение значений регистров – перейдите в окно регистров, подведите
курсор к тому регистру, значение которого хотите изменить и введите
число, если нужно изменить одну цифру, то подводите курсор к этой цифре
и меняйте, нажатие Enter подтверждает изменение, Esc отменяет.
Изменение значений флагов – перейдите в окно регистров, подведите
курсор к тому флагу, который хотите изменить. После чего, клавишей Ins
можно изменить значение флага на противоположное (маленькая буква
означает, что флаг не установлен, большая - установлен), Enter можно не
нажимать.
Изменение значений ячеек памяти – перейдите в окно данных, подведите
курсор к тому байту (слову, двойному слову и т.д.), которое хотите
изменить и вводите ваше значение, если хотите изменить одну или
несколько цифр в числе, то подведите курсор с помощью клавиатуры к
нужным числам и меняйте. Нажатие Enter или переход к следующему числу
подтверждает изменение, Esc отменяет.
Установка точек останова на исполнение – в окне команд наберите команду
BPX и введите адрес строки, на которой хотите остановиться.
Удаление из Watch Window переменных – перейдите в Watch Window,
установите курсор на переменную, которую хотите удалить, переменная
подсветиться, нажмите кнопку Del – переменная исчезнет.
После небольшой лекции по управлению SoftIce можно заняться и
собственно отладкой. Так как мы отлаживаем программу, написанную на
языке высокого уровня и с отладочной информацией, то можем отключить
окно регистров и окно данных, и включить Locals Window, что бы видеть
какие параметры передаются в процедуры (т.е. WD,WR,WL при условии, что
пользовались настройками приведенными выше).
Что бы посмотреть какие из исходных текстов программы были загружены -
дайте команду FILE *.
На экране в окне команд вы увидите имена файлов содержащих исходные
тексты программы GdiDemo: Bounce.c, Wininfo.c, Poly.c, Maze.c, Init.c,
Draw.c, Dialog.c, Xform.c, Gdidemo.c. Так как окно команд обычно
небольшое, то вы увидите несколько первых имен файлов. В строке помощи
будет присутствовать надпись "Press any key to continue; Esc to
cancel", вы можете с помощью клавиши Enter. Получить следующую строку с
именем файла, или, нажав на пробел, получить следующую порцию строк с
именами файлов (действительно для всех сообщений выводимых в окне
команд).
Если в процессе изучения листинга программы вы забрались слишком далеко
от текущего значения EIP, то вернутся можно командой:
:U EIP – дизасемблировать программу начина с текущего EIP адреса, либо
командой;
:. (точка) – переместиться к текущей исполняемой инструкции.
3. Трассировка программы.
Воспользуйтесь командой T (trace) для того чтобы оттрассировать одну
команду, или клавишей F8, которая закреплена по умолчанию за командой
T. Произойдет выполнение команды находящейся в текущей строке и курсор
перейдет на следующую строку и подсветит ее. Это строка:
LpszLine=LpszLine;
Еще раз нажмите F8, курсор передвинется на следующую строку:
if(!hPrevInst).
В Code Window вы видите исходный текст программы (source mode). Если вы
хотите посмотреть дизассемблированный (code mode) текст программы или
исходный и дизассемблированный (mixed mode) текст вместе,
воспользуйтесь командой SRC или клавишей F3 закрепленной за этой
командой. При первом нажатии вы увидите смешанный (исходный текст
программы и ассемблерные инструкции, из которых состоит эта строка)
текст, при втором нажатии дизассемблированный, третье нажатие вернет
вас в режим просмотра исходного текста программы.
Нажмите еще раз F8 и вы перейдете к строке
if(!RegisterAppClass(hInst));
Для того, чтобы отлаживать программу, вы пользуетесь командой Т,
которая исполняет один оператор исходной программы или одну машинную
команду.
Еще существует команда P или клавиша F10, которая выполняет один шаг в
программе, т.е. при трассировке какой-либо функции или прерывания вы не
получите управления до тех пор, пока выполнение функции не завершится,
и вы не вернетесь из функции обратно. Команду P удобно применять в том
случае, когда вы отлаживаете основной алгоритм и отвлекаться на
трассировку каждой процедуры нерационально.
Примечание: Командой T нельзя оттрассировать системные вызовы (WIN32
API calls) находясь в source mode, для их трассировки нужно перейти в
mixed или code mode.
4. Просмотр локальных переменных.
Окно Locals Window показывает текущий кадр стека. В нашем случае он
содержит локальные переменные для функции WinMain.
Командой T войдите в функцию RegisterAppClass, окно Locals Window
станет пустым, так как для этой функции еще не определены локальные
переменные. Функция RegisterAppClass находится в файле INIT.C. SoftIce
показывает текущий файл в левом верхнем углу Code Window
Введите команду T снова, окно Locals Window будет содержать параметр
переданный функции RegisterAppClass (hInstance) и локальную структуру
wndClass. Перед структурой стоит знак плюс, который означает что внутри
находятся переменные, которые можно посмотреть (так же можно смотреть
строковые переменные и массивы). Если у вас Pentium и вы пользуетесь
мышкой, то посмотреть структуру можно два раза щелкнув по ней мышкой,
знак + сменится на – и вы увидите переменные из которых состоит
структура. Закрыть структуру можно так же (двойным щелчком мыши). Если
вы пользуетесь клавиатурой то последовательность действий такова: жмем
Alt-L для перехода в Locals Window, затем курсорными клавишами подводим
светящуюся полоску к структуре, которую хотим посмотреть и нажимаем
Enter. Если требуется закрыть ее, то нажимаем Enter еще раз.
5. Установка точек останова на выполнение.
Точки останова на выполнение делятся на два вида: просто точки останова
и однократные точки останова.
Однократные точки останова:
Перейдите в Code Window, используя клавишу PgDn переместите курсор на
строку с номером 61 (тоже самое можно сделать используя команду U .61),
в этой строке находиться первый вызов функции Win32 API RegisterClass.
Используя команду HERE (клавиша F7) выполните программу до этой строки.
Команда HERE устанавливает точку останова в программе на адрес или
строку на которой находиться курсор и выполняет программу с текущего
адреса до адреса на котором находиться курсор, т.е. до тех пор пока не
сработает точка останова, после срабатывания SoftIce автоматически
отключит эту точку останова, что бы она больше не срабатывала.
Текущей строкой в отлаживаемой программе стала строка:
If(!RegisterClass(&wndClass))
Примечание: того же самого результата можно было добиться если бы вы
дали команду G .61 (исполнять программу до строки 61).
Обычные точки останова.
Следующие шаги демонстрируют использование обычных точек останова, т.е.
таких которые будут срабатывать до тех пор пока вы их не отмените.
Найдите следующий вызов функции RegisterClass, находящийся в строке 74.
Установите курсор на эту строку и введите команду BPX (BreakPoint
eXecutable) или клавишу F9 (по этой команде, в память на место команды
расположенной под курсором записывается команда INT3, но вы этого не
видите :-)). Строка должна подсветиться (если вы находитесь в code
mode, то после команды BPX необходимо указать адрес строки на которую
хотите поставить точку останова). Снять точку останова можно повторным
вводом этой же команды. Если вы счастливый обладатель процессора
Pentium, то процесс установки и снятия точки останова сводится к
двойному щелчку левой кнопкой на той команде, где хотите поставить
точку останова. После установки точки останова запустите программу
командой G или X (клавиша F5). Когда программа исполнит инструкцию
INT3, она передаст управление SoftIce, после чего он появиться перед
вами. Посмотреть информацию об установленных точках останова можно
командой BL (BreakPoint List):
:BL
00) BPX #0137:00402442 (адрес может быть другим).
Видим что установлена одна точка останова на исполнение по адресу
00402442, с порядковым номером 0. По этому адресу находиться команда,
расположенная в текущем файле INIT.C в строке 74. Вы можете
использовать вычисление выражений, для того чтобы получить адрес строки
по ее номеру:
:? .74
void * = 0x00402442
Так как дальнейшая пошаговая трассировка функции RegisterAppClass не
имеет для нас смысла, вернемся в то место, откуда эта функция
вызывалась. Для этого существует команда P с параметром RET (клавиша
F12). Она позволяет выполнять программу до тех пор пока не встретит
команду RET (RETF), исполнив эту команду SoftIce выйдет из подпрограммы
и остановиться на строке следующей за вызовом этой подпрограммы.
Применительно к нашей программе: функция RegisterAppClass вызывается из
функции WinMain, SoftIce остановиться в функции WinMain на строке
следующей за вызовом функции RegisterAppClass, т.е. подсвечена будет
строка:
Msg.wParam = 1;
Воспользуйтесь командой BC (Breakpoint Clear) с номером точки останова,
который вы посмотрели с помощью команды BL, для того, что бы убрать
именно эту точку останова, или вместо номера введите *, тогда вы
уберете все точки останова (можно вводить номера точек останова через
запятую, если хотите убрать несколько точек).
6. Использование информационных команд.
SoftIce имеет в своем распоряжении много разных команд, с помощью
которых можно узнать состояние и получить иную информацию об
операционной системе и запущенных в ней приложениях. Мы рассмотрим
только две команды: H (Help) и CLASS. Эти команды выводят достаточно
много информации в окне команд (Command Window), поэтому желательно
увеличить размер этого окна, для этого закроем окно локальных
переменных (Locals Window).
По команда H можно получить помощь по всем командам SoftIce или более
подробную информацию о конкретной команде, если введете ее имя в
качестве аргумента команды H:
:H CLASS
Display window class information
CLASS [-x] [task-name]
Ex: CLASS USER
Первая строка дает описание команды, вторая показывает информацию о
синтаксисе и аргументах, которые могут использоваться в команде, третья
строка содержит пример использования команды.
Целью выполнения функции RegisterAppClass является регистрация шаблона
для классов окон, которые будут использованы приложением GdiDemo для
создания окон. Используя команду CLASS можно посмотреть
зарегистрированные классы для GdiDemo:
:CLASS GDIDEMO
Результатом выполнения данной команды является информация о каждом
зарегистрированном классе окна. Информация включает в себя: имя класса,
адрес внутренней структуры данных WNDCLASS, модуль который
зарегистрировал данный класс, адрес процедуры, которая обслуживает
данный класс и состояние флагов стиля класса. Для получения подробной
информации воспользуйтесь ключом –X.
Handle
Class Name
Owner
WndwProc
Styles
5110
BOUNCEDEMO
GDIDEMO
2E9F:00000114
03000003
40AC
DRAWDEMO
GDIDEMO
2E9F:000000FE
03000003
409C
MAZEDEMO
GDIDEMO
2E9F:000000E8
03000003
3BC4
XFORMDEMO
GDIDEMO
2E9F:000000D2
03000003
3BB4
POLYDEMO
GDIDEMO
2E9F:000000BC
03000003
3A00
GDIDEMO
GDIDEMO
2E9F:000000A6
03000003
7. Символьные имена.
Когда вы загружаете приложение с отладочной информацией, SoftIce
автоматически создает таблицу символьных имен которая содержит все
имена, определенные в данном приложении. Используя команду TABLE можно
посмотреть какие таблицы символьных имен загружены в настоящий момент:
:TABLE
GDIDEMO [NM32]
0001044741 Bytes Of Symbol Memory Available
Используемая в данный момент таблица символьных имен выделена цветом.
Если текущая таблица символьных имен не соответствует той на которую
ссылается ваше приложение, то используя команду TABLE с именем вашего
приложения в качестве аргумента, вы подключите нужную таблицу (если для
вашего приложения создана таблица):
:TABLE GDIDEMO
Используя команду SYM вы можете посмотреть все символьные имена,
определенные в текущей таблице (на экран выводятся по сегментам, внутри
них в алфавитном порядке). Если интересует какие-то определенные имена,
то используйте шаблоны:
:SYM w*
.text
(0137:00401000
, 000145C1 bytes)
0137:004012E0
WinMain
0137:00405700
WinMainCRTStartup
0137:004013AD
WndProc
0137:0040AF50
wcslen
0137:0040C160
wcsncnt
0137:004107A0
wctomb
0137:0040FA50
write_char
0137:0040FAD0
write_multi_char
0137:0040FB20
write_string
На экране список всех символьных имен, начинающихся с буквы w, все они
расположены в сегменте .text (выполняемый сегмент, он начинается с
адреса 0137:00401000 и имеет длину 0145C1H байт), т.е. эти имена –
имена функций и процедур входящие в приложение GDIDEMO. Данные
находятся в сегментах .data, .rdata, .idata.
8. Условные точки останова.
Одним из символов, определенных в приложении GDIDEMO, является функция
LockWindowInfo. Назначение этой функции – возвращение адреса
переменных, которые определяют свойства окна. Для того, чтобы
ознакомиться с условными точками останова и точками останова на доступ
к памяти, мы выполним следующие действий:
Установим точку останова на функцию LockWindowInfo
Отредактируем поставленную точку останова таким образом, чтобы она
срабатывала по определенному нами условию.
Установим точку останова на доступ к ячейки памяти, для того чтобы
отследить обращения к этой ячейке.
Установка точки останова на функцию LockWindowInfo.
Командой BPX LockWindowInfo поставим точку останова на выполнение на
эту функцию. Каждый раз, когда в одном из окон приложения GDIDEMO нужно
будет обновить информацию, программой будет вызываться функция
LockWindowInfo, так как на эту функцию поставлена точка останова, то
будет вызываться SoftIce. Командой BL проверьте, установилась ли точка
останова. Запустите приложение командой X или G. Как только будет
вызвана функция LockWindowInfo, SoftIce всплывет. Так как обновление
происходит постоянно, то постоянно вызывается и SoftIce, что очень
неудобно, если нас интересует обновление какого-либо конкретного окна.
Чтобы перехватить вызов на обновление конкретного окна, к примеру,
POLYDEMO, воспользуемся условной точкой останова. Из исходного текста
программы (файл wininfo.c) видно, что функция LockWindowInfo получает в
качестве входного аргумента один параметр HWND (Handle Window) –
дескриптор окна, и возвращает в вызывающую функцию одно значение –
указатель на переменные для данного окна. То есть если бы мы заставили
срабатывать точку останова только на обработчик окна POLYDEMO, мы бы
добились своей цели. Для начала нам необходимо узнать дескриптор нашего
окна, для этого воспользуемся командой:
:HWND GDIDEMO
WindowHandle
hQueue
SZ
Qowner
ClassName
WindowProcedure
0724(1)
10FF
32
GDIDEMO
GDIDEMO
365F:000001C4
0728(2)
10FF
32
GDIDEMO
MdiClient
17A7:00001988
0734(3)
10FF
32
GDIDEMO
BOUNCEDEMO
365F:00000232
0730(3)
10FF
32
GDIDEMO
POLYDEMO
365F:000001DA
072C(3)
10FF
32
GDIDEMO
DRAWDEMO
365F:0000021c
дескриптор окна POLYDEMO имеет значение 0730, если в списке вы не
увидели нужного окна, то запустите приложение клавишей X или G, опять
сработает точка останова, проверьте, создалось ли окно, если нет, то
повторите последние действия. Теперь можно останавливать исполнение
программы только в том случае, когда в качестве параметра для функции
LockWindowInfo используется значение 0730. В Windows параметры для
функции обычно передаются через стек. При остановке в функции
LockWindowInfo стек будет выглядеть следующим образом (посмотреть
содержимое стека можно подведя курсор к регистру ESP, нажав правую
кнопку мыши вызвать контекстное меню и выбрать команду Display, неплохо
бы еще сменить командой DD формат вывода данных в DataWindow на показ
двойных слов, так как наше приложение 32-разрядное):
ESP = 0055FC00
013F:0055FC00 00404852 00000730 0055FC3C 00008CAA
число 00404852 – это адрес, на который программа перейдет после
завершения работы нашей функции (адрес возврата);
число 00000730 – это дескриптор окна POLYDEMO (собственно то, что нас
интересует);
Теперь зная, где и что у нас передается в функцию, мы можем выставить
условную точку останова. Для этого вызовем на редактирование точку
останова, поставленную на функции LockWindowInfo:
:BPE 0
в нижней строке командного окна появиться строка:
:BPX LockWindowInfo
и курсор установиться в конце строки, теперь можете редактировать точку
останова по своему усмотрению, в конце строки добавьте следующее
условие: IF ESP->4 == 00000730 и нажмите Enter.
Точка останова теперь будет выглядеть так:
:BPX LockWindowInfo IF ESP->4 == 00000730
То есть она будет срабатывать тогда, когда двойное слово по адресу
ESP+4 будет равным числу 00000730, которое соответствует дескриптору
окна POLYDEMO. Проверьте командой BL, соответствует ли точка останова
заданной, запускайте приложение и убедитесь, что вся эта конструкция
замечательно работает.
Установим точку останова на доступ к первому двойному слову данных
экземпляра окна POLYWINDOW. Как уже отмечалось выше, входным аргументом
для функции LockWindowInfo является дескриптор окна, выходным адрес
данных экземпляра окна. После срабатывания точки останова поставленной
на функции LockWindowInfo с параметром соответствующим дескриптору окна
POLYWINDOW, на выходе функции будем иметь адрес данных экземпляра окна
POLYWINDOW, по этому адресу и поставим точку останова на доступ к
памяти.
Для того чтобы получить адрес данных экземпляра окна, выполним
программу до строки с номером 57 (в файле WININFO.C):
:G .57
функция возвращает 32-битное значение (в нашем случае адрес) в регистре
EAX, поэтому можно используя команду BPMD (BreakPoint Memory Dword) и
значение адреса в регистре EAX, поставить точку останова на доступ к
первом слову данных экземляра окна POLYDEMO:
:BPMD EAX
Эта команда использует регистры аппаратной отладки встроенные в
процессор для отслеживания чтения и записи двойного слова по указанному
линейному адресу. В данном случае это первое слово данных экземпляра
окна POLYDEMO. Используйте команду BL что бы проверить правильность
установки точки останова.
:BL
00) BPX LOCKWINDOWINFO IF ((ESP->4)==0x00000730)
01) BPMD #015F:0052006C RW DR3
Точка останова с номером 0 установлена на исполнение функции
LockWindowInfo и точка останова с номером 1 стоит на доступ к памяти по
адресу #015F:0052006C.
Отключите 0 точку останова командой BD (Breakpoint Disable):
:BD 0
В отличие от команды BC, которая удаляет точку останова, команда BD
временно отключает точку, т.е. она не будет срабатывать, но ее в любой
момент можно включить обратно командой BE (Breakpoint Enable).
Отключенные точки останова выделяются звездочками рядом с порядковым
номером точки останова.
:BL
00) * BPX LOCKWINDOWINFO IF ((ESP->4)==0x00000730)
01) BPMD #015F:0052006C RW DR3
Запустите SoftIce командами X или G, когда окно POLYDEMO попытается
получить доступ к первому двойному слову экземпляра данных окна,
сработает точка останова и SoftIce всплывет, это будет происходить в
функциях PolyRedraw и PolyDrawBez. Эти функции обращаются к полю
nBezTotal, которое находиться по нулевому смещению в данных экземпляра
окна POLYDEMO. Значение этого поля задает количество кривых
одновременно выводимых в окно POLYDEMO.
Примечание: Из-за особенностей архитектуры процессоров Intel перехват
обращения к ячейки памяти произойдет после исполнения команды
обращающейся к памяти, т.е. SoftIce осановиться на следующей команде.
Сбросьте все точки останова командой BC * и выйдете из SoftIce.
Эпилог
Если вы добрались до этих строк – значит вы отладили свою первую
программу с помощью замечательного отладчика SOFTICE. Но возможности
SoftIce не ограничиваются теми, которые мы здесь вкратце рассмотрели,
они гораздо больше.
Замеченные ошибки в версии 3.24:
При отладке программы в Code Window неправильно дизассемблируются
команды перехода ( JXX SHORT), т.е. стрелочка показывает направление
перехода правильно, а в мнемонике он на 100H больше (или меньше – не
помню).
Удачи в крэкерстве!
|
|